summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--COPYING358
-rw-r--r--ChangeLog324
-rw-r--r--MANIFEST30
-rw-r--r--Makefile.in12
-rw-r--r--README.jp2
-rw-r--r--ToDo2
-rw-r--r--array.c84
-rw-r--r--class.c3
-rw-r--r--config_h.dj64
-rw-r--r--config_s.dj49
-rw-r--r--configure41
-rw-r--r--configure.bat3
-rw-r--r--configure.in5
-rw-r--r--defines.h4
-rw-r--r--dir.c19
-rw-r--r--dln.c2
-rw-r--r--enum.c1
-rw-r--r--eval.c415
-rw-r--r--ext/curses/curses.c8
-rw-r--r--ext/curses/extconf.rb2
-rw-r--r--ext/etc/etc.c22
-rw-r--r--ext/extmk.rb.in72
-rw-r--r--ext/md5/md5init.c4
-rw-r--r--ext/socket/socket.c7
-rw-r--r--file.c24
-rw-r--r--gc.c14
-rw-r--r--hash.c56
-rw-r--r--instruby.rb30
-rw-r--r--intern.h10
-rw-r--r--io.c63
-rw-r--r--lib/Env.rb1
-rw-r--r--lib/README61
-rw-r--r--lib/delegate.rb2
-rw-r--r--lib/ping.rb31
-rw-r--r--lib/telnet.rb103
-rw-r--r--lib/thread.rb8
-rw-r--r--lib/timeout.rb42
-rw-r--r--marshal.c8
-rw-r--r--missing/nt.c2
-rw-r--r--missing/nt.h6
-rw-r--r--missing/vsnprintf.c1150
-rw-r--r--mkconfig.rb2
-rw-r--r--node.h42
-rw-r--r--object.c32
-rw-r--r--parse.y195
-rw-r--r--process.c2
-rw-r--r--range.c71
-rw-r--r--re.c30
-rw-r--r--re.h2
-rw-r--r--regex.c55
-rw-r--r--ruby.c6
-rw-r--r--ruby.h107
-rw-r--r--sample/README60
-rw-r--r--sample/mkproto.rb8
-rw-r--r--sample/ruby-mode.el13
-rw-r--r--sample/test.rb63
-rw-r--r--sample/tsvr.rb2
-rw-r--r--signal.c3
-rw-r--r--sprintf.c4
-rw-r--r--st.c177
-rw-r--r--st.h16
-rw-r--r--string.c130
-rw-r--r--time.c80
-rw-r--r--top.sed96
-rw-r--r--variable.c9
65 files changed, 3357 insertions, 992 deletions
diff --git a/COPYING b/COPYING
index 3c68f02..eeb586b 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 55e65fe..45aa379 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,316 @@
+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.
+
+ * string.c (rb_str_dup): do not copy additional data (STR_NO_ORIG).
+
+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 10:48:09 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (read_all): SEGV on large files.
+
+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.
+
+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.
@@ -7,7 +320,7 @@ 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.
-Thu Oct 1 01:55:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+Mon Oct 1 01:55:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
* parse.y (rb_intern): should not raise exceptions.
@@ -83,20 +396,13 @@ Tue Sep 8 10:03:39 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
* eval.c (f_END): needed to initialize frame->argc;
-Tue Sep 8 01:42:30 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
-
- * enum.c (Init_Enumerable): Enumerable#reverse removed.
-
- * eval.c (call_trace_func): profiler support.
-
- * eval.c (rb_call0): ditto.
-
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.
diff --git a/MANIFEST b/MANIFEST
index c265be1..5193149 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -14,7 +14,8 @@ compar.c
configure
configure.bat
configure.in
-config.dj
+config_h.dj
+config_s.dj
config.guess
config.sub
defines.h
@@ -47,6 +48,7 @@ node.h
numeric.c
object.c
pack.c
+parse.c
parse.y
process.c
random.c
@@ -85,6 +87,7 @@ ext/extmk.rb.in
ext/extmk.rb.nt
lib/English.rb
lib/Env.rb
+lib/README
lib/base64.rb
lib/cgi-lib.rb
lib/complex.rb
@@ -125,20 +128,7 @@ lib/telnet.rb
lib/tempfile.rb
lib/thread.rb
lib/thwait.rb
-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
+lib/timeout.rb
lib/tracer.rb
lib/weakref.rb
missing/alloca.c
@@ -153,7 +143,6 @@ missing/mkdir.c
missing/nt.c
missing/nt.h
missing/setenv.c
-missing/snprintf.c
missing/strcasecmp.c
missing/strchr.c
missing/strdup.c
@@ -162,7 +151,9 @@ 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
@@ -210,13 +201,6 @@ 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
diff --git a/Makefile.in b/Makefile.in
index 730b3ad..ff1c2d1 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -11,7 +11,7 @@ PURIFY =
@SET_MAKE@
prefix = @prefix@
-CFLAGS = @CFLAGS@ -I@srcdir@ -I@includedir@
+CFLAGS = @CFLAGS@ -I. -I@srcdir@ -I@includedir@
LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@
EXTLIBS =
LIBS = @LIBS@ $(EXTLIBS)
@@ -84,13 +84,13 @@ ruby$(binsuffix): $(LIBRUBY) $(MAINOBJ) $(EXTOBJS)
libruby.a: $(OBJS) dmyext.o
@AR@ rcu $@ $(OBJS) dmyext.o
- @-@RANLIB@ $(LIBRUBY) 2> /dev/null || true
+ @-@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
@@ -117,7 +117,7 @@ rbconfig.rb: config.status miniruby$(binsuffix)
$(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) $<
@@ -147,8 +147,8 @@ mkdir.o: @srcdir@/missing/mkdir.c
setenv.o: @srcdir@/missing/setenv.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/setenv.c
-snprintf.o: @srcdir@/missing/snprintf.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/snprintf.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
diff --git a/README.jp b/README.jp
index 1b63f71..d137a43 100644
--- a/README.jp
+++ b/README.jp
@@ -95,7 +95,7 @@ UNIXであればconfigureがほとんどの差異を吸収してくれるはずで
すが,思わぬ見落としがあった場合(あるに違いない),作者にその
ことをレポートすれば,解決できるかも知れません.
-アークテクチャにもっとも依存するのはGC部です.RubyのGCは対象
+アーキテクチャにもっとも依存するのはGC部です.RubyのGCは対象
のアーキテクチャがsetjmp()によって全てのレジスタを jmp_bufに
格納することと,jmp_bufとスタックが32bitアラインメントされて
いることを仮定しています.特に前者が成立しない場合の対応は非
diff --git a/ToDo b/ToDo
index 9710c42..edb2389 100644
--- a/ToDo
+++ b/ToDo
@@ -1,3 +1,5 @@
* non-blocking open/write for thread
+* avoid blocking with gethostbyname/gethostbyaddr
* package or access control for global variables
* format
+* freeze or undump to bundle everything in birary format.
diff --git a/array.c b/array.c
index 9c75427..e21b211 100644
--- a/array.c
+++ b/array.c
@@ -45,9 +45,10 @@ static void
rb_ary_modify(ary)
VALUE ary;
{
- if (FL_TEST(ary, ARY_FREEZE|ARY_TMPLOCK)) {
+ if (FL_TEST(ary, ARY_FREEZE|ARY_TMPLOCK))
rb_raise(rb_eTypeError, "can't modify frozen array");
- }
+ if (rb_safe_level() >= 4 && !FL_TEST(ary, FL_TAINT))
+ rb_raise(rb_eSecurityError, "Insecure: can't modify array");
}
VALUE
@@ -116,7 +117,7 @@ rb_ary_new3(n, va_alist)
int i;
if (n < 0) {
- rb_raise(rb_eIndexError, "Negative number of items(%d)", n);
+ rb_raise(rb_eIndexError, "negative number of items(%d)", n);
}
ary = rb_ary_new2(n<ARY_DEFAULT_SIZE?ARY_DEFAULT_SIZE:n);
@@ -226,7 +227,10 @@ rb_ary_store(ary, idx, val)
{
rb_ary_modify(ary);
if (idx < 0) {
- rb_raise(rb_eIndexError, "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) {
@@ -339,16 +343,13 @@ rb_ary_subseq(ary, beg, len)
{
VALUE ary2;
- if (beg < 0) {
- beg = RARRAY(ary)->len + beg;
- if (beg < 0) beg = 0;
- }
- if (len < 0) {
- rb_raise(rb_eIndexError, "negative length %d", RARRAY(ary)->len);
- }
- if (len == 0) {
+ if (len <= 0) {
return rb_ary_new2(0);
}
+ if (beg < 0) {
+ len += beg;
+ beg = 0;
+ }
if (beg + len > RARRAY(ary)->len) {
len = RARRAY(ary)->len - beg;
}
@@ -370,32 +371,28 @@ beg_len(range, begp, lenp, len)
int len;
{
int beg, end;
+ int b, e;
if (!rb_range_beg_end(range, &beg, &end)) return Qfalse;
-
- if ((beg > 0 && end > 0 || beg < 0 && end < 0) && beg > end) {
- rb_raise(rb_eIndexError, "end smaller than beg [%d..%d]", beg, end);
- }
+ 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 Qtrue;
}
@@ -412,8 +409,8 @@ rb_ary_aref(argc, argv, ary)
if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
beg = NUM2INT(arg1);
len = NUM2INT(arg2);
- if (len <= 0) {
- return rb_ary_new();
+ if (beg < 0) {
+ beg = RARRAY(ary)->len + beg;
}
return rb_ary_subseq(ary, beg, len);
}
@@ -482,14 +479,23 @@ rb_ary_replace(ary, beg, len, rpl)
VALUE ary, rpl;
int beg, len;
{
- rb_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) {
@@ -506,9 +512,6 @@ rb_ary_replace(ary, beg, len, rpl)
if (beg + len > RARRAY(ary)->len) {
len = RARRAY(ary)->len - beg;
}
- if (len < 0) {
- rb_raise(rb_eIndexError, "negative length %d", RARRAY(ary)->len);
- }
alen = RARRAY(ary)->len + RARRAY(rpl)->len - len;
if (alen >= RARRAY(ary)->capa) {
@@ -538,6 +541,10 @@ rb_ary_aset(argc, argv, ary)
if (rb_scan_args(argc, argv, "21", &arg1, &arg2, &arg3) == 3) {
beg = NUM2INT(arg1);
len = NUM2INT(arg2);
+
+ if (beg < 0) {
+ beg = RARRAY(ary)->len + beg;
+ }
rb_ary_replace(ary, beg, len, arg3);
return arg3;
}
@@ -556,9 +563,6 @@ rb_ary_aset(argc, argv, ary)
offset = NUM2INT(arg1);
fixnum:
- if (offset < 0) {
- offset = RARRAY(ary)->len + offset;
- }
rb_ary_store(ary, offset, arg2);
return arg2;
}
@@ -677,7 +681,7 @@ rb_ary_join(ary, sep)
}
if (!NIL_P(sep)) rb_str_concat(result, sep);
rb_str_cat(result, RSTRING(tmp)->ptr, RSTRING(tmp)->len);
- if (rb_str_tainted(tmp)) rb_str_taint(result);
+ if (rb_obj_tainted(tmp)) rb_obj_taint(result);
}
return result;
@@ -1353,6 +1357,7 @@ Init_Array()
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);
@@ -1387,7 +1392,6 @@ Init_Array()
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_includes, 1);
rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
diff --git a/class.c b/class.c
index 904387f..86ac8c5 100644
--- a/class.c
+++ b/class.c
@@ -113,6 +113,7 @@ 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;
@@ -540,7 +541,7 @@ rb_define_global_function(name, func, argc)
VALUE (*func)();
int argc;
{
- rb_define_private_method(rb_mKernel, name, func, argc);
+ rb_define_module_function(rb_mKernel, name, func, argc);
}
void
diff --git a/config_h.dj b/config_h.dj
new file mode 100644
index 0000000..2a81c29
--- /dev/null
+++ b/config_h.dj
@@ -0,0 +1,64 @@
+#define 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 0000000..d6d3836
--- /dev/null
+++ b/config_s.dj
@@ -0,0 +1,49 @@
+s%@CFLAGS@%-g -O2%g
+s%@CPPFLAGS@%%g
+s%@CXXFLAGS@%%g
+s%@DEFS@% -DTHREAD=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%@arch@%i386-djgpp%g
diff --git a/configure b/configure
index d7b6645..803c6d1 100644
--- a/configure
+++ b/configure
@@ -2679,7 +2679,7 @@ echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6
test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.o"
for ac_func in dup2 setenv memmove mkdir strcasecmp strerror strftime\
- strchr strstr strtoul strdup crypt flock snprintf
+ strchr strstr strtoul strdup crypt flock vsnprintf
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:2686: checking for $ac_func" >&5
@@ -3460,6 +3460,9 @@ echo "configure:3427: 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"
@@ -3503,13 +3506,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:3507: checking whether matz's dln works" >&5
+echo "configure:3510: 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 3513 "configure"
+#line 3516 "configure"
#include "confdefs.h"
#define USE_DLN_A_OUT
@@ -3519,7 +3522,7 @@ int main() {
; return 0; }
EOF
-if { (eval echo configure:3523: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3526: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_dln_a_out=yes
else
@@ -3621,7 +3624,7 @@ fi
case "$host_os" in
human*)
echo $ac_n "checking for _harderr in -lsignal""... $ac_c" 1>&6
-echo "configure:3625: checking for _harderr in -lsignal" >&5
+echo "configure:3628: 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
@@ -3629,7 +3632,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lsignal $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 3633 "configure"
+#line 3636 "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
@@ -3640,7 +3643,7 @@ int main() {
_harderr()
; return 0; }
EOF
-if { (eval echo configure:3644: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:3647: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -3668,7 +3671,7 @@ else
fi
echo $ac_n "checking for hmemset in -lhmem""... $ac_c" 1>&6
-echo "configure:3672: checking for hmemset in -lhmem" >&5
+echo "configure:3675: 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
@@ -3676,7 +3679,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lhmem $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 3680 "configure"
+#line 3683 "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
@@ -3687,7 +3690,7 @@ int main() {
hmemset()
; return 0; }
EOF
-if { (eval echo configure:3691: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:3694: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -3717,12 +3720,12 @@ fi
for ac_func in select
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3721: checking for $ac_func" >&5
+echo "configure:3724: 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 3726 "configure"
+#line 3729 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -3745,7 +3748,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:3749: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
+if { (eval echo configure:3752: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -3770,7 +3773,7 @@ fi
done
echo $ac_n "checking whether PD libc _dtos18 fail to convert big number""... $ac_c" 1>&6
-echo "configure:3774: checking whether PD libc _dtos18 fail to convert big number" >&5
+echo "configure:3777: 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
@@ -3778,7 +3781,7 @@ else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 3782 "configure"
+#line 3785 "configure"
#include "confdefs.h"
#include <stdio.h>
@@ -3790,7 +3793,7 @@ main ()
}
EOF
-if { (eval echo configure:3794: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3797: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
rb_cv_missing__dtos18=yes
else
@@ -3812,7 +3815,7 @@ EOF
fi
echo $ac_n "checking whether PD libc fconvert fail to round""... $ac_c" 1>&6
-echo "configure:3816: checking whether PD libc fconvert fail to round" >&5
+echo "configure:3819: 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
@@ -3820,7 +3823,7 @@ else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 3824 "configure"
+#line 3827 "configure"
#include "confdefs.h"
#include <stdio.h>
@@ -3833,7 +3836,7 @@ main ()
}
EOF
-if { (eval echo configure:3837: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3840: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
then
rb_cv_missing_fconvert=yes
else
diff --git a/configure.bat b/configure.bat
index 35f9d48..093d435 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 6d89c58..6aa2254 100644
--- a/configure.in
+++ b/configure.in
@@ -159,7 +159,7 @@ AC_FUNC_ALLOCA
AC_FUNC_VFORK
AC_FUNC_MEMCMP
AC_REPLACE_FUNCS(dup2 setenv memmove mkdir strcasecmp strerror strftime\
- strchr strstr strtoul strdup crypt flock snprintf)
+ 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\
@@ -363,6 +363,9 @@ 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"
diff --git a/defines.h b/defines.h
index 139d62e..1a85758 100644
--- a/defines.h
+++ b/defines.h
@@ -34,6 +34,10 @@
#include "missing/nt.h"
#endif
+#ifndef EXTERN
+#define EXTERN extern
+#endif
+
#ifdef sparc
#define FLUSH_REGISTER_WINDOWS asm("ta 3")
#else
diff --git a/dir.c b/dir.c
index 6c670b8..ed48de0 100644
--- a/dir.c
+++ b/dir.c
@@ -119,7 +119,7 @@ dir_read(dir)
errno = 0;
dp = readdir(dirp);
if (dp)
- return rb_str_taint(rb_str_new(dp->d_name, NAMLEN(dp)));
+ return rb_tainted_str_new(dp->d_name, NAMLEN(dp));
else if (errno == 0) { /* end of stream */
return Qnil;
}
@@ -138,7 +138,7 @@ dir_each(dir)
GetDIR(dir, dirp);
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- file = rb_str_taint(rb_str_new(dp->d_name, NAMLEN(dp)));
+ file = rb_tainted_str_new(dp->d_name, NAMLEN(dp));
rb_yield(file);
}
return dir;
@@ -240,7 +240,7 @@ dir_s_getwd(dir)
if (getwd(path) == 0) rb_sys_fail(path);
#endif
- return rb_str_taint(rb_str_new2(path));
+ return rb_tainted_str_new2(path);
}
static VALUE
@@ -317,7 +317,7 @@ push_globs(ary, s)
if (fnames == (char**)-1) rb_sys_fail(s);
ff = fnames;
while (*ff) {
- rb_ary_push(ary, rb_str_taint(rb_str_new2(*ff)));
+ rb_ary_push(ary, rb_tainted_str_new2(*ff));
free(*ff);
ff++;
}
@@ -427,6 +427,16 @@ dir_foreach(io, dirname)
return rb_ensure(dir_each, dir, dir_close, dir);
}
+static VALUE
+dir_entries(io, dirname)
+ VALUE io, dirname;
+{
+ VALUE dir;
+
+ dir = rb_funcall(rb_cDir, rb_intern("open"), 1, dirname);
+ return rb_ensure(rb_Array, dir, dir_close, dir);
+}
+
void
Init_Dir()
{
@@ -437,6 +447,7 @@ Init_Dir()
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);
diff --git a/dln.c b/dln.c
index dc66b53..0c06a03 100644
--- a/dln.c
+++ b/dln.c
@@ -78,7 +78,7 @@ int eaccess();
#endif
#ifndef FUNCNAME_PATTERN
-# if defined(__hp9000s300) || defined(__NetBSD__) || defined(__BORLANDC__) || defined(__FreeBSD__) || defined(NeXT) || defined(__WATCOMC__)
+# 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"
diff --git a/enum.c b/enum.c
index ca76d2a..61d4761 100644
--- a/enum.c
+++ b/enum.c
@@ -364,6 +364,7 @@ Init_Enumerable()
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);
diff --git a/eval.c b/eval.c
index 4e6f8d2..79ce7ab 100644
--- a/eval.c
+++ b/eval.c
@@ -72,7 +72,7 @@ static int scope_vmode;
#define CACHE_SIZE 0x800
#define CACHE_MASK 0x7ff
-#define EXPR1(c,m) ((((long)(c)>>4)^(m))&CACHE_MASK)
+#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK)
struct cache_entry { /* method hash table. */
ID mid; /* method's id */
@@ -98,18 +98,37 @@ rb_clear_cache()
}
static int cache_conflict;
+static int eval_called;
static int
count_cent()
{
struct cache_entry *ent, *end;
- int n = 0;
+ int n = 0, n2 = 0;
+ int p = 0;
+ fprintf(stderr, "\n|");
ent = cache; end = ent + CACHE_SIZE;
while (ent < end) {
- if (ent->mid != 0) n++;
+ fprintf(stderr, (ent->klass != 0)?"*":" ");
+ p++;
+ if (p % 80 == 0) {
+ break;
+ }
+ ent++;
+ }
+ fprintf(stderr, "|\n|");
+ p = 0; ent = cache;
+ while (ent < end) {
+ if (ent->klass != 0) {n++; n2++;}
+ p++;
+ if (p % 24 == 0) {
+ fprintf(stderr, "%c", n2?(n2+'0'):' ');
+ n2 = 0;
+ }
ent++;
}
+ fprintf(stderr, "|\n");
return n;
}
@@ -426,6 +445,7 @@ struct BLOCK {
struct tag *tag;
int iter;
int vmode;
+ int used;
struct RVarmap *d_vars;
#ifdef USE_THREAD
VALUE orig_thread;
@@ -443,13 +463,14 @@ static struct BLOCK *ruby_calling_block;
_block.self = self; \
_block.frame = *ruby_frame; \
_block.klass = ruby_class; \
- _block.frame.file = ruby_sourcefile; \
- _block.frame.line = ruby_sourceline; \
+ _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; \
+ _block.used = 0; \
ruby_block = &_block;
#define POP_BLOCK() \
@@ -506,6 +527,19 @@ rb_dvar_defined(id)
return Qfalse;
}
+static int
+dvar_len()
+{
+ struct RVarmap *vars = ruby_dyna_vars;
+ int n = 0;
+
+ while (vars) {
+ n++;
+ vars = vars->next;
+ }
+ return n;
+}
+
VALUE
rb_dvar_ref(id)
ID id;
@@ -552,7 +586,7 @@ dvar_asgn_push(id, value)
ID id;
VALUE value;
{
- rb_dvar_push(id, value);
+ rb_dvar_asgn(id, value);
if (ruby_calling_block) {
ruby_calling_block->d_vars = ruby_dyna_vars;
}
@@ -678,7 +712,7 @@ static int safe_level = 0;
1 - no dangerous operation by tainted string
2 - process/file operations prohibited
3 - all genetated strings are tainted
- 4 - no global variable modification/no direct output
+ 4 - no global (non-tainted) variable modification/no direct output
*/
int
@@ -723,15 +757,11 @@ rb_check_safe_str(x)
rb_raise(rb_eTypeError, "wrong argument type %s (expected String)",
rb_class2name(CLASS_OF(x)));
}
- if (rb_str_tainted(x)) {
+ if (rb_obj_tainted(x)) {
if (safe_level > 0){
rb_raise(rb_eSecurityError, "Insecure operation - %s",
rb_id2name(ruby_frame->last_func));
}
- if (rb_verbose) {
- rb_warning("Insecure operation - %s",
- rb_id2name(ruby_frame->last_func));
- }
}
}
@@ -986,7 +1016,11 @@ ruby_run()
#endif
exec_end_proc();
rb_gc_call_finalizer_at_exit();
+#if 1
fprintf(stderr, "%d/%d(%d)\n", count_cent(), CACHE_SIZE, cache_conflict);
+#else
+ fprintf(stderr, "rb_eval() called %d times\n", eval_called);
+#endif
}
else {
ex = state;
@@ -1081,7 +1115,6 @@ rb_eval_cmd(cmd, arg)
volatile int safe = rb_safe_level();
if (TYPE(cmd) != T_STRING) {
- Check_Type(arg, T_ARRAY);
return rb_funcall2(cmd, rb_intern("call"),
RARRAY(arg)->len, RARRAY(arg)->ptr);
}
@@ -1092,8 +1125,8 @@ rb_eval_cmd(cmd, arg)
ruby_scope = top_scope;
ruby_class = rb_cObject;
- if (rb_str_tainted(cmd)) {
- safe_level = 5;
+ if (rb_obj_tainted(cmd)) {
+ safe_level = 4;
}
if ((state = EXEC_TAG()) == 0) {
@@ -1626,20 +1659,38 @@ 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; }
+ eval_called++;
+
again:
if (!node) RETURN(Qnil);
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:
rb_f_END();
nd_set_type(node, NODE_NIL); /* exec just once */
@@ -1697,7 +1748,11 @@ rb_eval(self, node)
case NODE_IF:
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 {
@@ -1709,7 +1764,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;
@@ -1725,7 +1784,21 @@ rb_eval(self, node)
}
ruby_sourcefile = tag->nd_file;
ruby_sourceline = nd_line(tag);
- if (RTEST(rb_funcall2(rb_eval(self, tag->nd_head),eqq,1,&val))){
+ 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;
}
@@ -1835,6 +1908,11 @@ rb_eval(self, node)
}
}
POP_TAG();
+ if (rb_verbose && !ruby_block->used) {
+ ruby_sourcefile = node->nd_file;
+ ruby_sourceline = nd_line(node);
+ rb_warn("unused block");
+ }
POP_BLOCK();
switch (state) {
case 0:
@@ -1871,8 +1949,19 @@ 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, 0);
+ result = rb_eval(self, node->nd_stts);
+ if (nd_type(node->nd_stts) == NODE_RESTARGS && RARRAY(result)->len == 1) {
+ result = RARRAY(result)->ptr[0];
+ }
+ result = rb_yield_0(result, 0, 0);
break;
case NODE_RESCUE:
@@ -1909,6 +1998,9 @@ rb_eval(self, node)
}
}
if (state) JUMP_TAG(state);
+ if (node->nd_else) { /* no exception raised, else clause given */
+ result = rb_eval(self, node->nd_else);
+ }
}
break;
@@ -1946,12 +2038,32 @@ rb_eval(self, node)
case NODE_DOT2:
case NODE_DOT3:
- RETURN(rb_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;
+ ruby_scope->local_vars[node->nd_cnt] =
+ RTEST(rb_eval(self, node->nd_end))?Qfalse:Qtrue;
result = Qtrue;
}
else {
@@ -1960,23 +2072,23 @@ rb_eval(self, node)
}
else {
if (RTEST(rb_eval(self, node->nd_end))) {
- node->nd_state = 0;
+ ruby_scope->local_vars[node->nd_cnt] = Qfalse;
}
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 = Qtrue;
- }
- result = Qfalse;
+ 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 = Qtrue;
}
@@ -1990,6 +2102,11 @@ rb_eval(self, node)
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;
@@ -1997,7 +2114,13 @@ rb_eval(self, node)
TMP_PROTECT;
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);
END_CALLARGS;
@@ -2069,7 +2192,7 @@ rb_eval(self, node)
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();
@@ -2167,44 +2290,29 @@ rb_eval(self, node)
break;
case NODE_GASGN:
- {
- VALUE val;
-
- val = rb_eval(self, node->nd_value);
- rb_gvar_set(node->nd_entry, val);
- result = val;
- }
+ 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;
-
- if (NIL_P(ruby_class)) {
- rb_raise(rb_eTypeError, "no class/module to define constant");
- }
- val = 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 (rb_verbose) {
- rb_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 (rb_verbose) {
+ rb_warning("already initialized constant %s",
+ rb_id2name(node->nd_vid));
}
- rb_const_set(ruby_class, node->nd_vid, val);
- result = val;
}
+ rb_const_set(ruby_class, node->nd_vid, result);
break;
case NODE_LVAR:
@@ -2358,6 +2466,7 @@ rb_eval(self, node)
}
if (str2) {
rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ if (rb_obj_tainted(str2)) rb_obj_taint(str);
}
list = list->nd_next;
}
@@ -2474,6 +2583,9 @@ rb_eval(self, node)
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) {
@@ -2590,7 +2702,7 @@ rb_eval(self, node)
rb_obj_call_init(klass);
}
- return rb_module_setup(klass, node->nd_body);
+ result = rb_module_setup(klass, node->nd_body);
}
break;
@@ -2673,6 +2785,18 @@ rb_eval(self, 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;
}
@@ -2715,7 +2839,7 @@ rb_module_setup(module, node)
call_trace_func("class", file, line,
ruby_class, ruby_frame->last_func, 0);
}
- result = rb_eval(ruby_class, node->nd_body);
+ result = rb_eval(ruby_class, node->nd_next);
}
POP_TAG();
POP_SCOPE();
@@ -2787,7 +2911,7 @@ rb_f_exit(argc, argv, obj)
{
VALUE status;
- rb_secure(2);
+ rb_secure(4);
if (rb_scan_args(argc, argv, "01", &status) == 1) {
status = NUM2INT(status);
}
@@ -2811,7 +2935,7 @@ rb_abort()
static VALUE
rb_f_abort()
{
- rb_secure(2);
+ rb_secure(4);
rb_abort();
}
@@ -2950,10 +3074,11 @@ rb_yield_0(val, self, klass)
int state;
static unsigned serial = 1;
- if (!rb_iterator_p() || !ruby_block) {
+ if (!ruby_frame->iter || !ruby_block) {
rb_raise(rb_eLocalJumpError, "yield called out of iterator");
}
+ ruby_block->used = 1;
PUSH_VARS();
PUSH_CLASS();
block = ruby_block;
@@ -3112,7 +3237,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 */
@@ -3120,7 +3245,8 @@ 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;
@@ -3500,7 +3626,7 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper)
break;
}
- if ((++tick & 0xfff) == 0 && stack_length() > STACK_LEVEL_MAX)
+ if ((++tick & 0x3ff) == 0 && stack_length() > STACK_LEVEL_MAX)
rb_raise(rb_eSysStackError, "stack level too deep");
PUSH_ITER(itr);
@@ -3572,7 +3698,7 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper)
local_vars = ruby_scope->local_vars = 0;
ruby_scope->local_tbl = 0;
}
- b2 = body = body->nd_body;
+ b2 = body = body->nd_next;
PUSH_VARS();
PUSH_TAG(PROT_FUNC);
@@ -3709,14 +3835,22 @@ rb_call(klass, recv, mid, argc, argv, scope)
noex = ent->noex;
body = ent->method;
}
- else { if (ent->mid) cache_conflict++;
+ else {
+ if (ent->mid) {
+ fprintf(stderr, "%s#%s -> %s#%s (%d)\n", rb_class2name(ent->klass),
+ rb_id2name(ent->mid),
+ rb_class2name(klass),
+ rb_id2name(id), ent-cache);
+ cache_conflict++;
+ }
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)
@@ -3911,7 +4045,7 @@ compile(src, place)
Check_Type(src, T_STRING);
if (place == 0) place = ruby_sourcefile;
- node = rb_compile_string(place, RSTRING(src)->ptr, RSTRING(src)->len);
+ node = rb_compile_string(place, src);
if (ruby_nerrs == 0) return node;
return 0;
@@ -4123,7 +4257,7 @@ static VALUE
yield_under(under, self)
VALUE under, self;
{
- rb_secure(3);
+ rb_secure(4);
return exec_under(yield_under_i, under, self);
}
@@ -4260,6 +4394,7 @@ rb_load(fname, priv)
volatile ID last_func;
TMP_PROTECT;
+ rb_secure(4);
Check_SafeStr(fname);
#ifndef __MACOS__
if (RSTRING(fname)->ptr[0] == '~') {
@@ -4453,7 +4588,6 @@ rb_f_require(obj, fname)
RSTRING(fname)->ptr);
dyna_load:
- rb_secure(2);
#ifdef USE_THREAD
if (rb_thread_loading(feature)) return Qfalse;
else {
@@ -4764,6 +4898,7 @@ rb_f_local_variables()
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])));
}
}
@@ -4869,7 +5004,7 @@ Init_eval()
rb_define_method(rb_mKernel, "respond_to?", rb_obj_respond_to, -1);
rb_define_global_function("raise", rb_f_raise, -1);
- rb_define_alias(rb_mKernel, "fail", "raise");
+ rb_define_global_function("fail", rb_f_raise, -1);
rb_define_global_function("caller", rb_f_caller, -1);
@@ -4972,6 +5107,7 @@ blk_mark(data)
rb_gc_mark(data->body);
rb_gc_mark(data->self);
rb_gc_mark(data->d_vars);
+ rb_gc_mark(data->klass);
data = data->prev;
}
}
@@ -5064,12 +5200,49 @@ rb_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(klass)
VALUE klass;
@@ -5078,9 +5251,10 @@ proc_s_new(klass)
struct BLOCK *data;
if (!rb_iterator_p() && !rb_f_iterator_p()) {
- rb_raise(rb_eArgError, "tryed to create Procedure-Object out of iterator");
+ rb_raise(rb_eArgError, "tried to create Procedure-Object out of iterator");
}
+ ruby_block->used = 1;
proc = Data_Make_Struct(klass, struct BLOCK, blk_mark, blk_free, data);
*data = *ruby_block;
@@ -5098,20 +5272,7 @@ proc_s_new(klass)
}
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;
@@ -5143,6 +5304,7 @@ static VALUE
proc_call(proc, args)
VALUE proc, args; /* OK */
{
+ struct BLOCK * volatile old_block;
struct BLOCK *data;
volatile VALUE result = Qnil;
int state;
@@ -5164,7 +5326,8 @@ proc_call(proc, args)
orphan = blk_orphan(data);
/* PUSH BLOCK from data */
- PUSH_BLOCK2(data);
+ old_block = ruby_block;
+ ruby_block = data;
PUSH_ITER(ITER_CUR);
ruby_frame->iter = ITER_CUR;
@@ -5177,23 +5340,10 @@ proc_call(proc, args)
}
}
- 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();
@@ -5202,7 +5352,7 @@ proc_call(proc, args)
if (ruby_block->tag->dst == state) {
state &= TAG_MASK;
}
- POP_BLOCK2();
+ ruby_block = old_block;
safe_level = safe;
if (state) {
@@ -5230,6 +5380,7 @@ block_pass(self, node)
NODE *node;
{
VALUE block = rb_eval(self, node->nd_body);
+ struct BLOCK * volatile old_block;
struct BLOCK *data;
volatile VALUE result = Qnil;
int state;
@@ -5251,36 +5402,24 @@ block_pass(self, node)
orphan = blk_orphan(data);
/* PUSH BLOCK from data */
- PUSH_BLOCK2(data);
+ old_block = ruby_block;
+ ruby_block = data;
PUSH_ITER(ITER_PRE);
ruby_frame->iter = ITER_PRE;
- if (FL_TEST(block, PROC_TAINT)) {
- switch (RBASIC(block)->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(block);
result = rb_eval(self, node->nd_iter);
}
POP_TAG();
-
POP_ITER();
if (ruby_block->tag->dst == state) {
state &= TAG_MASK;
orphan = 2;
}
- POP_BLOCK2();
+ ruby_block = old_block;
safe_level = safe;
if (state) {
@@ -5350,6 +5489,9 @@ rb_obj_method(obj, vid)
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;
}
@@ -5362,12 +5504,24 @@ method_call(argc, argv, 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);
- result = rb_call0(data->klass, data->recv, data->id,
- argc, argv, data->body, 0);
+ PUSH_TAG(PROT_NONE);
+ if (FL_TEST(data->recv, 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;
}
@@ -5566,7 +5720,7 @@ static thread_t main_thread;
#define STACK(addr) (th->stk_pos<(addr) && (addr)<th->stk_pos+th->stk_len)
static void
-rb_thread_mark(th)
+thread_mark(th)
thread_t th;
{
struct FRAME *frame;
@@ -5583,6 +5737,7 @@ rb_thread_mark(th)
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) {
rb_gc_mark_locations(th->stk_ptr, th->stk_ptr+th->stk_len);
@@ -5615,12 +5770,12 @@ rb_gc_mark_threads()
if (!curr_thread) return;
FOREACH_THREAD(th) {
- rb_thread_mark(th);
+ rb_gc_mark(th->thread);
} END_FOREACH(th);
}
static void
-rb_thread_free(th)
+thread_free(th)
thread_t th;
{
if (th->stk_ptr) free(th->stk_ptr);
@@ -5632,7 +5787,7 @@ static thread_t
rb_thread_check(data)
VALUE data;
{
- if (TYPE(data) != T_DATA || RDATA(data)->dfree != rb_thread_free) {
+ if (TYPE(data) != T_DATA || RDATA(data)->dfree != thread_free) {
rb_raise(rb_eTypeError, "wrong argument type %s (expected Thread)",
rb_class2name(CLASS_OF(data)));
}
@@ -6349,7 +6504,7 @@ rb_thread_alloc(klass)
th->last_match = 0;
th->abort = 0;
- th->thread = Data_Wrap_Struct(klass, 0, rb_thread_free, th);
+ th->thread = Data_Wrap_Struct(klass, thread_mark, thread_free, th);
if (curr_thread) {
th->prev = curr_thread;
diff --git a/ext/curses/curses.c b/ext/curses/curses.c
index edf677a..3d39913 100644
--- a/ext/curses/curses.c
+++ b/ext/curses/curses.c
@@ -155,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;
}
@@ -252,7 +256,9 @@ static VALUE
curses_flash(obj)
VALUE obj;
{
+#ifdef HAVE_FLASH
flash();
+#endif
return Qnil;
}
diff --git a/ext/curses/extconf.rb b/ext/curses/extconf.rb
index 720bccb..244c908 100644
--- a/ext/curses/extconf.rb
+++ b/ext/curses/extconf.rb
@@ -15,7 +15,7 @@ else
end
if make then
- for f in ["isendwin", "ungetch", "beep"]
+ for f in ["isendwin", "ungetch", "beep", "doupdate", "flash"]
have_func(f)
end
create_makefile("curses")
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index e2c8de4..c10680c 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -37,7 +37,7 @@ etc_getlogin(obj)
#endif
if (login)
- return rb_str_new2(login);
+ return rb_tainted_str_new2(login);
return Qnil;
}
@@ -48,15 +48,15 @@ setup_passwd(pwd)
{
if (pwd == 0) rb_sys_fail("/etc/passwd");
return rb_struct_new(sPasswd,
- rb_str_new2(pwd->pw_name),
- rb_str_new2(pwd->pw_passwd),
+ 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_str_new2(pwd->pw_gecos),
+ rb_tainted_str_new2(pwd->pw_gecos),
#endif
- rb_str_new2(pwd->pw_dir),
- rb_str_new2(pwd->pw_shell),
+ rb_tainted_str_new2(pwd->pw_dir),
+ rb_tainted_str_new2(pwd->pw_shell),
#ifdef PW_CHANGE
INT2FIX(pwd->pw_change),
#endif
@@ -67,10 +67,10 @@ setup_passwd(pwd)
INT2FIX(pwd->pw_age),
#endif
#ifdef PW_CLASS
- rb_str_new2(pwd->pw_class),
+ rb_tainted_str_new2(pwd->pw_class),
#endif
#ifdef PW_COMMENT
- rb_str_new2(pwd->pw_comment),
+ rb_tainted_str_new2(pwd->pw_comment),
#endif
#ifdef PW_EXPIRE
INT2FIX(pwd->pw_expire),
@@ -155,12 +155,12 @@ setup_group(grp)
mem = rb_ary_new();
tbl = grp->gr_mem;
while (*tbl) {
- rb_ary_push(mem, rb_str_new2(*tbl));
+ rb_ary_push(mem, rb_tainted_str_new2(*tbl));
tbl++;
}
return rb_struct_new(sGroup,
- rb_str_new2(grp->gr_name),
- rb_str_new2(grp->gr_passwd),
+ rb_tainted_str_new2(grp->gr_name),
+ rb_tainted_str_new2(grp->gr_passwd),
INT2FIX(grp->gr_gid),
mem);
}
diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in
index e8dc566..b609515 100644
--- a/ext/extmk.rb.in
+++ b/ext/extmk.rb.in
@@ -1,13 +1,14 @@
#! /usr/local/bin/ruby
$".push 'mkmf.rb' #"
-load '../lib/find.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
@@ -20,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
@@ -63,8 +72,8 @@ CFLAGS = "@CFLAGS@".gsub(/-c..-stack=[0-9]+ */, '')
else
CFLAGS = "@CFLAGS@"
end
-LINK = "@CC@ -o conftest -I#{$topdir} -I@includedir@ " + CFLAGS + " %s @LDFLAGS@ %s conftest.c @LIBS@ %s"
-CPP = "@CPP@ @CPPFLAGS@ -I#{$topdir} -I@includedir@ " + CFLAGS + " %s conftest.c"
+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 /win32|djgpp|mingw32|m68k-human/i =~ PLATFORM
$null = open("nul", "w")
@@ -105,10 +114,10 @@ def install_rb(mfile)
end
for f in dir
next if f == "."
- mfile.printf "\t@test -d $(libdir)/%s || mkdir $(libdir)/%s\n", f, 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 $(libdir)/%s\n", f, f
+ mfile.printf "\t$(INSTALL_DATA) lib/%s $(DESTDIR)$(pkglibdir)/%s\n", f, f
end
end
@@ -255,7 +264,7 @@ def create_makefile(target)
$DLDFLAGS = $DLDFLAGS + " -L" + $topdir
end
- $srcdir = $topdir + "/ext/" + target
+ $srcdir = $top_srcdir + "/ext/" + target
mfile = open("Makefile", "w")
mfile.printf "\
SHELL = /bin/sh
@@ -270,7 +279,7 @@ hdrdir = #{$topdir}
CC = @CC@
prefix = @prefix@
-CFLAGS = %s -I#{$topdir} -I@includedir@ %s #$CFLAGS %s
+CFLAGS = %s -I#{$topdir} -I#{$top_srcdir} -I@includedir@ %s #$CFLAGS %s
DLDFLAGS = #$DLDFLAGS #$LDFLAGS
LDSHARED = @LDSHARED@
", if $static then "" else "@CCDLFLAGS@" end, CFLAGS, $defs.join(" ")
@@ -282,8 +291,9 @@ RUBY_INSTALL_NAME = `t='$(program_transform_name)'; echo ruby | sed $$t`
prefix = @prefix@
exec_prefix = @exec_prefix@
-libdir = @libdir@/$(RUBY_INSTALL_NAME)
-archdir = $(libdir)/@arch@
+libdir = @libdir@
+pkglibdir = $(libdir)/$(RUBY_INSTALL_NAME)
+archdir = $(pkglibdir)/@arch@
@SET_MAKE@
#### End of system configuration section. ####
@@ -294,7 +304,7 @@ archdir = $(libdir)/@arch@
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
@@ -313,7 +323,7 @@ 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) *~
@@ -324,12 +334,13 @@ realclean: clean
mfile.printf "\
install:
- @test -d $(libdir) || mkdir $(libdir)
- @test -d $(archdir) || mkdir $(archdir)
+ @test -d $(DESTDIR)$(libdir) || mkdir $(DESTDIR)$(libdir)
+ @test -d $(DESTDIR)$(pkglibdir) || mkdir $(DESTDIR)$(pkglibdir)
+ @test -d $(DESTDIR)$(archdir) || mkdir $(DESTDIR)$(archdir)
"
if !$static
mfile.printf "\
- $(INSTALL) $(TARGET) $(archdir)/$(TARGET)
+ $(INSTALL) $(TARGET) $(DESTDIR)$(archdir)/$(TARGET)
"
end
install_rb(mfile)
@@ -339,7 +350,7 @@ install:
mfile.printf "\
$(TARGET): $(OBJS)
@AR@ cru $(TARGET) $(OBJS)
- @-@RANLIB@ $(LIBRUBY) 2> /dev/null || true
+ @-@RANLIB@ $(TARGET) 2> /dev/null || true
"
elsif "@DLEXT@" != "o"
mfile.printf "\
@@ -405,17 +416,18 @@ def extmake(target)
$LDFLAGS = nil
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
@@ -425,7 +437,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
@@ -445,7 +457,7 @@ 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()
@@ -463,7 +475,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
@@ -511,7 +523,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
@@ -526,11 +538,15 @@ 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
diff --git a/ext/md5/md5init.c b/ext/md5/md5init.c
index 9562646..a825f96 100644
--- a/ext/md5/md5init.c
+++ b/ext/md5/md5init.c
@@ -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;
@@ -72,7 +72,7 @@ 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);
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index 9dbd51f..e9bdbc9 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -378,7 +378,7 @@ s_recv(sock, argc, argv, from)
}
rb_sys_fail("recvfrom(2)");
}
- rb_str_taint(str);
+ rb_obj_taint(str);
switch (from) {
case RECV_RECV:
return (VALUE)str;
@@ -588,9 +588,7 @@ open_inet(class, h, serv, type)
host = RSTRING(h)->ptr;
hostent = gethostbyname(host);
if (hostent == NULL) {
- inet_aton(host, &sockaddr.sin_addr);
- hostaddr = sockaddr.sin_addr.s_addr;
- if (hostaddr == -1) {
+ if (!inet_aton(host, &sockaddr.sin_addr)) {
if (type == INET_SERVER && !strlen(host))
hostaddr = INADDR_ANY;
else {
@@ -602,6 +600,7 @@ open_inet(class, h, serv, type)
#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;
diff --git a/file.c b/file.c
index 1d81f52..704a5fd 100644
--- a/file.c
+++ b/file.c
@@ -115,7 +115,7 @@ rb_file_reopen(argc, argv, file)
char *mode;
OpenFile *fptr;
- rb_secure(2);
+ rb_secure(4);
if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) {
if (TYPE(fname) == T_FILE) { /* fname must be IO */
return rb_io_reopen(file, fname);
@@ -238,7 +238,7 @@ rb_stat(file, st)
if (TYPE(file) == T_FILE) {
OpenFile *fptr;
- rb_secure(2);
+ rb_secure(4);
GetOpenFile(file, fptr);
return fstat(fileno(fptr->f), st);
}
@@ -298,7 +298,7 @@ rb_file_lstat(obj)
OpenFile *fptr;
struct stat st;
- rb_secure(2);
+ rb_secure(4);
GetOpenFile(obj, fptr);
if (lstat(fptr->path, &st) == -1) {
rb_sys_fail(fptr->path);
@@ -860,7 +860,7 @@ rb_file_chmod(obj, vmode)
OpenFile *fptr;
int mode;
- rb_secure(2);
+ rb_secure(4);
mode = NUM2INT(vmode);
GetOpenFile(obj, fptr);
@@ -921,7 +921,7 @@ rb_file_chown(obj, owner, group)
{
OpenFile *fptr;
- rb_secure(2);
+ rb_secure(4);
GetOpenFile(obj, fptr);
#if defined(DJGPP) || defined(__CYGWIN32__) || defined(NT) || defined(USE_CWGUSI)
if (chown(fptr->path, NUM2INT(owner), NUM2INT(group)) == -1)
@@ -1062,7 +1062,7 @@ rb_file_s_readlink(obj, path)
if ((cc = readlink(RSTRING(path)->ptr, buf, MAXPATHLEN)) < 0)
rb_sys_fail(RSTRING(path)->ptr);
- return rb_str_new(buf, cc);
+ return rb_tainted_str_new(buf, cc);
#else
rb_notimplement();
#endif
@@ -1109,7 +1109,7 @@ rb_file_s_umask(argc, argv)
#else
int omask = 0;
- rb_secure(2);
+ rb_secure(4);
if (argc == 0) {
omask = umask(0);
umask(omask);
@@ -1225,7 +1225,7 @@ rb_file_s_expand_path(argc, argv)
if (p == buf || *p != '/') p++;
*p = '\0';
- return rb_str_taint(rb_str_new2(buf));
+ return rb_tainted_str_new2(buf);
}
static int
@@ -1277,7 +1277,7 @@ rb_file_s_basename(argc, argv)
f = rmext(p, ext);
if (f) return rb_str_new(p, f);
}
- return rb_str_taint(rb_str_new2(p));
+ return rb_tainted_str_new2(p);
}
static VALUE
@@ -1293,7 +1293,7 @@ rb_file_s_dirname(obj, fname)
}
if (p == name)
p++;
- return rb_str_taint(rb_str_new(name, p - name));
+ return rb_tainted_str_new(name, p - name);
}
static VALUE
@@ -1354,7 +1354,7 @@ rb_file_truncate(obj, len)
{
OpenFile *fptr;
- rb_secure(2);
+ rb_secure(4);
GetOpenFile(obj, fptr);
if (!(fptr->mode & FMODE_WRITABLE)) {
rb_raise(rb_eIOError, "not opened for writing");
@@ -1420,7 +1420,7 @@ rb_file_flock(obj, operation)
#else
OpenFile *fptr;
- rb_secure(2);
+ rb_secure(4);
GetOpenFile(obj, fptr);
if (flock(fileno(fptr->f), NUM2INT(operation)) < 0) {
diff --git a/gc.c b/gc.c
index 48f83d3..82b677c 100644
--- a/gc.c
+++ b/gc.c
@@ -96,6 +96,7 @@ xrealloc(ptr, size)
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) {
@@ -281,6 +282,9 @@ rb_data_object_alloc(klass, datap, dmark, dfree)
extern st_table *rb_class_tbl;
VALUE *rb_gc_stack_start;
+#if defined(__GNUC__) && __GNUC__ >= 2
+__inline__
+#endif
static int
looks_pointerp(ptr)
void *ptr;
@@ -402,6 +406,7 @@ rb_gc_mark(ptr)
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 */
@@ -434,7 +439,7 @@ rb_gc_mark(ptr)
case NODE_AND:
case NODE_OR:
case NODE_CASE:
- case NODE_RESCUE:
+ case NODE_SCLASS:
case NODE_ARGS:
case NODE_DOT2:
case NODE_DOT3:
@@ -442,11 +447,9 @@ rb_gc_mark(ptr)
case NODE_FLIP3:
case NODE_MATCH2:
case NODE_MATCH3:
- case NODE_SCLASS:
rb_gc_mark(obj->as.node.u1.node);
/* fall through */
case NODE_METHOD: /* 2 */
- case NODE_MODULE:
case NODE_NOT:
case NODE_GASGN:
case NODE_LASGN:
@@ -454,11 +457,11 @@ rb_gc_mark(ptr)
case NODE_DASGN_PUSH:
case NODE_IASGN:
case NODE_CASGN:
+ case NODE_MODULE:
case NODE_OP_ASGN_OR:
case NODE_OP_ASGN_AND:
case NODE_COLON3:
case NODE_OPT_N:
- case NODE_BLOCK_PASS:
obj = RANY(obj->as.node.u2.node);
goto Top;
@@ -476,6 +479,7 @@ rb_gc_mark(ptr)
case NODE_SCOPE: /* 2,3 */
case NODE_CLASS:
+ case NODE_BLOCK_PASS:
rb_gc_mark(obj->as.node.u3.node);
obj = RANY(obj->as.node.u2.node);
goto Top;
@@ -1028,7 +1032,7 @@ run_final(obj)
obj = INT2NUM((long)obj); /* make obj into id */
for (i=0; i<RARRAY(finalizers)->len; i++) {
- rb_eval_cmd(RARRAY(finalizers)->ptr[i], rb_ary_new3(1,obj));
+ rb_eval_cmd(RARRAY(finalizers)->ptr[i], rb_ary_new3(1, obj));
}
}
diff --git a/hash.c b/hash.c
index e049776..d7d6f4d 100644
--- a/hash.c
+++ b/hash.c
@@ -28,9 +28,10 @@ static void
rb_hash_modify(hash)
VALUE hash;
{
- if (FL_TEST(hash, HASH_FREEZE)) {
+ 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
@@ -80,9 +81,8 @@ rb_any_cmp(a, b)
}
static int
-rb_any_hash(a, mod)
+rb_any_hash(a)
VALUE a;
- int mod;
{
unsigned int hval;
@@ -104,8 +104,7 @@ rb_any_hash(a, mod)
ENABLE_INTS;
hval = FIX2LONG(hval);
}
- if (hval < 0) hval = -hval;
- return hval % mod;
+ return hval;
}
static struct st_hash_type objhash = {
@@ -126,7 +125,7 @@ rb_hash_foreach_iter(key, value, arg)
{
int status;
st_table *tbl = RHASH(arg->hash)->tbl;
- st_table_entry **bins = tbl->bins;
+ struct st_table_entry **bins = tbl->bins;
if (key == Qnil) return ST_CONTINUE;
status = (*arg->func)(key, value, arg->arg);
@@ -367,9 +366,16 @@ rb_hash_fetch(argc, argv, hash)
}
static VALUE
-rb_hash_default(hash, ifnone)
+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;
}
@@ -490,10 +496,12 @@ rb_hash_aset(hash, key, val)
rb_hash_delete(hash, key);
return Qnil;
}
- if (TYPE(key) == T_STRING) {
- key = rb_str_dup_frozen(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;
}
@@ -873,7 +881,7 @@ rb_f_getenv(obj, name)
if (env) {
if (strcmp(nam, "PATH") == 0 && !rb_env_path_tainted())
return rb_str_new2(env);
- return rb_str_taint(rb_str_new2(env));
+ return rb_tainted_str_new2(env);
}
return Qnil;
}
@@ -960,7 +968,7 @@ rb_f_setenv(obj, name, value)
setenv(RSTRING(name)->ptr, RSTRING(value)->ptr, 1);
if (strcmp(RSTRING(name)->ptr, "PATH") == 0) {
- if (rb_str_tainted(value)) {
+ if (rb_obj_tainted(value)) {
/* already tainted, no check */
path_tainted = 1;
return Qtrue;
@@ -980,7 +988,7 @@ env_keys()
env = environ;
while (*env) {
char *s = strchr(*env, '=');
- rb_ary_push(ary, rb_str_taint(rb_str_new(*env, s-*env)));
+ rb_ary_push(ary, rb_tainted_str_new(*env, s-*env));
env++;
}
return ary;
@@ -1002,7 +1010,7 @@ env_values()
env = environ;
while (*env) {
char *s = strchr(*env, '=');
- rb_ary_push(ary, rb_str_taint(rb_str_new2(s+1)));
+ rb_ary_push(ary, rb_tainted_str_new2(s+1));
env++;
}
return ary;
@@ -1036,9 +1044,14 @@ env_each(hash)
static VALUE
env_delete_if()
{
- VALUE ary = env_keys();
- VALUE *ptr = RARRAY(ary)->ptr;
- int len = RARRAY(ary)->len;
+ VALUE ary;
+ VALUE *ptr;
+ int len;
+
+ rb_secure(4);
+ ary = env_keys();
+ ptr = RARRAY(ary)->ptr;
+ len = RARRAY(ary)->len;
while (len--) {
VALUE val = rb_f_getenv(Qnil, *ptr);
@@ -1067,8 +1080,8 @@ env_to_a()
env = environ;
while (*env) {
char *s = strchr(*env, '=');
- rb_ary_push(ary, rb_assoc_new(rb_str_taint(rb_str_new(*env, s-*env)),
- rb_str_taint(rb_str_new2(s+1))));
+ rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(*env, s-*env),
+ rb_tainted_str_new2(s+1)));
env++;
}
return ary;
@@ -1200,7 +1213,8 @@ Init_Hash()
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, 1);
+ 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);
diff --git a/instruby.rb b/instruby.rb
index 7dee03a..93a6557 100644
--- a/instruby.rb
+++ b/instruby.rb
@@ -13,10 +13,11 @@ else
prefix = CONFIG["prefix"]
end
ruby_install_name = CONFIG["ruby_install_name"]
-bindir = prefix + "/bin"
-libdir = prefix + "/lib/" + ruby_install_name
+bindir = CONFIG["bindir"]
+libdir = CONFIG["libdir"] + "/" + ruby_install_name
archdir = libdir+"/"+CONFIG["arch"]
-mandir = prefix + "/man/man1"
+mandir = CONFIG["mandir"] + "/man1"
+wdir = Dir.getwd
File.makedirs bindir, TRUE
File.install "ruby#{binsuffix}",
@@ -24,26 +25,25 @@ File.install "ruby#{binsuffix}",
for dll in Dir['*.dll']
File.install dll, "#{bindir}/#{dll}", 0755, TRUE
end
-File.makedirs "#{prefix}/lib", TRUE
+File.makedirs "#{libdir}", TRUE
for lib in ["libruby.so", "libruby.so.LIB"]
if File.exist? lib
- File.install lib, "#{prefix}/lib", 0644, TRUE
+ File.install lib, "#{libdir}", 0644, TRUE
end
end
File.makedirs libdir, TRUE
Dir.chdir "ext"
system "../miniruby#{binsuffix} extmk.rb install"
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, "#{libdir}", 0644, TRUE
+end
+for f in Dir["*.h"]
+ File.install f, "#{archdir}", 0644, TRUE
end
-File.install "rbconfig.rb", archdir, 0644, TRUE
File.makedirs mandir, TRUE
-File.install "ruby.1", mandir, 0644, TRUE
+File.install "ruby.1", "#{mandir}", 0644, TRUE
+Dir.chdir wdir
+File.install "config.h", "#{archdir}", 0644, TRUE
+File.install "rbconfig.rb", "#{archdir}", 0644, TRUE
# vi:set sw=2:
diff --git a/intern.h b/intern.h
index 1192c27..86a74b8 100644
--- a/intern.h
+++ b/intern.h
@@ -100,6 +100,9 @@ VALUE rb_dvar_defined _((ID));
VALUE rb_dvar_ref _((ID));
void rb_dvar_asgn _((ID, VALUE));
void rb_dvar_push _((ID, VALUE));
+void ruby_init _((void));
+void ruby_options _((int, char**));
+void ruby_run _((void));
VALUE rb_eval_cmd _((VALUE, VALUE));
VALUE rb_trap_eval _((VALUE, int));
int rb_respond_to _((VALUE, ID));
@@ -180,6 +183,9 @@ VALUE rb_inspect _((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_taint _((VALUE));
+VALUE rb_obj_tainted _((VALUE));
+VALUE rb_obj_untaint _((VALUE));
VALUE rb_convert_type _((VALUE,int,char*,char*));
VALUE rb_Integer _((VALUE));
VALUE rb_Float _((VALUE));
@@ -243,6 +249,8 @@ VALUE rb_str_new _((char*, int));
VALUE rb_str_new2 _((char*));
VALUE rb_str_new3 _((VALUE));
VALUE rb_str_new4 _((VALUE));
+VALUE rb_tainted_str_new _((char*, int));
+VALUE rb_tainted_str_new2 _((char*));
VALUE rb_obj_as_string _((VALUE));
VALUE rb_str_to_str _((VALUE));
VALUE rb_str_dup _((VALUE));
@@ -252,8 +260,6 @@ VALUE rb_str_substr _((VALUE, int, int));
void rb_str_modify _((VALUE));
VALUE rb_str_freeze _((VALUE));
VALUE rb_str_dup_frozen _((VALUE));
-VALUE rb_str_taint _((VALUE));
-VALUE rb_str_tainted _((VALUE));
VALUE rb_str_resize _((VALUE, int));
VALUE rb_str_cat _((VALUE, char*, int));
VALUE rb_str_concat _((VALUE, VALUE));
diff --git a/io.c b/io.c
index 3c9e857..1da75b6 100644
--- a/io.c
+++ b/io.c
@@ -153,6 +153,7 @@ rb_io_write(io, str)
FILE *f;
int n;
+ rb_secure(4);
if (TYPE(str) != T_STRING)
str = rb_obj_as_string(str);
if (RSTRING(str)->len == 0) return INT2FIX(0);
@@ -162,7 +163,6 @@ rb_io_write(io, str)
return rb_funcall(io, id_write, 1, str);
}
- rb_secure(4);
GetOpenFile(io, fptr);
rb_io_check_writable(fptr);
f = GetWriteFile(fptr);
@@ -244,6 +244,12 @@ rb_io_seek(io, offset, ptrname)
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;
@@ -252,7 +258,7 @@ rb_io_set_pos(io, offset)
long pos;
GetOpenFile(io, fptr);
- pos = fseek(fptr->f, NUM2INT(offset), 0);
+ pos = fseek(fptr->f, NUM2INT(offset), SEEK_SET);
if (pos != 0) rb_sys_fail(fptr->path);
clearerr(fptr->f);
@@ -360,20 +366,20 @@ read_all(port)
OpenFile *fptr;
VALUE str = Qnil;
struct stat st;
- int siz = BUFSIZ;
- int bytes = 0;
+ long siz = BUFSIZ;
+ long bytes = 0;
int n;
GetOpenFile(port, fptr);
rb_io_check_readable(fptr);
-#ifdef __BEOS__
if (fstat(fileno(fptr->f), &st) == 0 && S_ISREG(st.st_mode)
- && (st.st_dev > 3)) {
-#else
- 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 Qnil;
+ )
+ {
+ if (st.st_size == 0) return rb_str_new(0, 0);
else {
int pos = ftell(fptr->f);
if (st.st_size > pos && pos >= 0) {
@@ -389,16 +395,16 @@ read_all(port)
TRAP_END;
if (n <= 0) {
if (ferror(fptr->f)) rb_sys_fail(fptr->path);
- return Qnil;
+ return rb_str_new(0,0);
}
bytes += n;
if (bytes < siz) break;
siz += BUFSIZ;
rb_str_resize(str, siz);
}
- if (bytes == 0) return Qnil;
+ if (bytes == 0) return rb_str_new(0,0);
if (bytes != siz) rb_str_resize(str, bytes);
- return rb_str_taint(str);
+ return rb_obj_taint(str);
}
static VALUE
@@ -411,7 +417,8 @@ rb_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);
}
@@ -432,7 +439,7 @@ rb_io_read(argc, argv, io)
RSTRING(str)->len = n;
RSTRING(str)->ptr[n] = '\0';
- return rb_str_taint(str);
+ return rb_obj_taint(str);
}
static VALUE
@@ -568,7 +575,7 @@ rb_io_gets_internal(argc, argv, io)
if (!NIL_P(str)) {
fptr->lineno++;
lineno = INT2FIX(fptr->lineno);
- rb_str_taint(str);
+ rb_obj_taint(str);
}
return str;
@@ -626,7 +633,7 @@ rb_io_gets(io)
if (!NIL_P(str)) {
fptr->lineno++;
lineno = INT2FIX(fptr->lineno);
- rb_str_taint(str);
+ rb_obj_taint(str);
}
return str;
@@ -978,7 +985,7 @@ rb_io_sysread(io, len)
RSTRING(str)->len = n;
RSTRING(str)->ptr[n] = '\0';
- return rb_str_taint(str);
+ return rb_obj_taint(str);
}
VALUE
@@ -1388,6 +1395,7 @@ rb_io_reopen(io, nfile)
char *mode;
int fd;
+ rb_secure(4);
GetOpenFile(io, fptr);
nfile = rb_io_get_io(nfile);
GetOpenFile(nfile, orig);
@@ -1661,8 +1669,10 @@ void
rb_p(obj) /* for debug print within C code */
VALUE obj;
{
- rb_io_write(rb_defout, rb_inspect(obj));
- rb_io_write(rb_defout, rb_default_rs);
+ 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
@@ -1990,11 +2000,7 @@ static VALUE
rb_f_ungetc(self, c)
VALUE self, c;
{
- if (!next_argv()) {
- rb_raise(rb_eArgError, "no stream to ungetc");
- }
-
- return rb_io_ungetc(file, c);
+ return rb_io_ungetc(rb_stdin, c);
}
static VALUE
@@ -2115,10 +2121,10 @@ rb_f_select(argc, argv, obj)
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);
}
}
}
@@ -2137,7 +2143,7 @@ rb_f_select(argc, argv, obj)
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);
}
}
}
@@ -2759,6 +2765,9 @@ Init_IO()
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);
diff --git a/lib/Env.rb b/lib/Env.rb
index df14023..b3ee3ba 100644
--- a/lib/Env.rb
+++ b/lib/Env.rb
@@ -2,6 +2,7 @@
#
# Usage:
#
+# require 'Env'
# p $USER
# $USER = "matz"
# p ENV["USER"]
diff --git a/lib/README b/lib/README
new file mode 100644
index 0000000..09e5946
--- /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/delegate.rb b/lib/delegate.rb
index 16e68c9..d784586 100644
--- a/lib/delegate.rb
+++ b/lib/delegate.rb
@@ -24,7 +24,7 @@ class Delegator
preserved |= t.instance_methods
break if t == Delegator
end
- preserved -= ["to_s","to_a","inspect","hash","eql?","==","=~","==="]
+ preserved -= ["to_s","to_a","inspect","==","=~","==="]
for method in obj.methods
next if preserved.include? method
eval <<EOS
diff --git a/lib/ping.rb b/lib/ping.rb
index d742a50..08e05a0 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, "echo")
+ s.close
+ end
rescue
- return FALSE;
- ensure
- Thread.kill y if y.status
+ return false
end
+ return true
end
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/telnet.rb b/lib/telnet.rb
index e5a8aa6..e3c590c 100644
--- a/lib/telnet.rb
+++ b/lib/telnet.rb
@@ -1,8 +1,17 @@
#
# telnet.rb
-# ver0.141 1998/09/22
+# 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/
@@ -33,7 +42,7 @@
# first release.
#
# == make new Telnet object
-# host = Telnet.new({"Binmode" => TRUE, default: TRUE
+# 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
@@ -76,6 +85,16 @@
# == 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",
@@ -204,6 +223,7 @@ class Telnet < SimpleDelegator
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"
@@ -212,7 +232,7 @@ class Telnet < SimpleDelegator
def initialize(options)
@options = options
- @options["Binmode"] = TRUE if not @options.include?("Binmode")
+ @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")
@@ -225,7 +245,7 @@ class Telnet < SimpleDelegator
if @options.include?("Output_log")
@log = File.open(@options["Output_log"], 'a+')
@log.sync = TRUE
- @log.binmode if @options["Binmode"]
+ @log.binmode
end
if @options.include?("Dump_log")
@@ -250,7 +270,7 @@ class Telnet < SimpleDelegator
}
raise TimeOut, "timed-out; opening of the host" if is_timeout
@sock.sync = TRUE
- @sock.binmode if @options["Binmode"]
+ @sock.binmode
message = "Connected to " + @options["Host"] + ".\n"
STDOUT.write(message)
@@ -260,46 +280,62 @@ class Telnet < SimpleDelegator
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)
- str.gsub!(/#{CR}#{NULL}/no, CR) # combine CR+NULL into CR
- str.gsub!(/#{EOL}/no, "\n") # combine EOL into "\n"
+
+ 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}(.|\n)/no){
- if OPT_BINARY == $2
+ 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)
- $1
else
- @sock.write(IAC + WONT + $2)
- $1
+ @sock.write(IAC + WONT + $1)
end
+ ''
}
# respond to "IAC DON'T x" with "IAC WON'T x"
- str.gsub!(/([^#{IAC}])?#{IAC}#{DONT}(.|\n)/no){
- @sock.write(IAC + WONT + $2)
- $1
+ 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}(.|\n)/no){
- if OPT_SGA == $2
+ 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)
- $1
- else
- $1
end
+ ''
}
# ignore "IAC WON'T x"
- str.gsub!(/([^#{IAC}])?#{IAC}#{WONT}(.|\n)/no, '\1')
+ 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){
+ str.gsub!(/(?:(?!#{IAC}))?#{IAC}#{AYT}/no){
@sock.write("nobody here but us pigeons" + EOL)
- $1
+ ''
}
str.gsub(/#{IAC}#{IAC}/no, IAC) # handle escaped IAC characters
@@ -340,15 +376,20 @@ class Telnet < SimpleDelegator
end
def print(string)
- 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)
+ string.gsub!(/#{IAC}/no, IAC + IAC) if @options["Telnetmode"]
+ if @options["Binmode"]
+ @sock.write(string)
else
- # NONE send EOL --> LF
- @sock.write(string.gsub(/\n/, LF) + LF)
+ 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
diff --git a/lib/thread.rb b/lib/thread.rb
index 7706d59..ec75144 100644
--- a/lib/thread.rb
+++ b/lib/thread.rb
@@ -21,6 +21,8 @@ class Mutex
def initialize
@waiting = []
@locked = false;
+ @waiting.taint # enable tainted comunication
+ self.taint
end
def locked?
@@ -72,6 +74,8 @@ class ConditionVariable
def initialize
@waiters = []
@waiters_mutex = Mutex.new
+ @waiters.taint # enable tainted comunication
+ self.taint
end
def wait(mutex)
@@ -104,6 +108,9 @@ class Queue
def initialize
@que = []
@waiting = []
+ @que.taint # enable tainted comunication
+ @waiting.taint
+ self.taint
end
def push(obj)
@@ -152,6 +159,7 @@ class SizedQueue<Queue
def initialize(max)
@max = max
@queue_wait = []
+ @queue_wait.taint # enable tainted comunication
super()
end
diff --git a/lib/timeout.rb b/lib/timeout.rb
new file mode 100644
index 0000000..d4ea758
--- /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/marshal.c b/marshal.c
index 4f49aa7..2b49d27 100644
--- a/marshal.c
+++ b/marshal.c
@@ -3,7 +3,6 @@
marshal.c -
$Author$
- $Revision$
$Date$
created at: Thu Apr 27 16:30:01 JST 1995
@@ -581,7 +580,7 @@ r_string(arg)
int len;
r_bytes2(buf, len, arg);
- return rb_str_taint(rb_str_new(buf, len));
+ return rb_str_new(buf, len);
}
static VALUE
@@ -589,6 +588,7 @@ r_regist(v, arg)
VALUE v;
struct load_arg *arg;
{
+ rb_obj_taint(v);
if (arg->proc) {
rb_funcall(arg->proc, rb_intern("call"), 1, v);
}
@@ -862,8 +862,8 @@ Init_marshal()
{
VALUE rb_mMarshal = rb_define_module("Marshal");
- s_dump = rb_intern("_dump_to");
- s_load = rb_intern("_load_from");
+ 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);
diff --git a/missing/nt.c b/missing/nt.c
index 56a8e62..a78d82e 100644
--- a/missing/nt.c
+++ b/missing/nt.c
@@ -243,7 +243,7 @@ int SafeFree(char **vec, int vecc)
char *p;
- p = (char *)(vec - (vecc * sizeof (char *) + 1));
+ p = (char *)vec;
free(p);
return 0;
diff --git a/missing/nt.h b/missing/nt.h
index be8d61f..a3d1f21 100644
--- a/missing/nt.h
+++ b/missing/nt.h
@@ -9,6 +9,12 @@
*
*/
+#if defined(IMPORT)
+#define EXTERN extern __declspec(dllimport)
+#elif defined(EXPORT)
+#define EXTERN extern __declspec(dllexport)
+#endif
+
//
// Definitions for NT port of Perl
//
diff --git a/missing/vsnprintf.c b/missing/vsnprintf.c
new file mode 100644
index 0000000..64076b5
--- /dev/null
+++ b/missing/vsnprintf.c
@@ -0,0 +1,1150 @@
+/*-
+ * 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>
+#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/mkconfig.rb b/mkconfig.rb
index cf5c1e1..8af3b0c 100644
--- a/mkconfig.rb
+++ b/mkconfig.rb
@@ -33,7 +33,7 @@ File.foreach "config.status" do |$_|
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 cfd325c..c1923fb 100644
--- a/node.h
+++ b/node.h
@@ -78,6 +78,8 @@ enum node_type {
NODE_DREGX,
NODE_DREGX_ONCE,
NODE_ARGS,
+ NODE_ARGSCAT,
+ NODE_RESTARGS,
NODE_BLOCK_ARG,
NODE_BLOCK_PASS,
NODE_DEFN,
@@ -141,9 +143,11 @@ typedef struct RNode {
#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
@@ -191,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
@@ -206,12 +210,11 @@ 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) rb_node_newnode(NODE_METHOD,x,n,0)
@@ -220,11 +223,19 @@ typedef struct RNode {
#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) rb_node_newnode(NODE_SCOPE,local_tbl(),(b),cur_cref)
+#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)
-#define NEW_UNLESS(c,t,e) rb_node_newnode(NODE_IF,c,e,t)
+#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)
@@ -236,7 +247,7 @@ typedef struct RNode {
#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) rb_node_newnode(NODE_RESCUE,b,res,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)
@@ -274,18 +285,24 @@ typedef struct RNode {
#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,0,n,o)
-#define NEW_VALIAS(n,o) rb_node_newnode(NODE_VALIAS,0,n,o)
+#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_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)
@@ -314,7 +331,8 @@ VALUE rb_method_booundp();
#define NOEX_PRIVATE 2
#define NOEX_PROTECTED 4
-NODE *rb_compile_string _((char *, char *, 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));
diff --git a/object.c b/object.c
index 6b94c87..033539f 100644
--- a/object.c
+++ b/object.c
@@ -254,6 +254,32 @@ rb_obj_dummy(obj)
return Qnil;
}
+VALUE
+rb_obj_tainted(obj)
+ VALUE obj;
+{
+ if (FL_TEST(obj, FL_TAINT))
+ return Qtrue;
+ return Qfalse;
+}
+
+VALUE
+rb_obj_taint(obj)
+ VALUE obj;
+{
+ FL_SET(obj, FL_TAINT);
+ 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;
@@ -951,6 +977,10 @@ Init_Object()
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);
@@ -968,7 +998,7 @@ Init_Object()
rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1);
rb_define_global_function("sprintf", rb_f_sprintf, -1);
- rb_define_alias(rb_mKernel, "format", "sprintf");
+ 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);
diff --git a/parse.y b/parse.y
index 4d494b4..9e8cfad 100644
--- a/parse.y
+++ b/parse.y
@@ -89,6 +89,7 @@ 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();
@@ -166,7 +167,7 @@ static void top_local_setup();
%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
-%type <node> opt_call_args call_args ret_args args
+%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
@@ -561,10 +562,11 @@ reswords : k__LINE__ | k__FILE__ | klBEGIN | klEND
| kTHEN | kTRUE | kUNDEF | kUNLESS_MOD | kUNTIL_MOD | kWHEN
| kWHILE_MOD | kYIELD
-arg : variable '=' arg
+arg : variable '=' {$$ = assignable($1, 0);} arg
{
- $$ = assignable($1, $3);
- fixpos($$, $3);
+ $$ = $<node>3;
+ $$->nd_value = $4;
+ fixpos($$, $4);
}
| primary '[' aref_args ']' '=' arg
{
@@ -576,34 +578,32 @@ arg : variable '=' arg
$$ = attrset($1, $3, $5);
fixpos($$, $5);
}
+ | primary '.' tCONSTANT '=' arg
+ {
+ $$ = attrset($1, $3, $5);
+ fixpos($$, $5);
+ }
| backref '=' arg
{
value_expr($3);
rb_backref_error($1);
$$ = 0;
}
- | variable tOP_ASGN arg
+ | variable tOP_ASGN {$$ = assignable($1, 0);} arg
{
- if (is_local_id($1)) {
- if (local_id($1)||!dyna_in_block()) {
- local_cnt($1);
- }
- else if (!rb_dvar_defined($1)) {
- rb_dvar_asgn($1, Qtrue);
- }
- }
if ($2 == tOROP) {
- $$ = NEW_OP_ASGN_OR(gettable($1),
- assignable($1, $3));
+ $<node>3->nd_value = $4;
+ $$ = NEW_OP_ASGN_OR(gettable($1), $<node>3);
}
else if ($2 == tANDOP) {
- $$ = NEW_OP_ASGN_AND(gettable($1),
- assignable($1, $3));
+ $<node>3->nd_value = $4;
+ $$ = NEW_OP_ASGN_AND(gettable($1), $<node>3);
}
else {
- $$ = assignable($1,call_op(gettable($1),$2,1,$3));
+ $$ = $<node>3;
+ $$->nd_value = call_op(gettable($1), $2, 1, $4);
}
- fixpos($$, $3);
+ fixpos($$, $4);
}
| primary '[' aref_args ']' tOP_ASGN arg
{
@@ -831,7 +831,7 @@ call_args : command_call
| tSTAR arg opt_block_arg
{
value_expr($2);
- $$ = arg_blk_pass($2, $3);
+ $$ = arg_blk_pass(NEW_RESTARGS($2), $3);
}
| block_arg
@@ -871,7 +871,8 @@ mrhs : args
{
if ($1 &&
nd_type($1) == NODE_ARRAY &&
- $1->nd_next == 0) {
+ $1->nd_next == 0)
+ {
$$ = $1->nd_head;
}
else {
@@ -1061,14 +1062,19 @@ 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);
@@ -1183,7 +1189,6 @@ then : term
do : term
| kDO
- | term kDO
if_tail : opt_else
| kELSIF expr then
@@ -1300,13 +1305,25 @@ method_call : operation '(' opt_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
@@ -1576,6 +1593,7 @@ 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;
@@ -1638,7 +1656,7 @@ yycompile(f)
ruby_eval_tree = 0;
newline_seen = 0;
- ruby_sourcefile = strdup(f);
+ ruby_sourcefile = f;
rb_in_compile = 1;
n = yyparse();
rb_in_compile = 0;
@@ -1647,14 +1665,36 @@ yycompile(f)
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) {
+ 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*
-rb_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;
+ 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;
@@ -1662,16 +1702,25 @@ rb_compile_string(f, s, len)
}
NODE*
+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;
ruby_sourceline = start;
- return yycompile(f);
+ return yycompile(strdup(f));
}
static int
@@ -1681,7 +1730,7 @@ nextc()
if (lex_p == lex_pend) {
if (lex_input) {
- VALUE v = rb_io_gets(lex_input);
+ VALUE v = (*lex_gets)(lex_input);
if (NIL_P(v)) return -1;
if (heredoc_end > 0) {
@@ -1691,7 +1740,7 @@ nextc()
while (RSTRING(v)->len >= 2 &&
RSTRING(v)->ptr[RSTRING(v)->len-1] == '\n' &&
RSTRING(v)->ptr[RSTRING(v)->len-2] == '\\') {
- VALUE v2 = rb_io_gets(lex_input);
+ VALUE v2 = (*lex_gets)(lex_input);
if (!NIL_P(v2)) {
rb_str_cat(v, RSTRING(v2)->ptr, RSTRING(v2)->len);
@@ -1888,6 +1937,9 @@ parse_regx(term, paren)
}
switch (c) {
+ case '\n':
+ ruby_sourceline++;
+ break;
case '[':
in_brack = 1;
break;
@@ -2026,6 +2078,12 @@ parse_string(func, term, paren)
if (func == '\'') {
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 = ruby_sourceline;
newtok();
while ((c = nextc()) != term || nest > 0) {
@@ -2063,7 +2121,10 @@ parse_string(func, term, paren)
continue;
}
if (c == paren) nest++;
- if (c == term) nest--;
+ if (c == term) {
+ nest--;
+ if (nest == 0) break;
+ }
tokadd(c);
}
@@ -2134,7 +2195,10 @@ parse_qstring(term, paren)
}
}
if (c == paren) nest++;
- if (c == term) nest--;
+ if (c == term) {
+ nest--;
+ if (nest == 0) break;
+ }
tokadd(c);
}
@@ -2175,14 +2239,15 @@ here_document(term)
while ((c = nextc()) != term) {
tokadd(c);
}
+ if (term == '\'') term = 0;
break;
default:
c = term;
term = '"';
if (!is_identchar(c)) {
- rb_compile_error("illegal here document");
- return 0;
+ rb_warn("Use of bare << to mean <<\"\" is deprecated");
+ break;
}
while (is_identchar(c)) {
tokadd(c);
@@ -2200,10 +2265,11 @@ here_document(term)
str = rb_str_new(0,0);
for (;;) {
- line = rb_io_gets(lex_input);
+ line = (*lex_gets)(lex_input);
if (NIL_P(line)) {
error:
- rb_compile_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;
}
@@ -2253,6 +2319,7 @@ here_document(term)
yylval.node = list;
}
switch (term) {
+ case '\0':
case '\'':
case '"':
if (list) return tDSTRING;
@@ -2420,9 +2487,6 @@ retry:
(lex_state != EXPR_ARG || space_seen)) {
int c2 = nextc();
if (!ISSPACE(c2) && (strchr("\"'`", c2) || is_identchar(c2))) {
- if (!lex_input) {
- rb_raise(rb_eArgError, "here document not available");
- }
return here_document(c2);
}
pushback(c2);
@@ -2473,7 +2537,6 @@ retry:
case '?':
if (lex_state == EXPR_END) {
- rb_warning("a?b:c is undocumented feature ^^;;;");
lex_state = EXPR_BEG;
return '?';
}
@@ -2482,7 +2545,6 @@ retry:
pushback(c);
arg_ambiguous();
lex_state = EXPR_BEG;
- rb_warning("a?b:c is undocumented feature ^^;;;");
return '?';
}
if (c == '\\') {
@@ -3508,7 +3570,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 *
@@ -3668,6 +3730,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:
@@ -3802,17 +3865,9 @@ 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, 4);
lvtbl->tbl[0] = 0;
@@ -3831,6 +3886,20 @@ 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;
{
@@ -4011,8 +4080,8 @@ static st_table *sym_rev_tbl;
void
Init_sym()
{
- sym_tbl = st_init_strtable_with_size(900);
- sym_rev_tbl = st_init_numtable_with_size(900);
+ 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);
}
@@ -4057,8 +4126,12 @@ rb_intern(name)
strncpy(buf, name, last);
buf[last] = '\0';
- id = rb_id_attrset(rb_intern(buf));
- goto id_regist;
+ id = rb_intern(buf);
+ if (id > LAST_TOKEN) {
+ id = rb_id_attrset(id);
+ goto id_regist;
+ }
+ id |= ID_ATTRSET;
}
else if (ISUPPER(name[0])) {
id = ID_CONST;
diff --git a/process.c b/process.c
index d9229a4..e4d0d0a 100644
--- a/process.c
+++ b/process.c
@@ -570,7 +570,7 @@ rb_f_exit_bang(obj, status)
{
int code = -1;
- rb_secure(2);
+ rb_secure(4);
if (FIXNUM_P(status)) {
code = INT2FIX(status);
}
diff --git a/range.c b/range.c
index 32c450f..9fc363e 100644
--- a/range.c
+++ b/range.c
@@ -31,49 +31,52 @@ range_failed()
}
static VALUE
-range_s_new(klass, first, last)
- VALUE klass, first, last;
+range_s_new(klass, beg, end)
+ VALUE klass, beg, end;
{
VALUE obj;
- VALUE args[2];
- args[0] = first; args[1] = last;
- rb_rescue(range_check, (VALUE)args, range_failed, 0);
+ 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 = rb_obj_alloc(klass);
- rb_ivar_set(obj, id_beg, first);
- rb_ivar_set(obj, id_end, last);
+ rb_ivar_set(obj, id_beg, beg);
+ rb_ivar_set(obj, id_end, end);
rb_obj_call_init(obj);
return obj;
}
VALUE
-rb_range_new(first, last)
- VALUE first, last;
+rb_range_new(beg, end)
+ VALUE beg, end;
{
- return range_s_new(rb_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_ivar_get(rng, id_beg);
- last = rb_ivar_get(rng, id_end);
+ 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)) {
+ if (FIXNUM_P(beg) && FIXNUM_P(obj) && FIXNUM_P(end)) {
+ if (FIX2INT(beg) <= FIX2INT(obj) && FIX2INT(obj) <= FIX2INT(end)) {
return Qtrue;
}
return Qfalse;
}
else {
- if (RTEST(rb_funcall(first, rb_intern("<="), 1, obj)) &&
- RTEST(rb_funcall(last, rb_intern(">="), 1, obj))) {
+ if (RTEST(rb_funcall(beg, rb_intern("<="), 1, obj)) &&
+ RTEST(rb_funcall(end, rb_intern(">="), 1, obj))) {
return Qtrue;
}
return Qfalse;
@@ -81,15 +84,15 @@ range_eqq(rng, obj)
}
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, id_upto, 1, data->last);
+ return rb_funcall(data->beg, id_upto, 1, data->end);
}
static VALUE
@@ -107,8 +110,8 @@ range_each(obj)
else {
struct upto_data data;
- data.first = b;
- data.last = e;
+ data.beg = b;
+ data.end = e;
rb_iterate(range_upto, (VALUE)&data, rb_yield, 0);
}
@@ -141,12 +144,12 @@ rb_range_beg_end(range, begp, endp)
VALUE range;
int *begp, *endp;
{
- VALUE first, last;
+ VALUE beg, end;
if (!rb_obj_is_kind_of(range, rb_cRange)) return Qfalse;
- first = rb_ivar_get(range, id_beg); *begp = NUM2INT(first);
- last = rb_ivar_get(range, id_end); *endp = NUM2INT(last);
+ beg = rb_ivar_get(range, id_beg); *begp = NUM2INT(beg);
+ end = rb_ivar_get(range, id_end); *endp = NUM2INT(end);
return Qtrue;
}
@@ -182,19 +185,19 @@ static VALUE
range_length(rng)
VALUE rng;
{
- VALUE first, last;
+ VALUE beg, end;
VALUE size;
- first = rb_ivar_get(rng, id_beg);
- last = rb_ivar_get(rng, id_end);
+ beg = rb_ivar_get(rng, id_beg);
+ end = rb_ivar_get(rng, id_end);
- if (RTEST(rb_funcall(first, '>', 1, last))) {
+ if (RTEST(rb_funcall(beg, '>', 1, end))) {
return INT2FIX(0);
}
- if (!rb_obj_is_kind_of(first, rb_cNumeric)) {
+ 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;
@@ -210,6 +213,8 @@ Init_Range()
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);
@@ -218,6 +223,6 @@ Init_Range()
id_upto = rb_intern("upto");
id_cmp = rb_intern("<=>");
- id_beg = rb_intern("first");
- id_end = rb_intern("last");
+ id_beg = rb_intern("begin");
+ id_end = rb_intern("end");
}
diff --git a/re.c b/re.c
index 29d8c35..2a7f475 100644
--- a/re.c
+++ b/re.c
@@ -368,7 +368,7 @@ match_clone(orig)
return (VALUE)match;
}
-static int ignorecase;
+int ruby_ignorecase;
static int may_need_recompile;
static VALUE matchcache;
@@ -382,7 +382,7 @@ rb_reg_prepare_re(reg)
if (!FL_TEST(reg, REG_IGNORECASE)) {
int state = FL_TEST(reg, REG_CASESTATE);
- if ((ignorecase || state) && !(ignorecase && state)) {
+ if ((ruby_ignorecase || state) && !(ruby_ignorecase && state)) {
RBASIC(reg)->flags ^= REG_CASESTATE;
need_recompile = 1;
}
@@ -659,7 +659,7 @@ rb_reg_new_1(klass, s, len, options)
if (options & ~0x3) {
kcode_set_option((VALUE)re);
}
- if (ignorecase) {
+ if (ruby_ignorecase) {
options |= RE_OPTION_IGNORECASE;
FL_SET(re, REG_CASESTATE);
}
@@ -693,15 +693,15 @@ rb_reg_regcomp(str)
VALUE str;
{
if (reg_cache && RREGEXP(reg_cache)->len == RSTRING(str)->len
- && case_cache == ignorecase
+ && case_cache == ruby_ignorecase
&& kcode_cache == reg_kcode
&& memcmp(RREGEXP(reg_cache)->str, RSTRING(str)->ptr, RSTRING(str)->len) == 0)
return reg_cache;
- case_cache = ignorecase;
+ case_cache = ruby_ignorecase;
kcode_cache = reg_kcode;
return reg_cache = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
- ignorecase);
+ ruby_ignorecase);
}
static int
@@ -739,11 +739,11 @@ rb_reg_match(re, str)
{
int start;
- if (NIL_P(str)) return Qfalse;
+ if (NIL_P(str)) return Qnil;
str = rb_str_to_str(str);
start = rb_reg_search(re, str, 0, 0);
if (start < 0) {
- return Qfalse;
+ return Qnil;
}
return INT2FIX(start);
}
@@ -756,11 +756,11 @@ rb_reg_match2(re)
VALUE line = rb_lastline_get();
if (TYPE(line) != T_STRING)
- return Qfalse;
+ return Qnil;
start = rb_reg_search(re, line, 0, 0);
if (start < 0) {
- return Qfalse;
+ return Qnil;
}
return INT2FIX(start);
}
@@ -1024,7 +1024,7 @@ kcode_setter(val)
static VALUE
ignorecase_getter()
{
- return ignorecase?Qtrue:Qfalse;
+ return ruby_ignorecase?Qtrue:Qfalse;
}
static void
@@ -1032,13 +1032,7 @@ ignorecase_setter(val)
VALUE val;
{
may_need_recompile = 1;
- ignorecase = RTEST(val);
-}
-
-int
-rb_ignorecase_p()
-{
- return (int)ignorecase;
+ ruby_ignorecase = RTEST(val);
}
static VALUE
diff --git a/re.h b/re.h
index 3c3811c..8aeb4e3 100644
--- a/re.h
+++ b/re.h
@@ -33,4 +33,6 @@ 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 *));
+
+extern int ruby_ignorecase;
#endif
diff --git a/regex.c b/regex.c
index 279297a..b3cbb77 100644
--- a/regex.c
+++ b/regex.c
@@ -567,8 +567,8 @@ set_list_bits(c1, c2, b)
if (beg != end) {
if (c1 > EXTRACT_MBC(&b[beg*4]))
c1 = EXTRACT_MBC(&b[beg*4]);
- if (c2 < EXTRACT_MBC(&b[(end - 1)*4]))
- c2 = EXTRACT_MBC(&b[(end - 1)*4]);
+ if (c2 < EXTRACT_MBC(&b[(end - 1)*4+2]))
+ c2 = EXTRACT_MBC(&b[(end - 1)*4+2]);
}
if (end < mbc_size && end != beg + 1)
/* NOTE: memcpy() would not work here. */
@@ -2021,25 +2021,27 @@ re_compile_pattern(pattern, size, bufp)
/* set optimize flags */
laststart = bufp->buffer;
- if (*laststart == start_memory) laststart += 3;
- if (*laststart == dummy_failure_jump) laststart += 3;
- else if (*laststart == try_next) laststart += 3;
- if (*laststart == on_failure_jump) {
- int mcnt;
-
- laststart++;
- EXTRACT_NUMBER_AND_INCR(mcnt, laststart);
- if (mcnt == 4 && *laststart == anychar) {
- bufp->options |= RE_OPTIMIZE_ANCHOR;
- }
- else if (*laststart == charset || *laststart == charset_not) {
- p0 = laststart;
- mcnt = *++p0 ;
- p0 += mcnt+1;
- mcnt = EXTRACT_UNSIGNED_AND_INCR(p0);
- p0 += 4*mcnt;
- if (*p0 == maybe_finalize_jump) {
- bufp->stclass = laststart;
+ if (laststart != b) {
+ if (*laststart == start_memory) laststart += 3;
+ if (*laststart == dummy_failure_jump) laststart += 3;
+ else if (*laststart == try_next) laststart += 3;
+ if (*laststart == on_failure_jump) {
+ int mcnt;
+
+ laststart++;
+ EXTRACT_NUMBER_AND_INCR(mcnt, laststart);
+ if (mcnt == 4 && *laststart == anychar) {
+ bufp->options |= RE_OPTIMIZE_ANCHOR;
+ }
+ else if (*laststart == charset || *laststart == charset_not) {
+ p0 = laststart;
+ mcnt = *++p0 ;
+ p0 += mcnt+1;
+ mcnt = EXTRACT_UNSIGNED_AND_INCR(p0);
+ p0 += 4*mcnt;
+ if (*p0 == maybe_finalize_jump) {
+ bufp->stclass = laststart;
+ }
}
}
}
@@ -2047,10 +2049,12 @@ re_compile_pattern(pattern, size, bufp)
bufp->used = b - bufp->buffer;
bufp->re_nsub = regnum;
laststart = bufp->buffer;
- if (*laststart == start_memory) laststart += 3;
- if (*laststart == exactn) {
- bufp->options |= RE_OPTIMIZE_EXACTN;
- bufp->must = laststart+1;
+ if (laststart != b) {
+ if (*laststart == start_memory) laststart += 3;
+ if (*laststart == exactn) {
+ bufp->options |= RE_OPTIMIZE_EXACTN;
+ bufp->must = laststart+1;
+ }
}
else {
bufp->must = calculate_must_string(bufp->buffer, b);
@@ -3917,6 +3921,7 @@ re_match(bufp, string_arg, size, pos, regs)
EXTRACT_NUMBER_AND_INCR (mcnt, p1);
p1 += mcnt;
+ if (p1 >= pend) break;
if ((is_a_jump_n && (enum regexpcode) *p1 == succeed_n)
|| (!is_a_jump_n
&& (enum regexpcode) *p1 == on_failure_jump))
diff --git a/ruby.c b/ruby.c
index f510e0b..289798a 100644
--- a/ruby.c
+++ b/ruby.c
@@ -629,7 +629,7 @@ set_arg0(val, id)
while (++i < len)
*s++ = ' ';
}
- rb_progname = rb_str_taint(rb_str_new2(origargv[0]));
+ rb_progname = rb_tainted_str_new2(origargv[0]);
}
void
@@ -637,7 +637,7 @@ ruby_script(name)
char *name;
{
if (name) {
- rb_progname = rb_str_taint(rb_str_new2(name));
+ rb_progname = rb_tainted_str_new2(name);
ruby_sourcefile = name;
}
}
@@ -780,7 +780,7 @@ ruby_set_argv(argc, argv)
else dln_argv0 = argv[0];
#endif
for (i=0; i < argc; i++) {
- rb_ary_push(rb_argv, rb_str_taint(rb_str_new2(argv[i])));
+ rb_ary_push(rb_argv, rb_tainted_str_new2(argv[i]));
}
}
diff --git a/ruby.h b/ruby.h
index 15d0e1c..174cfd6 100644
--- a/ruby.h
+++ b/ruby.h
@@ -213,6 +213,7 @@ VALUE rb_newobj _((void));
#define OBJSETUP(obj,c,t) {\
RBASIC(obj)->klass = (c);\
RBASIC(obj)->flags = (t);\
+ if (rb_safe_level() >= 3) FL_SET(obj, FL_TAINT);\
}
#define CLONESETUP(clone,obj) {\
OBJSETUP(clone,rb_singleton_class_clone(RBASIC(obj)->klass),RBASIC(obj)->flags);\
@@ -281,7 +282,6 @@ struct RData {
};
extern VALUE rb_cData;
-
#define DATA_PTR(dta) (RDATA(dta)->data)
VALUE rb_data_object_alloc _((VALUE,void*,void (*)(),void (*)()));
@@ -331,8 +331,9 @@ struct RBignum {
#define FL_SINGLETON FL_USER0
#define FL_MARK (1<<8)
#define FL_FINALIZE (1<<9)
+#define FL_TAINT (1<<10)
-#define FL_USHIFT 10
+#define FL_USHIFT 11
#define FL_USER0 (1<<(FL_USHIFT+0))
#define FL_USER1 (1<<(FL_USHIFT+1))
@@ -407,7 +408,7 @@ void rb_const_set _((VALUE, ID, VALUE));
VALUE rb_equal _((VALUE,VALUE));
-extern VALUE rb_verbose, rb_debug;
+EXTERN VALUE rb_verbose, rb_debug;
int rb_safe_level _((void));
void rb_set_safe_level _((int));
@@ -436,56 +437,56 @@ 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;
+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));
diff --git a/sample/README b/sample/README
new file mode 100644
index 0000000..90ac0c7
--- /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/mkproto.rb b/sample/mkproto.rb
index 97006f9..8661240 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/ruby-mode.el b/sample/ruby-mode.el
index d379a63..8bf843c 100644
--- a/sample/ruby-mode.el
+++ b/sample/ruby-mode.el
@@ -209,7 +209,7 @@ The variable ruby-indent-level controls the amount of indentation.
(looking-at ruby-block-mid-re))
(progn
(goto-char (match-end 0))
- (looking-at "[^_]")))))))))
+ (looking-at "\\>")))))))))
(defun ruby-parse-region (start end)
(let ((indent-point end)
@@ -253,7 +253,7 @@ The variable ruby-indent-level controls the amount of indentation.
((looking-at "%")
(cond
((and (not (eobp)) (ruby-expr-beg)
- (looking-at "%[Qqrx]?\\(.\\)"))
+ (looking-at "%[Qqrxw]?\\(.\\)"))
(setq w (buffer-substring (match-beginning 1)
(match-end 1)))
(cond
@@ -598,7 +598,7 @@ An end of a defun is found by moving forward from the beginning of one."
("[^$\\?]\\('[^\\']*\\(\\\\\\(.\\|\n\\)[^\\']*\\)*'\\)" 1 string)
("[^$\\?]\\(`[^\\`]*\\(\\\\\\(.\\|\n\\)[^\\`]*\\)*`\\)" 1 string)
("^\\s *#.*$" nil comment)
- ("[^$@?\\]\\(#[^$@{].*$\\)" 1 comment)
+ ("[^$@?\\]\\(#[^$@{\n].*$\\)" 1 comment)
("[^a-zA-Z_]\\(\\?\\(\\\\[CM]-\\)*.\\)" 1 string)
("^\\s *\\(require\\|load\\).*$" nil include)
("^\\s *\\(include\\|alias\\|undef\\).*$" nil decl)
@@ -624,6 +624,7 @@ An end of a defun is found by moving forward from the beginning of one."
"break"
"case"
"class"
+ "def"
"do"
"elsif"
"else"
@@ -652,7 +653,7 @@ An end of a defun is found by moving forward from the beginning of one."
"while"
)
"\\|")
- "\\)[ \n\t()]")
+ "\\)\\b")
2)
;; variables
'("\\(^\\|[^_]\\)\\b\\(nil\\|self\\|true\\|false\\)\\b\\([^_]\\|$\\)"
@@ -664,8 +665,8 @@ An end of a defun is found by moving forward from the beginning of one."
'("\\(^\\|[^_]\\)\\b\\([A-Z]+[a-zA-Z0-9_]*\\)"
2 font-lock-type-face)
;; functions
- '("^\\s *def[ \t]+[^ \t(]*"
- 0 font-lock-function-name-face t))
+ '("^\\s *def[ \t]+\\([^ \t(]*\\)"
+ 1 font-lock-function-name-face t))
"*Additional expressions to highlight in ruby mode.")
(if (and (>= (string-to-int emacs-version) 19)
(not (featurep 'xemacs)))
diff --git a/sample/test.rb b/sample/test.rb
index 0adcb22..8748b60 100644
--- a/sample/test.rb
+++ b/sample/test.rb
@@ -484,6 +484,63 @@ 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
@@ -546,9 +603,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" =~ /^$/)
diff --git a/sample/tsvr.rb b/sample/tsvr.rb
index fbc6545..d6a5620 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 ab3e791..d7ce492 100644
--- a/signal.c
+++ b/signal.c
@@ -338,8 +338,9 @@ void
rb_trap_exit()
{
#ifndef MACOS_UNUSE_SIGNAL
- if (trap_list[0])
+ if (trap_list[0]) {
rb_eval_cmd(trap_list[0], rb_ary_new3(1, INT2FIX(0)));
+ }
#endif
}
diff --git a/sprintf.c b/sprintf.c
index 6514893..3c09a8e 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -396,7 +396,7 @@ rb_f_sprintf(argc, argv)
sc = ' ';
width--;
}
- sprintf(fbuf, "%l%%c", c);
+ sprintf(fbuf, "%%l%c", c);
sprintf(nbuf, fbuf, v);
s = nbuf;
goto format_integer;
@@ -406,7 +406,7 @@ rb_f_sprintf(argc, argv)
strcpy(s, "..");
s += 2;
}
- sprintf(fbuf, "%l%%c", *p);
+ sprintf(fbuf, "%%l%c", *p);
sprintf(s, fbuf, v);
if (v < 0) {
char d = 0;
diff --git a/st.c b/st.c
index 930d40b..a48d11e 100644
--- a/st.c
+++ b/st.c
@@ -10,6 +10,15 @@ static char sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible";
#include <stdlib.h>
#endif
+typedef struct st_table_entry st_table_entry;
+
+struct st_table_entry {
+ unsigned int hash;
+ char *key;
+ char *record;
+ st_table_entry *next;
+};
+
#define ST_DEFAULT_MAX_DENSITY 5
#define ST_DEFAULT_INIT_TABLE_SIZE 11
@@ -47,8 +56,66 @@ static void rehash();
#define EQUAL(table, x, y) ((*table->type->compare)(x, y) == 0)
-#define do_hash(key, table) (*(table)->type->hash)((key), (table)->num_bins)
-#define do_hash2(key, table, bins) (*(table)->type->hash)((key), bins)
+#define do_hash(key, table) (unsigned int)(*(table)->type->hash)((key))
+#define do_hash_bin(key, table) (do_hash(key, table)%(table)->num_bins)
+
+/*
+ * MINSIZE is the minimum size of a dictionary.
+ */
+
+#define MINSIZE 8
+
+/*
+Table of irreducible polynomials to efficiently cycle through
+GF(2^n)-{0}, 2<=n<=30.
+*/
+static long polys[] = {
+ 8 + 3,
+ 16 + 3,
+ 32 + 5,
+ 64 + 3,
+ 128 + 3,
+ 256 + 29,
+ 512 + 17,
+ 1024 + 9,
+ 2048 + 5,
+ 4096 + 83,
+ 8192 + 27,
+ 16384 + 43,
+ 32768 + 3,
+ 65536 + 45,
+ 131072 + 9,
+ 262144 + 39,
+ 524288 + 39,
+ 1048576 + 9,
+ 2097152 + 5,
+ 4194304 + 3,
+ 8388608 + 33,
+ 16777216 + 27,
+ 33554432 + 9,
+ 67108864 + 71,
+ 134217728 + 39,
+ 268435456 + 9,
+ 536870912 + 5,
+ 1073741824 + 83,
+ 0
+};
+
+static int
+new_size(size)
+ int size;
+{
+ int i, newsize;
+
+ for (i = 0, newsize = MINSIZE;
+ i < sizeof(polys)/sizeof(polys[0]);
+ i++, newsize <<= 1)
+ {
+ if (newsize > size) return polys[i];
+ }
+ /* Ran out of polynomials */
+ return -1; /* should raise exception */
+}
st_table*
st_init_table_with_size(type, size)
@@ -57,17 +124,14 @@ st_init_table_with_size(type, size)
{
st_table *tbl;
- if (size == 0) size = ST_DEFAULT_INIT_TABLE_SIZE;
- else size /= ST_DEFAULT_MAX_DENSITY*0.87;
-
- if (size < ST_DEFAULT_INIT_TABLE_SIZE)
- size = ST_DEFAULT_INIT_TABLE_SIZE;
+ size = new_size(size); /* round up to prime number */
tbl = alloc(st_table);
tbl->type = type;
tbl->num_entries = 0;
tbl->num_bins = size;
tbl->bins = (st_table_entry **)Calloc(size, sizeof(st_table_entry*));
+
return tbl;
}
@@ -123,13 +187,14 @@ st_free_table(table)
free(table);
}
-#define PTR_NOT_EQUAL(table, ptr, key) \
-(ptr != 0 && !EQUAL(table, key, (ptr)->key))
+#define PTR_NOT_EQUAL(table, ptr, hash_val, key) \
+((ptr) != 0 && ptr->hash != (hash_val) && !EQUAL((table), (key), (ptr)->key))
-#define FIND_ENTRY(table, ptr, hash_val) \
-ptr = (table)->bins[hash_val];\
-if (PTR_NOT_EQUAL(table, ptr, key)) {\
- while (PTR_NOT_EQUAL(table, ptr->next, key)) {\
+#define FIND_ENTRY(table, ptr, hash_val, bin_pos) \
+bin_pos = hash_val%(table)->num_bins;\
+ptr = (table)->bins[bin_pos];\
+if (PTR_NOT_EQUAL(table, ptr, hash_val, key)) {\
+ while (PTR_NOT_EQUAL(table, ptr->next, hash_val, key)) {\
ptr = ptr->next;\
}\
ptr = ptr->next;\
@@ -141,12 +206,11 @@ st_lookup(table, key, value)
register char *key;
char **value;
{
- int hash_val;
+ unsigned int hash_val, bin_pos;
register st_table_entry *ptr;
hash_val = do_hash(key, table);
-
- FIND_ENTRY(table, ptr, hash_val);
+ FIND_ENTRY(table, ptr, hash_val, bin_pos);
if (ptr == 0) {
return 0;
@@ -156,19 +220,21 @@ st_lookup(table, key, value)
}
}
-#define ADD_DIRECT(table, key, value, hash_val, tbl)\
+#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\
{\
+ st_table_entry *tbl;\
if (table->num_entries/table->num_bins > ST_DEFAULT_MAX_DENSITY) {\
rehash(table);\
- hash_val = do_hash(key, table);\
+ bin_pos = hash_val % table->num_bins;\
}\
\
tbl = alloc(st_table_entry);\
\
+ tbl->hash = hash_val;\
tbl->key = key;\
tbl->record = value;\
- tbl->next = table->bins[hash_val];\
- table->bins[hash_val] = tbl;\
+ tbl->next = table->bins[bin_pos];\
+ table->bins[bin_pos] = tbl;\
table->num_entries++;\
}
@@ -178,16 +244,14 @@ st_insert(table, key, value)
register char *key;
char *value;
{
- int hash_val;
- st_table_entry *tbl;
+ unsigned int hash_val, bin_pos;
register st_table_entry *ptr;
hash_val = do_hash(key, table);
-
- FIND_ENTRY(table, ptr, hash_val);
+ FIND_ENTRY(table, ptr, hash_val, bin_pos);
if (ptr == 0) {
- ADD_DIRECT(table,key,value,hash_val,tbl);
+ ADD_DIRECT(table, key, value, hash_val, bin_pos);
return 0;
} else {
ptr->record = value;
@@ -201,34 +265,12 @@ st_add_direct(table, key, value)
char *key;
char *value;
{
- int hash_val;
+ unsigned int hash_val, bin_pos;
st_table_entry *tbl;
hash_val = do_hash(key, table);
- ADD_DIRECT(table, key, value, hash_val, tbl);
-}
-
-int
-st_find_or_add(table, key, slot)
- st_table *table;
- char *key;
- char ***slot;
-{
- int hash_val;
- st_table_entry *tbl, *ptr;
-
- hash_val = do_hash(key, table);
-
- FIND_ENTRY(table, ptr, hash_val);
-
- if (ptr == 0) {
- ADD_DIRECT(table, key, (char*)0, hash_val, tbl)
- if (slot != 0) *slot = &tbl->record;
- return 0;
- } else {
- if (slot != 0) *slot = &ptr->record;
- return 1;
- }
+ bin_pos = hash_val % table->num_bins;
+ ADD_DIRECT(table, key, value, hash_val, bin_pos);
}
static void
@@ -236,22 +278,17 @@ rehash(table)
register st_table *table;
{
register st_table_entry *ptr, *next, **new_bins;
- int i, old_num_bins = table->num_bins, new_num_bins, hash_val;
+ int i, old_num_bins = table->num_bins, new_num_bins;
+ unsigned int hash_val;
- new_num_bins = 1.79*old_num_bins;
-
- if (new_num_bins%2 == 0) {
- new_num_bins += 1;
- }
-
- new_bins = (st_table_entry **)
- Calloc((unsigned)new_num_bins, sizeof(st_table_entry*));
+ new_num_bins = new_size(old_num_bins);
+ new_bins = (st_table_entry**)Calloc(new_num_bins, sizeof(st_table_entry*));
for(i = 0; i < old_num_bins ; i++) {
ptr = table->bins[i];
while (ptr != 0) {
next = ptr->next;
- hash_val = do_hash2(ptr->key, table, new_num_bins);
+ hash_val = ptr->hash % new_num_bins;
ptr->next = new_bins[hash_val];
new_bins[hash_val] = ptr;
ptr = next;
@@ -309,12 +346,11 @@ st_delete(table, key, value)
register char **key;
char **value;
{
- int hash_val;
+ unsigned int hash_val;
st_table_entry *tmp;
register st_table_entry *ptr;
- hash_val = do_hash(*key, table);
-
+ hash_val = do_hash_bin(*key, table);
ptr = table->bins[hash_val];
if (ptr == 0) {
@@ -353,11 +389,10 @@ st_delete_safe(table, key, value, never)
char **value;
char *never;
{
- int hash_val;
+ unsigned int hash_val;
register st_table_entry *ptr;
- hash_val = do_hash(*key, table);
-
+ hash_val = do_hash_bin(*key, table);
ptr = table->bins[hash_val];
if (ptr == 0) {
@@ -423,9 +458,8 @@ st_foreach(table, func, arg)
}
static int
-strhash(string, modulus)
+strhash(string)
register char *string;
- int modulus;
{
register int val = 0;
register int c;
@@ -434,7 +468,7 @@ strhash(string, modulus)
val = val*997 + c;
}
- return ((val < 0) ? -val : val)%modulus;
+ return val;
}
static int
@@ -445,9 +479,8 @@ numcmp(x, y)
}
static int
-numhash(n, modulus)
+numhash(n)
int n;
- int modulus;
{
- return n % modulus;
+ return n;
}
diff --git a/st.h b/st.h
index 71ae003..ce87df6 100644
--- a/st.h
+++ b/st.h
@@ -6,14 +6,6 @@
#define ST_INCLUDED
-typedef struct st_table_entry st_table_entry;
-
-struct st_table_entry {
- char *key;
- char *record;
- st_table_entry *next;
-};
-
typedef struct st_table st_table;
struct st_hash_type {
@@ -25,10 +17,10 @@ struct st_table {
struct st_hash_type *type;
int num_bins;
int num_entries;
- st_table_entry **bins;
+ struct st_table_entry **bins;
};
-#define st_is_member(table,key) st_lookup(table,key,(char **) 0)
+#define st_is_member(table,key) st_lookup(table,key,(char **)0)
enum st_retval {ST_CONTINUE, ST_STOP, ST_DELETE};
@@ -38,8 +30,8 @@ st_table *st_init_numtable();
st_table *st_init_numtable_with_size();
st_table *st_init_strtable();
st_table *st_init_strtable_with_size();
-int st_delete(), st_delete_safe(), st_insert();
-int st_lookup(), st_find_or_add();
+int st_delete(), st_delete_safe();
+int st_insert(), st_lookup();
void st_foreach(), st_add_direct(), st_free_table();
st_table *st_copy();
diff --git a/string.c b/string.c
index 1b4d2e3..710de1a 100644
--- a/string.c
+++ b/string.c
@@ -25,7 +25,6 @@
VALUE rb_cString;
#define STR_FREEZE FL_USER1
-#define STR_TAINT FL_USER2
#define STR_NO_ORIG FL_USER3
extern VALUE rb_rs;
@@ -38,9 +37,6 @@ rb_str_new(ptr, len)
NEWOBJ(str, struct RString);
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;
@@ -60,6 +56,21 @@ rb_str_new2(ptr)
}
VALUE
+rb_tainted_str_new(ptr, len)
+ char *ptr;
+ int len;
+{
+ return rb_str_new(ptr, len);
+}
+
+VALUE
+rb_tainted_str_new2(ptr)
+ char *ptr;
+{
+ return rb_str_new2(ptr);
+}
+
+VALUE
rb_str_new3(str)
VALUE str;
{
@@ -70,10 +81,6 @@ rb_str_new3(str)
str2->ptr = RSTRING(str)->ptr;
str2->orig = str;
- if (rb_safe_level() >= 3) {
- FL_SET(str2, STR_TAINT);
- }
-
return (VALUE)str2;
}
@@ -96,7 +103,7 @@ rb_str_new4(orig)
RSTRING(orig)->orig = (VALUE)str;
str->orig = 0;
if (rb_safe_level() >= 3) {
- FL_SET(str, STR_TAINT);
+ FL_SET(str, FL_TAINT);
}
return (VALUE)str;
}
@@ -127,7 +134,7 @@ rb_str_assign(str, str2)
RSTRING(str)->orig = RSTRING(str2)->orig;
RSTRING(str2)->ptr = 0; /* abandon str2 */
RSTRING(str2)->len = 0;
- if (rb_str_tainted(str2)) rb_str_taint(str);
+ if (rb_obj_tainted(str2)) rb_obj_taint(str);
}
static ID pr_str;
@@ -171,9 +178,7 @@ rb_str_dup(str)
if (TYPE(str) != T_STRING) str = rb_str_to_str(str);
s = rb_str_new(RSTRING(str)->ptr, RSTRING(str)->len);
- if (rb_str_tainted(str)) s = rb_str_taint(s);
- if (RSTRING(str)->orig && FL_TEST(str, STR_NO_ORIG))
- RSTRING(s)->orig = RSTRING(str)->orig;
+ if (rb_obj_tainted(str)) s = rb_obj_taint(s);
return s;
}
@@ -195,7 +200,7 @@ rb_str_s_new(klass, orig)
}
if (rb_safe_level() >= 3) {
- FL_SET(str, STR_TAINT);
+ FL_SET(str, FL_TAINT);
}
rb_obj_call_init((VALUE)str);
@@ -231,8 +236,8 @@ rb_str_plus(str1, str2)
RSTRING(str2)->ptr, RSTRING(str2)->len);
RSTRING(str3)->ptr[RSTRING(str3)->len] = '\0';
- if (rb_str_tainted(str1) || rb_str_tainted(str2))
- return rb_str_taint(str3);
+ if (rb_obj_tainted(str1) || rb_obj_tainted(str2))
+ return rb_obj_taint(str3);
return str3;
}
@@ -256,8 +261,8 @@ rb_str_times(str, times)
}
RSTRING(str2)->ptr[RSTRING(str2)->len] = '\0';
- if (rb_str_tainted(str)) {
- return rb_str_taint(str2);
+ if (rb_obj_tainted(str)) {
+ return rb_obj_taint(str2);
}
return str2;
@@ -300,7 +305,7 @@ rb_str_substr(str, start, len)
}
str2 = rb_str_new(RSTRING(str)->ptr+start, len);
- if (rb_str_tainted(str)) rb_str_taint(str2);
+ if (rb_obj_tainted(str)) rb_obj_taint(str2);
return str2;
}
@@ -348,6 +353,8 @@ rb_str_modify(str)
if (FL_TEST(str, STR_FREEZE))
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);
@@ -388,25 +395,6 @@ rb_str_dup_frozen(str)
}
VALUE
-rb_str_taint(str)
- VALUE str;
-{
- if (TYPE(str) == T_STRING) {
- FL_SET(str, STR_TAINT);
- }
- return str;
-}
-
-VALUE
-rb_str_tainted(str)
- VALUE str;
-{
- if (FL_TEST(str, STR_TAINT))
- return Qtrue;
- return Qfalse;
-}
-
-VALUE
rb_str_resize(str, len)
VALUE str;
int len;
@@ -457,7 +445,7 @@ rb_str_hash(str)
register char *p = RSTRING(str)->ptr;
register int key = 0;
- if (rb_ignorecase_p()) {
+ if (ruby_ignorecase) {
while (len--) {
key = key*65599 + toupper(*p);
p++;
@@ -489,7 +477,7 @@ rb_str_cmp(str1, str2)
unsigned int len;
int retval;
- if (rb_ignorecase_p()) {
+ if (ruby_ignorecase) {
return rb_str_cicmp(str1, str2);
}
@@ -740,8 +728,8 @@ rb_str_succ(orig)
}
}
- if (rb_str_tainted(orig)) {
- return rb_str_taint(str);
+ if (rb_obj_tainted(orig)) {
+ return rb_obj_taint(str);
}
return str;
@@ -799,8 +787,8 @@ rb_str_aref(str, indx)
return INT2FIX(RSTRING(str)->ptr[idx] & 0xff);
case T_REGEXP:
- if (rb_str_match(str, indx))
- return rb_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:
@@ -931,13 +919,11 @@ rb_str_aset(str, indx, val)
return val;
case T_STRING:
- for (offset=0;
- (beg=rb_str_index(str, indx, offset)) >= 0;
- offset=beg+RSTRING(val)->len) {
+ beg = rb_str_index(str, indx, 0);
+ if (beg >= 0) {
end = beg + RSTRING(indx)->len - 1;
rb_str_replace2(str, beg, end, val);
}
- if (offset == 0) return Qnil;
return val;
default:
@@ -1014,17 +1000,17 @@ rb_str_sub_bang(argc, argv, str)
int iter = 0;
int plen;
- if (rb_scan_args(argc, argv, "11", &pat, &repl) == 1) {
- if (!rb_iterator_p()) {
- rb_raise(rb_eArgError, "Wrong # of arguments(1 for 2)");
- }
+ if (argc == 1 && rb_iterator_p()) {
iter = 1;
}
+ else if (argc == 2) {
+ repl = repl = rb_obj_as_string(argv[1]);;
+ }
else {
- repl = rb_obj_as_string(repl);
+ rb_raise(rb_eArgError, "Wrong # of arguments(%d for 2)", argc);
}
- pat = get_pat(pat);
+ pat = get_pat(argv[0]);
if (rb_reg_search(pat, str, 0, 0) >= 0) {
rb_str_modify(str);
match = rb_backref_get();
@@ -1079,17 +1065,17 @@ rb_str_gsub_bang(argc, argv, str)
char *buf, *bp, *cp;
int blen, len;
- if (rb_scan_args(argc, argv, "11", &pat, &repl) == 1) {
- if (!rb_iterator_p()) {
- rb_raise(rb_eArgError, "Wrong # of arguments(1 for 2)");
- }
+ if (argc == 1 && rb_iterator_p()) {
iter = 1;
}
+ else if (argc == 2) {
+ repl = repl = rb_obj_as_string(argv[1]);;
+ }
else {
- repl = rb_obj_as_string(repl);
+ rb_raise(rb_eArgError, "Wrong # of arguments(%d for 2)", argc);
}
- pat = get_pat(pat);
+ 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 */
@@ -1178,7 +1164,7 @@ rb_str_replace_method(str, str2)
rb_str_modify(str);
rb_str_resize(str, RSTRING(str2)->len);
memcpy(RSTRING(str)->ptr, RSTRING(str2)->ptr, RSTRING(str2)->len);
- if (rb_str_tainted(str2)) rb_str_taint(str);
+ if (rb_obj_tainted(str2)) rb_obj_taint(str);
return str;
}
@@ -1491,7 +1477,7 @@ rb_str_dump(str)
}
else {
*q++ = '\\';
- sprintf(q, "%03o", c);
+ sprintf(q, "%03o", c&0xff);
q += 3;
}
}
@@ -1950,12 +1936,12 @@ rb_str_split_method(argc, argv, str)
VALUE spat;
VALUE limit;
int char_sep = -1;
- int beg, end, lim, i;
+ int beg, end, i, lim = 0;
VALUE result, tmp;
if (rb_scan_args(argc, argv, "02", &spat, &limit) == 2) {
lim = NUM2INT(limit);
- if (lim == 0) limit = Qnil;
+ if (lim <= 0) limit = Qnil;
else if (lim == 1) return rb_ary_new3(1, str);
i = 1;
}
@@ -1981,7 +1967,7 @@ rb_str_split_method(argc, argv, str)
case T_REGEXP:
break;
default:
- rb_raise(rb_eArgError, "split(): bad separator");
+ rb_raise(rb_eArgError, "bad separator");
}
}
@@ -2068,9 +2054,14 @@ rb_str_split_method(argc, argv, str)
if (!NIL_P(limit) && lim <= ++i) break;
}
}
- if (RSTRING(str)->len > beg) {
+ 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;
}
@@ -2280,9 +2271,6 @@ rb_f_chomp(argc, argv)
{
VALUE str = rb_str_dup(uscore_get());
VALUE val = rb_str_chomp_bang(argc, argv, str);
-
- if (NIL_P(val)) return str;
- rb_lastline_set(val);
return val;
}
@@ -2326,7 +2314,6 @@ 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;
@@ -2579,9 +2566,6 @@ Init_String()
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, "taint", rb_str_taint, 0);
- rb_define_method(rb_cString, "tainted?", rb_str_tainted, 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);
diff --git a/time.c b/time.c
index 016ec87..757e42c 100644
--- a/time.c
+++ b/time.c
@@ -60,7 +60,7 @@ time_s_now(klass)
VALUE obj;
struct time_object *tobj;
- obj = Data_Make_Struct(klass, 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) {
@@ -79,7 +79,9 @@ time_new_internal(klass, sec, usec)
VALUE obj;
struct time_object *tobj;
- obj = Data_Make_Struct(klass, 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;
@@ -103,27 +105,23 @@ rb_time_timeval(time)
switch (TYPE(time)) {
case T_FIXNUM:
- t.tv_sec = FIX2UINT(time);
+ t.tv_sec = FIX2INT(time);
if (t.tv_sec < 0)
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)
- rb_raise(rb_eArgError, "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 = floor(RFLOAT(time)->value);
+ t.tv_usec = (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;
@@ -231,8 +229,8 @@ time_arg(argc, argv, args)
|| 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)
+ || args[4] < 0 || args[4] > 59
+ || args[5] < 0 || args[5] > 60)
rb_raise(rb_eArgError, "argument out of range");
}
@@ -796,6 +794,54 @@ time_s_times(obj)
#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()
{
@@ -850,4 +896,8 @@ Init_Time()
#if defined(HAVE_TIMES) || defined(NT)
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 934f601..bb9a96c 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 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.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/variable.c b/variable.c
index 14b5cf4..85d6eaf 100644
--- a/variable.c
+++ b/variable.c
@@ -615,9 +615,8 @@ rb_gvar_set(entry, val)
{
struct trace_data trace;
- if (rb_safe_level() >= 4) {
- rb_raise(rb_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) {
@@ -726,6 +725,8 @@ rb_ivar_set(obj, id, val)
case T_OBJECT:
case T_CLASS:
case T_MODULE:
+ 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;
@@ -1016,6 +1017,8 @@ rb_const_set(klass, id, val)
ID id;
VALUE val;
{
+ 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();
}