summaryrefslogtreecommitdiff
path: root/spec/ruby/library/csv/stringreader/initialize_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/library/csv/stringreader/initialize_spec.rb')
-rw-r--r--spec/ruby/library/csv/stringreader/initialize_spec.rb6
1 files changed, 6 insertions, 0 deletions
diff --git a/spec/ruby/library/csv/stringreader/initialize_spec.rb b/spec/ruby/library/csv/stringreader/initialize_spec.rb
new file mode 100644
index 0000000000..4e3634847e
--- /dev/null
+++ b/spec/ruby/library/csv/stringreader/initialize_spec.rb
@@ -0,0 +1,6 @@
+require_relative '../../../spec_helper'
+require 'csv'
+
+describe "CSV::StringReader#initialize" do
+ it "needs to be reviewed for spec completeness"
+end
2cd74e7a03b416cfbf5b9276acfe'>README.EXT1022
-rw-r--r--README.EXT.jp729
-rw-r--r--README.jp131
-rw-r--r--ToDo132
-rw-r--r--array.c1404
-rw-r--r--bignum.c954
-rw-r--r--class.c340
-rw-r--r--compar.c77
-rw-r--r--config.dj36
-rw-r--r--config.guess371
-rw-r--r--config.sub360
-rw-r--r--configure4091
-rw-r--r--configure.bat5
-rw-r--r--configure.in859
-rw-r--r--cygwin/GNUmakefile.in41
-rw-r--r--defines.h50
-rw-r--r--dir.c632
-rw-r--r--djgpp/README.djgpp21
-rw-r--r--djgpp/config.hin72
-rw-r--r--djgpp/config.sed80
-rw-r--r--djgpp/configure.bat21
-rw-r--r--djgpp/mkver.sed1
-rw-r--r--dln.c435
-rw-r--r--dln.h15
-rw-r--r--doc/forwardable.rd84
-rw-r--r--doc/forwardable.rd.jp81
-rw-r--r--doc/irb/irb-tools.rd.jp185
-rw-r--r--doc/irb/irb.rd377
-rw-r--r--doc/irb/irb.rd.jp391
-rw-r--r--doc/shell.rd348
-rw-r--r--doc/shell.rd.jp336
-rw-r--r--enum.c312
-rw-r--r--env.h26
-rw-r--r--error.c734
-rw-r--r--eval.c7344
-rw-r--r--ext/.cvsignore1
-rw-r--r--ext/Setup4
-rw-r--r--ext/Setup.dj5
-rw-r--r--ext/Setup.emx16
-rw-r--r--ext/Setup.nt15
-rw-r--r--ext/Win32API/Win32API.c198
-rw-r--r--ext/Win32API/depend1
-rw-r--r--ext/Win32API/extconf.rb10
-rw-r--r--ext/aix_ld.rb73
-rw-r--r--ext/aix_mksym.rb33
-rw-r--r--ext/configsub.rb32
-rw-r--r--ext/curses/.cvsignore1
-rw-r--r--ext/curses/MANIFEST1
-rw-r--r--ext/curses/curses.c101
-rw-r--r--ext/curses/depend1
-rw-r--r--ext/curses/extconf.rb24
-rw-r--r--ext/cygwin32_ld.rb90
-rw-r--r--ext/dbm/.cvsignore1
-rw-r--r--ext/dbm/dbm.c320
-rw-r--r--ext/dbm/depend2
-rw-r--r--ext/dbm/extconf.rb15
-rw-r--r--ext/etc/.cvsignore1
-rw-r--r--ext/etc/MANIFEST3
-rw-r--r--ext/etc/depend2
-rw-r--r--ext/etc/etc.c110
-rw-r--r--ext/etc/etc.txt72
-rw-r--r--ext/etc/etc.txt.jp (renamed from ext/etc/etc.doc)3
-rw-r--r--ext/etc/extconf.rb24
-rw-r--r--ext/extmk.rb.in761
-rw-r--r--ext/extmk.rb.nt497
-rw-r--r--ext/fcntl/.cvsignore1
-rw-r--r--ext/fcntl/depend2
-rw-r--r--ext/fcntl/fcntl.c1
-rw-r--r--ext/gdbm/.cvsignore1
-rw-r--r--ext/gdbm/MANIFEST5
-rw-r--r--ext/gdbm/README1
-rw-r--r--ext/gdbm/depend1
-rw-r--r--ext/gdbm/extconf.rb7
-rw-r--r--ext/gdbm/gdbm.c978
-rw-r--r--ext/kconv/MANIFEST3
-rw-r--r--ext/kconv/depend1
-rw-r--r--ext/md5/.cvsignore1
-rw-r--r--ext/md5/MANIFEST4
-rw-r--r--ext/md5/depend4
-rw-r--r--ext/md5/extconf.rb3
-rw-r--r--ext/md5/md5.doc36
-rw-r--r--ext/md5/md5.txt50
-rw-r--r--ext/md5/md5.txt.jp50
-rw-r--r--ext/md5/md5init.c39
-rw-r--r--ext/nkf/.cvsignore1
-rw-r--r--ext/nkf/MANIFEST7
-rw-r--r--ext/nkf/depend1
-rw-r--r--ext/nkf/extconf.rb2
-rw-r--r--ext/nkf/lib/kconv.rb73
-rw-r--r--ext/nkf/nkf.c196
-rw-r--r--ext/nkf/nkf1.7/nkf.c (renamed from ext/kconv/kconv.c)1265
-rw-r--r--ext/nkf/test.rb318
-rw-r--r--ext/pty/.cvsignore1
-rw-r--r--ext/pty/MANIFEST12
-rw-r--r--ext/pty/README93
-rw-r--r--ext/pty/README.expect22
-rw-r--r--ext/pty/README.expect.jp21
-rw-r--r--ext/pty/README.jp89
-rw-r--r--ext/pty/depend1
-rw-r--r--ext/pty/expect_sample.rb56
-rw-r--r--ext/pty/extconf.rb12
-rw-r--r--ext/pty/lib/expect.rb36
-rw-r--r--ext/pty/pty.c499
-rw-r--r--ext/pty/script.rb38
-rw-r--r--ext/pty/shl.rb96
-rw-r--r--ext/readline/.cvsignore1
-rw-r--r--ext/readline/MANIFEST5
-rw-r--r--ext/readline/README55
-rw-r--r--ext/readline/depend1
-rw-r--r--ext/readline/extconf.rb16
-rw-r--r--ext/readline/readline.c427
-rw-r--r--ext/sdbm/.cvsignore1
-rw-r--r--ext/sdbm/MANIFEST6
-rw-r--r--ext/sdbm/_sdbm.c (renamed from win32/sdbm.c)56
-rw-r--r--ext/sdbm/depend2
-rw-r--r--ext/sdbm/extconf.rb3
-rw-r--r--ext/sdbm/init.c719
-rw-r--r--ext/sdbm/sdbm.h (renamed from win32/sdbm.h)36
-rw-r--r--ext/socket/.cvsignore1
-rw-r--r--ext/socket/MANIFEST4
-rw-r--r--ext/socket/addrinfo.h167
-rw-r--r--ext/socket/depend4
-rw-r--r--ext/socket/extconf.rb339
-rw-r--r--ext/socket/getaddrinfo.c683
-rw-r--r--ext/socket/getnameinfo.c261
-rw-r--r--ext/socket/socket.c1822
-rw-r--r--ext/socket/sockport.h76
-rw-r--r--ext/tcltklib/.cvsignore1
-rw-r--r--ext/tcltklib/MANIFEST1
-rw-r--r--ext/tcltklib/depend3
-rw-r--r--ext/tcltklib/extconf.rb127
-rw-r--r--ext/tcltklib/lib/tcltk.rb287
-rw-r--r--ext/tcltklib/stubs.c86
-rw-r--r--ext/tcltklib/tcltklib.c396
-rw-r--r--ext/tk/.cvsignore1
-rw-r--r--ext/tk/MANIFEST25
-rw-r--r--ext/tk/depend1
-rw-r--r--ext/tk/extconf.rb2
-rw-r--r--ext/tk/lib/tk.rb3427
-rw-r--r--ext/tk/lib/tkafter.rb316
-rw-r--r--ext/tk/lib/tkbgerror.rb17
-rw-r--r--ext/tk/lib/tkcanvas.rb941
-rw-r--r--ext/tk/lib/tkclass.rb (renamed from lib/tkclass.rb)0
-rw-r--r--ext/tk/lib/tkdialog.rb141
-rw-r--r--ext/tk/lib/tkentry.rb213
-rw-r--r--ext/tk/lib/tkfont.rb1026
-rw-r--r--ext/tk/lib/tkmenubar.rb (renamed from lib/tkmenubar.rb)0
-rw-r--r--ext/tk/lib/tkmngfocus.rb27
-rw-r--r--ext/tk/lib/tkpalette.rb48
-rw-r--r--ext/tk/lib/tkscrollbox.rb (renamed from lib/tkscrollbox.rb)6
-rw-r--r--ext/tk/lib/tktext.rb1085
-rw-r--r--ext/tk/lib/tkvirtevent.rb81
-rw-r--r--ext/tk/sample/tkbiff.rb (renamed from sample/tkbiff.rb)0
-rw-r--r--ext/tk/sample/tkbrowse.rb79
-rw-r--r--ext/tk/sample/tkdialog.rb (renamed from sample/tkdialog.rb)0
-rw-r--r--ext/tk/sample/tkfrom.rb (renamed from sample/tkfrom.rb)0
-rw-r--r--ext/tk/sample/tkhello.rb (renamed from sample/tkhello.rb)0
-rw-r--r--ext/tk/sample/tkline.rb (renamed from sample/tkline.rb)0
-rw-r--r--ext/tk/sample/tktimer.rb (renamed from sample/tktimer.rb)0
-rw-r--r--ext/tk/tkutil.c (renamed from ext/tkutil/tkutil.c)15
-rw-r--r--ext/tkutil/MANIFEST3
-rw-r--r--ext/tkutil/depend1
-rw-r--r--file.c1670
-rw-r--r--fnmatch.c190
-rw-r--r--fnmatch.h36
-rw-r--r--gc.c853
-rw-r--r--glob.c574
-rw-r--r--hash.c1232
-rw-r--r--inits.c10
-rw-r--r--install-sh238
-rw-r--r--instruby.rb106
-rw-r--r--intern.h563
-rw-r--r--io.c2505
-rw-r--r--keywords8
-rw-r--r--lex.c149
-rw-r--r--lib/Env.rb32
-rw-r--r--lib/README48
-rw-r--r--lib/base64.rb19
-rw-r--r--lib/cgi-lib.rb295
-rw-r--r--lib/cgi.rb1955
-rw-r--r--lib/cgi/session.rb183
-rw-r--r--lib/complex.rb72
-rw-r--r--lib/date.rb527
-rw-r--r--lib/date2.rb197
-rw-r--r--lib/debug.rb1081
-rw-r--r--lib/delegate.rb72
-rw-r--r--lib/e2mmap.rb258
-rw-r--r--lib/eregex.rb12
-rw-r--r--lib/final.rb39
-rw-r--r--lib/finalize.rb60
-rw-r--r--lib/find.rb36
-rw-r--r--lib/forwardable.rb94
-rw-r--r--lib/ftools.rb63
-rw-r--r--lib/ftplib.rb582
-rw-r--r--lib/getoptlong.rb474
-rw-r--r--lib/getopts.rb209
-rw-r--r--lib/importenv.rb23
-rw-r--r--lib/irb.rb314
-rw-r--r--lib/irb/completion.rb177
-rw-r--r--lib/irb/context.rb289
-rw-r--r--lib/irb/extend-command.rb126
-rw-r--r--lib/irb/frame.rb67
-rw-r--r--lib/irb/help.rb33
-rw-r--r--lib/irb/init.rb232
-rw-r--r--lib/irb/input-method.rb118
-rw-r--r--lib/irb/lc/error.rb30
-rw-r--r--lib/irb/lc/help-message34
-rw-r--r--lib/irb/lc/ja/error.rb29
-rw-r--r--lib/irb/lc/ja/help-message35
-rw-r--r--lib/irb/loader.rb118
-rw-r--r--lib/irb/locale.rb187
-rw-r--r--lib/irb/multi-irb.rb232
-rw-r--r--lib/irb/ruby-lex.rb971
-rw-r--r--lib/irb/ruby-token.rb271
-rw-r--r--lib/irb/slex.rb279
-rw-r--r--lib/irb/version.rb16
-rw-r--r--lib/irb/workspace.rb106
-rw-r--r--lib/irb/ws-for-case-2.rb15
-rw-r--r--lib/irb/xmp.rb84
-rw-r--r--lib/jcode.rb275
-rw-r--r--lib/mailread.rb26
-rw-r--r--lib/mathn.rb4
-rw-r--r--lib/matrix.rb379
-rw-r--r--lib/mkmf.rb678
-rw-r--r--lib/monitor.rb384
-rw-r--r--lib/mutex_m.rb226
-rw-r--r--lib/net/ftp.rb671
-rw-r--r--lib/net/http.rb1199
-rw-r--r--lib/net/imap.rb2371
-rw-r--r--lib/net/pop.rb457
-rw-r--r--lib/net/protocol.rb875
-rw-r--r--lib/net/smtp.rb304
-rw-r--r--lib/net/telnet.rb604
-rw-r--r--lib/observer.rb28
-rw-r--r--lib/open3.rb66
-rw-r--r--lib/parsearg.rb1
-rw-r--r--lib/parsedate.rb196
-rw-r--r--lib/ping.rb37
-rw-r--r--lib/profile.rb55
-rw-r--r--lib/pstore.rb74
-rw-r--r--lib/rational.rb36
-rw-r--r--lib/readbytes.rb36
-rw-r--r--lib/shell.rb274
-rw-r--r--lib/shell/builtin-command.rb154
-rw-r--r--lib/shell/command-processor.rb584
-rw-r--r--lib/shell/error.rb26
-rw-r--r--lib/shell/filter.rb111
-rw-r--r--lib/shell/process-controller.rb258
-rw-r--r--lib/shell/system-command.rb168
-rw-r--r--lib/shell/version.rb16
-rw-r--r--lib/shellwords.rb39
-rw-r--r--lib/singleton.rb43
-rw-r--r--lib/sync.rb274
-rw-r--r--lib/telnet.rb9
-rw-r--r--lib/tempfile.rb41
-rw-r--r--lib/thread.rb153
-rw-r--r--lib/thwait.rb125
-rw-r--r--lib/timeout.rb50
-rw-r--r--lib/tk.rb1272
-rw-r--r--lib/tkcanvas.rb326
-rw-r--r--lib/tkdialog.rb62
-rw-r--r--lib/tkentry.rb67
-rw-r--r--lib/tktext.rb164
-rw-r--r--lib/tracer.rb99
-rw-r--r--lib/weakref.rb82
-rw-r--r--main.c27
-rw-r--r--marshal.c627
-rw-r--r--math.c70
-rw-r--r--misc/README5
-rw-r--r--misc/inf-ruby.el (renamed from sample/inf-ruby.el)132
-rw-r--r--misc/ruby-mode.el (renamed from sample/ruby-mode.el)339
-rw-r--r--misc/rubydb2x.el (renamed from sample/rubydb2x.el)0
-rw-r--r--misc/rubydb3x.el (renamed from sample/rubydb3x.el)49
-rw-r--r--missing/alloca.c5
-rw-r--r--missing/dir.h137
-rw-r--r--missing/dup2.c69
-rw-r--r--missing/file.h33
-rw-r--r--missing/finite.c6
-rw-r--r--missing/flock.c74
-rw-r--r--missing/isinf.c44
-rw-r--r--missing/isnan.c29
-rw-r--r--missing/os2.c111
-rw-r--r--missing/setenv.c149
-rw-r--r--missing/strcasecmp.c1
-rw-r--r--missing/strdup.c25
-rw-r--r--missing/strftime.c31
-rw-r--r--missing/strncasecmp.c18
-rw-r--r--missing/strtod.c271
-rw-r--r--missing/vsnprintf.c1131
-rw-r--r--missing/x68.c2
-rw-r--r--mkconfig.rb109
-rw-r--r--node.h246
-rw-r--r--numeric.c1255
-rw-r--r--object.c1083
-rw-r--r--pack.c1281
-rw-r--r--parse.y2775
-rw-r--r--prec.c81
-rw-r--r--process.c583
-rw-r--r--random.c186
-rw-r--r--range.c362
-rw-r--r--re.c1133
-rw-r--r--re.h25
-rw-r--r--regex.c5737
-rw-r--r--regex.h286
-rw-r--r--ruby.1278
-rw-r--r--ruby.c816
-rw-r--r--ruby.h533
-rw-r--r--rubyio.h (renamed from io.h)35
-rw-r--r--rubysig.h88
-rw-r--r--rubytest.rb34
-rw-r--r--sample/README49
-rw-r--r--sample/biorhythm.rb59
-rw-r--r--sample/cal.rb111
-rw-r--r--sample/eval.rb4
-rw-r--r--sample/fib.pl19
-rw-r--r--sample/fib.scm2
-rw-r--r--sample/freq.rb13
-rw-r--r--sample/from.rb16
-rw-r--r--sample/goodfriday.rb8
-rw-r--r--sample/io.rb44
-rw-r--r--sample/irb.rb21
-rw-r--r--sample/list.rb16
-rw-r--r--sample/mine.rb175
-rw-r--r--sample/mkproto.rb10
-rw-r--r--sample/mpart.rb2
-rw-r--r--sample/mrshtest.rb1
-rw-r--r--sample/observ.rb15
-rw-r--r--sample/occur.rb8
-rw-r--r--sample/occur2.rb2
-rw-r--r--sample/philos.rb4
-rw-r--r--sample/rbc.rb1016
-rw-r--r--sample/rcs.rb10
-rw-r--r--sample/rename.rb297
-rw-r--r--sample/sieve.rb22
-rw-r--r--sample/svr.rb2
-rw-r--r--sample/test.rb878
-rw-r--r--sample/time.rb2
-rw-r--r--sample/tkbrowse.rb69
-rw-r--r--sample/trojan.rb7
-rw-r--r--sample/tsvr.rb9
-rw-r--r--sample/uumerge.rb4
-rw-r--r--sig.h55
-rw-r--r--signal.c310
-rw-r--r--sprintf.c560
-rw-r--r--st.c412
-rw-r--r--st.h22
-rw-r--r--string.c2581
-rw-r--r--struct.c513
-rw-r--r--time.c880
-rw-r--r--top.sed52
-rw-r--r--util.c639
-rw-r--r--util.h45
-rw-r--r--variable.c917
-rw-r--r--version.c29
-rw-r--r--version.h6
-rw-r--r--win32/Makefile241
-rw-r--r--win32/Makefile.sub280
-rw-r--r--win32/README.win32123
-rw-r--r--win32/config.h.in (renamed from win32/config.h)57
-rw-r--r--win32/config.status.in66
-rwxr-xr-xwin32/configure.bat13
-rw-r--r--win32/mkexports.rb30
-rwxr-xr-xwin32/ntsetup.bat10
-rw-r--r--win32/resource.rb94
-rw-r--r--win32/ruby.def424
-rw-r--r--win32/setup.mak27
-rw-r--r--win32/win32.c (renamed from missing/nt.c)1350
-rw-r--r--win32/win32.h (renamed from missing/nt.h)168
-rw-r--r--win32/winmain.c10
375 files changed, 82705 insertions, 33369 deletions
diff --git a/.cvsignore b/.cvsignore
index 2474526e2a..35fff17b58 100644
--- a/.cvsignore
+++ b/.cvsignore
@@ -1,18 +1,20 @@
+*.bak
+*.orig
+*.rej
+*.sav
+*~
+.cvsignore
Makefile
-parse.c
-newver.rb
-ruby
-miniruby
README.fat-patch
+archive
config.cache
config.h
config.log
config.status
-Makefile
+configure
+miniruby
+newver.rb
+parse.c
ppack
-archive
-*.orig
-*.rej
-*.bak
-*.sav
-*~
+rbconfig.rb
+ruby
diff --git a/COPYING b/COPYING
index 3c68f02bb4..eeb586b392 100644
--- a/COPYING
+++ b/COPYING
@@ -1,37 +1,40 @@
GNU GENERAL PUBLIC LICENSE
- Version 1, February 1989
+ Version 2, June 1991
- Copyright (C) 1989 Free Software Foundation, Inc.
- 675 Mass Ave, Cambridge, MA 02139, USA
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
- The license agreements of most software companies try to keep users
-at the mercy of those companies. By contrast, our General Public
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
-software--to make sure the software is free for all its users. The
-General Public License applies to the Free Software Foundation's
-software and to any other program whose authors commit to using it.
-You can use it for your programs, too.
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
When we speak of free software, we are referring to freedom, not
-price. Specifically, the General Public License is designed to make
-sure that you have the freedom to give away or sell copies of free
-software, that you receive source code or can get it if you want it,
-that you can change the software or use pieces of it in new free
-programs; and that you know you can do these things.
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
- For example, if you distribute copies of a such a program, whether
+ For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
-source code. And you must tell them their rights.
+source code. And you must show them these terms so they know their
+rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
@@ -44,120 +47,207 @@ want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
- 0. This License Agreement applies to any program or other work which
-contains a notice placed by the copyright holder saying it may be
-distributed under the terms of this General Public License. The
-"Program", below, refers to any such program or work, and a "work based
-on the Program" means either the Program or any work containing the
-Program or a portion of it, either verbatim or with modifications. Each
-licensee is addressed as "you".
-
- 1. You may copy and distribute verbatim copies of the Program's source
-code as you receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice and
-disclaimer of warranty; keep intact all the notices that refer to this
-General Public License and to the absence of any warranty; and give any
-other recipients of the Program a copy of this General Public License
-along with the Program. You may charge a fee for the physical act of
-transferring a copy.
-
- 2. You may modify your copy or copies of the Program or any portion of
-it, and copy and distribute such modifications under the terms of Paragraph
-1 above, provided that you also do the following:
-
- a) cause the modified files to carry prominent notices stating that
- you changed the files and the date of any change; and
-
- b) cause the whole of any work that you distribute or publish, that
- in whole or in part contains the Program or any part thereof, either
- with or without modifications, to be licensed at no charge to all
- third parties under the terms of this General Public License (except
- that you may choose to grant warranty protection to some or all
- third parties, at your option).
-
- c) If the modified program normally reads commands interactively when
- run, you must cause it, when started running for such interactive use
- in the simplest and most usual way, to print or display an
- announcement including an appropriate copyright notice and a notice
- that there is no warranty (or else, saying that you provide a
- warranty) and that users may redistribute the program under these
- conditions, and telling the user how to view a copy of this General
- Public License.
-
- d) You may charge a fee for the physical act of transferring a
- copy, and you may at your option offer warranty protection in
- exchange for a fee.
-
-Mere aggregation of another independent work with the Program (or its
-derivative) on a volume of a storage or distribution medium does not bring
-the other work under the scope of these terms.
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
- 3. You may copy and distribute the Program (or a portion or derivative of
-it, under Paragraph 2) in object code or executable form under the terms of
-Paragraphs 1 and 2 above provided that you also do one of the following:
-
- a) accompany it with the complete corresponding machine-readable
- source code, which must be distributed under the terms of
- Paragraphs 1 and 2 above; or,
-
- b) accompany it with a written offer, valid for at least three
- years, to give any third party free (except for a nominal charge
- for the cost of distribution) a complete machine-readable copy of the
- corresponding source code, to be distributed under the terms of
- Paragraphs 1 and 2 above; or,
-
- c) accompany it with the information you received as to where the
- corresponding source code may be obtained. (This alternative is
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
- received the program in object code or executable form alone.)
-
-Source code for a work means the preferred form of the work for making
-modifications to it. For an executable file, complete source code means
-all the source code for all modules it contains; but, as a special
-exception, it need not include source code for modules which are standard
-libraries that accompany the operating system on which the executable
-file runs, or for standard header files or definitions files that
-accompany that operating system.
-
- 4. You may not copy, modify, sublicense, distribute or transfer the
-Program except as expressly provided under this General Public License.
-Any attempt otherwise to copy, modify, sublicense, distribute or transfer
-the Program is void, and will automatically terminate your rights to use
-the Program under this License. However, parties who have received
-copies, or rights to use copies, from you under this General Public
-License will not have their licenses terminated so long as such parties
-remain in full compliance.
-
- 5. By copying, distributing or modifying the Program (or any work based
-on the Program) you indicate your acceptance of this license to do so,
-and all its terms and conditions.
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
-Program), the recipient automatically receives a license from the original
-licensor to copy, distribute or modify the Program subject to these
-terms and conditions. You may not impose any further restrictions on the
-recipients' exercise of the rights granted herein.
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
- 7. The Free Software Foundation may publish revised and/or new versions
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
-specifies a version number of the license which applies to it and "any
+specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
-the license, you may choose any version ever published by the Free Software
+this License, you may choose any version ever published by the Free Software
Foundation.
- 8. If you wish to incorporate parts of the Program into other free
+ 10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
@@ -167,7 +257,7 @@ of promoting the sharing and reuse of software generally.
NO WARRANTY
- 9. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
@@ -177,7 +267,7 @@ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
- 10. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
@@ -189,25 +279,24 @@ POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
- Appendix: How to Apply These Terms to Your New Programs
+ How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
-possible use to humanity, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these
-terms.
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
- To do so, attach the following notices to the program. It is safest to
-attach them to the start of each source file to most effectively convey
-the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -216,33 +305,36 @@ the exclusion of warranty; and each file should have at least the
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
- Gnomovision version 69, Copyright (C) 19xx name of author
+ Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
-The hypothetical commands `show w' and `show c' should show the
-appropriate parts of the General Public License. Of course, the
-commands you use may be called something other than `show w' and `show
-c'; they could even be mouse-clicks or menu items--whatever suits your
-program.
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. Here a sample; alter the names:
+necessary. Here is a sample; alter the names:
- Yoyodyne, Inc., hereby disclaims all copyright interest in the
- program `Gnomovision' (a program to direct compilers to make passes
- at assemblers) written by James Hacker.
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
-That's all there is to it!
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/ChangeLog b/ChangeLog
index 58d0b9cb05..2ba8c07285 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8774 @@
+Thu May 24 16:08:21 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * mkconfig.rb: autoconf 2.50 support.
+
+Thu May 24 14:23:35 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_yield_0): need argument adjustment for C defined
+ blocks too.
+
+Tue May 22 17:10:35 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * variable.c (rb_alias_variable): should not allow variable
+ aliasing if $SAFE >= 4.
+
+Mon May 21 15:26:05 JST 2001 Keiju Ishitsuka <keiju@ishitsuka.com>
+
+ * lib/irb/multi-irb.rb: delete japanese messages.
+
+Mon May 21 13:15:25 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big2str): t should be protected from GC.
+
+Sun May 20 00:28:43 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/socket/extconf.rb: do not clobber $CFLAGS when setting
+ -DSOCKS.
+
+Fri May 18 05:42:28 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/thread.rb: rescue ThreadError in case the thread is dead
+ just before calling Thread#run.
+
+Fri May 18 05:29:21 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/mkmf.rb (xsystem): make a temporary fix to get $(...) macros
+ properly expanded on a command execution.
+
+Fri May 18 03:49:55 2001 Brian F. Feldman <green@FreeBSD.org>
+
+ * lib/mkmf.rb: unbreak "make install". lib/* must be installed
+ under $rubylibdir, not under $libdir.
+
+Thu May 17 19:36:47 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/shell.rb, lib/shell/process-controller.rb,
+ lib/shell/command-processor.rb: translate Japanese comments into
+ English.
+
+ * doc/shell.rd.jp: RD'ify and make some fixes.
+
+ * doc/shell.rd: RD'ify, delete Japanese leftovers, make overall
+ English fixes, and sync with doc/shell.rd.jp.
+
+Thu May 17 19:34:11 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * doc/shell.rd*, lib/shell*: bring shell.rb 0.6 onto the ruby_1_6
+ branch.
+
+Thu May 17 17:35:04 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_call0): address of local_vars might change during eval.
+
+Thu May 17 07:30:15 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/md5/md5.txt, ext/md5/md5.txt.jp: s/SuperClass/Superclass/.
+
+Thu May 17 06:37:14 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/md5/md5.txt: make wording fixes.
+
+ * ext/md5/md5.txt.jp: ditto.
+
+Thu May 17 05:23:52 2001 Keiju Ishitsuka <keiju@ishitsuka.com>
+ * lib/irb.rb lib/irb/multi-irb.rb lib/irb/ruby-lex.rb lib/irb/version.rb
+ resolve ctrl-c problem
+
+Tue May 15 17:46:37 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_and): should not push frozen key string.
+
+ * array.c (rb_ary_or): ditto.
+
+Mon May 14 13:50:22 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_schedule): should save context before raising
+ deadlock, saved context for current thread might be obsolete.
+
+ * time.c (make_time_t): non DST timezone shift supported (hopefully).
+
+Mon May 14 11:54:20 2001 Tanaka Akira <akr@m17n.org>
+
+ * signal.c: SIGINFO added.
+
+Mon May 14 08:57:06 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_ensure): should not SEGV when prot_tag is NULL.
+
+Sun May 13 23:49:25 2001 Usaku Nakamura <usa@osb.att.ne.jp>
+
+ * win32/resource.rb: Modify copyright in resource script.
+
+Fri May 11 23:51:54 2001 Usaku Nakamura <usa@osb.att.ne.jp>
+
+ * process.c: silence VC++ warnings.
+
+ * sprintf.c: ditto.
+
+Fri May 11 03:38:11 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * README.EXT: Document find_library(), with_config() and
+ dir_config().
+
+Fri May 11 03:37:53 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * README.EXT.jp: Remove the description of find_header() because
+ such a function does not actually exist.
+
+ * README.EXT.jp: Update the description of dir_config().
+
+Fri May 11 02:42:40 2001 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * README, README.jp: Fix CVS access and mailing lists info.
+
+Fri May 11 02:00:44 2001 Ryo HAYASAKA <ryoh@jaist.ac.jp>
+
+ * bignum.c (bigdivrem): access boundary bug.
+
+Tue May 8 17:12:43 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * eval.c (is_defined): core dumped during instance_eval for
+ special constants.
+
+ * eval.c (rb_eval): ditto.
+
+Tue May 8 08:59:01 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * doc/forwardable.rd, doc/forwardable.rd.jp: Hit `=begin' and
+ `=end' in proper places so rd2 can format them without a problem.
+
+ * doc/irb/irb-tools.rd.jp, doc/irb/irb.rd, doc/irb/irb.rd.jp:
+ ditto.
+
+Tue May 8 08:56:05 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * doc/forwardable.rd, doc/forwardable.rd.jp, lib/forwardable.rb:
+ Bring forwardable 1.1 onto the ruby_1_6 branch.
+
+Tue May 8 08:35:09 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * doc/irb/irb-tools.rd.jp, doc/irb/irb.rd.jp: Convert from JIS to
+ EUC.
+
+Tue May 8 03:46:24 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * sample/rbc.rb: Obsoleted by IRB.
+
+Mon May 7 15:58:45 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (arg): "||=" should not warn for uninitialized instance
+ variables.
+
+ * eval.c (rb_eval): ditto.
+
+ * eval.c (eval): preserve and restore ruby_cref as well.
+
+Mon May 7 15:45:48 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/ftools.rb (syscopy): chmod destination file only if
+ it does not exist.
+
+Thu May 3 03:41:01 2001 SHIROYAMA Takayuki <psi@fortune.nest.or.jp>
+
+ * configure.in: get --enable-shared to work on MacOS X.
+
+ * Makefile.in: make $(LIBRUBY_SO) depend on miniruby properly.
+ Now `make -jN' should work without a problem.
+
+Wed May 2 20:39:35 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * dir.c (rb_glob, rb_iglob): remove unnecessary FNM_PATHNAME.
+
+Wed May 2 11:46:13 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * eval.c (block_pass): should not downgrade safe level.
+
+Tue May 1 17:55:58 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (yylex): lex_state after RESCUE_MOD should be EXPR_BEG.
+
+Tue May 1 03:36:50 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * sample/irb.rb, lib/irb.rb, lib/irb/*, doc/irb/*: Merge from irb
+ 0.7.3 and irb-tools 0.7.1.
+
+ * instruby.rb: Install help-message's too.
+
+ * lib/irb/main.rb: This file is not needed anymore.
+
+Thu Apr 26 22:36:11 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in: don't use tzname on cygwin 1.3.1+.
+
+ * configure.in: add -mieee/-ieee to CFLAGS on OSF1/Alpha
+ to disable "DIVISION BY ZERO" exception.
+
+Thu Apr 26 22:30:43 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): should preserve value of ruby_errinfo.
+
+Thu Apr 26 10:36:09 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_schedule): infinite sleep should not cause
+ dead lock.
+
+Wed Apr 25 16:40:44 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_flatten_bang): proper recursive detection.
+
+Wed Apr 25 15:36:15 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * eval.c (yield_under): need not to prohibit at safe level 4.
+
+Tue Apr 24 16:03:25 2001 Hiroshi Igarashi <iga@ruby-lang.org>
+
+ * ext/extmk.rb.in: add target `distclean' in Makefile for extlib.
+ target `clean' doesn't remove Makefile.
+
+Tue Apr 24 15:57:45 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/extmk.rb.in, lib/mkmf.rb: (dir_config) do not add the
+ specified include directory if already included in $CPPFLAGS.
+
+ * ext/extmk.rb.in, lib/mkmf.rb: (dir_config) return a more useful
+ value, [include_dir, lib_dir].
+
+Tue Apr 24 15:35:32 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.c (set_arg0): wrong predicate when new $0 value is bigger
+ than original space.
+
+Mon Apr 23 14:43:59 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (id2ref): should use NUM2ULONG()
+
+ * object.c (rb_mod_const_get): check whether name is a class
+ variable name.
+
+ * object.c (rb_mod_const_set): ditto.
+
+ * object.c (rb_mod_const_defined): ditto.
+
+Sun Apr 22 17:44:37 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in: add -mieee to CFLAGS on Linux/Alpha
+ to disable "DIVISION BY ZERO" exception.
+
+ * configure.in: remove -ansi on OSF/1.
+
+Sat Apr 21 22:33:26 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (w_float): precision changed to "%.16g"
+
+Sat Apr 21 22:07:58 2001 Guy Decoux <decoux@moulon.inra.fr>
+
+ * eval.c (rb_call0): wrong retry behavior.
+
+Fri Apr 20 19:12:20 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (fix_aref): a bug on long>int architecture.
+
+Fri Apr 20 14:57:15 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * eval.c (rb_eval_string_wrap): should restore ruby_wrapper.
+
+Wed Apr 18 04:37:51 2001 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/cgi.rb: CGI::Cookie: no use PATH_INFO.
+
+Wed Apr 18 00:24:40 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * regex.c (re_compile_pattern): char class at either edge of range
+ should be invalid.
+
+Tue Apr 17 16:54:39 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * eval.c (safe_getter): should use INT2NUM().
+
+Tue Apr 17 15:12:56 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big2long): 2**31 cannot fit in 31 bit long.
+
+Sat Apr 14 22:46:43 2001 Guy Decoux <decoux@moulon.inra.fr>
+
+ * regex.c (calculate_must_string): wrong length calculation.
+
+Sat Apr 14 13:33:32 2001 Usaku Nakamura <usa@osb.att.ne.jp>
+
+ * win32/config.status.in: no longer use missing/alloca.c.
+
+ * win32/Makefile.sub: ditto.
+
+Fri Apr 13 12:40:48 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * eval.c (rb_thread_start_0): fixed memory leak.
+
+Fri Apr 13 16:41:18 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (none): should clear cmdarg_stack too.
+
+Fri Apr 13 06:19:29 2001 GOTOU YUUZOU <gotoyuzo@notwork.org>
+
+ * io.c (rb_fopen): use setvbuf() to avoid recursive malloc() on
+ some platforms.
+
+Wed Apr 11 23:36:26 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * file.c (rb_stat_dev): device functions should honor stat field
+ types (except long long such as dev_t).
+
+Wed Apr 11 18:07:53 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * eval.c (rb_mod_nesting): should not push nil for nesting array.
+
+ * eval.c (rb_mod_s_constants): should not search array by
+ rb_mod_const_at() for nil (happens for singleton class).
+
+Wed Apr 11 13:29:26 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (rb_singleton_class_attached): should modify iv_tbl by
+ itself, no longer use rb_iv_set() to avoid freeze check error.
+
+ * variable.c (rb_const_get): error message "uninitialized constant
+ Foo at Bar::Baz" instead of "uninitialized constant Bar::Baz::Foo".
+
+Tue Apr 10 02:24:40 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * io.c (opt_i_set): should strdup() inplace_edit string.
+
+Mon Apr 9 23:29:54 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (exec_under): need to push cref too.
+
+Mon Apr 9 12:05:44 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * file.c (Init_File): should redifine "new" class method.
+
+Mon Apr 9 11:56:52 2001 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb: fix typo.
+
+Thu Apr 5 22:40:12 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_const_get): no recursion to show full class path
+ for modules.
+
+ * eval.c (rb_set_safe_level): should set safe level in curr_thread
+ as well.
+
+ * eval.c (safe_setter): ditto.
+
+Thu Apr 5 13:46:06 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * object.c (rb_obj_is_instance_of): nil belongs to false, not true.
+
+Thu Apr 5 02:19:03 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (make_time_t): proper (I hope) daylight saving time
+ handling for both US and Europe. I HATE SUMMER TIME!
+
+ * eval.c (rb_thread_wait_for): non blocked signal interrupt should
+ stop the interval.
+
+Wed Apr 4 03:47:03 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (rb_mod_clone): should copy method bodies too.
+
+ * bignum.c (bigdivrem): should trim trailing zero bdigits of
+ remainder, even if dd == 0.
+
+Tue Apr 3 15:29:10 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * Makefile.in: Introduce MAINLIBS.
+
+ * configure.in: Link libc_r against the ruby executable on
+ FreeBSD, which is the first attempt to work around a certain
+ problem regarding pthread on FreeBSD. It should make ruby/libruby
+ happy when it loads an extention to a library compiled and linked
+ with -pthread. Note, however, that libruby is _not_ linked with
+ libc_r so as not to mess up pthread unfriendly stuff including
+ apache+mod_ruby and vim6+ruby_interp.
+
+Tue Apr 3 09:56:20 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/extmk.rb.in (create_makefile): create def file only if
+ it does not yet exist.
+
+ * lib/mkmf.rb: ditto.
+
+Tue Apr 3 00:05:07 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (make_time_t): remove HAVE_TM_ZONE code since it
+ sometimes reports wrong time.
+
+ * time.c (make_time_t): remove unnecessary range check for
+ platforms where negative time_t is available.
+
+Mon Apr 2 14:25:49 2001 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/monitor.rb (wait): ensure reentrance.
+
+ * lib/monitor.rb (wait): fix timeout support.
+
+Mon Apr 2 12:44:53 2001 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb: backport from ruby-1.7.
+
+Mon Apr 2 01:16:24 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/win32.c: use ruby's opendir on mingw32.
+
+ * missing/dir.h, dir.c, Makefile: ditto.
+
+Sun Apr 1 23:26:14 2001 TOYOFUKU Chikanobu <toyofuku@juice.or.jp>
+
+ * numeric.c (flodivmod): a bug in no fmod case.
+
+Sun Apr 1 18:36:14 2001 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * process.c (pst_wifsignaled): should apply WIFSIGNALED for status
+ (int), not st (VALUE).
+
+Sat Mar 31 03:24:10 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (rb_include_module): module inclusion should be check
+ taints.
+
+Fri Mar 30 12:51:19 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (rb_include_module): freeze check at first.
+
+Thu Mar 29 17:05:09 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_attr): sprintf() and rb_intern() moved into
+ conditional body.
+
+Wed Mar 28 23:43:00 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * ext/extmk.rb.in, lib/mkmf.rb: add C++ rules in addition to C
+ rules for the mswin32 platforms.
+
+Wed Mar 28 19:29:21 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/extmk.rb.in, lib/mkmf.rb: move C++ rules to the right place.
+
+Wed Mar 28 17:39:04 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_str2cstr): warn if string contains \0 and length
+ value is ignored.
+
+Wed Mar 28 15:00:31 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * class.c (rb_singleton_class_clone): should copy class constant
+ table as well.
+
+Wed Mar 28 15:03:23 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * class.c (rb_include_module): sometimes cache was mistakenly left
+ uncleared - based on the patch by K.Kosako.
+
+Wed Mar 28 09:52:33 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/Makefile.sub: disable global optimization.
+
+Tue Mar 27 15:00:54 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * eval.c (rb_mod_define_method): should have clear method cache.
+
+ * eval.c (rb_mod_define_method): should have raised exception for
+ type error.
+
+Tue Mar 27 14:48:17 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.h: changed "extern INLINE" to "static inline".
+
+Mon Mar 26 23:19:33 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * time.c (rb_strftime): check whether strftime returns empty string.
+
+Mon Mar 26 18:14:47 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (rb_glob_helper): part of 1.7 globber backported to proper
+ following of symlinks.
+
+Mon Mar 26 17:21:07 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c: remove TMP_PROTECT_END to prevent C_ALLOCA crash.
+
+Mon Mar 26 14:04:41 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/Win32API/Win32API.c: remove Init_win32api().
+
+Sat Mar 24 23:44:50 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (ev_const_defined): should ignore toplevel cbase (Object).
+
+ * eval.c (ev_const_get): ditto.
+
+Fri Mar 23 12:18:44 2001 SHIROYAMA Takayuki <psi@fortune.nest.or.jp>
+
+ * ext/curses/curses.c: curses on Mac OS X public beta does not
+ have _maxx etc.
+
+Fri Mar 23 10:50:31 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (w_object): should truncate trailing zero short for
+ bignums.
+
+Thu Mar 22 22:15:45 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/Win32API/extconf.rb: add -fno-omit-frame-pointer.
+
+Thu Mar 22 17:43:44 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.h: better inline function support.
+
+ * configure.in (NO_C_INLINE): check if inline is available for the
+ C compiler.
+
+Wed Mar 21 23:07:45 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/win32.c (win32_stat): WinNT/2k "//host/share" support.
+
+Wed Mar 21 01:26:14 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (id2ref): sometimes confused symbol and reference.
+
+Tue Mar 20 23:09:33 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/win32.c (win32_stat): UNC support.
+
+ * dir.c (extract_path): fix "./*" problem.
+
+Mon Mar 19 19:14:47 2001 Guy Decoux <decoux@moulon.inra.fr>
+
+ * marshal.c (shortlen): shortlen should return number of bytes
+ written.
+
+Mon Mar 19 18:56:55 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * stable version 1.6.3 released.
+
+Mon Mar 19 16:52:23 2001 K.Kosako <kosako@sofnec.co.jp>
+
+ * eval.c (ev_const_defined): need not to check if cbase->nd_class
+ is rb_cObject.
+
+ * eval.c (ev_const_get): ditto.
+
+Mon Mar 19 16:27:32 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (THREAD_ALLOC): flags should be initialized.
+
+ * signal.c (rb_f_kill): should use FIX2INT, not FIX2UINT.
+
+Mon Mar 19 11:03:10 2001 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * marshal.c (r_object): len calculation patch was wrong for
+ machines SIZEOF_BDIGITS == SIZEOF_SHORT.
+
+ * gc.c: alloca prototype reorganized for C_ALLOCA machine.
+
+Sun Mar 18 08:58:18 2001 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/cgi.rb: // === '' --> //.match('')
+
+ * lib/cgi.rb: cgi#header(): improvement for mod_ruby.
+
+ * lib/cgi.rb: cgi#rfc1123date(): improvement.
+ thanks to TADA Tadashi <sho@spc.gr.jp>.
+
+ * lib/cgi.rb: cgi#rfc1123date(): document bug fix.
+ thanks to Kazuhiro NISHIYAMA <zn@mbf.nifty.com>.
+
+ * lib/cgi.rb: cgi#header(): bug fix.
+ thanks to IWATSUKI Hiroyuki <don@na.rim.or.jp>.
+
+Fri Mar 16 17:21:25 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * configure.in: Set SOLIBS properly for all ELF and
+ FreeBSD/NetBSD/OpenBSD a.out platforms so that the shlib
+ dependencies are recorded in the libruby shlib.
+
+Wed Mar 14 16:41:45 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_schedule): raise FATAL just once to
+ THREAD_TO_KILL.
+
+Wed Mar 14 10:41:34 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_yield_0): 0 (= Qfalse) is a valid value, so that
+ default self should be checked by klass == 0.
+
+ * bignum.c (rb_cstr2inum): should disallow '++1', '+-1', etc.
+
+Tue Mar 13 17:51:09 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (ev_const_defined): add new parameter self for special
+ const fallback.
+
+ * eval.c (ev_const_get): ditto.
+
+Tue Mar 13 16:39:45 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * dir.c (rb_glob_helper): fix drive letter handling on DOSISH.
+
+Tue Mar 13 15:01:12 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/http.rb: add HTTPRequest#basic_auth.
+
+ * lib/net/smtp.rb: raise if only account or password is given.
+
+ * lib/net/protocol.rb: WriteAdapter#<< returns self.
+
+Tue Mar 13 14:41:16 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (argf_seek): wrong calling sequence of rb_io_seek().
+
+Mon Mar 12 18:59:38 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/mkmf.rb (create_makefile): save/restore $libs and $LIBPATH.
+
+Sun Mar 11 00:55:31 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/mkmf.rb (install_rb): fix handling of destination path.
+
+Sat Mar 10 02:34:18 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * math.c (math_log, math_log10): use nan() instead of 0.0/0.0 on Cygwin.
+
+Thu Mar 8 17:43:59 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb: one write(2) per one line.
+
+Wed Mar 7 14:26:11 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * math.c (math_log, math_log10): should return NaN if x < 0.0
+ on Cygwin.
+
+Thu Mar 7 10:31:26 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * parse.y (stmt): while/until modifier must work for empty body.
+
+Tue Mar 6 22:53:58 2001 Kazuhiro Yoshida <moriq.kazuhiro@nifty.ne.jp>
+
+ * ruby.c (ruby_set_argv): clear ARGV contents before adding args.
+
+Tue Mar 6 10:50:29 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (primary): rescue and ensure clauses should be allowed
+ to appear in singleton method body.
+
+Mon Mar 5 17:25:13 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (proc_eq): compare Procs using blocktag equality.
+
+ * eval.c (proc_to_s): stringify according to block tag address.
+
+Mon Mar 5 17:19:56 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/win32.c (gettimeofday): use GetLocalTime() instead of ftime()
+ for high-resolution timing.
+
+Sun Mar 4 20:45:20 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * ext/extmk.rb.in, lib/mkmf.rb: add C++ rules in addition to C
+ rules.
+
+Sun Mar 4 17:01:09 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * string.c (trnext): support backslash escape in String#tr.
+
+Wed Feb 28 11:02:41 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_delete_bang): delete! should take at least 1
+ argument.
+
+Tue Feb 27 16:38:15 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (ev_const_get): retrieve Object's caonstat if no current
+ class is available (e.g. defining singleton class for Fixnums).
+
+ * eval.c (ev_const_defined): check Object's constant if no current
+ class is available (e.g. defining singleton class for Fixnums).
+
+ * eval.c (proc_call): ignore block to `call' always, despite of
+ being orphan or not.
+
+Wed Feb 27 10:16:32 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * eval.c (rb_yield_0): should check based on rb_block_given_p()
+ and rb_f_block_given_p().
+
+Mon Feb 26 16:20:27 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.c (proc_options): call ruby_show_version() just once.
+
+Mon Feb 26 00:04:52 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (proc_call): should not modify ruby_block->frame.iter
+ based on ruby_frame->iter altered by PUSH_ITER().
+
+Mon Feb 26 05:27:52 2001 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/net/telnet.rb: #telnetmode(), #binmode(): bug fix.
+ thanks to nobu.nakada@nifty.ne.jp.
+
+Mon Feb 26 04:55:50 2001 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/cgi.rb: CGI#form(): bug fix.
+ thanks to MoonWolf <moonwolf@moonwolf.com>.
+
+ * lib/cgi.rb: CGI#rfc1123_date(): improvement.
+ thanks to Tomoyasu Akita <genzo-@dm4lab.to>.
+
+ * lib/cgi.rb: CGI#header(): improvement for mod_ruby.
+ thanks to Shugo Maeda <shugo@ruby-lang.org>.
+
+Sun Feb 25 02:45:30 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * file.c (rb_file_s_rename): avoid Cygwin's bug.
+
+Sat Feb 24 23:32:55 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_fd_close): should save current context before
+ raising exception.
+
+Sat Feb 24 22:14:00 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/win32.c (myrename): fix error handling.
+
+Sat Feb 24 15:43:31 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb: use net 1.2 for also ruby 1.6 branch.
+
+ * lib/net/smtp.rb: ditto.
+
+ * lib/net/pop.rb: ditto.
+
+ * lib/net/http.rb: ditto.
+
+Fri Feb 23 16:36:09 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/http.rb: always close connection if body is not exist.
+
+Fri Feb 23 13:27:05 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/http.rb: keep-alive detection was incomplete.
+
+Fri Feb 23 08:24:53 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb: clear read buffer after reopen.
+
+ * lib/net/http.rb: update RD document.
+
+Tue Feb 20 16:37:58 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big2long): should not raise RangeError for Bignum
+ LONG_MIN value.
+
+Mon Feb 19 17:46:37 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_substr): "a"[1,2] should return ""; need
+ rubicon upgrade.
+
+Mon Feb 19 01:55:43 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (secure_visibility): visibility check for untainted modules.
+
+Mon Feb 19 00:29:29 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * signal.c (sigpipe): sighandler which does nothing.
+
+ * signal.c (trap): set sigpipe function for SIGPIPE.
+
+ * signal.c (Init_signal): default SIGPIPE handler should be
+ sigpipe function.
+
+Sun Feb 18 15:42:38 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/curses/extconf.rb: add dir_config.
+
+ * missing/flock.c: use fcntl(2) instead of lockf(2).
+
+Sun Feb 18 13:02:03 2001 Yasushi Shoji <yashi@yashi.com>
+
+ * array.c (rb_ary_subseq): wrong boundary check.
+
+Fri Feb 16 01:44:56 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (set_outfile): f should be the FILE* from the assigning value.
+
+Thu Feb 15 11:33:49 2001 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/cgi/session.rb (close): fixed reversed condition.
+
+Wed Feb 14 17:28:24 2001 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb: supports unknown resp_text_code.
+
+Wed Feb 14 00:44:17 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * dir.c (dir_s_glob): call rb_yield directly (via push_pattern) if
+ block is given to the method.
+
+ * dir.c (push_pattern): do not call rb_ary_push; yield directly.
+
+Tue Feb 13 23:05:38 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * dir.c (lstat): should use rb_sys_stat if lstat(2) is not
+ available.
+
+Tue Feb 13 17:00:18 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/http.rb: supports HTTP 1.0 server.
+
+Tue Feb 13 01:13:43 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (primary): preserve and clear in_single and in_def using
+ stack to prevent nested method errors in singleton class bodies.
+
+Sun Feb 11 16:00:30 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * eval.c (stack_length): use __builtin_frame_address() only if
+ GCC and i386 CPU.
+
+ * gc.c (rb_gc, Init_stack): ditto.
+
+ * configure.in: add ac_cv_func_getpgrp_void=yes on DJGPP.
+
+Sat Feb 10 23:43:49 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * hash.c (rb_any_hash): dumped core on machines sizeof(int) != sizeof(long).
+
+Sat Feb 10 23:07:15 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * regex.c (PREV_IS_A_LETTER): should not treat c>0x7f as a word
+ character if -Kn.
+
+Sat Feb 10 00:06:28 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * win32/win32.c (win32_stat): replace stat for enable when pathname
+ ends with '/' or '\' for mswin32 on Win9X / Win2k.
+
+ * win32/win32.h: ditto.
+
+ * ruby.h: ditto.
+
+ * dir.c (rb_glob_helper): ditto.
+
+ * file.c (rb_stat, rb_file_s_stat, eaccess, check3rdbyte): ditto.
+
+Fri Feb 9 22:54:57 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ruby.c (ruby_init_loadpath): convert '\\' to '/'
+ before finding executable file path.
+
+Fri Feb 9 17:41:53 2001 Triet H. Lai <thlai@mail.usyd.edu.au>
+
+ * dir.c (rb_glob_helper): do not follow symbolic links.
+
+Fri Feb 8 23:53:08 2001 Usaku Nakamura <usa@osb.att.ne.jp>
+
+ * win32/config.h.in (inline): add inline definition.
+
+Thu Feb 8 21:27:24 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/mkmf.rb (install_rb): fix handling of relative path.
+
+ * lib/mkmf.rb (create_makefile): add srcdir.
+
+Wed Feb 7 16:05:22 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * parse.y (parse_quotedwords): %w should allow parenthesis escape.
+
+Wed Feb 7 00:57:42 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (parse_qstring): %q should allow terminator escape.
+
+Wed Feb 7 00:57:42 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * re.c (rb_reg_equal): all option flags should be same to be equal.
+
+Tue Feb 6 21:01:29 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb: ignore EOFError on only specified case.
+
+ * lib/net/http.rb: take HTTP 1.0 server into account.
+
+Mon Feb 5 00:39:06 2001 KANEKO Naoshi <wbs01621@mail.wbs.ne.jp>
+
+ * dir.c: use ISXXX() instead of isxxx().
+
+ * dln.c (aix_loaderror): ditto.
+
+ * file.c (rb_file_s_expand_path): ditto.
+
+ * string.c (rb_str_upcase_bang): ditto.
+
+ * win32/win32.c (do_spawn): ditto.
+
+ * win32/win32.c (NtMakeCmdVector): ditto.
+
+ * win32/win32.c (opendir): ditto.
+
+Fri Feb 3 00:48:50 2001 Usaku Nakamura <usa@osb.att.ne.jp>
+
+ * win32/win32.c (isInternalCmd): ignore case for shell's internal
+ command. (marge from HEAD)
+
+Fri Feb 2 16:14:51 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (POP_VARS): propagate DVAR_DONT_RECYCLE, if
+ SCOPE_DONT_RECYCLE of ruby_scope is set.
+
+Wed Jan 31 22:27:29 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in: gcc-2.95.2-7(cygwin) support.
+ add -mwin32 if available.
+
+ * cygwin/GNUmakefile: ditto.
+
+Mon Jan 29 17:36:19 2001 TOYOFUKU Chikanobu <toyofuku@juice.or.jp>
+
+ * eval.c (rb_eval): nd_iter evaluation should be wrapped by
+ BEGIN_CALLARGS and END_CALLARGS.
+
+Mon Jan 29 01:40:27 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (str_independent): should not clear str->orig here.
+ it's too early.
+
+Wed Jan 24 01:45:49 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (POP_BLOCK_TAG): call rb_gc_force_recycle() if block has
+ not been objectified.
+
+ * eval.c (rb_callcc): should nail down block->tag history to avoid
+ rb_gc_force_recycle().
+
+Tue Jan 23 18:51:57 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (rb_gc_call_finalizer_at_exit): should finalize objects in
+ deferred_final_list too.
+
+Tue Jan 23 16:10:12 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (os_live_obj): do not list terminated object.
+
+ * gc.c (os_obj_of): ditto.
+
+ * gc.c (rb_gc_mark): support new T_BLKTAG tag.
+
+ * gc.c (obj_free): ditto.
+
+ * eval.c (new_blktag): creation of new block tag, which holds
+ destination of global jump and orphan status.
+
+ * eval.c (block_pass): break from orphan Proc object will raise a
+ LocalJumpError exception.
+
+Mon Jan 22 16:33:16 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * mkconfig.rb: autoconf 2.49 support.
+
+Sat Jan 20 03:54:00 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (yylex): fixed serious syntax misbehavior. do's
+ preceding was too high. a block in `foo bar do .. end' should
+ be passed to `foo', not `bar'.
+
+ * parse.y (block_call): syntax restructure.
+
+Fri Jan 19 04:04:31 2001 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/irb/ruby-lex.rb: Merge from HEAD: rev.1.4
+
+Wed Jan 17 13:28:26 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in: remove DEFS definition.
+
+ * mkconfig.rb: ditto.
+
+ * win32/config.status.in: ditto.
+
+Tue Jan 16 16:59:14 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb: ignore EOFError for read
+
+Sun Jan 14 21:49:28 2001 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * sprintf.c (rb_f_sprintf): simple typo. binary base should be 2,
+ not '2'.
+
+Sun Jan 14 02:49:57 2001 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb (adding): too few "yield" in case of arg is
+ not String/File.
+
+Sat Jan 13 19:18:18 2001 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * re.c (rb_reg_desc): separate RE_OPTION_MULTILINE
+
+ * re.c (rb_reg_options): add RE_OPTION_{POSIXLINE,RE_OPTION_MULTILINE,
+ RE_OPTION_EXTENDED}
+
+Thu Jan 11 06:45:55 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_mod_dup): should propagate FL_SINGLETON.
+
+ * object.c (inspect_obj): handles the case of no instance variable.
+
+Wed Jan 10 01:50:45 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_reverse_bang): forgot to call rb_str_modify().
+
+Tue Jan 9 17:41:40 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_obj_taint): check frozen status before modifying
+ taint status.
+
+ * object.c (rb_obj_untaint): ditto.
+
+Mon Jan 8 21:35:10 2001 Guy Decoux <decoux@moulon.inra.fr>
+
+ * file.c (path_check_1): should restore modified path.
+
+Mon Jan 8 21:24:37 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (bigdivrem): t2 might be too big for signed long; do
+ not use rb_int2big(), but rb_uint2big().
+
+Mon Jan 8 03:09:58 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * error.c (rb_load_fail): new func to report LoadError.
+
+ * ruby.c (load_file): use rb_load_fail.
+
+Sat Jan 6 00:55:59 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * pack.c (pack_pack): template "m2" or "u2" caused inifinite loop.
+
+Fri Jan 5 01:02:17 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (ruby_finalize): should enclosed by PUSH_TAG/POP_TAG.
+
+Sun Dec 31 01:39:16 2000 Guy Decoux <decoux@moulon.inra.fr>
+
+ * eval.c (rb_mod_define_method): wrong comparison for blocks.
+
+Sat Dec 30 19:28:50 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (id2ref): should handle Symbol too.
+
+ * gc.c (id2ref): should print original ptr value
+
+Sat Dec 30 03:14:22 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_iterate): NODE_CFUNC does not protect its data
+ (nd_tval), so create new node NODE_IFUNC for iteration C
+ function.
+
+ * eval.c (rb_yield_0): use NODE_IFUNC.
+
+ * gc.c (rb_gc_mark): support NODE_IFUNC.
+
+Fri Dec 29 11:41:55 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (mem_error): prohibit recursive mem_error().
+ (ruby-bugs-ja:PR#36)
+
+Fri Dec 29 11:05:41 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_fd_writable): should not switch context if
+ rb_thread_critical is set.
+
+ * eval.c (rb_thread_wait_fd): ditto.
+
+ * eval.c (rb_thread_wait_for): ditto.
+
+ * eval.c (rb_thread_select): ditto.
+
+ * eval.c (rb_thread_join): join during critical section causes
+ deadlock.
+
+Tue Dec 26 18:46:41 2000 NAKAMURA Hiroshi <nakahiro@sarion.co.jp>
+
+ * lib/debug.rb: Avoid thread deadlock in debugging stopped thread.
+
+ * lib/debug.rb: Uncleared 'finish' state.
+
+Tue Dec 26 16:53:55 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_yield_0): remove dvar node by rb_gc_force_recycle()
+ more eagerly.
+
+ * eval.c (rb_f_binding): recycling should be stopped for outer
+ scope too.
+
+ * eval.c (proc_new): ditto.
+
+Tue Dec 26 15:45:35 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_inspect): should treat multibyte chracters
+ properly.
+
+Mon Dec 25 17:49:08 2000 K.Kosako <kosako@sofnec.co.jp>
+
+ * string.c (rb_str_replace_m): unexpected string share happens if
+ replace is done for associated (STR_NO_ORIG) string.
+
+Tue Dec 26 15:01:53 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_f_p): should not call rb_io_flush() if rb_defout is not
+ a IO (T_FILE).
+
+Mon Dec 25 15:52:39 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * stable version 1.6.2 released.
+
+Mon Dec 25 05:11:04 2000 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/cgi.rb: version 2.1.2 (some bug fixes).
+
+ * lib/cgi.rb: Regexp::last_match[1] --> $1
+
+ * lib/net/telnet.rb: ditto.
+
+Mon Dec 25 04:43:02 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/http.rb: does not send HEAD on closing socket.
+
+Mon Dec 25 00:44:48 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * hash.c (rb_any_cmp): should use rb_str_cmp() if TYPE == T_STRING
+ and CLASS_OF == rb_cString.
+
+ * string.c (rb_str_new4): should copy class of original too.
+
+Mon Dec 25 00:04:54 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * eval.c (rb_thread_schedule): initial value of `max' changed to -1.
+
+Mon Dec 25 00:16:14 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_replace_m): copy-on-write replace.
+
+ * parse.y (yylex): should handle => after identifier as well as ==
+ and =~.
+
+Sat Dec 23 23:55:57 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_cstr2inum): Integer("") should not return 0.
+
+Sat Dec 23 11:55:57 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_and): Array#& should preverve original order.
+
+Sat Dec 23 03:44:16 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb: set @closed false in Socket#reopen.
+
+ * lib/net/pop.rb: add POP3.foreach, delete_all.
+
+ * lib/net/pop.rb: add POP3#delete_all.
+
+ * lib/net/http.rb: add HTTP.version_1_1, version_1_2
+
+ * lib/net/http.rb: refactoring.
+
+Fri Dec 22 23:11:12 2000 Ueno Katsuhiro <unnie@blue.sky.or.jp>
+
+ * eval.c (rb_feature_p): ext might be null.
+
+Fri Dec 22 17:04:12 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * win32/win32.c (myselect): avoid busy loop by adjusting fd_count.
+
+Fri Dec 22 15:07:55 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_cstr2inum): prefix like '0x' had removed too much.
+
+Thu Dec 21 13:01:46 2000 Tanaka Akira <akr@m17n.org>
+
+ * lib/net/ftp.rb (makeport): don't use TCPsocket.getaddress.
+
+Wed Dec 20 12:00:15 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big_lshift): should cast up to BDIGIT_DBL.
+
+ * parse.y (yylex): disallow trailing '_' for numeric litrals.
+
+ * bignum.c (rb_cstr2inum): allow `_' within converting string.
+
+ * eval.c (specific_eval): should take no argument if block is
+ supplied.
+
+Tue Dec 19 13:44:50 2000 K.Kosako <kosako@sofnec.co.jp>
+
+ * io.c (rb_f_p): should flush rb_defout, not stdout.
+
+Tue Dec 19 00:57:10 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (time_minus): usec might overflow. (ruby-bugs-ja:PR#35)
+
+ * eval.c (rb_obj_extend): Object#extend should take at least one
+ argument.
+
+ * parse.y (mrhs_basic): should check value_expr($3), not $1.
+
+Mon Dec 18 23:18:39 2000 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * util.c (mblen, __crt0_glob_function): add for multibyte
+ on DJGPP 2.03.
+
+Mon Dec 18 18:10:30 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (time_plus): usec might underflow (ruby-bugs-ja:#PR33).
+
+Mon Dec 18 08:11:20 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * hash.c (rb_hash_set_default): should call rb_hash_modify().
+
+Sat Dec 16 02:58:26 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * eval.c (rb_eval): should clear ruby_errinfo on retry.
+
+ * eval.c (rb_rescue2): ditto.
+
+Thu Dec 14 13:06:18 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * class.c (rb_include_module): prohibit fronzen class/module.
+
+ * eval.c (rb_frozen_class_p): make external.
+
+ * intern.h (rb_frozen_class_p): prototyped.
+
+ * intern.h (rb_undef): prototyped not but rb_undef_method()
+ which is also in ruby.h.
+
+Thu Dec 14 09:20:26 2000 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/cgi.rb: support -T1 on ruby 1.6.2
+
+ * lib/cgi.rb: $1 --> Regexp::last_match[1]
+
+ * lib/net/telnet.rb: ditto.
+
+Wed Dec 13 23:27:06 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): handles case statement without expr, which
+ looks for any TRUE (non nil, non false) when expression.
+
+ * parse.y (primary): case expression should not be compstmt, but
+ mere expr.
+
+ * parse.y (primary): case without following expression is now
+ separated rule.
+
+Wed Dec 13 12:41:27 2000 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ruby.c (proc_options): accept "--^M" for DOS line endings.
+
+Tue Dec 12 15:45:42 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (newline_node): cancel newline unification.
+
+Mon Dec 11 23:01:57 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (yylex): supports cases `?' precedes EOF and newline.
+
+Mon Dec 11 12:11:25 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (call_end_proc): some frame members were left
+ uninitialized.
+
+Mon Dec 11 01:14:58 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_fptr_finalize): do not fclose stdin, stdout and
+ stderr at exit.
+
+Sat Dec 9 17:34:48 2000 Tachino Nobuhiro <tachino@open.nm.fujitsu.co.jp>
+
+ * time.c (time_cmp): should check with kind_of?, not instance_of?
+
+ * time.c (time_eql): ditto.
+
+ * time.c (time_minus): ditto.
+
+Fri Dec 8 17:23:25 2000 Tachino Nobuhiro <tachino@open.nm.fujitsu.co.jp>
+
+ * sprintf.c (rb_f_sprintf): proper string precision treat.
+
+Fri Dec 8 10:44:05 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_mod_remove_cvar): Module#remove_class_variable
+ added.
+
+Thu Dec 7 17:35:51 2000 Shugo Maeda <shugo@ruby-lang.org>
+
+ * eval.c (stack_length): don't use __builtin_frame_address() on alpha.
+
+Wed Dec 6 18:07:13 2000 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * djgpp/config.sed, win32/Makefile.sub: typo.
+
+ * eval.c (rb_mod_define_method): avoid VC4.0 warnings.
+
+Wed Dec 6 13:38:08 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_and): tuning, make hash from shorter operand.
+
+Wed Dec 6 01:28:50 2000 SHIROYAMA Takayuki <psi@fortune.nest.or.jp>
+
+ * gc.c (rb_gc): __builtin_frame_address() should not be used on
+ MacOS X.
+
+ * gc.c (Init_stack): ditto.
+
+Mon Dec 4 13:44:01 2000 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * lib/jcode.rb: consider multibyte. not /n.
+
+Mon Dec 4 09:49:36 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_inspect): output whole string contents. no more `...'
+
+ * string.c (rb_str_dump): should propagate taintness.
+
+ * hash.c (env_inspect): hash like human readable output.
+
+ * variable.c (rb_ivar_get): prohibiting instance variable access
+ is too much restriction.
+
+ * class.c (method_list): retrieving information should not be
+ restricted where $SAFE=4.
+
+ * class.c (rb_obj_singleton_methods): ditto.
+
+ * eval.c (rb_thread_priority): ditto.
+
+ * eval.c (rb_thread_local_aref): ditto.
+
+ * variable.c (rb_obj_instance_variables): ditto.
+
+ * variable.c (rb_mod_const_at): ditto.
+
+ * variable.c (rb_mod_class_variables): ditto.
+
+ * eval.c (rb_exec_end_proc): end_proc should be preserved.
+
+Sat Dec 2 22:32:43 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_yield_0): || should accept exactly zero argument.
+
+ * parse.y (stmt): multiple right hand side for single assignment
+ (e.g. a = 1,2) is allowed.
+
+Wed Nov 29 07:55:29 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (w_long): dumping long should be smaller than 32bit max.
+
+ * marshal.c (w_long): shorter long format for small integers(-123..122).
+
+ * marshal.c (r_long): ditto.
+
+Tue Nov 28 18:10:51 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_mod_define_method): quick hack to implement
+ on-the-fly method definition. experimental.
+
+Mon Nov 27 17:00:35 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): should not redefine builtin classes/modules
+ from within wrapped load.
+
+Mon Nov 27 08:57:33 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (call_end_proc): should be isolated from outer block.
+
+Mon Nov 27 00:10:08 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_ctl): call ioctl/fcntl for fptr->f2 too.
+
+ * process.c (rb_f_fork): call rb_thread_atfork() after creating
+ child process.
+
+ * eval.c (rb_thread_atfork): kill all other threads immediately,
+ then turn the current thread into the main thread.
+
+Sat Nov 25 23:12:22 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (ruby_run): move calling point of rb_trap_exit after
+ cleaning up threads.
+
+ * eval.c (ruby_finalize): new function to call EXIT trap, END
+ procs and GC finalizers.
+
+ * eval.c (rb_exec_end_proc): prevent recursion.
+
+ * gc.c (rb_gc_call_finalizer_at_exit): ditto.
+
+ * signal.c (rb_trap_exit): ditto. made static.
+
+ * process.c (rb_f_fork): should swallow all exceptions from block
+ execution.
+
+ * process.c (fork_rescue): should call ruby_finalize().
+
+ * parse.y (yycompile): rb_gc() removed. I don't remember why I put
+ this here. test code?
+
+Fri Nov 24 22:03:48 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * range.c (EXCL): exclusive infomation is now stored in an
+ instance variable. this enables proper marshal dump.
+
+ * process.c (proc_waitpid): should clear rb_last_status ($?) if
+ no pid was given by waitpid(2).
+
+Thu Nov 23 01:35:38 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * process.c (proc_waitpid2): returns nil if no pid found.
+
+Wed Nov 22 23:45:15 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * range.c (range_eq): new method. Compares start and end of range
+ respectively.
+
+Wed Nov 22 11:01:32 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_mod_class_variables): should honor singleton
+ class variable rule defined yesterday.
+
+Tue Nov 21 23:24:14 2000 Mitsuteru S Nakao <nakao@kuicr.kyoto-u.ac.jp>
+
+ * numeric.c (flodivmod): missing second operand (typo).
+
+Tue Nov 21 03:39:41 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (marshal_load): marshal format compatibility check
+ revised. greater minor revision is UPWARD compatibile;
+ downward compatibility is not assured.
+
+ * eval.c (is_defined): clarify class variable behavior for
+ singleton classes. class variables within singleton class
+ should be treated like within singleton method.
+
+Mon Nov 20 13:45:21 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): set ruby_sourceline before evaluating
+ exceptions.
+
+ * gc.c (gc_sweep): defer finalization in GC during compilation or
+ interrupt prohibit section.
+
+ * gc.c (gc_sweep): mark all nodes before sweeping if GC happened
+ during compilation.
+
+ * eval.c (rb_eval): should treat class variables specially in a
+ method defined in the singleton class.
+
+Mon Nov 20 10:20:21 2000 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * dir.c, win32/win32.c, ruby.h: add rb_iglob().
+
+Mon Nov 20 00:18:16 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_subseq): should return nil for outbound start
+ index.
+
+ * marshal.c (marshal_load): show format versions explicitly when
+ format version mismatch happens.
+
+Sun Nov 19 06:13:24 2000 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * marshal.c: use long for string/array length.
+
+ * pack.c (swaps): use bit-or(|) instead of plus(+).
+
+ * pack.c (swapl): ditto.
+
+Sat Nov 18 15:18:16 2000 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * array.c (rb_ary_replace): array size should be in long.
+
+ * array.c (rb_ary_concat): ditto.
+
+ * array.c (rb_ary_hash): ditto.
+
+Sat Nov 18 14:07:20 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/http.rb: Socket#readline() reads until "\n", not "\r\n"
+
+Fri Nov 17 14:55:18 2000 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * string.c (rb_str_succ): output should be NUL terminated.
+
+Fri Nov 17 02:54:15 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_close): need not to flush before closing.
+
+ * eval.c (rb_thread_join): should preserve last thread status when
+ THREAD_TO_KILL.
+
+ * eval.c (rb_thread_stop): ditto.
+
+ * io.c (io_fflush): wrap fflush by TRAP_BEG, TRAP_END.
+
+ * eval.c (rb_eval): method defined within singleton class
+ definition should behave like singleton method about class
+ variables.
+
+ * eval.c (is_defined): ditto.
+
+Thu Nov 16 23:06:07 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/http.rb: can call {old,new}_implementation any times.
+
+ * lib/net/http.rb: HTTP#connecting, receive ->
+ common_oper, connecting.
+
+ * lib/net/http.rb: output warning if u_header includes
+ duplicated header.
+
+ * lib/net/http.rb: not check Connection:/Proxy-Connection;
+ always read until eof.
+
+ * lib/net/protocol.rb: detects and catches "break" from block.
+
+Thu Nov 16 16:32:45 2000 Masahiro Tanaka <masa@stars.gsfc.nasa.gov>
+
+ * bignum.c (bigdivrem): should have incremented ny first.
+
+Thu Nov 16 14:58:00 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * ext/socket/socket.c (sock_new): duplicates file descriptor
+ with myfddup() on mswin32/mingw32.
+
+ * win32/win32.h: uses system original fdopen().
+
+ * win32/win32.c (myfddup): newly added instead of myfdopen().
+
+ * win32/win32.c (mybind, myconnect, mygetsockname, mygetsockopt,
+ mylisten, mysetsockopt): now accept file descriptor only, not
+ SOCKET.
+
+ * win32/win32.c (myaccept, mysocket): return file descriptor,
+ instead of SOCKET.
+
+Thu Nov 16 10:23:24 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (massign): too strict check for nameless rest argument.
+
+ * eval.c (method_arity): mere * should return -1.
+
+ * eval.c (intersect_fds): should check all FDs in the fd_set.
+
+Wed Nov 15 19:33:20 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * eval.c (rb_attr): should clear method cache before calling hook.
+
+ * eval.c (rb_eval): ditto.
+
+ * eval.c (rb_mod_modfunc): ditto.
+
+Mon Nov 13 22:44:52 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * error.c (rb_bug): print version to stderr.
+
+Mon Nov 13 19:02:08 2000 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * win32/win32.c, io.c, process.c: the exit status of program must be
+ multiplied 256 on mswin32 and msdosdjgpp(system(), ``).
+
+Sat Nov 11 22:57:38 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (arg): uniformed treatment of -a**b, where a is a
+ number literal; hacky but behavior appears more consistent.
+
+ * parse.y (newline_node): reduce newline node (one per line).
+
+ * random.c (rb_f_srand): should be prohibited in safe level
+ greater than 4.
+
+Sat Nov 11 22:37:36 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * rubysig.h: do not use rb_trap_immediate on win32.
+
+ * rubysig.h: new macros, ATOMIC_TEST, ATOMIC_SET, ATOMIC_INC,
+ ATOMIC_DEC, RUBY_CRITICAL and new definition of TRAP_BEG,
+ TRAP_END.
+
+ * gc.c (ruby_xmalloc): should wrap malloc() by RUBY_CRITICAL.
+
+ * signal.c (sighandle): better win32 sig handling.
+
+ * win32/win32.c (flock): better implementation.
+
+ * win32/win32.c (myselect): ditto.
+
+ * win32/win32.c (myaccept): ditto.
+
+ * win32/win32.c (waitpid): ditto.
+
+ * win32/win32.c (myrename): ditto.
+
+ * win32/win32.c (wait_events): support function for win32 signal
+ handling.
+
+Sat Nov 11 08:34:18 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.31.
+
+ * lib/net/http.rb: initializes header in HTTP, not HTTPCommand.
+
+ * lib/net/protocol.rb, http.rb: rewrites proxy code.
+
+Fri Nov 10 16:15:53 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (rb_num2long): use to_int, not to_i.
+
+ * error.c: T_SYMBOL was misplaced by T_UNDEF.
+
+ * parse.y (yylex): eval("^") caused infinite loop.
+
+Thu Nov 9 14:22:13 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (rb_io_taint_check): should check IO taintness; no
+ operation for untainted IO should be allowed in the sandbox.
+
+ * rubyio.h (GetOpenFile): check IO taintness inside using
+ rb_io_taint_check().
+
+Wed Nov 8 03:08:53 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (io_fflush): ensure fflush(3) would not block by calling
+ rb_thread_fd_writable().
+
+Tue Nov 7 20:29:56 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.30.
+
+ * lib/net/protocol.rb, smtp.rb: Command#critical_ok -> error_ok
+
+ * lib/net/http.rb: reads header when also "100 Continue".
+
+Tue Nov 7 04:32:19 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (bigdivrem): use bit shift to make y's MSB set.
+
+Mon Nov 6 1:22:49 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * error.c (warn_print): do not use err_append(), to ensure output
+ to stderr.
+
+ * error.c (rb_warn): use warn_print() instead of err_print().
+
+ * error.c (rb_warning): ditto.
+
+ * error.c (rb_bug): ditto.
+
+ * eval.c (rb_load): re-raise exceptions during load.
+
+ * time.c (make_time_t): remove useless adjust
+
+Thu Nov 2 18:01:16 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * random.c (rb_f_rand): half-baked float support fixed. This fix
+ was originally proposed by K.Kosako <kosako@sofnec.co.jp>.
+
+Tue Oct 31 17:27:17 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c: change digit size to `long|int' if long long is
+ available.
+
+ * marshal.c (w_object): support `long|int' digits.
+
+ * marshal.c (r_object): ditto.
+
+Sat Oct 28 23:54:22 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (yylex): allow =end at the end of file (without a
+ newline at the end).
+
+Fri Oct 27 10:00:27 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_cstr2inum): should ignore trailing white spaces.
+
+ * bignum.c (rb_str2inum): string may not have sentinel NUL.
+
+Fri Oct 27 02:37:22 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_cstr2inum): wrongly assigned base to c before
+ badcheck check.
+
+Thu Oct 26 02:42:50 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb: Command#critical_ok
+
+ * lib/net/smtp.rb: clear critical flag before go to SMTP
+
+Wed Oct 25 12:30:19 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_concat): replacing array might be the receiver
+ itself. do not call rb_ary_push_m.
+
+ * array.c (rb_ary_replace): replacing array might be the receiver
+ itself. use memmove.
+
+Fri Oct 20 07:56:23 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): ARGSPUSH should not modify args array.
+
+Thu Oct 19 14:58:17 2000 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * pack.c (NUM2U32): should use NUM2ULONG().
+
+Tue Oct 17 17:30:34 2000 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * eval.c (error_print): ruby_sourcefile may be NULL.
+
+Tue Oct 17 16:36:28 2000 Wes Nakamura <wknaka@pobox.com>
+
+ * pack.c (NATINT_U32): wrong use of sizeof.
+
+Tue Oct 17 12:48:20 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * eval.c (rb_abort): nil check against ruby_errinfo.
+
+ * eval.c (rb_thread_schedule): use FOREACH_THREAD_FROM instead of
+ FOREACH_THREAD, since curr_thread may be removed from thread ring.
+
+ * eval.c (THREAD_ALLOC): errinfo should be Qnil.
+
+ * eval.c (rb_callcc): th->prev,th->next are now already
+ initialized in THREAD_ALLOC.
+
+Mon Oct 16 15:37:33 2000 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * eval.c (rb_thread_inspect): tag size was shorter than required.
+
+ * object.c (rb_obj_inspect): ditto.
+
+Mon Oct 16 14:25:18 2000 Shugo Maeda <shugo@ruby-lang.org>
+
+ * object.c (sym_inspect): used `name' before initialization.
+
+Mon Oct 16 14:06:00 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * pack.c (pack_pack): use NATINT_U32 for 'l', 'L', and 'N'.
+
+ * pack.c (I32,U32): 32 bit sized integer.
+
+ * pack.c (OFF16,OFF32B): big endian offset for network byteorder.
+
+Mon Oct 16 06:39:32 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/http.rb: hex-alpha is not [a-h] but [a-f].
+
+Mon Oct 16 01:02:02 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_start_0): should not abort on exception if
+ $SAFE >= 4.
+
+ * parse.y (sym): symbols for class variable names.
+
+Sun Oct 15 01:49:18 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * file.c (rb_file_flock): should accept interrupt.
+
+ * process.c (rb_waitpid): ditto.
+
+ * process.c (rb_waitpid): ditto.
+
+ * process.c (proc_wait): ditto.
+
+ * process.c (proc_waitpid2): wrong recursion.
+
+Sat Oct 14 03:32:13 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_alloc): should not link a new thread in the
+ live thread ring before initialization.
+
+Fri Oct 13 17:08:09 2000 Shugo Maeda <shugo@ruby-lang.org>
+
+ * lib/net/imap.rb: new file.
+
+Thu Oct 12 18:56:28 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/pop.rb: POP3#reset
+
+ * lib/net/http.rb: a code for "Switch Protocol" was wrongly 100.
+
+Thu Oct 12 01:23:38 2000 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/cgi.rb: bug fix: CGI::html(): PRETTY option didn't work.
+
+Thu Oct 12 00:03:02 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (sym_inspect): should adjust string length.
+
+ * struct.c (rb_struct_to_s): ditto.
+
+ * struct.c (rb_struct_inspect): ditto.
+
+Wed Oct 11 22:15:47 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * eval.c (rb_thread_inspect): should adjust string length.
+
+ * object.c (rb_any_to_s): ditto.
+
+ * object.c (rb_obj_inspect): ditto.
+
+Wed Oct 11 18:13:50 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_start_0): should check insecure exit.
+
+Wed Oct 11 14:29:51 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb: 2nd arg for ProtocolError#initialize is
+ optional.
+
+ * lib/net/http.rb: code refining.
+
+Wed Oct 11 11:13:03 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (primary): setter method (e.g. foo=) should always be
+ public.
+
+ * eval.c (rb_thread_raise): should not raise SecurityError if
+ exception raised by the interpreter.
+
+ * eval.c (rb_thread_cleanup): skip all THREAD_KILLED threads
+ before FOREACH_THREAD.
+
+Tue Oct 10 16:11:54 2000 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * dln.c (dln_load): remove unused code for cygwin.
+
+Tue Oct 10 09:49:23 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * file.c (Init_File): FileTest.size should return 0 (not nil) for
+ empty files.
+
+Sun Oct 8 13:20:26 2000 Guy Decoux <decoux@moulon.inra.fr>
+
+ * eval.c (POP_SCOPE): not just set SCOPE_DONT_RECYCLE, but do
+ scope_dup().
+
+Sat Oct 7 15:10:50 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_reverse_bang): unnecessary ALLOCA_N() was
+ removed.
+
+Fri Oct 6 14:50:24 2000 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * ext/extmk.rb.in, lib/mkmf.rb: remove "DESTDIR =".
+
+ * Makefile.in, win32/Makefile.sub, ruby.1: renamed -X to -C.
+
+Fri Oct 6 12:50:52 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * array.c (rb_ary_plus): use to_ary(), not Check_Type().
+
+ * array.c (rb_ary_concat): ditto.
+
+ * gc.c (rb_gc): use __builtin_frame_address() for gcc.
+
+ * eval.c (stack_length): ditto.
+
+ * parse.y (assign_in_cond): stop warning till some better warning
+ condition will be found.
+
+Thu Oct 5 18:02:39 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_obj_dup): should have propagated taint flag.
+ (ruby-bugs:#PR64,65)
+
+Wed Oct 4 00:26:11 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (proc_arity): proc{|a|}'s arity should be -1.
+
+Mon Oct 2 05:28:58 2000 akira yamada <akira@ruby-lang.org>
+
+ * string.c (trnext): minus at the end of pattern.
+
+Sun Oct 1 00:43:34 2000 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * configure.in: exp-name was wrong on cygwin and mingw32.
+
+Thu Sep 28 14:57:09 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * regex.c (re_compile_pattern): should try must_string calculation
+ every time.
+
+Tue Sep 19 23:47:44 2000 SHIROYAMA Takayuki <psi@fortune.nest.or.jp>
+
+ * configure.in, config.guess, config.sub: MacOS X support.
+
+Wed Sep 27 18:40:05 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * stable version 1.6.1 released.
+
+Wed Sep 27 16:13:05 2000 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * mkconfig.rb: variables should be expanded only if /\$\{?\w+\}?/.
+
+Tue Sep 26 18:09:51 2000 WATANABE Hirofumi <eban@ruby-lang.org>
+
+ * string.c: include <math.h>
+
+Tue Sep 26 15:59:50 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * object.c (rb_mod_dup): metaclasses of class/module should not be
+ cleared by rb_obj_dup.
+
+Tue Sep 26 02:44:54 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (GC_MALLOC_LIMIT): size extended.
+
+ * regex.c (DOUBLE_STACK): use machine's stack region for regex
+ stack if its size is small enough.
+
+Mon Sep 25 18:13:07 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * regex.c: include <defines.h>.
+
+ * eval.c (rb_add_method): cache mismatch by method
+ definition. need to clear_cache_by_id every time.
+
+Mon Sep 25 13:31:45 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * win32/win32.c (NtCmdGlob): substitute '\\' with '/'.
+
+Mon Sep 25 00:35:01 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * defines.h: #undef HAVE_SETITIMER on cygwin.
+
+Sun Sep 24 03:01:53 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, http.rb: typo.
+
+Sat Sep 23 07:33:20 2000 Aleksi Niemela <aleksi.niemela@cinnober.com>
+
+ * regex.c (re_compile_pattern): nicer regexp error messages for
+ invalid patterns.
+
+Sat Sep 23 03:06:25 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_autoload_load): should not require already
+ provided features.
+
+Fri Sep 22 15:46:21 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/http.rb: too early parameter expansion in string.
+
+Fri Sep 22 13:58:51 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ext/extmk.rb.in: don't use default $:
+
+Fri Sep 22 13:42:50 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * regex.c (PUSH_FAILURE_COUNT): avoid casting warning on alpha.
+
+ * regex.c (PUSH_FAILURE_POINT): ditto.
+
+Fri Sep 22 10:16:21 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * win32/config.h.in: add HAVE_TELLDIR, HAVE_SEEKDIR
+
+Thu Sep 21 19:04:34 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ext/extmk.rb, lib/mkmf.rb (install_rb): check whether libdir is
+ directory or not.
+
+Thu Sep 21 17:23:05 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * file.c (rb_file_s_symlink): use HAVE_SYMLINK.
+
+ * file.c (rb_file_s_readlink): use HAVE_READLINK.
+
+ * dir.c (dir_tell): use HAVE_TELLDIR.
+
+ * dir.c (dir_seek): use HAVE_SEEKDIR.
+
+ * configure.in (AC_CHECK_FUNCS): lstat, symlink, readlink,
+ telldir, seekdir checks added.
+
+ * file.c (lstat): should use stat(2) if lstat(2) is not
+ available.
+
+Thu Sep 21 15:59:23 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.29.
+
+ * lib/net/http.rb: HTTPReadAdapter -> HTTPResponseReceiver
+
+ * lib/net/http.rb (connecting): response is got in receive()
+
+Thu Sep 21 15:49:07 2000 Wayne Scott <wscott@ichips.intel.com>
+
+ * lib/find.rb (find): should not follow symbolic links;
+ tuned performance too.
+
+Wed Sep 20 23:21:38 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.c (load_file): two Ctrl-D was required to stop ruby at the
+ beginning of stdin script read.
+
+Wed Sep 20 14:01:45 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_provided): detect infinite load loop.
+
+ * eval.c (rb_provided): too weak filename comparison.
+
+ * eval.c (rb_thread_alloc): avoid recycling still referenced
+ dvar structures.
+
+ * eval.c (rb_callcc): ditto.
+
+ * eval.c (THREAD_ALLOC): fiil dyna_vars field by ruby_dyna_vars.
+
+Tue Sep 19 17:47:03 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * stable version 1.6.0 released.
+
+Tue Sep 19 16:24:52 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * marshal.c (Init_marshal): provide marshal.so no more.
+
+Tue Sep 19 14:01:01 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in, win32/setup.mak: include version number
+ in RUBY_SO_NAME.
+
+Tue Sep 19 13:07:47 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (yylex): was confusing $~ and $_.
+
+Tue Sep 19 13:06:53 2000 GOTOU YUUZOU <gotoyuzo@notwork.org>
+
+ * signal.c (rb_f_kill): signum may be a negative number, should be
+ treated by signed number.
+
+Tue Sep 19 01:14:56 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_provide): better feature handling.
+
+ * eval.c (rb_f_require): loading ruby library may be partial
+ state. checks in rb_thread_loading is integrated.
+
+ * eval.c (rb_provided): better thread awareness.
+
+ * lib/irb/frame.rb: 6 (not 5) parameters for trace_func proc.
+
+ * eval.c (error_print): should print error position even if
+ get_backtrace() failed.
+
+Sat Sep 16 03:29:59 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_f_require): rb_provided() was called too early; does
+ not work well with threads.
+
+ * parse.y (ensure): should distinguish empty ensure and non
+ existing ensure.
+
+ * file.c (Init_File): extending File by class of FileTest was
+ serious mistake.
+
+Thu Sep 14 02:46:54 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_yield): array strip should be done in this
+ function.
+
+Wed Sep 13 17:01:03 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * bignum.c (rb_big_eq): incomplete value comparison of bignums.
+
+Wed Sep 13 06:39:54 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_mod_class_variables): Module#class_variables added.
+
+Wed Sep 13 06:09:26 2000 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/cgi.rb: bug fix: CGI::header(): output status header.
+
+Wed Sep 13 01:09:12 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (yylex): allow global variables like '$__a'.
+
+Tue Sep 12 22:28:43 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ext/socket/extconf.rb: avoid using terrible <netinet/tcp.h>
+ on cygwin 1.1.5.
+
+Tue Sep 12 16:01:58 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * array.c (rb_ary_unshift_m): typo.
+
+Tue Sep 12 15:37:55 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_yield_0): stripped array too much, should remove just
+ for proc_call().
+
+Tue Sep 12 07:05:24 2000 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/cgi.rb: version 2.0.0: require ruby1.5.4 or later.
+
+ * lib/net/telnet.rb: version 1.6.0
+
+Tue Sep 12 03:26:07 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (massign): use to_ary to get an array if available.
+
+ * object.c (rb_Array): ditto.
+
+Mon Sep 11 14:24:47 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * hash.c (ruby_setenv): should not free the element of
+ origenvironment.
+
+ * parse.y (command_call): kYIELD moved to this rule to allow
+ 'a = yield b'. (ruby-bugs-ja:#PR15)
+
+Mon Sep 11 01:27:54 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_yield_0): proc#call([]) should pass single value to
+ the block.
+
+ * eval.c (callargs): reduce array allocation.
+
+ * eval.c (massign): precise check for argument number.
+
+Fri Sep 8 10:05:17 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (STR_NO_ORIG): should be FL_USER2.
+
+Thu Sep 7 14:17:51 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * string.c (rb_str_cat): should work even for concatenating same
+ string.
+
+Wed Sep 6 17:06:38 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_cvar_declare): should check superclass's class
+ variable first.
+
+Wed Sep 6 10:42:02 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * misc/ruby-mode.el (ruby-calculate-indent): shift continuing line
+ if previous line ends with modifier keyword.
+
+ * misc/ruby-mode.el (ruby-parse-region): should not give up if
+ modifiers are at the end of line.
+
+ * misc/ruby-mode.el (ruby-expr-beg): indented wrongly if modified
+ statement was size 1.
+
+Wed Sep 6 10:41:19 2000 Kenichi Komiya <kom@mail1.accsnet.ne.jp>
+
+ * misc/ruby-mode.el (ruby-parse-region): modifier was not handled
+ well on emacs19.
+
+Tue Sep 5 17:10:12 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (time_to_s): fixed zone string UTC for utc time object.
+
+Tue Sep 5 00:26:06 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * regex.c (re_search): range worked wrongly on bm_search().
+
+Mon Sep 4 13:40:40 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in: renamed libruby.a to libruby.{cygwin,mingw32}.a
+ on cygwin and mingw32.
+
+Sun Sep 3 23:44:04 2000 Noriaki Harada <tenmei@maoh.office.ne.jp>
+
+ * io.c (NO_SAFE_RENAME): for BeOS too.
+
+Sun Sep 3 11:31:53 2000 Takaaki Tateishi <ttate@jaist.ac.jp>
+
+ * parse.y (rescue): no assignment was done if rescue body was
+ empty.
+
+Sat Sep 2 10:52:21 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (call_args,aref_args): block_call can be the last
+ argument.
+
+ * parse.y (COND_PUSH,COND_POP): maintain condition stack to allow
+ kDO2 in parentheses in while/until/for conditions.
+
+ * parse.y (yylex): generate kDO2 for EXPR_ARG outside of
+ while/until/for condition.
+
+Fri Sep 1 10:36:29 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (aref_args,opt_call_args): add block_call to allow a
+ method without parentheses and with block as a last argument.
+
+ * hash.c (rb_hash_sort): should not return nil.
+
+ * re.c (match_aref): should use rb_reg_nth_match().
+
+ * eval.c (POP_SCOPE): recycled scopes too much
+
+ * eval.c (Init_eval): extend room for stack allowance.
+
+ * eval.c (POP_SCOPE): frees scope too much.
+
+Thu Aug 31 14:28:39 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * gc.c (rb_gc_mark): T_SCOPE condition must be more precise.
+
+ * eval.c (scope_dup): should not make all duped scope orphan.
+
+Thu Aug 31 10:11:47 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (stmt): allow stmt_rhs to be right hand side of multiple
+ assignment.
+
+ * time.c (rb_time_timeval): type error should not mention the word
+ 'interval'.
+
+Wed Aug 30 23:21:20 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * numeric.c (rb_num2long): use rb_Integer() instead of independent
+ convert routine.
+
+ * eval.c (rb_rescue2): now takes arbitrary number of exception types.
+
+ * object.c (rb_convert_type): use rb_rescue2 now to handle NameError.
+
+ * object.c (rb_convert_type): better error message.
+
+Wed Aug 30 17:09:14 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ext/Win32API/Win32API.c (Win32API_initialize): AlphaNT support.
+
+Wed Aug 30 14:19:07 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (node_assign): should support NODE_CVASGN2 too.
+
+Wed Aug 30 11:31:47 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * ext/Win32API/Win32API.c (Win32API_initialize): add the
+ arguments checking.
+
+ * ext/Win32API/Win32API.c (Win32API_initialize): add taint
+ checking. allow String object in the third argument.
+
+Wed Aug 30 10:29:40 2000 Masahiro Tomita <tommy@tmtm.org>
+
+ * io.c (rb_f_p): flush output buffer.
+
+Tue Aug 29 16:29:15 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (assignable): remove NODE_CVASGN3.
+
+ * parse.y (gettable): remove NODE_CVAR3.
+
+Tue Aug 29 02:02:14 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * lib/mkmf.rb (create_makefile): handles create_makefile("a/b").
+
+ * ext/extmk.rb.in (create_makefile): ditto
+
+Mon Aug 28 18:43:54 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (is_defined): now handles class variables.
+
+ * eval.c (rb_eval): class variable behavior revisited.
+
+ * parse.y (assignable): ditto.
+
+ * parse.y (gettable): ditto.
+
+ * regex.c (PUSH_FAILURE_COUNT): push/pop interval count on failure
+ stack. this fix is inspired by the Emacs21 patch from Stefan
+ Monnier <monnier@cs.yale.edu>.
+
+Fri Aug 25 15:24:39 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * variable.c (rb_cvar_get): should not follow __attached__.
+
+ * variable.c (rb_cvar_set): ditto.
+
+ * variable.c (rb_cvar_declare): ditto.
+
+ * variable.c (mod_av_set): second class variable assignment at the
+ toplevel should not give warning.
+
+Fri Aug 25 01:18:36 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (next_argv): prepare path for open file.
+
+ * string.c (rb_str_setter): moved from io.c.
+
+ * io.c (next_argv): filename should be "-" for refreshed ARGF.
+
+Thu Aug 24 15:27:39 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ext/socket/socketport.h: use `extern int h_errno' if needed.
+
+Sat Aug 19 01:34:02 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ext/sdbm/_sdbm.c (sdbm_prep): flags should be or-ed by O_BINARY on
+ Win32 too.
+
+ * ext/sdbm/_sdbm.c (makroom): fill hole with 0 on Win32 too.
+
+Fri Aug 18 13:23:59 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_eval): should preserve and clear $! value before
+ compilation.
+
+ * eval.c (eval): ditto.
+
+Fri Aug 18 11:06:19 2000 Shugo Maeda <shugo@ruby-lang.org>
+
+ * ext/socket/socket.c (s_accept): start GC on EMFILE/ENFILE.
+
+Thu Aug 17 16:04:48 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (is_defined): should clear ruby_errinfo.
+
+Thu Aug 17 04:26:31 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.27.
+
+ * lib/net/protocol.rb: writing methods returns written byte size.
+
+ * lib/net/smtp.rb: send_mail accepts many destinations.
+
+Wed Aug 16 00:43:47 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * time.c (time_s_times): use CLK_TCK for HZ if it's defined.
+
+Tue Aug 15 17:30:59 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (frame_dup): should set flag FRAME_MALLOC after
+ argv allocation.
+
+ * eval.c (blk_free): should not free argv if GC was called before
+ frame_dup.
+
+Tue Aug 15 16:08:40 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in: add ac_cv_func_times=yes for mingw32.
+
+ * win32/win32.c (mytimes): typo.
+
+Tue Aug 15 01:45:28 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * io.c (argf_eof): should return true at the end of ARGF without
+ checking stdout if arguments are given.
+
+Mon Aug 14 10:34:32 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_thread_status): status should return false for normal
+ termination, nil for termination by exception.
+
+Fri Aug 11 15:43:46 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_undef): give warning for undefining __id__, __send__.
+
+Thu Aug 10 08:05:03 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_callcc): returned current thread instead of
+ continuation wrongly.
+
+Thu Aug 10 05:40:28 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ext/extmk.rb.in: $CPPFLAGS should be initialized.
+
+ * ext/tcltklib/depend: add stubs.o.
+
+ * ext/tcltklib/extconf.rb: use $CPPFLAGS instead of $CFLAGS.
+
+Wed Aug 9 16:31:48 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * eval.c (rb_callcc): thread status for continuations must be
+ THREAD_KILLED, otherwise thread_free() breaks other threads.
+
+Wed Aug 9 13:24:25 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * win32/win32.[ch]: emulate rename(2).
+
+Tue Aug 8 14:01:46 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ext/tcltklib/tcltklib.c: support --enable-tcltk_stubs
+
+ * ext/tcltklib/extconf.rb: ditto.
+
+ * ext/tcltklib/stubs.c: created. examine candidate shared libraries.
+
+Mon Aug 7 13:59:12 2000 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * ruby.h (CLONESETUP): should copy flags before any potential
+ object allocation.
+
+ * regex.c (re_match): check for stack depth was needed.
+
+Sat Aug 5 16:43:43 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * djgpp/*: convert DOS line endings to UNIX style.
+
+ * djgpp/config.status: rename to config.sed for SFN.
+
+ * lib/ftools.rb (compare, safe_unlink, chmod): avoid warnings.
+
+ * lib/ftools.rb (move): typo. not `tpath', but `to'.
+
+Fri Aug 4 23:26:48 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (proc_call): gives warning if a block is supplied.
+
+ * eval.c (rb_eval): no warning for discarding if an alias for the
+ method is already made.
+
+Fri Aug 4 16:32:29 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (rb_ary_reject_bang): returns nil if no element removed.
+
+ * hash.c (rb_hash_reject_bang): returns nil if no element removed.
+
+Thu Aug 3 19:44:26 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_fd_writable): should return integer value.
+
+ * array.c (rb_ary_assoc): search array element whose length is
+ longer than 0 (not 1).
+
+Wed Aug 2 18:27:47 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_wait_fd): prohibit thread context switch
+ during compilation.
+
+ * eval.c (rb_cont_call): prohibit Continuation#call across threads.
+
+Wed Aug 2 08:22:04 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * gc.c (rb_gc): clear malloc_memories to zero, to avoid potential
+ super frequent GC invocation. (ruby-bugs:#PR48)
+
+ * gc.c (rb_gc): only add_heap() if GC trigger condition is
+ satisfied.
+
+Tue Aug 1 16:41:58 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (proc_options): global load path setting moved from
+ ruby_prog_init().
+
+ * ruby.c (incpush): renamed. push path entry at the END of the
+ load path array. This makes -I directories sorted in order in
+ the arguments.
+
+Sat Jul 29 23:42:04 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * dir.c (dir_each): should check whether dir is closed during the
+ block execution. (ruby-bugs:#PR47)
+
+Sat Jul 29 21:57:30 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ruby.c (rubylib_mangle): provide another buffer for the result.
+
+Wed Jul 26 10:09:01 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in: set SOLIBS to LIBS on Cygwin.
+
+ * configure.in: LIBRUBY_SO='$(RUBY_INSTALL_NAME)'.$target_os.dll
+ on cygwin and mingw32. ruby-cygwin.dll is bad. why?
+
+Wed Jul 26 10:04:03 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * gc.c (gc_sweep): avoid full scan during compilation.
+
+ * gc.c (rb_gc): add heap during no gc period (including
+ compilation).
+
+Tue Jul 25 19:03:04 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * cygwin/GNUmakefile: use puts instead of print, because
+ Cygwin DLL's behavior is changed(or bug?).
+
+ * configure.in: LIBRUBY_SO='$(RUBY_INSTALL_NAME)'-$target_os.dll
+ on cygwin and mingw32.
+
+ * cygwin/GNUmakefile: ditto.
+
+ * Makefile.in: $(SOLIBS) should be put after dmyext.@OBJEXT@.
+
+ * instruby.rb: install $(LIBRUBY) to libdir
+ if $(LIBRUBY) != $(LIBRUBY_A_).
+
+Tue Jul 25 15:16:00 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_p): redirect to $defout.
+
+Mon Jul 24 18:52:55 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * win32/win32.c (win32_getenv): should remove `static'.
+
+ * ruby.c (rubylib_mangle): support "/hoge;/foo"
+
+Mon Jul 24 10:28:55 2000 GOTO Kentaro <gotoken@math.sci.hokudai.ac.jp>
+
+ * string.c (rb_str_count): raise exception if no argument is
+ given.
+
+Sun Jul 23 12:55:04 2000 Dave Thomas <Dave@Thomases.com>
+
+ * string.c (rb_str_rindex): Support negative end position.
+
+Fri Jul 21 17:35:01 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (aref_args): command_call now be permitted as
+ aref_args.
+
+ * process.c (proc_getpriority): getpriority(2) may return valid
+ negative number. use errno to detect error.
+
+ * marshal.c (dump_ensure): dumped string should be tainted if
+ any among target objects is tainted.
+
+ * marshal.c (r_regist): restored object should be tainted if and
+ only if the source is a file or a tainted string.
+
+Wed Jul 19 15:14:04 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (bigdivrem): should use rb_int2big(), not rb_uint2big().
+
+Tue Jul 18 14:58:30 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (ruby_options): should treat SystemExit etc. properly.
+
+ * parse.y (yycompile): should check compile_for_eval, not
+ ruby_in_eval.
+
+Mon Jul 17 04:29:50 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/mkmf.rb: converts extension of $objs into $OBJEXT.
+
+Sun Jul 16 03:02:34 2000 Dave Thomas <dave@thomases.com>
+
+ * lib/weakref.rb: Change to use new ObjectSpace calls.
+
+Sat Jul 15 21:59:58 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_eval): should not redefine __id__ nor __send__.
+
+ * gc.c (define_final): integrate final.rb features into the
+ interpreter. define_finalizer and undefine_finalizer was
+ added to ObjectSpace. plus, add_finalizer, remove_finalizer,
+ and call_finalizer are deprecated now.
+
+Sat Jul 15 01:32:34 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_mod_method): implements unbound method.
+
+ * eval.c (Init_eval): should prohibit `module_function' for class
+ Class.
+
+Fri Jul 14 17:19:59 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * cygwin/GNUmakefile.in: use miniruby instead of sed.
+
+Fri Jul 14 12:49:50 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (argf_eof): need to check stdin, when next_p == -1.
+
+ * io.c (read_all): use io_fread() instead of fread(3).
+
+ * io.c (io_reopen): should clearerr FILE if fd < 3.
+
+ * re.c (rb_reg_match_m): the result is exported, so it should be
+ declared as busy.
+
+ * eval.c (rb_eval): should preserve errinfo even if return, break,
+ etc. is called in rescue clause.
+
+ * instruby.rb: install irb too.
+
+Wed Jul 12 15:32:57 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (rb_const_get): constants for builtin classes must
+ have higher priority than constants from included modules at
+ Object class.
+
+ * bignum.c (bigdivrem): small embarrassing typo.
+
+Wed Jul 12 15:06:28 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_eval): use rb_const_get_at().
+
+ * variable.c (top_const_get): retrieve toplevel constants only,
+ not ones of Object (and its included modules) in general.
+
+Wed Jul 12 15:04:11 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.26.
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb:
+ add module Net::NetPrivate and its inner classes
+ {Read,Write}Adapter, Command, Socket,
+ SMTPCommand, POP3Command, APOPCommand, HTTPCommand
+
+Wed Jul 12 13:10:30 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (bigdivrem): defer bignorm().
+
+ * bignum.c (bignorm): accepts accidental fixnums.
+
+Tue Jul 11 16:54:17 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): `@<digit>' is no longer a valid instance
+ variable name.
+
+Tue Jul 11 01:51:50 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (rb_big_divmod): should not use Integer(float) for
+ the right operand.
+
+ * bignum.c (rb_big_remainder): ditto.
+
+ * bignum.c (rb_big_modulo): ditto.
+
+Mon Jul 10 15:27:16 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * io.c (pipe_finalize): should set rb_last_status when pclose().
+
+Mon Jul 10 09:07:54 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * error.c (rb_bug): print version number and such too.
+
+Sat Jul 8 23:08:40 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_start_0): should copy previous scopes to
+ prevent rb_gc_force_recycle().
+
+Fri Jul 7 23:36:36 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ext/socket/addrinfo.h: move IN_EXPERIMENTAL and IN_LOOPBACKNET
+ definitions to ext/socket/sockport.h.
+
+ * ext/socket/extconf.rb: add getservbyport() and arpa/inet.h check.
+
+ * ext/socket/getaddrinfo.c (getaddrinfo): SOCK_RAW may not be
+ defined (ex. BeOS, Palm OS 2.x or before).
+
+ * ext/socket/getnameinfo.c (getnameinfo): getservbyport() may not
+ exist (ex. BeOS, Palm OS).
+
+ * ext/socket/sockport.h: add IN_EXPERIMENTAL, IN_CLASSA_NSHIFT,
+ IN_LOOPBACKNET, AF_UNSPEC, PF_UNSPEC and PF_INET.
+
+Fri Jul 7 03:30:00 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (aref_args): should allow Hash[:a=>2] etc.
+
+ * numeric.c (fix_aref): convert index by NUM2INT, not FIX2INT.
+ (ruby-bugs:#PR37)
+
+ * time.c (time_localtime): should prohibit for frozen time.
+
+ * time.c (time_gmtime): ditto.
+
+Thu Jul 6 19:12:12 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_file_s_open): should not terminate fptr; just clear it.
+
+ * ruby.c (proc_options): should not call require_libraries()
+ twice.
+
+ * ruby.c (require_libraries): clear req_list_head.next after
+ execution.
+
+Thu Jul 6 13:51:57 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * object.c (rb_to_id): name may not be symbol nor fixnum.
+
+ * struct.c (rb_struct_s_def): name may be nil.
+
+Thu Jul 6 02:09:06 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (bigdivrem): new function to return remainder.
+
+ * numeric.c (fixdivmod): now returns modulo, not remainder.
+
+ * numeric.c (flodivmod): ditto.
+
+ * bignum.c (bigdivmod): ditto.
+
+ * numeric.c (num_modulo): new method; alias to '%'.
+
+Thu Jul 6 00:51:43 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * win32/win32.c (NtCmdGlob): patterns should be separated and
+ NUL terminated.
+
+Wed Jul 5 22:27:56 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * cygwin/GNUmakefile: use ruby.def to make rubycw.dll.
+
+ * ext/extmk.rb.in: create target.def.
+
+ * lib/mkmf.rb: ditto.
+
+Wed Jul 5 09:47:14 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (time_arg): Time::local, Time::gm now take 7th optional
+ argument for usec.
+
+ * numeric.c (num_ceil, etc): default ceil, floor, round, truncate
+ implementation for Numeric, using `to_f'.
+
+ * io.c (rb_io_reopen): clear fptr->path after free() to prevent
+ potential GC crash.
+
+ * io.c (rb_file_s_open): terminate fptr unless null.
+
+ * io.c (rb_file_initialize): ditto.
+
+ * lib/tempfile.rb: specify FILE::CREAT|File::EXCL to open for
+ better security.
+
+ * numeric.c (flo_truncate): new method.
+
+Wed Jul 5 01:02:53 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ext/extmk.rb.in: join ' ' -> join(' ').
+
+ * lib/mkmf.rb: ditto.
+
+Tue Jul 4 13:51:29 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/dbm/dbm.c: add methods added to Hash in 1.5.x.
+
+ * ext/gdbm/gdbm.c: ditto.
+
+ * ext/sdbm/init.c: ditto.
+
+ * eval.c (proc_call): args may be Qundef (means no argument), do
+ not call TYPE() for args.
+
+Tue Jul 4 13:20:56 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ext/extmk.rb.in: make command line must be single-quoted.
+ $(RUBY_INSTALL_NAME) is command substitution in the POSIX sh.
+
+Tue Jul 4 13:16:02 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * util.c (rb_type): should add T_UNDEF.
+
+Tue Jul 4 09:30:35 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (here_document): supports EOF right after terminator.
+
+ * random.c (rb_f_rand): argument is now optional (rand(max=0)).
+
+Tue Jul 4 01:50:49 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * win32/ruby.def: remove ruby_mktemp.
+
+Tue Jul 4 01:27:13 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_rescue2): new function to rescue arbitrary exception.
+
+ * numeric.c (do_coerce): should catch NameError explicitly.
+
+Tue Jul 4 00:15:23 2000 Dave Thomas <Dave@thomases.com>
+
+ * numeric.c (Init_Numeric): forgot to register Numeric#remainder.
+
+Mon Jul 3 23:46:56 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * win32/win32.c (myselect, myaccept): disable interrupt while
+ executing accept() or select() to avoid Ctrl-C causes
+ "unknown software exception (0xc0000029)".
+
+Mon Jul 3 18:35:41 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * lib/mkmf.rb: use null device if it exists for cross-compiling.
+
+Mon Jul 3 18:19:51 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.26.
+
+ * lib/net/protocol.rb (finish): do nothing unless active.
+
+ * lib/net/http.rb: HTTP#{get,post}2 again (for new impl).
+
+Mon Jul 3 16:47:22 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * cygwin/GNUmakefile: librubys.a -> lib$(RUBY_INSTALL_NAME)s.a
+
+ * configure.in: use AC_CANONICAL_{HOST,TARGET,BUILD}.
+
+Mon Jul 3 13:15:02 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * numeric.c (fix_divmod): x * d + m = y where d, m = x.divmod(y).
+
+ * bignum.c (rb_big_divmod): ditto.
+
+ * numeric.c (fixdivmod): does not depend C's undefined %
+ behavior. adopt to fmod(3m) behavior.
+
+ * numeric.c (flo_mod): modulo now reserves fmod(3m) behavior.
+
+ * numeric.c (num_remainder): 'deprecated' warning.
+
+Mon Jul 3 10:27:28 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in: use AC_CANONICAL_SYSTEM.
+
+Sun Jul 2 21:17:37 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in: support without --enable-shared for cygwin/mingw32.
+
+ * cygwin/GNUmakefile: ditto.
+
+ * ext/extmk.rb.in: use null device if it exists for cross-compiling.
+
+ * lib/mkmf.rb: ditto.
+
+ * util.c (ruby_mktemp): remove unused ruby_mktemp().
+
+Sun Jul 2 14:18:04 2000 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * eval.c (TMP_PROTECT_END): tmp__protect_tmp may be NULL.
+
+Sun Jul 2 03:37:50 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.25.
+
+ * lib/net/protocol.rb (each_crlf_line): beg = 0 is needed in adding{}
+
+ * lib/net/smtp.rb: allow String for to_addr of SMTP#sendmail
+
+Sat Jul 1 15:22:35 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * numeric.c (fix_rshift): should handle shift value more than
+ sizeof(long).
+
+Sat Jul 1 15:22:35 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_eval): the value from RTEST() is not valid Ruby
+ object. result should be either true or false.
+
+Sat Jul 1 09:30:06 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * re.c (rb_reg_initialize): was freeing invalid pointer.
+
+Sat Jul 1 03:25:56 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (call_args): command_call can be the last argument of
+ call_args. It had to be the only argument.
+
+ * re.c (rb_reg_s_quote): should not dump core even for unsane mbc
+ string.
+
+Fri Jun 30 01:36:20 2000 Aleksi Niemela <aleksi.niemela@cinnober.com>
+
+ * parse.y (f_norm_arg): better, nicer error message.
+
+Thu Jun 29 07:45:33 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/socket/socket.c (udp_send): destination may be packed
+ struct sockaddr.
+
+ * object.c (rb_Integer): Integer(nil) should be invalid, on the
+ other hand, nil.to_i is OK.
+
+Wed Jun 28 17:26:06 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/socket/socket.c (ip_recvfrom): udp_recvfrom and tcp_recvfrom
+ is merged and moved to IPSocket#recvfrom.
+
+ * ext/socket/socket.c (sock_s_getaddrinfo): family can be a
+ strings such as "AF_INET" etc.
+
+ * ruby.c (require_libraries): . and RUBYLIB added to $load_path
+ just before -r procedure.
+
+ * ruby.c (proc_options): -e, - did not exec -r.
+
+Wed Jun 28 14:52:28 2000 Koga Youichirou <y-koga@mms.mt.nec.co.jp>
+
+ * config.sub: NetBSD/hpcmips support.
+
+Wed Jun 28 10:11:06 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * gc.c: gc trigger threshold changed; GC_NEWOBJ_LIMIT removed,
+ FREE_MIN is increased to 4096.
+
+Tue Jun 27 22:39:28 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.24.
+
+ * lib/net/protocol.rb: modified each_crlf_line again.
+
+ * lib/net/protocol.rb: do_write_beg,do_write_end -> writing{}
+ do_write_do -> do_write
+
+ * lib/net/http.rb: can make proxy connection by passing
+ addresses to HTTP.new, start.
+
+ * lib/net/http.rb: HTTP.new_implementation, old_implementation:
+ can use 1.2 implementation of head, get, post, put.
+ (see document)
+
+Tue Jun 27 12:05:10 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * win32.c (myfdclr): new function.
+
+ * win32.h: add FD_CLR.
+
+Mon Jun 26 23:41:41 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ruby.h: add cast for ANSI style.
+
+ * gc.c (rb_data_object_alloc): use RUBY_DATA_FUNC.
+
+Mon Jun 26 22:20:03 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * win32/win32.c (is_socket, extract_file_fd): New function.
+
+ * win32/win32.c (myfdopen): use is_socket().
+
+ * win32/win32.c (myselect): return non socket files immediately
+ if file and socket handles are mixed.
+
+Mon Jun 26 16:21:30 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_schedule): wait_for cleared too early.
+
+Mon Jun 26 09:15:31 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * pack.c: remove obsolete 'F', 'D' specifiers.
+
+Sun Jun 25 00:55:03 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ext/socket/socket.c (sock_s_getnameinfo): `res' would not
+ be assigned if TYPE(sa) == T_STRING.
+
+Sat Jun 24 14:36:29 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * config*.dj, configure.bat, top.sed: move to djgpp/.
+
+Sat Jun 24 02:34:17 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (load_file): call require_libraries() here to let
+ debug.rb work properly.
+
+Fri Jun 23 22:34:51 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * bignum.c (rb_big_lshift): reorder xds assignment to avoid
+ reusing `x' as `len' by VC++ 6.0 SP3 compiler with -Ox switch.
+
+Fri Jun 23 01:11:27 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_substr): should return empty string (""),
+ if beg == str.size and len == zero, mostly for convenience and
+ backward compatibility.
+
+ * parse.y (new_super): should tweak block_pass node for super too.
+
+ * string.c (rb_str_split_m): last split element should not be nil,
+ but "" when limit is specified.
+
+Thu Jun 22 17:27:46 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_substr): str[n,m] now returns nil when n equals
+ to str.size.
+
+Thu Jun 22 13:49:02 2000 Uechi Yasumasa <uechi@ryucom.ne.jp>
+
+ * lib/net/ftp.rb: support resuming.
+
+Thu Jun 22 13:37:19 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * eval.c (rb_thread_sleep_forever): merge pause() macro.
+
+Wed Jun 21 08:49:04 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_eval): should not raise exception just by defining
+ singleton class.
+
+Wed Jun 21 01:18:03 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.h: two macros RUBY_DATA_FUNC and RUBY_METHOD_FUNC are added
+ to make writing C++ extensions easier.
+
+ * array.c (rb_ary_dup): internal classes should not be shared by dup.
+
+ * hash.c (rb_hash_dup): ditto.
+
+ * object.c (rb_obj_dup): ditto.
+
+ * string.c (rb_str_dup): ditto.
+
+ * error.c (Init_Exception): renamed NotImplementError to
+ NotImplementedError.
+
+Tue Jun 20 16:22:38 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (make_time_t): bug in DST boundary.
+
+Tue Jun 20 10:54:19 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in: add eval sitedir.
+
+Tue Jun 20 06:14:43 2000 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/cgi.rb: change: version syntax. old: x.yz, now: x.y.z
+
+ * lib/net/telnet.rb: ditto.
+
+Tue Jun 20 00:37:45 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (rb_reg_kcode_m): Regexp#kcode returns nil for code unfixed
+ regexp object.
+
+ * bignum.c (bigdivmod): bignum zero check was wrong.
+
+Mon Jun 19 10:48:28 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (rb_cvar_set): forgot to add security check for class
+ variable assignment.
+
+Sun Jun 18 22:49:13 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in: single quoted sitedir.
+
+ * mkconfig.rb: add DESTDIR for cross-compiling.
+
+ * lib/mkmf.rb: add DESTDIR.
+
+ * ruby.c (load_file): force binmode if fname includes ".exe"
+ on DOSISH.
+
+Sat Jun 17 23:22:17 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sprintf.c (rb_f_sprintf): should ignore negative precision given
+ by <%.*>.
+
+ * sprintf.c (rb_f_sprintf): should allow zero precision.
+
+Sat Jun 17 03:13:29 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (time_localtime): avoid unnecessary call of localtime.
+
+ * time.c (time_gmtime): avoid unnecessary call of gmtime.
+
+ * process.c (proc_wait2): new method.
+
+ * process.c (proc_waitpid): second argument made optional.
+
+ * process.c (proc_waitpid2): new method.
+
+Sat Jun 17 00:05:00 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (rb_reg_clone): should initialize member fields.
+
+Fri Jun 16 22:49:34 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_rewind): set lineno to zero.
+
+Fri Jun 16 22:47:47 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.23.
+
+ * lib/net/protocol.rb: too many CRLF in last line.
+
+Fri Jun 16 21:23:59 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in: add pause(2) checking.
+
+ * eval.c: define pause() if missing.
+
+Fri Jun 16 18:41:58 2000 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * process.c (proc_setsid): BSD-style setpgrp() don't return
+ process group ID, but 0 or -1.
+
+Fri Jun 16 16:23:35 2000 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * file.c (rb_stat_inspect): gives detailed information;
+ compatibility with ruby-1.4.x.
+
+Fri Jun 16 05:18:45 2000 Yasuhiro Fukuma <yasuf@bsdclub.org>
+
+ * configure.in: FreeBSD: do not link dummy libxpg4 which was
+ merged into libc.
+
+Fri Jun 16 03:17:36 2000 Satoshi Nojo <nojo@t-samukawa.or.jp>
+
+ * ext/dbm/dbm.c (fdbm_length): use GetDBM. empty?, [] too.
+
+ * ext/gdbm/gdbm.c (fgdbm_length): ditto.
+
+ * ext/sdbm/init.c (fsdbm_length): ditto.
+
+Fri Jun 16 01:57:31 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_sleep_forever): pause(2) instead of sleep(3).
+
+Thu Jun 15 10:46:36 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_sub_bang): should probagate taintness from
+ replacement string.
+
+Wed Jun 14 17:01:41 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * rubytest.rb: add CONFIG['EXEEXT'] to the executable file name.
+
+Wed Jun 14 14:50:00 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_f_sub): assign to $_ only if modification happens.
+
+ * string.c (rb_f_gsub): ditto.
+
+ * string.c (rb_f_chop): ditto.
+
+ * string.c (rb_f_chomp): ditto.
+
+ * io.c (io_reopen): preserve file position by ftell/fseek, if io
+ is a seekable.
+
+ * eval.c (method_arity): wrong arity number for the methods with
+ optional arguments.
+
+ * time.c (make_time_t): opposite timezone shift (should be negative).
+
+Wed Jun 14 14:07:38 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * io.c: typo(ig/if).
+
+ * re.c: typo(re/reg). add rb_reg_check().
+
+ * time.c: remove unneeded declare(daylight, timezone).
+
+ * configure.in: add include <time.h> when daylight checking.
+
+Wed Jun 14 11:36:52 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * marshal.c (r_object): modified for symbols.
+
+ * marshal.c (w_object): ditto.
+
+Wed Jun 14 10:04:58 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (rb_memcmp): should compare according to ruby_ignorecase.
+
+ * string.c (rb_str_cmp): use rb_memcmp.
+
+ * string.c (rb_str_index): ditto.
+
+ * string.c (rb_str_rindex): ditto.
+
+ * string.c (rb_str_each_line): ditto.
+
+Wed Jun 14 04:58:53 2000 Dave Thomas <dave@thomases.com>
+
+ * io.c (rb_io_set_lineno): should have returned VALUE, not
+ integer.
+
+Wed Jun 14 09:29:42 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_dup): dup should always propagate taintness.
+
+Wed Jun 14 00:50:14 2000 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/cgi.rb: read_multipart(): if no content body then raise EOFError.
+
+Tue Jun 13 11:46:17 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * process.c (proc_setsid): try implement it using setpgrp() and
+ ioctl(fd, TIOCNOTTY, NULL).
+
+ * re.c (rb_reg_prepare_re): magic variable $= should affect regex
+ pattern match.
+
+ * time.c (make_time_t): use tm.tm_gmtoff if possible.
+
+ * time.c (time_zone): use tm.tm_zone if available.
+
+Tue Jun 13 01:50:57 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.22.
+
+ * lib/net/http.rb: HTTPResponse#body returns body.
+
+Mon Jun 12 23:41:54 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in (daylight): avoid GCC optimization.
+
+Mon Jun 12 19:02:27 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in: cygwin has strange timezone.
+
+ * time.c (time_zone): use tzname and daylight.
+
+Sat Jun 10 23:10:32 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_seek): whence is optional, default is SEEK_SET.
+
+Fri Jun 9 17:00:29 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.21.
+
+ * lib/net/http.rb: exception is raised with response object.
+
+Fri Jun 9 15:11:35 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (make_time_t): supports daylight saving time.
+
+ * eval.c (rb_thread_safe_level): should retrieve current $SAFE
+ value if a thread is the current thread.
+
+Thu Jun 8 14:25:45 2000 Hiroshi Igarashi <iga@ruby-lang.org>
+
+ * lib/mkmf.rb: add target `distclean' in Makefile for extlib.
+ target `clean' doesn't remove Makefile.
+
+Thu Jun 8 13:34:03 2000 Dave Thomas <dave@thomases.com>
+
+ * numeric.c: add nan?, infinite?, and finite? to Float
+
+Thu Jun 8 00:31:04 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * regex.h: export re_mbctab properly on cygwin.
+
+ * dln.c: use dlopen instead of LoadLibrary on cygwin.
+
+Thu Jun 8 13:41:34 2000 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * file.c (rb_file_s_basename): might dump core.
+
+Tue Jun 6 03:29:12 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * dir.c (dir_foreach): now returns nil for consistency.
+
+ * bignum.c (bigdivmod): modulo by small numbers was wrong.
+
+Mon Jun 5 00:18:08 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * bignum.c: avoid conflict with USHORT on mingw32.
+
+Mon Jun 5 00:13:35 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * eval.c (rb_thread_schedule): =/== typo.
+
+Sun Jun 4 03:17:36 2000 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/cgi.rb: improve: CGI::pretty()
+
+Sun Jun 4 02:01:10 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * lib/mkmf.rb: do not need to add -L$(topdir) in --enable-shared case.
+
+Sat Jun 3 13:50:06 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (rb_id2name): should support constant attrset
+ identifiers.
+
+ * bignum.c (rb_big_eq): Bignum#== should not raise exception.
+
+Fri Jun 2 11:24:48 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_popen): open with a block returns the value from the
+ block. old behavior was back.
+
+Fri Jun 2 00:42:31 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+
+ * eval.c (rb_thread_cleanup): should clear priority for thread
+ termination.
+
+Thu Jun 01 22:39:41 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.20.
+
+ * lib/net/http.rb: wrongly closed the socket twice
+ when no Content-Length: was given.
+
+Thu Jun 1 00:59:15 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_yield_0): convert Qundef to [].
+
+Wed May 31 20:45:59 2000 Dave Thomas <Dave@Thomases.com>
+
+ * string.c (rb_str_slice_bang): wrong argument number.
+
+Wed May 31 12:37:04 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_exec_end_proc): print error message from END procs.
+
+Wed May 31 04:06:41 2000 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/cgi.rb: change: CGI#out() if "HEAD" == REQUEST_METHOD then
+ output only HTTP header.
+
+Wed May 31 01:54:21 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_schedule): set main_thread->status to
+ THREAD_TO_KILL, before raising deadlock error.
+
+ * eval.c (rb_thread_deadlock): if curr_thread == main_thread, do
+ not call rb_thread_restore_context()
+
+Tue May 30 23:33:41 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * lib/mkmf.rb (create_makefile): add $(TARGET).ilk and *.pdb
+ to cleanup files for mswin32.
+
+Mon May 29 10:41:10 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * file.c (rb_file_s_basename): should propagate taintness.
+
+Sun May 28 21:37:13 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * eval.c: bug fix: DLEXT2.
+
+Sun May 28 19:21:43 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * win32/win32.c: use ruby's glob.
+
+ * dir.c: "glob" exported and renamed to "rb_glob".
+
+ * ruby.h: ditto.
+
+ * main.c: turn off command line mingw32's globbing.
+
+Wed May 25 22:25:13 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ext/extmk.rb.in: use "ftools" instead of "rm -f".
+
+ * lib/mkmf.rb: ditto.
+
+Thu May 25 22:01:32 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * defines.h: mswin32: remove obsolete USHORT definition.
+
+ * re.h: mswin32: use EXTERN instead of extern.
+
+ * regex.h: mswin32: export re_mbctab properly.
+
+ * win32/ruby.def: add ruby_ignorecase and regex.c's exports.
+
+Thu May 25 21:28:44 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * re.c (rb_reg_expr_str): escape un-printable character.
+
+Thu May 25 01:35:15 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (tokadd_escape): forgot to add `\x' to hexadecimal
+ escape sequences.
+
+ * object.c (rb_obj_dup): dup for normal object (T_OBJECT) copies
+ instance variables only.
+
+Wed May 24 23:49:47 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (rb_mod_initialize): should provide initialize.
+
+Wed May 24 23:17:50 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * win32/Makefile: remove unnecessary mv and rm command call.
+
+Wed May 24 21:01:04 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ext/pty/pty.c: use "" instead of <> to include ruby.h and rubyio.h
+ for BeOS (PowerPC).
+
+ * file.c (rb_find_file): should check dln_find_file() result.
+
+ * win32/ruby.def: add rb_block_given_p.
+
+Wed May 24 16:32:45 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_popen): popen does not take 3rd argument anymore.
+
+ * re.c (rb_reg_desc): re may be zero, check before dereferencing.
+
+Wed May 24 16:03:06 2000 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/cgi.rb: bug fix: CGI::escape(), CGI::Cookie::new()
+
+ * lib/net/telnet.rb: improve: binmode(), telnetmode() interface
+
+Wed May 24 13:12:31 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * misc/ruby-mode.el (ruby-parse-region): support `while .. do'
+ etc. But corresponding keywords must be at the beginning of
+ line.
+
+Tue May 23 23:50:12 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (rb_reg_initialize_m): wrong kcode value.
+
+ * re.c (rb_reg_s_new): forgot to initialize re->ptr.
+
+Tue May 23 08:36:24 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): forgot to restore old option
+ status by (?ix-ix).
+
+ * regex.c (re_compile_fastmap): anychar may match newline if
+ RE_OPTION_MULTILINE or RE_OPTION_POSIXLINE is set.
+
+Mon May 22 22:45:06 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.19.
+
+ * lib/net/http.rb: do not use Regexp "p" option.
+
+Mon May 22 21:56:43 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * struct.c (rb_struct_getmember): should use ID2SYM, not INT2NUM.
+
+Mon May 22 15:07:37 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * file.c (rb_find_file): should check if the file really exists.
+
+Mon May 22 09:08:12 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_popen): _exit(0) after processing block under the
+ child process.
+
+ * io.c (rb_io_popen): flush stdout/stderr before subprocess
+ termination.
+
+ * eval.c (rb_check_safe_str): insert rb_secure(4); operation
+ requires untainted string should be prohibited in level 4.
+
+Sun May 21 21:17:00 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in: add Setup.dj for djgpp cross-compiling.
+
+ * Setup.dj: add readline.
+
+ * instruby.rb: copy win32/win32.h to archlibdir on mingw32.
+
+Sun May 21 20:58:08 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * pack.c: fix OFF16 and OFF32 definitions for Alpha and IRIX64.
+
+Sun May 21 17:31:37 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * instruby.rb: support "make install" for cross-compiling.
+
+ * ext/extmk.rb.in: ditto.
+
+Sun May 21 14:22:49 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * Makefile.in: rename prep.rb to fake.rb.
+
+ * configure.in: ditto.
+
+Sat May 20 23:29:14 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * dir.c (dir_s_new): does not take block; "open" does.
+
+ * io.c (rb_io_s_new): ditto.
+
+Fri May 19 07:44:26 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * dir.c (dir_s_open): Dir#open does not returns closed Dir if a
+ block is given to the method.
+
+ * re.c (rb_reg_initialize_m): Regexp::new calls initialize now.
+
+ * string.c (Init_String): String#delete_at removed.
+
+ * string.c (rb_str_aset_m): should have checked argc != 2.
+
+ * eval.c (rb_thread_schedule): select(2) was called too many.
+
+ * regex.c (re_compile_pattern): a bug in (?m) support. Pointed
+ out by Dave Thomas <Dave@thomases.com>.
+
+Thu May 18 23:55:26 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * dln.c (search_undef): st_lookup()'s 3rd parameter should be
+ a pointer of the variable which has the same size and alignment
+ as `char *'.
+
+ * marshal.c (w_symbol, w_object): ditto.
+
+ * parse.y (rb_intern): ditto.
+
+Thu May 18 18:00:35 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.18.
+
+ * lib/net/protocol.rb: Net::Version was removed.
+
+ * lib/net/smtp.rb: use Socket.gethostname to get local host name.
+
+Thu May 18 13:34:57 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/socket/socket.c (ruby_connect): should not have replaced
+ thread_write_select() by rb_thread_fd_writable().
+
+Thu May 18 09:01:25 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * configure.in, ext/extmk.rb.in, lib/mkmf.rb: remove BeOS R3 support.
+ Make a shared library (libruby.so) only if the --enable-shared
+ option is specified.
+
+ * instruby.rb: no longer use libruby.so.LIB and import.h.
+
+ * io.c: fix READ_DATA_PENDING definition for BeOS (PowerPC).
+
+Wed May 17 14:14:23 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (rb_reg_new_1): use /m instead of /p.
+
+Wed May 17 02:22:03 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_polling): wait 0.06 second to let other
+ processes run.
+
+ * process.c (rb_waitpid): avoid busy wait using rb_thread_polling.
+
+ * file.c (rb_thread_flock): ditto.
+
+ * parse.y (expr): avoid calling value_expr() twice.
+
+Wed May 17 00:45:57 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * io.c (rb_io_binmode): should check PLATFORMs, not O_BINARY, sigh...
+
+Wed May 17 00:40:15 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * win32/config.h: add DLEXT2, now DLEXT on mswin32 is "so".
+
+ * win32/config.status: ditto.
+
+ * win32/ruby.def: add symbol "rb_big_divmod".
+
+Tue May 16 19:45:32 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * intern.h: use EXTERN instead of extern.
+
+ * win32/ruby.def: add rb_defout, rb_stdout, ruby_errinfo,
+ ruby_sourceline, ruby_sourcefile to work with eruby
+ reported by Hiroshi Saito <HiroshiSaito@pob.org>.
+ Export both ruby_xmalloc and xmalloc etc.
+
+Tue May 16 17:00:05 2000 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
+
+ * eval.c (rb_thread_select): should check whether fds are null.
+
+Tue May 16 11:51:31 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (pipe_open): synchronize subprocess stdout/stderr.
+
+Mon May 15 15:38:09 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.h: exported symbols should be for xmalloc etc. are now
+ prefixed by 'ruby_', e.g. ruby_xmalloc().
+
+ * eval.c (rb_thread_select): remove busy wait for select.
+
+ * dir.c (glob): trailing path may be null, e.g. glob("**").
+
+Mon May 15 14:48:41 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * io.c (rb_io_pid): new method; returns nil if no process attached
+ to the IO.
+
+Mon May 15 01:18:20 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_s_popen): _exit after Proc execution.
+
+Sun May 14 18:05:59 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * Makefile.in: missing/nt.c -> win32/win32.c
+
+ * configure.in: bug fix; static linking on mingw32.
+
+ * cygwin/GNUmakefile.in: remove VPATH.
+
+ * ext/extmk.rb.in: Makefile set binmode with mingw32 on cygwin32.
+
+ * lib/mkmf.rb: ditto.
+
+ * win32/config.h: undef HAVE_SYS_FILE_H.
+
+Sun May 14 02:02:48 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * lib/irb/ruby-lex.rb: '/' should be escaped in character class.
+
+Sun May 14 00:54:43 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in, ...: support mingw32.
+
+ * defines.h: ditto. undef EXTERN for tcl/tk on cygwin.
+
+ * ext/*/extconf.rb: replace PLATFORM with RUBY_PLATFORM.
+
+ * ext/socket/sockport.h: define IN_MULTICAST for missing IN_MULTICAST.
+
+ * ext/tcltklib/tcltklib.c: remove declaration of rb_argv0.
+
+ * file.c: should check S_IXGRP, S_ISGID, not NT.
+
+ * io.c (rb_io_binmode): should check _IOBIN, O_BINARY, not PLATFORMs.
+
+Sat May 13 14:21:15 2000 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * io.c (rb_io_s_popen): should check whether a block is given.
+
+Fri May 12 17:33:44 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): charset_not should not exclude
+ newline from matching set.
+
+Thu May 11 22:51:05 2000 Ryunosuke Ohshima <ryu@jaist.ac.jp>
+
+ * pack.c (pack_pack): Bignum support.
+
+ * pack.c (pack_unpack): ditto.
+
+Thu May 11 21:19:29 2000 Hiroshi Igarashi <iga@ruby-lang.org>
+
+ * intern.h: add missing declarations of ruby API functions.
+
+ * ruby.h: fix function name in declarations.
+
+Thu May 11 22:29:25 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ext/md5/depend: add $(topdir)/config.h dependency to md5c.o.
+
+ * ext/md5/extconf.rb: new file to add -DHAVE_CONFIG_H flag for Alpha.
+
+Thu May 11 10:55:52 2000 Ryunosuke Ohshima <ryu@jaist.ac.jp>
+
+ * pack.c (pack_pack): packing BER compressed integer by `w'.
+
+ * pack.c (pack_unpack): unpacking BER.
+
+Thu May 11 00:37:55 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (parse_regx): remove in_brack.
+
+Wed May 10 12:51:18 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (proc_options): move adding RUBYLIB and "." to the load
+ path after #! line parsing.
+
+ * parse.y (parse_regx): should parse backslash escape like `\c['
+ here to avoid causing `unterminated regexp' error.
+
+Wed May 10 00:19:53 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * MANIFEST, beos/GNUmakefile.in, configure.in: no longer need
+ beos/GNUmakefile.in to support BeOS R4.5.2 (Intel) as a result
+ of eban's Makefile.in change.
+
+ * io.c: NOFILE is already defined on BeOS R4.5 (Intel) or later.
+
+ * lib/matrix.rb: remove debug print.
+
+ * regex.c: don't use nested comment.
+
+Tue May 9 17:08:43 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (massign): no longer convert nil into empty array.
+
+ * io.c (rb_io_s_popen): optional 3rd argument to give proc, which
+ will be executed in spawned child process.
+
+Mon May 8 23:47:39 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * eval.c (rb_callcc): prev & next should be initialized to zero.
+
+Mon May 8 23:17:36 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * dln.c (dln_init): remove possible buffer overrun. This is
+ suggested by Aleksi Niemela <aleksi.niemela@cinnober.com>.
+
+ * dln.c (init_funcname): ditto.
+
+Sat May 6 23:35:47 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (lhs): should allow `obj.Attr = 5' type expression.
+
+Sat May 6 15:46:08 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ext/socket/extconf.rb: add a new configure option to force use
+ of the WIDE Project's getaddrinfo(): --enbale-wide-getaddrinfo.
+
+Fri May 5 21:19:22 2000 MOROHOSHI Akihiko <moro@remus.dti.ne.jp>
+
+ * parse.y (yylex): allow '$1foo' and such.
+
+Fri May 5 17:57:24 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.17.
+
+ * lib/net/http.rb: write also port number in Host: field.
+
+ * lib/net/http.rb: see Proxy-Connection: to decide socket connection.
+
+Fri May 5 03:25:15 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_fastmap): charset_not for multibyte
+ characters excluded too many characters.
+
+Tue May 2 13:23:43 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_schedule): little bit more impartial context
+ switching.
+
+Tue May 2 09:50:03 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * configure.in: add DLDLIBS to set platform specific library
+ for extensions.
+
+ * ext/extmk.rb.in: use @DLDLIBS@ instead of RUBY_PLATFORM choice.
+
+ * lib/mkmf.rb: use CONFIG["DLDLIBS"] instead of RUBY_PLATFORM choice.
+
+ * config_s.dj: add @DLDLIBS@.
+
+ * win32/config.status: ditto.
+
+ * win32/ruby.def: regular maintenance.
+
+Mon May 1 23:42:44 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in, eval.c: add DLEXT2. now DLEXT on Cygwin is "so".
+
+ * defines.h: use dllimport, dllexport for Cygwin 1.1.x.
+
+ * ruby.h: ditto.
+
+ * cygwin/GNUmakefile.in: ditto.
+
+ * ext/Win32API/Win32API.c: directly "call" in asm statement for
+ gcc 2.95.x or newer.
+
+Sat Apr 29 04:58:12 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * array.c (rb_ary_unshift_m): performance improvement.
+
+Fri Apr 28 00:19:22 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * array.c (rb_ary_unshift_m): takes items to push.
+
+Wed Apr 26 15:23:02 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_succ): insert carrying character just before
+ the leftmost alpha numeric character.
+
+ * string.c (rb_str_succ): proper behavior for "".succ and "\377".succ.
+
+ * string.c (rb_str_succ): use realloc and memmove.
+
+Tue Apr 25 18:28:45 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.16.
+
+ * lib/net/smtp.rb: add SMTP AUTH
+
+Tue Apr 25 14:30:13 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_gets_internal): shortcut when rs == rb_default_rs.
+
+Sat Apr 22 23:14:41 2000 SHIROYAMA Takayuki <psi@fortune.nest.or.jp>
+
+ * configure.in: MacOS X support.
+
+Sat Apr 22 16:37:10 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.15.
+
+ * lib/net/http.rb: closing socket by watching both
+ user header and server response
+
+Fri Apr 21 21:44:34 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * io.c (rb_io_s_pipe): should set FMODE_SYNC.
+
+Thu Apr 20 16:59:22 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * eval.c (massign): `*lvalue = false' should assign `[false]' to
+ lvalue.
+
+Wed Apr 19 08:35:08 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * class.c (rb_singleton_class): generate singleton class for
+ special constants: nil, true, false.
+
+Wed Apr 19 02:09:30 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * class.c (rb_singleton_class): singleton method for nil, true,
+ false is possible now.
+
+ * eval.c (rb_eval): ditto.
+
+Tue Apr 18 18:54:25 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.14.
+
+ * lib/net/http.rb: new method HTTP#head2.
+
+ * lib/net/http.rb: get2/post2 does not raise exceptions.
+
+Mon Apr 17 15:16:31 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_close): to detect some exceptional status, writable
+ IO should be flushed before close;
+
+Sat Apr 15 18:29:00 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (rb_ary_collect_bang): Array#filter renamed.
+
+Fri Apr 14 19:47:11 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.13.
+
+ * lib/net/pop.rb: accept illegal timestamp
+
+ * lib/net/http.rb: when body was chunked, does not set Content-Length:
+
+Tue Apr 11 21:14:42 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * config_s.dj: add @sitedir@.
+ * configure.in: add --with-sitedir=DIR option.
+ * instruby.rb: use CONFIG["sitedir"].
+ * lib/mkmf.rb: support 'make site-install'.
+ * win32/config.status: add @sitedir@.
+
+Tue Apr 11 16:25:15 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (rb_big_2comp): unnecessary lvalue cast removed.
+
+Tue Apr 11 02:25:53 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (env_fetch): new method.
+
+ * marshal.c (marshal_dump): accepts depth = nil for unlimited depth.
+
+Sun Apr 9 20:49:19 2000 Dave Thomas <Dave@Thomases.com>
+
+ * parse.y (str_extend): Allow class variables to be expanded.
+
+Fri Apr 7 02:03:54 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * error.c (rb_sys_fail): escape non-printable characters.
+
+Thu Apr 6 20:10:47 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ext/extmk.rb.in (create_makefile): BeOS --program-suffix support.
+ * lib/mkmf.rb (create_makefile): ditto.
+
+Thu Apr 6 09:55:26 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * error.c (rb_sys_fail): need rb_exc_new2() call on BeOS.
+
+Mon Apr 3 17:22:27 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_reopen): support tempfile.
+
+ * eval.c (catch_i): should supply argument.
+
+Sat Apr 1 22:50:28 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * marshal.c (r_object): wrong symbol restoration.
+
+Sat Apr 1 21:30:53 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * io.c(rb_io_printf, rb_f_printf): should use rb_io_write.
+
+Sat Apr 1 00:16:05 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * gc.c (rb_gc_call_finalizer_at_exit): should be clear flags
+ before calling finalizers.
+
+ * eval.c (specific_eval): can be called without SecurityError, if
+ $SAFE >= 4.
+
+ * object.c (sym_inspect): inspect gives ":sym", to_s gives "sym".
+
+Fri Mar 31 22:07:04 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.12.
+
+ * lib/net/protocol.rb: update Net::Protocol::Proxy#connect
+
+ * lib/net/protocol.rb: ReplyCode is not a class
+
+ * lib/net/http.rb: header value format was change:
+ values do not include header name
+
+ * lib/net/http.rb: header is not a Hash, but HTTPResponse
+
+Thu Mar 30 12:19:44 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * enum.c (enum_find): rb_eval_cmd() should be called with array.
+
+Tue Mar 28 13:57:05 2000 Clemens Hintze <c.hintze@gmx.net>
+
+ * ext/dbm/dbm.c (fdbm_invert): should return new hash.
+
+ * ext/gdbm/gdbm.c (fgdbm_invert): ditto.
+
+Tue Mar 28 00:58:03 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.11.
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: does not
+ dispatch any commands while dispatching command.
+
+ * lib/net/protocol.rb: failed to get error class of
+ inherited ReplyCode
+
+ * lib/net/http.rb: change feature of "get2", "post2"
+
+Mon Mar 27 01:34:58 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.10.
+
+ * lib/net/http.rb: return value of 'head' was wrong.
+
+Sun Mar 26 17:47:35 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.9.
+
+ * lib/net/smtp.rb: SMTP#do_ready wrongly took no arguments
+
+Sat Mar 25 23:21:10 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * marshal.c (w_object): symbols should be converted to ID before
+ dumping out.
+
+Sun Mar 25 16:52:48 2001 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * file.c (rb_file_flock): do not trap EINTR.
+
+ * missing/flock.c (flock): returns the value from lockf(2)
+ directly.
+
+Fri Mar 24 18:26:51 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * file.c (test_check): should have checked exact number of arguments.
+
+Fri Mar 24 21:02:11 2000 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * signal.c (trap): should treat some symbols as the signal.
+
+Fri Mar 24 06:58:03 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.8.
+
+ * lib/net/http.rb: post, get2, post2, get_body
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: separate
+ Command/Socket documentation.
+
+Thu Mar 23 02:26:14 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_fptr_finalize): fptr may be null.
+
+ * io.c (rb_io_s_new): now calls `initialize'.
+
+ * io.c (rb_io_initialize): actual open done in this method.
+
+ * io.c (rb_file_initialize): ditto.
+
+ * eval.c (rb_eval): class variables in singleton class definition
+ is now handled properly (I hope).
+
+Wed Mar 22 21:49:36 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * st.c (st_delete_safe): skip already deleted entry.
+
+ * hash.c (rb_hash_delete): modify brace miss.
+
+Wed Mar 22 08:53:58 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (exec_under): do not push cbase if ruby_cbase == under.
+
+ * node.h (NEW_CREF0): preserve cbase nesting.
+
+Tue Mar 21 12:57:50 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (rb_class_s_new): Class::new should call `inherited'.
+
+Sat Mar 18 12:36:09 2000 Nobuyoshi Nakada <nobu.nokada@softhome.net>
+
+ * eval.c (rb_backtrace, make_backtrace): removed unused variable
+ `lev'.
+
+ * eval.c (rb_attr): calls `method_added' at attribute definition.
+
+ * eval.c (rb_mod_modfunc): calls `singleton_method_added' while
+ `module_function'.
+
+ * eval.c (rb_eval): parameter to `method_added' and
+ `singleton_method_added' is Symbol.
+
+ * eval.c (Init_eval): caches IDs for `method_added' and
+ `singleton_method_added'.
+
+Sat Mar 18 11:25:10 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (rescue): allows `rescue Error in foo'. experimental.
+ which is better this or preparing alias `exception' for `$!'?
+
+Fri Mar 17 15:02:45 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (rb_autoload_id): defining new autoload should be
+ prohibited for $SAFE > 4.
+
+ * variable.c (rb_autoload_load): autoload should be possible for
+ $SAFE > 4.
+
+ * eval.c (call_trace_func): should handle T_ICLASS properly.
+
+Fri Mar 17 14:34:30 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_gsub): forgot to initialize str->orig.
+
+Fri Mar 17 01:24:59 2000 Dave Thomas <Dave@thomases.com>
+
+ * string.c (rb_str_clone): forgot to copy str->orig if STR_NO_ORIG
+ is set by Array#pack.
+
+Wed Mar 15 21:25:04 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * array.c (rb_ary_join): 'result' is always duplicated
+ before concat string.
+
+Wed Mar 15 17:26:05 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (rb_hash_s_create): unexpected recursive call removed.
+ this bug was found by Satoshi Nojo <nojo@t-samukawa.or.jp>.
+
+Wed Mar 15 13:12:39 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (Init_Thread): Thread.join removed finally.
+
+ * string.c (rb_str_chomp_bang): forgot to call rb_str_modify().
+
+Mon Mar 13 16:12:13 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (block_pass): distinguish real orphan block and still
+ on-stack block passed by block argument.
+
+Mon Mar 13 00:20:25 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (f_norm_arg): proper error message when constant comes
+ in formal argument list. this message is suggested by Muvaw
+ Pnazte <bugathlon@yahoo.com>.
+
+ * eval.c (rb_f_raise): proper error message when the first
+ argument is not an exception class/object.
+
+ * string.c (rb_str_dup): dup now postpone buffer copy as long as
+ possible. performance improved by lazy copying.
+
+Sun Mar 12 13:58:52 2000 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * signal.c (rb_f_kill): should treat some symbols as the signal.
+
+Sat Mar 11 22:03:03 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_gsub): performance tune by avoiding buffer copy.
+
+ * eval.c (rb_f_missing): check if argv[0] is ID.
+
+Sat Mar 11 15:49:41 2000 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * struct.c (rb_struct_aref): struct aref by symbol.
+
+Sat Mar 11 05:07:11 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * process.c (proc_setpriority): should return 0, not nil.
+
+ * process.c (proc_setpgid): ditto.
+
+Fri Mar 10 18:14:54 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * file.c (path_check_1): confusing buf and path. this bug found
+ by <decoux@moulon.inra.fr>.
+
+Fri Mar 10 09:37:49 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * MANIFEST: add beos/GNUmakefile.in.
+ * configure.in: support BeOS R4.5.2 (Intel).
+ * beos/GNUmakefile.in: new file to support BeOS R4.5.2 (Intel).
+
+Thu Mar 9 11:13:32 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_fastmap): fixed embarrassing brace bug.
+
+Thu Mar 9 01:36:32 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * missing/flock.c: emulate missing flock() with fcntl().
+
+Thu Mar 9 00:29:35 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (sym_to_s): returns ":sym".
+
+ * object.c (sym_id2name): separated from to_s; returns "sym".
+
+Wed Mar 8 19:16:19 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.7.
+
+ * lib/net/http.rb (connecting): returns header
+
+Wed Mar 8 02:08:43 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y: escape expansion too early.
+
+ * string.c (rb_f_scan): Kernel#scan added.
+
+ * regex.c (re_compile_pattern): support \cX et al.
+
+Tue Mar 7 01:44:27 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (set_stdin): simplified procedure, allows $stdin = DATA;
+ experimental.
+
+ * io.c (set_outfile): ditto.
+
+ * re.c (Init_Regexp): new method Regexp#last_match added; it's an
+ alternative for $~.
+
+ * configure.in (DEFAULT_KCODE): KCODE_NONE should be the default.
+
+ * dir.c (dir_s_rmdir): should return 0 on success.
+
+ * signal.c: remove CWGUSI support.
+
+Mon Mar 6 12:28:37 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * marshal.c (w_symbol): support symbol object.
+
+ * util.c: make symbol as separated class.
+
+ * error.c (Init_Exception): new exception RangeError.
+
+ * ext/socket/socket.c (ip_addrsetup): should check length of hostname.
+
+ * ext/socket/socket.c (ip_addrsetup): check newline at the end of
+ hostname. These fixes suggested by Muvaw Pnazte <bugathlon@yahoo.com>.
+
+Sun Mar 5 20:35:45 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ext/Win32API/Win32API.c (Win32API_initialize): should call
+ LoadLibrary() everytime and should assign the hdll to Win32API
+ object(protect the hdll from GC).
+
+Sun Mar 5 18:49:06 2000 Nakada.Nobuyoshi <nobu.nokada@softhome.net>
+
+ * misc/ruby-mode.el (ruby-parse-region): not treat method `begin'
+ and `end' as reserved words.
+
+ * misc/ruby-mode.el (ruby-font-lock-docs): ignore after `=begin'
+ and `=end'.
+
+ * misc/ruby-mode.el (ruby-font-lock-keywords, hilit-set-mode-patterns):
+ added `yield' to keywords.
+
+ * misc/ruby-mode.el (ruby-font-lock-keywords, hilit-set-mode-patterns):
+ matches keywords at end of buffer.
+
+Sun Mar 5 18:08:53 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.6.
+
+ * lib/net/http.rb: allow to omit 'start'
+
+Tue Feb 29 01:08:26 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * range.c (range_initialize): initialization done in `initialize';
+ `initialize' should not be called more than once.
+
+ * object.c (Init_Object): default `initialize' should take zero
+ argument.
+
+ * time.c (time_s_new): call `initialize' in Time::new.
+
+Sat Feb 26 22:39:31 2000 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * string.c (rb_str_times): fix String#* with huge string.
+
+Sat Feb 26 00:14:59 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * dir.c (dir_s_new): call `initialize' in Dir::new.
+
+Fri Feb 25 23:01:49 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ruby.h: export ruby_safe_level by EXTERN for mswin32.
+ * win32/ruby.def: regular maintenance.
+
+Fri Feb 25 22:12:46 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_reopen): IO#reopen should accept path as well.
+
+ * string.c (rb_str_s_new): call `initialize' in String::new.
+
+ * hash.c (rb_hash_s_new): call `initialize' in Hash::new.
+
+ * array.c (rb_ary_s_new): call `initialize' in Array::new.
+
+Fri Feb 25 12:50:20 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_start_timer): interval changed to 10ms from 50ms.
+
+Fri Feb 25 06:42:26 2000 GOTOU YUUZOU <gotoyuzo@notwork.org>
+
+ * ext/socket/socket.c (ip_addrsetup): hostp should remain NULL if
+ host is nil.
+
+Thu Feb 24 16:53:47 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_schedule): priority check for sleep expired
+ threads needed.
+
+Wed Feb 23 14:22:32 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (rb_ary_join): forgot to initialize a local variable
+ `taint'.
+
+Tue Feb 22 07:40:55 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (Init_Regexp): renamed to MatchData, old name MatchingData
+ remain as alias.
+
+Tue Feb 22 00:20:21 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/protocol.rb, smtp.rb, pop.rb, http.rb: 1.1.5.
+
+ * lib/net/session.rb: rename to protocol.rb
+
+ * lib/net/protocol.rb: ProtocolSocket -> Net::Socket
+
+ * lib/net/protocol.rb: Net::Socket#write, write_pendstr
+ can take block
+
+ * lib/net/smtp.rb: new methods SMTP#ready SMTPCommand#write_mail
+
+ * lib/net/pop.rb: POPMail#pop can take block
+
+Sat Feb 19 23:58:51 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): pop_loop should not pop at forward jump.
+
+Fri Feb 18 17:15:40 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (method_clone): method objects are now clonable.
+
+Fri Feb 18 00:27:34 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (rb_shared_variable_declare): shared variable (aka
+ class/module variable) introduced. prefix `@@'. experimental.
+
+ * class.c (rb_scan_args): new format char '&'.
+
+Thu Feb 17 19:09:05 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * win32/win32.c (mypopen): don't close handle if it is not assigned.
+ * win32/win32.c (my_open_osfhandle): support O_NOINHERIT flag.
+ * win32/win32.c (win32_getcwd): rename getcwd to win32_getcwd
+ in order to avoid using the C/C++ runtime DLL's getcwd.
+ Use CharNext() to process directory name.
+ * win32/win32.h: map getcwd to win32_getcwd.
+
+Wed Feb 16 00:32:49 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (method_arity): nd_rest is -1 for no rest argument.
+
+ * process.c (proc_waitpid): returns nil when waitpid(2) returns 0.
+
+Tue Feb 15 01:47:00 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * process.c (rb_f_waitpid): pid_t should be signed.
+
+Mon Feb 14 13:59:01 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): yylex yields wrong tokens for `:foo=~expr'.
+
+ * ruby.c (load_file): exit if reading file is empty.
+
+Mon Feb 14 03:34:52 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): `foo.bar=1' should be <foo><.><bar><=><1>,
+ not <foo><.><bar=><1>.
+
+ * eval.c (rb_thread_restore_context): process according to
+ RESTORE_* is moved after longjmp().
+
+ * eval.c (thread_switch): new function to process RESTORE_*.
+
+Sun Feb 13 16:19:49 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ruby.c (require_libraries): don't access freed memory.
+
+ * ruby.c (add_modules): ditto.
+
+Fri Feb 11 12:06:22 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (parse_quotedwords): %w() need to split not only by mere
+ spaces, but by all whitespaces.
+
+Thu Feb 10 02:12:04 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_index_m): did not support negative offset.
+
+Wed Feb 9 21:54:26 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ext/socket/getaddrinfo.c: gcc --traditional support.
+ Rearrange headers to work AC_C_CONST.
+ * ext/socket/getnameinfo.c: ditto.
+ * ext/socket/socket.c: mswin32: use double instead of long long.
+
+Wed Feb 9 16:30:41 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * numeric.c (num_coerce): should return [y, x].
+
+Wed Feb 9 11:07:30 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (ruby_prog_init): loadpath structure changed.
+
+Tue Feb 8 02:07:33 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_search): optimize for \G at top.
+
+ * regex.c (re_compile_pattern): \G introduced.
+
+ * regex.c (re_match): ditto.
+
+ * string.c (str_sub_bang): old behavior restored: bang method
+ returns nil if string not changed.
+
+ * regex.c (re_compile_pattern): support independent subexpression
+ `(?>pattern)'.
+
+ * regex.c (re_match): ditto.
+
+Mon Feb 7 15:51:08 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): now understands interrupts under Ruby.
+
+Mon Feb 7 07:51:52 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (rb_ary_uniq_bang): always return an Array.
+
+ * array.c (rb_ary_compact_bang): ditto.
+
+ * array.c (rb_ary_flatten_bang): ditto.
+
+ * hash.c (rb_hash_reject): returns a Hash, not an Array.
+
+ * hash.c (env_reject): ditto.
+
+Fri Feb 4 10:20:25 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (scan_once): scan now leaves information about the last
+ successful pattern match in $&.
+
+ * io.c (rb_io_close): should not check closed IO.
+
+Fri Feb 4 05:44:01 2000 Kentaro Inagaki <inagaki@tg.rim.or.jp>
+
+ * ext/socket/socket.c (s_recv): TRAP_BEG after retry entry.
+
+Wed Feb 2 22:33:45 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * eval.c (rb_thread_start): receives argument from outside, like
+ `Thread::start(1,2,3){|a,b,c| ... }'.
+
+Wed Feb 2 22:14:40 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (rb_reg_regsub): should check regs->num_regs.
+
+ * re.c (rb_reg_search): remove matchcache, use static struct
+ re_register instead.
+
+ * re.c (match_getter): avoid cloning match data.
+
+Wed Feb 2 17:12:15 2000 Dave Thomas <Dave@Thomases.com>
+
+ * samples/eval.rb: Rescue new ScriptError exception
+
+Wed Feb 2 02:06:07 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_gsub_bang): gsub! now leaves information about the
+ last successful pattern match in $&.
+
+Mon Jan 31 15:24:58 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_sub_bang): bang method returns string always.
+ experimental.
+
+Sun Jan 30 17:58:09 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * eval.c: arrange to use setitimer(2) for BOW, DJGPP
+
+ * defines.h: ditto. use random(3) on cygwin b20.1.
+
+Sun Jan 30 17:20:16 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * eval.c: use getrlimit(2) on DJGPP.
+
+Thu Jan 27 01:27:10 2000 GOTO Kentaro <gotoken@math.sci.hokudai.ac.jp>
+
+ * dir.c (glob): glob pattern "/*" did not match.
+
+Wed Jan 26 22:30:47 2000 Shigeo Kobayashi <shigeo@tinyforest.gr.jp>
+
+ * numeric.c (flo_modulo): wrong result for negative modulo.
+
+Wed Jan 26 02:01:57 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * file.c (test_c): should use S_ISCHR.
+
+ * file.c (rb_stat_c): ditto.
+
+ * string.c (rb_str_each_line): should propagate tainting.
+
+Tue Jan 25 04:01:34 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (rb_obj_freeze): all objects made freezable.
+
+Tue Jan 25 00:37:01 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in: use AC_CHECK_TOOL for cross compiling.
+
+Mon Jan 24 19:01:54 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * array.c (rb_protect_inspect): should be checked by id of
+ objects; not by object themselves.
+
+Mon Jan 24 18:48:08 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * eval.c (rb_eval): too many warnings; warned on every method
+ overriding. should be on method discarding.
+
+Mon Jan 24 02:56:44 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): -2.abs should be `(-2).abs' to accomplish the
+ principle of less surprise. `+2' too.
+
+ * eval.c (rb_eval): when defining class is already there, and
+ superclass differ, throw away the old class.
+
+ * variable.c (rb_const_set): gives warning again on constant
+ redefinition.
+
+ * error.c (Init_Exception): SyntaxError, NameError, LoadError and
+ NotImplementError are subclasses of ScriptError<Exception, not
+ StandardError. experimental.
+
+Sat Jan 22 00:00:41 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (parse_quotedwords): no longer use `String#split'.
+ and enable space escape within quoted word list.
+ e.g. %w(a\ b\ c abc) => ["a b c", "abc"].
+
+ * string.c (rb_str_slice_bang): new method `slice!'.
+
+Fri Jan 21 21:56:08 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/session.rb, smtp.rb, pop.rb, http.rb: 1.1.4.
+
+ * lib/net/http.rb: can receive messages which have
+ no Content-Length:.
+
+Fri Jan 21 16:15:59 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (thgroup_s_new): new class ThreadGroup.
+
+Tue Jan 18 12:24:28 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * struct.c (Init_Struct): remove Struct's own hash and eql?.
+
+Sat Jan 15 22:21:08 2000 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * eval.c (search_method): argument klass may be 0.
+
+Sat Jan 15 15:03:46 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * enum.c (enum_index): remove this method.
+
+ * enum.c: remove use of pointers to local variables. find,
+ find_all, min, max, index, member?, each_with_index,
+
+ * eval.c (massign): multiple assignment does not use to_a anymore.
+ experimental.
+
+Fri Jan 14 12:22:04 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_replace): use memmove instead of memcpy for
+ overwrapping strings (e.g. a[1] = a).
+
+Thu Jan 13 11:12:40 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (arg_add): use new node, ARGSPUSH.
+
+Mon Jan 10 18:32:28 2000 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * marshal.c (w_object): forgot an argument to call w_ivar().
+
+Sun Jan 9 18:13:51 2000 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * random.c: first was not defined unless HAVE_RANDOM.
+
+Sat Jan 8 19:02:49 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_sysread): raise IOError for buffered IO.
+
+ * ext/socket/socket.c (s_recv): ditto.
+
+Fri Jan 7 00:59:29 2000 Masahiro Tomita <tommy@tmtm.org>
+
+ * io.c (io_fread): TRAP_BEG/TRAP_END added around getc().
+
+Thu Jan 6 00:39:54 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * random.c (rb_f_rand): should be initialized unless srand is
+ called before.
+
+Wed Jan 5 16:59:34 2000 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/session.rb, smtp.rb, pop.rb, http.rb: 1.1.3.
+
+ * lib/net/session.rb: Session -> Protocol, ...
+
+ * lib/net/http.rb: HTTPCommand implementation was changed.
+
+Wed Jan 5 02:14:46 2000 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * parse.y: Fix SEGV on empty parens with UMINUS or UPLUS.
+
+Tue Jan 4 22:25:54 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (stmt): `() while cond' dumped core.
+
+Tue Jan 4 06:04:14 2000 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * configure.in: modify for cross-compiling.
+ use target_* instead of host_*.
+ use AC_CANONICAL_TARGET.
+
+ * Makefile.in: ditto.
+
+ * cygwin/GNUmakefile.in: ditto.
+
+Sat Jan 1 13:26:14 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_yield_0): force_recycle ruby_dyna_vars to gain
+ performance.
+
+ * array.c (rb_ary_delete_at_m): takes same argument pattern with
+ rb_ary_aref.
+
+Sat Jan 1 10:12:26 2000 Nobuyoshi Nakada <nobu.nokada@softhome.net>
+
+ * ruby.h,util.c (rb_special_const_p): peep hole optimization.
+
+ * ruby.h,util.c (rb_test_false_or_nil): removed.
+
+ * ruby.h (RTEST, SPECIAL_CONST_P): peep hole optimization.
+
+ * ruby.h (FL_ABLE, FL_SET, FL_UNSET, FL_REVERSE): made expressions
+ not statements.
+
+ * ruby.h (OBJ_INFECT): newly added macro which copies taint from
+ `s' to `x'.
+
+Sat Jan 1 02:04:18 2000 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_safe_level): new method.
+
+ * eval.c (rb_yield_0): recycle dyna_var_map to reduce object
+ allocation.
+
+Fri Dec 31 00:52:48 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c: thread independent trace_func not needed.
+
+Thu Dec 30 14:47:31 1999 akira yamada <akira@ruby-lang.org>
+
+ * configure.in: specifies -soname in LIBRUBY_DLDFLAGS on linux
+ platforms.
+
+Thu Dec 30 10:51:27 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c,io.c,hash,c,re.c,string.c: `_m' suffix instead of
+ `_method' for wrapper functions to implement method,
+ e.g. `rb_str_join_m()'.
+
+Thu Dec 30 02:08:02 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (rb_cstr2inum): non-numeric format check added.
+ currently it works only with base == 0 (i.e. Integer()).
+
+ * bignum.c (rb_str2inum): now takes VALUE to 1st argument. null
+ byte check added.
+
+ * array.c (rb_ary_replace): unless replacement is an array,
+ replacement shall be converted to array by `[replacement]', not
+ by `replacement.to_a'.
+
+ * array.c (rb_ary_plus): right operand must be an array.
+
+ * array.c (rb_ary_concat): argument must be an array.
+
+Mon Dec 27 12:35:47 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ext/socket/socket.c (sock_finalize): mswin32: fix socket handle leak.
+
+ * win32/win32.c (myfdclose): ditto.
+
+Sun Dec 26 23:15:13 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * win32/win32.c (mypopen): raise catchable error instead of rb_fatal.
+ * win32/win32.c (mypclose): fix process handle leak.
+
+Sun Dec 26 16:17:11 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ext/Win32API/Win32API.c (Win32API_initialize): use UINT2NUM
+ instead of INT2NUM to set __dll__ and __proc__.
+
+Sat Dec 25 00:08:59 1999 KANEKO Naoshi <wbs01621@mail.wbs.ne.jp>
+
+ * ext/Win32API/Win32API.c (Win32API_Call): remove 'dword ptr'
+ from _asm.
+
+Fri Dec 24 10:26:47 1999 Koji Oda <oda@bsd1.qnes.nec.co.jp>
+
+ * win32/win32.h: use "C++" linkage.
+
+Fri Dec 24 02:00:57 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (THREAD_ALLOC): should initialize th->trace.
+
+Fri Dec 24 00:43:39 1999 KANEKO Naoshi <wbs01621@mail.wbs.ne.jp>
+
+ * io.c (pipe_open): check for `fptr->f == NULL'.
+ * win32/win32.c (mypopen): STDERR does not work during ` function.
+
+Wed Dec 22 22:50:40 1999 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/session.rb, smtp.rb, pop.rb, http.rb: 1.1.2.
+
+ * lib/net/http.rb: HTTP support is enhanced a little
+
+ * lib/net/http.rb: support proxy
+
+Tue Dec 21 17:21:28 1999 Koji Oda <oda@bsd1.qnes.nec.co.jp>
+
+ * ext/socket/socket.c (sock_finalize): mswin32: fix FILE* leak.
+
+Tue Dec 21 05:33:56 1999 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/session.rb, smtp.rb, pop.rb, http.rb: 1.1.1.
+
+ * lib/net/http.rb: support HTTP chunk
+
+Mon Dec 20 19:08:12 1999 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * file.c (rb_file_s_expand_path): handle dir separator correctly.
+
+Sun Dec 19 22:56:31 1999 KANEKO Naoshi <wbs01621@mail.wbs.ne.jp>
+
+ * lib/find.rb: support dosish root directory.
+ * win32/Makefile: ditto.
+ * win32/config.status: ditto.
+ * win32/win32.c (opendir): ditto.
+ * win32/win32.c (opendir): use CharPrev() to get last character
+ of the directory name.
+
+Sat Dec 18 03:00:01 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * file.c (path_check_1): check should be done by absolute path.
+
+ * marshal.c (r_ivar): should restore generic_ivar too.
+
+ * marshal.c (w_ivar): should dump generic_ivar too.
+
+Fri Dec 17 22:46:46 1999 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/session.rb, smtp.rb, pop.rb, http.rb: 1.1.0.
+
+ * lib/net/http.rb: test release
+
+ * lib/net/session.rb: support class swapping
+
+ * lib/net/session.rb: Socket#flush_rbuf
+
+ * lib/net/session.rb: doquote -> Net.quote
+
+Fri Dec 17 19:27:43 1999 IWAMURO Motonori <iwa@mmp.fujitsu.co.jp>
+
+ * eval.c (rb_load): should initialize ruby_frame->last_class.
+
+Wed Dec 15 01:35:29 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (proc_options): option to change directory changed to
+ `-C' like tar.
+
+ * ruby.c (proc_options): argv boundary check for `-X'.
+
+Mon Dec 13 15:15:31 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_adjust_startpos): separate startpos adjustment
+ because of major performance drawback.
+
+ * class.c (rb_singleton_class): tainted status of the singleton
+ class must be synchronized with the object.
+
+ * eval.c (rb_thread_schedule): implement thread priority.
+
+Sat Dec 11 03:34:38 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * gc.c (mark_hashentry): key should be VALUE, not ID.
+
+ * io.c (argf_eof): should check next_p too.
+
+Thu Dec 9 18:09:13 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * error.c (exc_set_backtrace): forgot to declare a VALUE argument.
+
+Thu Dec 9 14:19:31 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (rb_obj_taint): explicit tainting must be prohibited at
+ level 4 to prevent polluting trusted object by untrusted code.
+
+ * file.c: file operations (stat, lstat, chmod, chown, umask,
+ truncate, flock) are prohibited in level 2 (was level 4).
+
+Wed Dec 8 11:48:23 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_f_require): prohibiting require() in the secure mode
+ cause serious autoloading error.
+
+ * variable.c (rb_obj_instance_variables): don't need to prohibit
+ to get list of instance variable names of untainted objects.
+
+ * variable.c (rb_ivar_get): don't need to prohibit to get instance
+ variables of untainted objects.
+
+ * variable.c (rb_mod_remove_const): should prohibit constant
+ removals too.
+
+Wed Dec 8 09:23:01 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_eval): should try autoloading before defining
+ class/module at the toplevel.
+
+Tue Dec 7 22:15:30 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * configure.in: Modified rb_cv_rshift_sign detect routine and
+ more simple/fast RSHIFT() for hpux-10.x.
+
+Tue Dec 7 11:16:30 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (Init_eval): calculate stack limit from rlimit where
+ getrlimit(2) is available.
+
+Tue Dec 7 09:57:33 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * file.c (rb_file_ftype): should have removed mode_t.
+
+Mon Dec 6 15:55:30 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * numeric.c (fix_rshift): Fix -1 >> 32 returned 0 (should be -1).
+
+ * numeric.c (fix_rshift): Fix 1 >> -1 returned 0 (should be 2).
+
+Mon Dec 6 11:47:23 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sprintf.c (rb_f_sprintf): formatted string must be tainted if
+ any of parameters is a tainted string.
+
+ * file.c (rb_file_s_expand_path): expanded file path need not to
+ be tainted always.
+
+Sun Dec 5 20:25:29 1999 Katsuhiro Ueno <unnie@blue.sky.or.jp>
+
+ * eval.c (Init_Proc): simple typo.
+
+ * gc.c (add_heap): sizeof(RVALUE*), not sizeof(RVALUE).
+
+Sat Dec 4 01:40:22 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_search): adjust startpos for multibyte match unless
+ the first pattern is forced byte match.
+
+ * bignum.c (rb_big_rand): should not use rand/random where drand48
+ may be available. RANDOM_NUMBER should be provided from outside.
+
+Fri Dec 3 09:54:59 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (moreswitches): there may be trailing garbage at #!
+ line.
+
+ * eval.c (rb_f_require): should check require 'feature.o' too.
+
+Thu Dec 2 11:58:15 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * eval.c (rb_thread_loading): should maintain loading_tbl.
+
+Thu Dec 2 10:21:43 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_loading_done): wrong parameter to st_delete().
+
+Wed Dec 1 11:24:06 1999 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * ruby.c (process_sflag): process -s properly (should not force `--').
+
+Wed Dec 1 09:47:33 1999 Kazunori NISHI <kazunori@swlab.csce.kyushu-u.ac.jp>
+
+ * string.c (rb_str_split_method): should increment end too.
+
+Tue Nov 30 18:00:45 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * marshal.c: MARSHAL_MINOR incremented; format version is 4.2.
+
+ * marshal.c (w_object): distinguish class and module.
+
+ * marshal.c (w_object): save hash's default value.
+
+ * marshal.c (r_object): restore hash's default value.
+
+Tue Nov 30 01:46:18 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (rb_reg_source): generated source string must be tainted if
+ regex is tainted.
+
+ * file.c (rb_file_s_basename): basename should not be tainted
+ unless the original path is tainted.
+
+ * file.c (rb_file_s_dirname): ditto.
+
+Mon Nov 29 20:42:13 1999 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * file.c (stat_new): Struct::Stat -> File::Stat; Stat is no longer
+ a Struct.
+
+Mon Nov 29 15:28:52 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (rb_path2class): evaluated value from path should be
+ module or class.
+
+Fri Nov 26 18:12:49 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_exec_end_proc): should remove only end_procs defined
+ within load wrapper.
+
+ * eval.c (rb_load): save and restore ruby_wrapper around loading.
+
+ * eval.c (rb_mark_end_proc): mark end procs registered by END{} or
+ at_exit{}.
+
+ * eval.c (rb_set_end_proc): should not call rb_global_variable()
+ on heap address; it crashed mod_ruby.
+
+Mon Nov 22 14:07:24 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * ruby.c (proc_options): variable e_script should be visited by
+ garbage collector.
+
+Sat Nov 20 10:10:41 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (inspect_i): value may be nil, check revised.
+
+Fri Nov 19 18:06:21 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * dir.c (glob): recursive wildcard match by `**' ala zsh.
+
+Fri Nov 19 11:44:26 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * variable.c: was returning void value.
+
+Fri Nov 19 03:57:22 1999 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * file.c: add methods Stat struct class to reduce stat(2).
+
+Thu Nov 18 16:18:27 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * lib/pstore.rb: mutual lock by flock(2).
+
+Thu Nov 18 11:44:13 1999 Masahiro Tomita <tommy@tmtm.org>
+
+ * io.c (read_all): should check bytes too.
+
+Wed Nov 17 02:40:40 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (Init_IO): $defout (alias of $>) added.
+
+Tue Nov 16 09:47:14 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * lib/pstore.rb: add mutual lock using symlink.
+
+Mon Nov 15 16:50:34 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * enum.c (enum_grep): non matching grep returns an empty array, no
+ longer returns nil.
+
+ * enum.c (enum_grep): grep with block returns collection of
+ evaluated values of block over matched elements.
+
+Mon Nov 15 04:50:33 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * re.c (rb_reg_source): should not call rb_reg_expr_str()
+ everytime.
+
+Sat Nov 13 07:34:18 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (rb_mod_constants): traverse superclasses to collect
+ constants.
+
+ * eval.c (assign): modified for shared variables.
+
+ * eval.c (rb_eval): search nested scope, then superclasses to
+ assign shared variables within methods.
+
+ * eval.c (rb_eval): remove warnings from constants modification,
+ because they are no longer constants.
+
+ * parse.y (node_assign): modified for shared variables.
+
+ * parse.y (assignable): allow constant assignment in methods;
+ constants should be called `shared variable'.
+
+Fri Nov 12 23:52:19 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * process.c (rb_f_system): argument check for NT, __EMX__, DJGPP.
+
+Wed Nov 10 21:54:11 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * hash.c (rb_any_cmp): Fixed return without value.
+
+Wed Nov 10 17:57:06 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sprintf.c: incorporate <yasuf@big.or.jp>'s sprintf patch at
+ [ruby-dev:7754].
+
+Wed Nov 10 08:28:53 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_call0): supply class parameter for each invocation.
+
+Tue Nov 9 13:21:04 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * configure.in: AC_MINIX move to before AC_EXEEXT and AC_OBJEXT.
+
+Mon Nov 8 19:52:29 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * configure.in: Renamed AC_CHAR_UNSIGNED to AC_C_CHAR_UNSIGNED.
+
+ * configure.in: Added default to AC_CHECK_SIZEOF().
+
+Mon Nov 8 14:28:18 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (stmt): rescue modifier added to the syntax.
+
+ * keywords: kRESCUE_MOD added.
+
+ * eval.c (rb_f_eval): fake outer scope when eval() called without
+ bindings.
+
+ * eval.c (rb_f_binding): should copy last_class in the outer frame too.
+
+Sun Nov 7 18:31:04 1999 Yasuhiro Fukuma <yasuf@big.or.jp>
+
+ * eval.c (is_defined): last_class may be 0.
+
+Sat Nov 6 19:26:55 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * Makefile.in: Added depend entry make parse.@OBJEXT@ from parse.c
+ for UCB make
+
+Thu Nov 4 17:41:18 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): \< (wordbeg), \> (wordend) disabled.
+
+Wed Nov 3 08:52:57 1999 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
+
+ * io.c (Init_IO): forgot to use INT2FIX() around SEEK_SET, etc.
+
+Wed Nov 3 00:25:20 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_split_method): use mbclen2() to handle kcode
+ option of regexp objects.
+
+Mon Nov 1 14:22:15 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * eval.c (rb_eval): reduce recursive calls to rb_eval()
+ case of ||= and &&= .
+
+Sun Oct 31 13:12:42 1999 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * regex.c (re_compile_pattern): wrong [\W] match.
+
+Fri Oct 29 16:57:30 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/nkf/lib/kconv.rb: new String methods (kconv, tojis, toeuc,
+ tosjis).
+
+ * time.c (time_s_at): now accepts optional second argument to
+ specify micro second.
+
+Thu Oct 28 13:35:40 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_split_method): should be mbchar aware with
+ single char separators.
+
+Wed Oct 27 12:57:21 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * random.c (rb_f_srand): random seed should be unsigned.
+
+Tue Oct 26 23:58:15 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (rb_ary_collect): collect for better performance.
+
+Tue Oct 26 19:20:54 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * marshal.c (r_object): should register class/module objects.
+
+Sat Oct 23 15:59:39 1999 Takaaki Tateishi <ttate@jaist.ac.jp>
+
+ * process.c (rb_f_system): should require at least one argument.
+
+Sat Oct 23 12:42:44 1999 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * enum.c (enum_collect): collect without block will collect
+ elements in enumerable.
+
+Thu Oct 21 16:14:19 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (moreswitches): function to process string option;
+ the name is stolen from perl (not implementation).
+
+ * ruby.c (proc_options): use RUBYOPT environment variable to
+ retrieve the default options.
+
+ * dir.c (fnmatch): use eban's fnmatch; do not depend on system's
+ fnmatch (which may have portability problem) anymore.
+
+Wed Oct 20 15:14:24 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * marshal.c (marshal_load): should protect the generated object
+ table (arg->data) from GC.
+
+Mon Oct 18 16:15:52 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/nkf/nkf.c (rb_nkf_kconv): output should be NUL terminated.
+
+Mon Oct 18 09:03:01 1999 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/session.rb, smtp.rb, pop.rb: 1.0.3
+
+ * lib/net/pop.rb: new methods POP3Command#uidl, POPMail#uidl.
+
+Sun Oct 17 03:35:33 1999 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
+
+ * array.c (rb_ary_pop): forgot some freeze checks.
+
+Sat Oct 16 12:57:53 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * array.c (rb_ary_sort): always returns the copied array.
+
+Fri Oct 15 22:50:41 1999 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * error.c (sys_nerr): on CYGWIN, it is _sys_nerr.
+
+Fri Oct 15 01:32:31 1999 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * io.c (rb_io_ctl) :need to use NUM2ULONG, not NUM2INT.
+
+ * ext/Win32API/Win32API.c (Win32API_Call): need to use NUM2ULONG,
+ not NUM2INT.
+
+Fri Oct 15 00:22:30 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (Init_Regexp): super class of the MatchingData, which was
+ Data, to be Object.
+
+ * eval.c (ruby_run): evaluate required libraries before load &
+ compiling the script.
+
+ * parse.y (lex_getline): retrieve a line from the stream, saving
+ lines in the table in debug mode.
+
+ * eval.c (call_trace_func): treat the case ruby_sourcefile is null.
+
+Thu Oct 14 02:00:10 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (string): compile time string concatenation.
+
+Wed Oct 13 07:28:09 1999 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/session.rb, smtp.rb, pop.rb: 1.0.2
+
+ * lib/net/session.rb: new method Session#set_pipe.
+
+ * lib/net/session.rb, smtp.rb, pop.rb: add RD documentation.
+
+Wed Oct 13 02:17:05 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * array.c (rb_ary_plus): remove recursion.
+
+ * array.c (rb_ary_sort_bang): detect modify attempt.
+
+Wed Oct 13 02:17:05 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (block_pass): should copy block to prevent modifications.
+ tag in the structure should be updated from latest prot_tag.
+
+ * eval.c (proc_s_new): tag in struct BLOCK should not point into
+ unused stack.
+
+ * dir.c (dir_s_glob): iterate over generated matching filenames if
+ the block is given to the method.
+
+ * array.c (rb_ary_at): new methods; at, first, last.
+
+ * hash.c (rb_hash_fetch): raises exception unless the default
+ value is supplied.
+
+ * hash.c (rb_hash_s_create): need not remove nil from value.
+
+ * hash.c (rb_hash_aset): setting value to nil does not remove key
+ anymore.
+
+Tue Oct 12 22:29:04 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (io_read): length may be 0 or negative.
+
+Tue Oct 12 13:26:27 1999 Jun-ichiro itojun Hagino <itojun@itojun.org>
+
+ * signal.c (posix_signal): RETSIGTYPE may be void.
+
+Tue Oct 12 03:28:03 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * array.c (rb_ary_delete_at): allows negative position.
+
+Mon Oct 11 17:42:25 1999 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * parse.y (rb_intern): should generate distinct ID_ATTRSET symbols
+ for the name with multiple `='s at the end.
+
+ * Makefile.in (CPPFLAGS): separate cpp flags from CFLAGS.
+
+Mon Oct 11 07:27:05 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_eval): should not execute the `else' clause on the
+ case the exceptions are handled by the `rescue' clause.
+
+ * signal.c (Init_signal): ignore SIGPIPE by default.
+
+Wed Oct 6 17:13:19 1999 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * ruby.c (addpath): rubylib_mangled_path() modified.
+
+Mon Oct 4 12:42:32 1999 Kazuhiko Izawa <izawa@erec.che.tohoku.ac.jp>
+
+ * pack.c (pack_unpack): % in printf format should be %%.
+
+Mon Oct 4 10:01:40 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (rb_obj_instance_variables): should always return
+ array for all object can have instance variables now.
+
+Mon Oct 4 00:08:34 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * pack.c (OFF16): need to adjust pointer address to pack/unpack on
+ 64bit machines.
+
+Sun Oct 03 03:05:59 1999 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * time.c (time_arg): mktime y2k problem.
+
+Sun Sep 26 16:54:45 1999 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * parse.y (here_document): `\r' handling for here documents.
+
+Wed Sep 22 09:20:11 1999 Masahiro Tomita <tommy@tmtm.org>
+
+ * ext/socket/socket.c: SOCKS5 support.
+
+Wed Sep 22 07:33:23 1999 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/session.rb, smtp.rb, pop.rb: 1.0.1
+
+ * lib/net/pop.rb: APOP did not work.
+
+ * lib/net/pop.rb: modify the way to make APOP challenge.
+
+Wed Sep 22 00:35:30 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_include): should return boolean value.
+
+ * regex.c (re_compile_fastmap): wrong comparison with mbc.
+
+ * eval.c (specific_eval): default sourcefile name should be
+ "(eval)" for module_eval etc.
+
+Wed Sep 22 00:06:07 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * win32/Makefile: update rules.
+
+ * io.c (io_fread): should not assign in char, it maybe -1.
+
+Tue Sep 21 23:57:54 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (call_trace_func): should not propagate retval in
+ trace_func.
+
+Mon Sep 20 21:35:39 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * win32/win32.c (myselect): assume non socket files are always
+ readable/writable.
+
+Mon Sep 20 01:08:02 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (io_fread): should not block other threads.
+
+ * io.c (rb_io_synchronized): renamed from rb_io_unbuffered(); do
+ not call setbuf(NULL) anymore.
+
+Sat Sep 18 13:45:43 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * stable version 1.4.2 released.
+
+Fri Sep 17 23:24:17 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * eval.c (rb_f_missing): dumped core if no argument given.
+
+Fri Sep 17 23:21:06 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * win32/win32.c (myselect): translate WSAEINTR, WSAENOTSOCK into
+ UNIX errno constants.
+
+Fri Sep 17 00:52:27 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (arg): assignable() may return 0.
+
+Thu Sep 16 20:46:23 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * eval.c (rb_eval): was doubly evaluating the return expression.
+
+Thu Sep 16 18:40:08 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * stable version 1.4.1 released.
+
+Thu Sep 16 11:33:22 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * string.c (rb_str_match): should return nil.
+
+Wed Sep 15 22:46:37 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (rb_reg_s_quote): should quote `-' too.
+
+Tue Sep 14 15:23:22 1999 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
+
+ * parse.y (yylex): no need to ignore `\r' here.
+
+ * parse.y (nextc): strip `\r' from text.
+
+ * parse.y (nextc): support `__END__\r\n' type terminator.
+
+Mon Sep 13 10:49:19 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * eval.c (rb_eval): needless RTEST(ruby_verbose) removed.
+
+Mon Sep 13 09:10:11 1999 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/net/session.rb, smtp.rb, pop.rb: 1.0.0
+
+Wed Sep 8 11:37:38 1999 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * time.c (make_time_t): bit more strict comparison.
+
+Tue Sep 7 00:50:56 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * range.c (range_each): use rb_str_upto() for strings.
+
+ * string.c (rb_str_upto): set upper limit by comparing curr <= end.
+
+ * range.c (range_each): should check equality to handle magic
+ increment.
+
+Mon Sep 6 22:43:33 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_eval): break/next/redo available within -n/-p loop.
+
+Fri Sep 3 11:14:31 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * compar.c (cmp_equal): should not raise exception; protect by
+ rb_rescue().
+
+Thu Sep 2 05:23:05 1999 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * file.c (rb_file_s_expand_path): use dirsep, instead of character
+ literal '/'.
+
+ * file.c (rb_file_s_expand_path): reduce multiple dirsep at the top.
+
+Wed Sep 1 00:28:27 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_call): call rb_undefined() if a method appears not to
+ be exist explicitly from cache.
+
+ * eval.c (rb_method_boundp): check method cache before calling
+ rb_get_method_body().
+
+ * eval.c (rb_get_method_body): store method non-existence
+ information in the cache.
+
+ * random.c (rb_f_srand): use getpid(2) to generate seed.
+
+ * regex.c (re_match): do not apply partial mbc match for
+ charset_not.
+
+ * regex.c (re_compile_pattern): put extended literal prefix (0xff)
+ only before numeric literals, not before all >0x80 char.
+
+ * regex.c (re_compile_pattern): put numeric literal in extended
+ charset region, not normal charset bits.
+
+ * regex.c (re_compile_fastmap): calculate fastmap for charset and
+ charset_not to treat numeric literal (e.g. \246) specially.
+
+Fri Aug 28 17:32:55 1999 Yasuhiro Fukuma <yasuf@big.or.jp>
+
+ * eval.c (rb_eval): should set return value (nil) explicitly if a
+ value is omitted for return statement.
+
+Thu Aug 26 15:06:11 1999 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
+
+ * gc.c (rb_gc): local variables may be placed beyond stack_end, so
+ use an address from alloca(1) on non C_ALLOCA platforms.
+
+Thu Aug 26 01:24:17 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sprintf.c (rb_f_sprintf): "%%" is legal, but "%3.14%" is not.
+
+Mon Aug 23 00:00:54 1999 Tsukada Takuya <tsukada@fminn.nagano.nagano.jp>
+
+ * regex.c (re_compile_fastmap): wrong macro caused memory leak.
+
+Sat Aug 21 11:30:51 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (ADJ): should not adjust addresses to data on heap.
+
+Fri Aug 20 20:50:58 1999 Kenji Nagasawa <kenn@hma.att.ne.jp>
+
+ * defines.h (PATH_SEP): path separator is ";" for OS/2.
+
+Thu Aug 19 10:50:43 1999 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * gc.c (rb_gc): add volatile to avoid GCC optimize bug(?).
+
+Wed Aug 18 23:48:10 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * due to disk trouble, some change records were lost. several
+ modification made to eval.c, gc.c, io.c, pack.c,
+ ext/extmk.rb.in, and lib/mkmf.rb.
+
+Fri Aug 13 15:41:39 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * stable version 1.4.0 released.
+
+Fri Aug 13 03:16:07 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (argf_forward): since $stdout may be non-IO, ARGF.file is
+ not guaranteed to be IO. check and forwarding added to every ARGF
+ method.
+
+ * io.c (set_outfile): $stdout/$stderr may not be IO now.
+
+ * io.c (set_stdin): $stdin may not be IO now.
+
+ * range.c (rb_range_beg_len): round `end' to length as documented.
+
+ * io.c (Init_IO): preserve original stdin/stdout/stderr.
+
+Thu Aug 12 13:44:33 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (Init_load): require receives 1 argument.
+
+ * eval.c (frame_dup): should clear tmp to avoid dangling
+ references.
+
+Wed Aug 11 13:33:13 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * eval.c (rb_eval): no automatic aggregate initialization.
+
+ * eval.c (module_setup): ditto.
+
+Wed Aug 11 18:18:41 1999 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * eval.c (yield_under_i): automatic aggregate initialization is an
+ ANSI feature.
+
+Wed Aug 11 10:10:02 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): parse `[].length==0' as `([].length)==0', not
+ `([].length=)=0'
+
+ * parse.y (yylex): parse `[].length!=0' as `([].length)!=0', not
+ `([].length!)=0'
+
+ * parse.y (peek): peek-in lexical buffer.
+
+Wed Aug 11 00:34:05 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): bug on backward jump adjustment concerning
+ stop_paren.
+
+Tue Aug 10 14:54:25 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/nkf/nkf.c (rb_nkf_guess): binary detection was wrong.
+
+Tue Aug 10 00:07:36 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_clone): should use CLONESETUP().
+
+Mon Aug 9 23:57:07 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.h (CLONESETUP): should have copied generic instance
+ variables too.
+
+Mon Aug 9 10:46:54 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ext/socket/extconf.rb: add check for <arpa/nameser.h> and
+ <resolv.h>.
+
+Sat Aug 7 13:19:06 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * numeric.c (flo_cmp): comparing NaN should not return value.
+ raises FloatDomainError.
+
+Sat Aug 7 03:09:08 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (blk_free): free copied frames too.
+
+ * eval.c (frame_dup): should copy previous frames from stack to
+ heap to preserve frame information.
+
+Fri Aug 6 15:01:07 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.3.7 - version 1.4 beta
+
+ * ext/socket/socket.c (s_recv): UDPsocket#recvfrom now returns
+ IPsocket#addr information.
+
+ * array.c (rb_ary_subary): ary[-3,3] should not return nil.
+
+Thu Aug 5 10:58:01 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (thread_mark): protect old ruby_frame from GC during it
+ replaced by eval().
+
+ * eval.c (eval): do not modify frame.prev; binding should preserve
+ information about calling() too.
+
+ * eval.c (rb_yield_0): no arity check for mere yield; but only for
+ Proc#call.
+
+Tue Aug 3 22:07:13 1999 Kazuhiro HIWADA <hiwada@kuee.kyoto-u.ac.jp>
+
+ * object.c (rb_mod_clone): should check if iv_tbl, m_tbl are
+ initialized.
+
+Tue Aug 3 19:03:02 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (rb_any_cmp): use rb_with_disable_interrupt() to ensure
+ clearance of rb_prohibit_interrupt even on failure.
+
+ * eval.c (rb_with_disable_interrupt): new function added.
+
+Sat Jul 31 23:23:44 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_create_0): set THREAD_RAISED flag on thread
+ termination by exception.
+
+ * eval.c (rb_thread_join): `$!' may not be nil for the threads
+ created in rescue clause.
+
+ * eval.c (rb_thread_status): ditto.
+
+ * eval.c (rb_thread_join): should re-raise exception for already
+ dead threads too.
+
+Fri Jul 30 17:56:54 1999 GOTO Kentaro <gotoken@math.sci.hokudai.ac.jp>
+
+ * object.c (rb_mod_ge): wrong comparison.
+
+Fri Jul 30 12:15:44 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ext/tcltklib/extconf.rb: win32 support.
+
+ * lib/mkmf.rb: use append_library().
+
+ * ext/extmk.rb.in: ditto.
+
+Fri Jul 30 02:11:48 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (rb_ary_delete): should return nil for deleting non
+ existing item.
+
+ * io.c (rb_io_close): call rb_sys_wait() on explicit close.
+
+ * io.c (rb_io_fptr_close): do not call rb_sys_wait() on finalize.
+
+ * eval.c (yield_under_i): cbase context should be maintained for
+ Module#module_eval(). suggested by <inaba@st.rim.or.jp>.
+
+Wed Jul 28 01:18:28 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * Makefile.in: add -I$(hdrdir)/lib to install using ftools.
+
+ * util.c: use HAVE_FCNTL_H, not HAVE_FCNTL
+
+Wed Jul 28 18:24:45 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.3.6 - version 1.4 alpha
+
+Tue Jul 27 09:38:08 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * eval.c (rb_eval): reduce recursive rb_eval() calls by
+ NODE_BLOCKs.
+
+Tue Jul 27 01:20:40 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * file.c (rb_file_s_expand_path): drive letter patch.
+
+Mon Jul 26 02:36:31 1999 Shugo Maeda <shugo@netlab.co.jp>
+
+ * eval.c (rb_load): should clear ruby_nerr.
+
+ * eval.c (rb_thread_join): oldbt should not be empty to unshift.
+
+Sun Jul 25 12:09:16 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * dir.c (push_braces): should treat nested braces.
+
+Fri Jul 23 02:49:49 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (rb_hash_clear): dummy argument added; suggested by
+ <eguchi@shizuokanet.ne.jp>. thanks.
+
+Thu Jul 22 19:37:22 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_join): get_backtrace() may return Qnil.
+ typecheck added.
+
+Tue Jul 20 14:36:43 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * range.c (range_each): do not treat String specially (for future
+ override).
+
+Tue Jul 20 02:28:34 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_gets): $_ should be nil, when get returns nil.
+
+ * io.c (rb_f_gets): ditto.
+
+Mon Jul 19 17:13:09 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_fastmap): should continue fastmap compile
+ for anychar_repeat, for it's repeat anyway.
+
+Mon Jul 26 13:33:45 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * lib/jcode.rb: replaced by faster code.
+
+Mon Jul 19 01:57:28 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * lib/mkmf.rb: no longer use install program.
+
+ * ext/extmk.rb.in: use miniruby to install programs.
+
+Sat Jul 17 00:06:21 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/socket/socket.c (ipaddr): don't do reverse lookup if
+ attribute do_not_reverse_lookup is set for socket classes.
+ Experimental. Note this is a global attribute.
+
+Fri Jul 16 22:18:29 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_eof): use feof() to check EOF already met.
+
+ * io.c (read_all): should return nil at EOF.
+
+Fri Jul 16 13:39:42 1999 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/telnet.rb: version 0.231.
+
+Fri Jul 16 10:58:22 1999 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * regex.c (re_match): debug print removed.
+
+Fri Jul 16 09:58:15 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * many files: clean up unused variables found by gcc -Wall.
+
+ * lib/mkmf.rb: better cygwin support etc.
+
+ * ext/extmk.rb.in: ditto.
+
+ * instruby.rb: ditto.
+
+Fri Jul 16 01:37:50 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * string.c (rb_str_squeeze_bang): the type of local variable `c'
+ should be int, not char.
+
+ * string.c (rb_str_reverse): should always return copy.
+
+Thu Jul 15 23:25:57 1999 NAKAMURA Hiroshi <nakahiro@sarion.co.jp>
+
+ * lib/debug.rb: better display & frame treatment.
+
+Thu Jul 15 21:16:41 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (rb_ary_each): returns self for normal termination;
+ returns nil for break.
+
+ * string.c: non bang methods (e.g. String#sub) should always
+ return copy of the receiver.
+
+Thu Jul 15 21:09:15 1999 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
+
+ * eval.c (find_file): do not add empty string to the path.
+
+ * configure.in (with-search-path): should not add empty string if
+ the option is not supplied.
+
+Thu Jul 15 17:49:08 1999 Ryo HAYASAKA <hayasaka@univ21.u-aizu.ac.jp>
+
+ * ext/tcltklib/tcltklib.c: move `#include "ruby.h"' forward.
+
+Thu Jul 15 16:54:16 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.3.5 - version 1.4 alpha
+
+Wed Jul 14 23:45:33 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * eval.c (ruby_init): initialize for the first time only.
+
+Tue Jul 13 00:15:19 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (rb_hash_index): re-defined; method to retrieve a key
+ from the value.
+
+ * hash.c (Init_Hash): member? should be re-defined for Hash.
+
+Tue Jul 12 13:54:51 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * io.c (rb_file_sysopen): wrong number of argument.
+
+Mon Jul 12 11:52:35 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_f_missing): class name included in message.
+
+ * eval.c (print_undef): better error message.
+
+Sun Jul 11 05:36:17 1999 NAKAMURA, Hiroshi <nakahiro@sarion.co.jp>
+
+ * lib/debug.rb: patch to show proper position.
+
+Fri Jul 9 23:56:14 1999 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * dln.c (dln_find_1): path conv. moved to conv_to_posix_path.
+
+ * dln.c (conv_to_posix_path): path conv. should be done.
+
+Fri Jul 9 10:26:47 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * random.c (RANDOM_NUMBER): should place parentheses.
+
+Fri Jul 8 11:00:51 1999 Shugo Maeda <shugo@netlab.co.jp>
+
+ * numeric.c (fix_div): division may be out of fixnum range.
+
+ * bignum.c (bigdivmod): proper sign calculation to result.
+
+Wed Jul 7 18:27:41 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * st.c (st_delete_safe): was modifying wrong slot.
+
+Mon Jul 5 13:17:46 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * gc.c (rb_gc_call_finalizer_at_exit): close all files at exit.
+
+Fri Jul 2 18:00:21 1999 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * lib/Mail/README: Mail-0.3.0 added to the distribution.
+
+Fri Jul 2 01:45:32 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_fastmap): avoid allocation of register
+ variables for each invocation of re_match(). Suggested by
+ Zasukhin Ruslan <ruslan@paradigmasoft.com>. Thanks.
+
+Tue Jun 29 20:39:24 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * ext/tk/lib/tk.rb (TkVariable): bug fix; should value type check
+ be added?
+
+ * string.c (rb_str_each_line): a bug in paragraph mode.
+
+ * ruby.c (load_file): shifted too much to skip #!.
+
+Tue Jun 29 06:50:21 1999 Wakou Aoyama <wakou@fsinet.or.jp>
+
+ * lib/CGI.rb: 0.30 - cleanup release, incompatible.
+
+ * lib/telnet.rb: 0.22 - timeout added.
+
+Tue Jun 29 10:49:25 1999 SHIROYAMA Takayuki <psi@fortune.nest.or.jp>
+
+ * configure.in: better Rhapsody support.
+
+ * lib/mkmf.rb: Rhapsody/NEXTSTEP support.
+
+Tue Jun 29 01:42:13 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/pty/pty.c (chld_changed): should use POSIX.1 style wait.
+
+Mon Jun 28 21:07:36 1999 KIMURA Koichi <kbk@kt.rim.or.jp>
+
+ * ext/extmk.rb.nt: wrong result for have_library().
+
+Mon Jun 28 15:24:05 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * missing/isinf.c: OSF/1 raises SIGFPE on one()/zero().
+
+ * regex.c (re_search): should search til EOS, for patterns may
+ match beyond the end of range.
+
+Mon Jun 28 12:49:12 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_f_select): should not accept Time objects as an
+ argument for it is time interval.
+
+ * process.c (rb_f_sleep): ditto.
+
+ * file.c (test_s): should return nil for false condition.
+
+Mon Jun 28 12:23:52 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * bignum.c (rb_dbl2big): typo.
+
+ * file.c (rb_f_test): ditto.
+
+ * string.c (rb_str_crypt): wrong message.
+
+Sun Jun 27 19:50:11 1999 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * eval.c (rb_f_exit): should have treat signed integer status, not
+ VALUE.
+
+ * process.c (rb_f_exit_bang): should work like exit().
+
+Sun Jun 27 16:21:32 1999 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * string.c (rb_str_rindex): wrong position to search.
+
+Sat Jun 26 04:05:30 1999 Takaaki Tateishi <ttate@jaist.ac.jp>
+
+ * configure.in (configure_args): --with-search-path to specify
+ additional ruby search path.
+
+ * ruby.c (ruby_prog_init): additional search path.
+
+Fri Jun 25 13:09:12 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * pack.c (pack_unpack): needed to initialize natint.
+
+ * regex.c (re_compile_pattern): add start_paren to avoid too much
+ finalization on maybe_finalize_jump.
+
+Fri Jun 25 13:07:20 1999 Koji Oda <oda@bsd1.qnes.nec.co.jp>
+
+ * missing/isinf.c: include "config.h" added.
+
+Fri Jun 25 07:25:05 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * lib/mkmf.rb: initialize $(topdir).
+
+ * ext/extmk.rb.in (install_rb): install lib/*.rb properly.
+
+ * configure.in (linux): specifies -rpath on --enable-shared.
+
+ * configure.in (aix): ruby.imp must reside in $(topdir).
+
+Thu Jun 24 19:11:29 1999 Yoshida Masato <yoshidam@yoshidam.net>
+
+ * parse.y (rb_str_extend): multi-byte identifier in expression
+ interpolation in strings.
+
+ * parse.y (yylex): support multi-byte char identifiers.
+
+Thu Jun 24 15:27:13 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (f_arg): check duplicate argument names.
+
+ * gc.c (rb_gc_mark): marking wrong member for NODE_ARGS.
+
+ * string.c (rb_str_rindex): POSITION specifies start point, not
+ end point.
+
+Thu Jun 24 13:00:17 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (print_mbc): wrong boundary.
+
+ * pack.c (uv_to_utf8): raises ArgError for too big value.
+
+Thu Jun 24 11:02:51 1999 Yoshida Masato <yoshidam@yoshidam.net>
+
+ * pack.c (uv_to_utf8): mask needed.
+
+Wed Jun 23 21:03:56 1999 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * ruby.h (struct RFile): remove iv_tbl from struct. instance
+ variables are handled as generic ivs.
+
+Wed Jun 23 22:06:26 1999 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * pack.c (utf8_to_uv): pack to 7 bytes sequence.
+
+ * pack.c (uv_to_utf8): wrong boundary.
+
+ * pack.c (pack_unpack): should treat as unsigned long.
+
+Wed Jun 23 15:10:11 1999 Inaba Hiroto <inaba@sdd.tokyo-sc.toshiba.co.jp>
+
+ * parse.y (parse_string): failed to parse nested braces.
+
+ * parse.y (parse_regx): nested braces within #{} available.
+
+Wed Jun 23 11:18:38 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (slow_search): wrong shift width for mbcs.
+
+ * eval.c (rb_thread_save_context): should not clear th->locals.
+
+Wed Jun 23 02:06:14 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): UMINUS binds too tight with digits. changed so
+ that -2**2 => -4.
+
+ * parse.y (close_paren): `do' for expr termination now works it
+ used to be.
+
+Wed Jun 22 18:26:42 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * pack.c (pack_pack): should initialize local variable `j'.
+
+Wed Jun 22 15:24:59 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * parse.y (here_document): a bug for multiline heredoc.
+
+Tue Jun 22 15:06:36 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * ext/socket/socket.c (ruby_socket): forgot to return fd
+ explicitly.
+
+Tue Jun 22 13:34:12 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * rubyio.h (MakeOpenFile): should initialize member `iv_tbl'.
+
+Wed Jun 22 10:35:51 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * io.c (rb_io_gets_internal): getc(3) may not set errno on
+ interrupt.
+
+Mon Jun 21 22:39:28 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (call_required_libraries): ruby_sourceline should be
+ cleared before loading libraries.
+
+ * io.c (set_stdin): do not use reopen(), so that we don't need to
+ dup original stdin before assigning $stdin.
+
+Mon Jun 21 18:04:27 1999 Ryo HAYASAKA <hayasaka@univ21.u-aizu.ac.jp>
+
+ * ext/dbm/dbm.c: include <cdefs.h> for solaris 2.6.
+
+Mon Jun 21 15:59:47 1999 Nobuyoshi Nakada <nobu.nokada@softhome.net>
+
+ * ext/socket/socket.c (ip_addrsetup): forgot to put `else'.
+
+Mon Jun 21 15:38:37 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (fptr_finalize): remove rb_syswait() invocation to avoid
+ wait4(2) within GC. rb_syswait() moved to rb_io_fptr_close().
+
+Mon Jun 21 12:05:59 1999 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * dir.c (dir_s_glob): remove MAXPATHLEN restriction.
+
+ * ext/md5/md5init.c (md5_hexdigest): should have used "%02x".
+
+Sun Jun 20 19:50:38 1999 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * string.c (rb_str_each_line): should have checked string
+ boundary.
+
+Sat Jun 19 22:24:12 1999 Kenji Nagasawa <kenn@hma.att.ne.jp>
+
+ * OS/2 patch improved.
+
+Fri Jun 18 08:30:17 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * marshal.c (r_byte): add data length check.
+
+ * ext/tcltklib/tcltklib.c (_timer_for_tcl): was doing busy-wait.
+
+Tue Jun 15 10:01:21 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * configure.in: remove trailing slash from interpreter embedded
+ shared library path.
+
+ * configure.in (INSTALL_DLLIB): install shared lib with 0555.
+
+ * instruby.rb: changed mode for shared library into 0555.
+
+Fri Jun 11 23:27:00 1999 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * ext/etc/etc.c (etc_passwd): should return nil, not exception for
+ call after last passwd entry.
+
+Fri Jun 11 15:21:21 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * gc.c (rb_gc_mark_locations): add safety margin 1.
+
+ * eval.c (ruby_run): should protect toplevel node tree.
+
+ * ext/etc/etc.c (etc_group): dumps core if there's no more group.
+
+Fri Jun 11 01:50:25 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (ruby_run): Init_stack() was called too late; local
+ variables happened to be higher (or lower) than stack_start.
+
+Thu Jun 10 16:41:48 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c: do not call `initialize' for IO objects. So with Array,
+ Hash, Range, and Time objects.
+
+ * ext/curses/curses.c (curses_getch): made thread aware using
+ rb_read_check().
+
+ * ext/curses/curses.c (window_getch): ditto.
+
+ * ext/curses/curses.c (curses_getstr): made (partially) thread
+ aware using rb_read_check().
+
+ * ext/curses/curses.c (window_getstr): ditto.
+
+ * io.c (rb_read_check): new function to help making something
+ (like extension libraries) thread aware.
+
+ * eval.c (is_defined): `defined? super' should be true even for
+ private superclass methods.
+
+Fri Jun 10 13:42:10 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * pack.c (pack_pack): template `Z' should be allowed.
+
+Wed Jun 9 13:26:38 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_loading): modified to avoid nested race
+ condition of require().
+
+ * ext/tcltklib/tcltklib.c (ip_invoke): queue invocation on non
+ main threads.
+
+ * ext/tcltklib/tcltklib.c (lib_mainloop): flush invocation
+ queues periodically.
+
+ * version.c (ruby_show_version): now print the message to stdout.
+
+ * version.c (ruby_show_copyright): ditto.
+
+Tue Jun 8 00:00:34 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * pack.c (pack_unpack): append sentinel (NUL) to the string.
+
+ * ext/md5/md5init.c (md5_hexdigest): new method to obtain
+ printable hash string.
+
+ * ext/md5/md5init.c (md5_update): should return self.
+
+ * pack.c (pack_pack): undocumented template 'U' for UTF8.
+
+ * pack.c (pack_unpack): ditto.
+
+ * marshal.c (r_byte): should replace getc() with rb_getc().
+
+ * io.c (rb_getc): getc() replacement uses READ_DATA_PENDING() and
+ rb_thread_wait_fd().
+
+Mon Jun 7 23:23:38 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (rb_mod_clone): should call CLOSESETUP().
+
+ * eval.c (bind_clone): should call CLONESETUP() for new clone.
+
+Sat Jun 5 10:32:40 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_oct): binary (e.g. 0b10111) support.
+
+ * variable.c (rb_const_set): raise warning, not exception.
+
+ * parse.y (yycompile): initialize parser internal variables.
+
+ * parse.y (close_paren): set lex_state to EXPR_PAREN after closing
+ parenthesis.
+
+ * parse.y (yylex): returns kDO for `do' right after method_call.
+
+Thu Jun 3 11:05:30 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * regex.c (read_backslash): should decode \b within class.
+
+Thu Jun 3 01:06:18 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * dln.c (dln_load): AIX improvement (aix_findmain removed).
+
+Wed Jun 2 00:41:31 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * pack.c (pack_unpack): new undocumented template Z which strips
+ stuff after first null.
+
+ * pack.c (pack_pack): should preserve specified length of the
+ resulting string.
+
+Tue Jun 1 15:29:33 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/socket/socket.c (ruby_socket): retry after GC, if socket(2)
+ failed on EMFILE or ENFILE.
+
+ * ext/socket/socket.c (sock_s_socketpair): ditto.
+
+ * eval.c (module_setup): need to add PUSH_VAR/POP_VAR to clear
+ dyna vars link list.
+
+ * version.h (RUBY_RELEASE_CODE): integer macro constant for source
+ version detection.
+
+Sun May 30 22:19:12 1999 Kenji Nagasawa <kenn@tcp-ip.or.jp>
+
+ * ext/socket/socket.c: emx/gcc 0.9d now fixes things about
+ AF_UNIX.
+
+ * process.c: OS/2 EMX kludge.
+
+ * Makefile.in (strncasecmp.o): added dependency.
+
+Mon May 31 16:06:28 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.3.4 - preliminary release for 1.4
+
+Mon May 31 15:57:41 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_fptr_close): close on IO which main_thread is
+ waiting cause serious exception, that vanishes the actual fd
+ closing. Invocation of rb_thread_fd_close() is deferred
+ a little.
+
+Sat May 29 18:27:13 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * regex.c (re_match): stack boundary check needed.
+
+Sat May 29 12:27:00 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_invoke): proper ref count management
+ to avoid leak. I HATE REF COUNTING!!
+
+ * eval.c (ruby_run): moved ruby_require_libraries() to handle `-r'
+ from ruby_options() to avoid stack corruption for threads
+ created in libraries.
+
+Sat May 29 02:22:12 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_yield_0): when `for' appeared in blocks, it
+ introduced new scope for local variables.
+
+Fri May 28 17:16:49 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_squeeze_bang): squeeze AND of the arguments.
+ UNDOCUMENTED.
+
+ * string.c (rb_str_count): new UNDOCUMENTED method.
+
+ * string.c (rb_str_delete_bang): delete AND of the arg ranges.
+ UNDOCUMENTED FEATURE for 1.3.x.
+
+ * ext/socket/socket.c (setipaddr): re-wrote using ip_addrsetup().
+
+ * ext/socket/socket.c (ip_addrsetup): decode symbolic address
+ <broadcast>.
+
+Thu May 27 12:27:42 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (tr_trans): should handle NUL (\0) within strings.
+
+Tue May 25 16:45:11 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_f_syscall): syscall may return values other than zero
+ on success.
+
+ * regex.c (re_match): handle empty loop properly (hopefully).
+
+ * regex.c (re_match): remove empty group check, because it does
+ not help non-grouping parentheses (?:..).
+
+ * regex.c (re_compile_fastmap): treating try_next, finalize_push
+ wrong way.
+
+ * regex.c: remove some obsolete functions such as
+ group_match_null_string_p().
+
+Mon May 24 14:47:54 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (read_backslash): read backslash by regex.
+
+Sun May 23 19:44:58 1999 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ext/pty/pty.c (getDevice): portability patch.
+
+Fri May 21 23:01:26 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ext/socket/getaddrinfo.c (GET_AI): should set error code.
+
+Thu May 20 03:43:44 1999 Jun-ichiro itojun Hagino <itojun@itojun.org>
+
+ * ext/socket/socket.c: you should use sockaddr_storage to handle
+ IPv6 addresses.
+
+ * ext/socket/getaddrinfo.c (getaddrinfo): prevent retrieving
+ AF_INET6 address if hints.ai_flags == AI_PASSIVE.
+
+Wed May 19 12:27:07 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (exec_end_proc): should protect exceptions.
+
+ * gc.c (run_final): ditto.
+
+ * parse.y (f_rest_arg): allow just * for rest arg.
+
+ * parse.y (mlhs_basic): allow * without formal argument.
+
+ * regex.c (re_match): the variable `part' should be initialized.
+
+Tue May 18 15:25:45 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_search): a bug in range adjustment.
+
+Tue May 18 11:35:59 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * dln.c (conv_to_posix_path): path_len argument added.
+
+Mon May 17 12:26:31 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * numeric.c (fix_rev): should treat Fixnum as signed long.
+
+ * eval.c (massign): add strict number check for yield (and call).
+
+ * eval.c (proc_arity): new method to return number of arguments.
+
+ * eval.c (method_arity): new method to return number of arguments.
+
+ * parse.y (read_escape): char may be unsigned.
+
+ * string.c (rb_str_succ): ditto.
+
+ * string.c (tr_trans): ditto.
+
+ * object.c (Init_Object): methods `&', `|', `^' are added to nil.
+
+ * range.c (rb_range_beg_len): it should be OK for [0..-len-1].
+
+ * regex.c (re_search): search for byte literal within mbcs.
+
+ * regex.c (is_in_list): parsh
+
+ * regex.c (re_compile_fastmap): should have not alter the loop
+ variable `j' if TRASLATE_P().
+
+ * regex.c (re_compile_pattern): escaped characters should be read
+ by PATFETCH_RAW(c).
+
+Sat May 15 11:23:51 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): endline2 (\Z) should not match at the point
+ between a newline and end-of-line, like endline ($).
+
+ * class.c (include_class_new): should initialize iv_tbl to share
+ between module and iclass.
+
+Fri May 14 08:50:27 1999 Akira Endo <akendo@t3.rim.or.jp>
+
+ * regex.c (re_compile_fastmap): it should be k != 0 to skip.
+
+Fri May 14 12:46:56 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (time_load): a bug in old marshal format support.
+
+ * instruby.rb: make site_ruby directory.
+
+Fri May 14 10:18:02 1999 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * regex.c (re_match): a bug in inline `.*' etc.
+
+Fri May 14 09:58:46 1999 Minero Aoki <aamine@dp.u-netsurf.ne.jp>
+
+ * ruby.c (addpath): should have specified string length.
+
+Thu May 13 10:40:44 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_eval_string_wrap): new function.
+
+ * regex.c (re_compile_pattern): POSIX line match should alter
+ behavior for `^' and `$' to begbuf and endbuf2 respectively.
+
+ * ext/pty/pty.c: un-ANSI-fy function arguments.
+
+Wed May 12 14:19:38 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * struct.c (iv_get): in case of inheritance of generated struct
+ class, __member__ and __size__ should also be inherited.
+ Thanks for Pros Yeboah <yeboah@tu-harburg.de>.
+
+ * io.c (rb_f_gets_internal): should check number of arguments
+ before checking rb_rs == rb_default_rs. Thanks for Koji Arai
+ <JCA02266@nifty.ne.jp>.
+
+Tue May 11 08:29:28 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): .?, .+ did not work.
+
+Mon May 10 00:59:33 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * lib/jcode.rb: forgot to squeeze on reverse (complement) case.
+
+ * string.c (tr_squeeze): should not set modify flag to be honest,
+ if the string is not modified.
+
+ * signal.c (Init_signal): SIGTERM should not be handled.
+
+ * regex.c (re_match): seeking for longest match is now optional,
+ which can be set using RE_OPTION_POSIXMATCH. This satisfies
+ POSIX longest match as much as Emacs's posix-* functions, which
+ are known to be incomplete.
+
+Sun May 9 13:04:01 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ext/socket/socket.c (sock_s_getaddrinfo): conversion from
+ Fixnums to C integers needed.
+
+Sun May 9 11:51:43 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * range.c (range_eqq): reverse condition.
+
+ * range.c (range_s_new): default should be end inclusive.
+
+Sat May 8 03:27:51 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/socket/socket.c (thread_connect): replace nasty
+ rb_thread_fd_writable() with rb_thread_select().
+
+Fri May 7 20:49:00 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * ext/socket/getaddrinfo.c (inet_pton): wrong parameter to
+ inet_aton().
+
+ * ext/socket/addrinfo.h (__P): silly cut and paste typo.
+
+Fri May 7 17:03:57 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * dir.c (glob): removed GPL'ed glob.c completely.
+
+Fri May 7 08:17:19 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/sdbm/extconf.rb: sdbm extension added to the distribution.
+
+Fri May 7 01:42:20 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/socket/socket.c (tcp_s_gethostbyname): avoid using struct
+ sockaddr_storage.
+
+Thu May 6 13:21:41 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (rb_ary_indexes): should not use rb_ary_concat().
+
+Thu May 4 12:34:18 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * parse.y (parse_string): there should be newline escape by
+ backslashes in strings.
+
+ * parse.y (parse_qstring): ditto.
+
+Mon May 3 04:37:20 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * ext/tcltklib/extconf.rb: better search for libX11.
+
+ * range.c (range_s_new): embarrassing =/== typo.
+
+ * re.c (Init_Regexp): failed to set default kcode.
+
+Mon May 3 02:39:55 1999 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * ext/socket/socket.c (open_inet): typo (res and res0).
+
+Tue May 4 02:07:49 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * mkconfig.rb: leave undefined $(VARIABLE) unexpanded in the
+ Config::CONFIG hash table.
+
+Mon May 3 09:37:22 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): expand exactn{n} at compile time.
+ handles stop_paren specially.
+
+ * regex.c (re_compile_pattern): expand x{n} at compile time.
+
+ * regex.c (re_search): posix line match should be checked.
+
+ * regex.c (re_search): a bug in anchor condition.
+
+Fri Apr 30 18:57:41 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.3.3
+
+ * string.c (rb_str_rindex): position should be END point, not
+ START point.
+
+ * re.c (rb_reg_search): pos means end point on reverse now.
+
+ * array.c (rb_ary_s_create): should clear ary->ptr to avoid
+ potential gc crash.
+
+Fri Apr 30 15:24:58 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/socket/addrinfo.h: compatibility hack for ipv4.
+
+ * ext/socket/socket.c: itojun's ipv6 patches applied.
+
+ * ext/socket/extconf.rb: detect ipv6 features based on itojun's
+ ipv6 patches.
+
+ * ext/extmk.rb.in (enable_config): can handle --enable-xxx now.
+
+ * lib/mkmf.rb (enable_config): ditto.
+
+Fri Apr 30 05:22:23 1999 Shugo Maeda <shugo@netlab.co.jp>
+
+ * string.c (rb_str_aset): last index should not append.
+
+Thu Apr 29 18:55:31 1999 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * dln.c (conv_to_posix_path): remove const from args.
+
+ * ruby.c (rubylib_mangle): remove Fatal(), the obsolete function.
+
+Tue Apr 27 14:11:45 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (fname): lazy workaround for keywords did not work well.
+
+ * ext/extmk.rb.in: `--with-xxx=yyy' argument configuration.
+
+ * lib/mkmf.rb: ditto.
+
+ * misc/ruby-mode.el: forgot to handle $`.
+
+ * ext/extmk.rb.in: better AIX link support proposed by
+ <komatsu@sarion.co.jp>.
+
+Mon Apr 26 16:46:59 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/extmk.rb.in: AIX shared library support modified.
+
+ * ext/aix_mksym.rb: ditto.
+
+ * configure.in: ditto.
+
+ * sprintf.c (rb_f_sprintf): should allocate proper sized buffer
+ for float numbers.
+
+Sat Apr 24 00:00:16 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (operation): syntax like `a.[]=(1,2)' is allowed.
+
+Fri Apr 23 23:54:09 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (argf_binmode): binmode method added to ARGF.
+
+Fri Apr 23 13:55:22 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_f_chomp): should assign the result to $_. or maybe
+ sub/gsub/chop/chomp should NOT assign $_ altogether.
+
+Thu Apr 22 16:50:54 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_callcc): call scope_dup() for all scopes in
+ the interpreter stack.
+
+Tue Apr 20 11:24:18 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_dump): `#' should be escaped.
+
+Tue Apr 20 02:32:42 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (parse_regx): option /p for posix match added.
+
+ * re.c (rb_reg_desc): did not print options properly.
+
+ * io.c (rb_file_s_open): initialize was called twice.
+
+Mon Apr 19 18:56:21 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * configure.in (DEFAULT_KCODE): can specify default code for
+ $KCODE by --with-default-kcode=(euc|sjis|utf8|none).
+
+ * regex.c (IS_A_LETTER): a byte sequence shorter than mbc should
+ not match with \w etc.
+
+Mon Apr 19 13:49:11 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (eval): should restore ruby_dyna_vars.
+
+Fri Apr 16 21:40:43 1999 Nobuyoshi Nakada <gea02117@nifty.ne.jp>
+
+ * io.c (f_backquote): pipe_open may return nil.
+
+ * io.c (f_open): rb_io_open may return nil.
+
+ * io.c (io_s_foreach): ditto.
+
+ * io.c (io_s_readlines): ditto.
+
+ * io.c (io_defset): wrong message.
+
+Fri Apr 16 15:09:20 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (rb_str2inum): strtoul() returns long, not int.
+
+ * eval.c (rb_load): size of VALUE and ID may be different.
+
+ * util.c (mmprepare): int is too small to cast from pointers.
+
+ * config.guess: avoid 'linux-gnu' for alpha-unknown-linux.
+
+Thu Apr 15 23:46:20 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * ruby.c (rubylib_mangle): mangle path by RUBYLIB_PREFIX.
+
+Wed Apr 14 23:52:51 1999 SHIROYAMA Takayuki <psi@fortune.nest.or.jp>
+
+ * node.h (NODE_LMASK): should be long to avoid overflow.
+
+Wed Apr 14 13:14:35 1999 Katsuyuki Komatsu <komatsu@sarion.co.jp>
+
+ * dln.c: AIX dynamic link.
+
+ * ext/aix_ld.rb: ditto.
+
+Wed Apr 14 12:19:09 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * lib/thread.rb: Queue#{enq,deq} added.
+
+Tue Apr 13 17:43:56 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (rb_hash_s_create): Hash::[] acts more like casting.
+
+Tue Apr 13 00:33:52 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_stdio_set): warning for assignment to the variables
+ $std{in,out,err}.
+
+Mon Apr 12 23:12:32 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_reopen): check for reopening same IO.
+
+Fri Apr 9 17:45:11 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (rb_compile_string): bug for nested eval().
+
+ * regex.c (re_match): should pop non-greedy stack items on
+ failure, after best_regs are fixed.
+
+Thu Apr 8 17:30:40 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * pack.c (PACK_LENGTH_ADJUST): need to adjust for `*' length.
+
+Tue Apr 6 23:28:44 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (void_check): add void context checks.
+
+Mon Apr 5 12:23:42 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (time_s_at): should copy gmt-mode.
+
+ * eval.c (eval_node): preserve ruby_eval_tree.
+
+Fri Apr 2 14:00:34 1999 NAKAMURA, Hiroshi <nakahiro@sarion.co.jp>
+
+ * lib/debug.rb: wrong command interpreting.
+
+Fri Apr 2 11:46:22 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.3.2
+
+Fri Apr 2 10:40:04 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_s_pipe): forgot to define IO::pipe.
+
+Thu Apr 1 14:40:46 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (assign): modified for rhs change.
+
+ * parse.y (stmt): unparenthesisized method calls can be right hand
+ side expression of the assignment.
+
+Sat Mar 27 22:42:47 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * ext/nkf/nkf.c (rb_nkf_kconv): check size output_ctr before
+ decrement.
+
+Thu Mar 25 09:11:03 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (time_s_at): preserve gmt-mode for result.
+
+ * parse.y (rb_compile_string): do not use cur_mid, use
+ compile_for_eval instead.
+
+ * st.c (PTR_NOT_EQUAL): wrong logical condition.
+
+Wed Mar 24 13:06:43 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yycompile): should clear cur_mid after compilation.
+
+ * io.c (next_argv): need to check type for ARGV.shift.
+
+ * eval.c (blk_copy_prev): need to preserve outer scope as well as
+ outer frames.
+
+ * parse.y (rb_compile_string): return can appear within eval().
+
+Tue Mar 23 10:15:07 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * configure.in: AC_C_CONST check added.
+
+Tue Mar 23 02:07:35 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (time_plus): preserve gmt-mode for result.
+
+Mon Mar 22 01:32:37 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_eval): adjust line numbers before expression
+ interpolation within strings.
+
+ * eval.c (rb_eval): defined? returns nil for false condition.
+
+ * numeric.c (num_nonzero_p): returns nil for false condition.
+
+Sat Mar 20 13:07:43 1999 Keiju Ishitsuka <keiju@rational.com>
+
+ * lib/weakref.rb: avoid leak for two weakrefs for one object.
+
+Fri Mar 19 11:26:45 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * eval.c (ruby_run): needed to eval END{} on exit.
+
+ * eval.c (rb_exit): ditto.
+
+Fri Mar 19 02:17:27 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * signal.c (Init_signal): handles terminating signals HUP, TERM,
+ QUIT, PIPE, etc.
+
+Thu Mar 18 15:47:18 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (rb_big_and): bug in sign calculation.
+
+ * bignum.c (rb_big_or): ditto.
+
+ * io.c (rb_f_select): forgot to use to_io to retrieve IO, after
+ calling select(2).
+
+Tue Mar 16 19:54:31 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * ext/extmk.rb.in: static linking cause infinite make loop.
+
+Tue Mar 16 18:50:04 1999 Yoshida Masato <yoshidam@yoshidam.net>
+
+ * ext/socket/socket.c (tcp_s_gethostbyname): typo, not NUM2INT(),
+ but INT2NUM().
+
+ * ext/socket/socket.c (mkhostent): ditto.
+
+Tue Mar 16 12:31:44 1999 Ryo HAYASAKA <hayasaka@cheer.u-aizu.ac.jp>
+
+ * file.c (utime_internal): suppress warning by const.
+
+ * time.c (time_gmtime): ditto.
+
+Tue Mar 16 10:23:05 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (time_clone): Time object can be cloned.
+
+Tue Mar 16 03:13:10 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * ruby.c (load_file): argv[argc] should be NULL.
+
+Mon Mar 15 22:12:08 1999 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * sprintf.c (rb_f_sprintf): typo in arg_num check at exit.
+
+Mon Mar 15 16:42:22 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (rb_ary_dup): dup2 should copy class too.
+
+Mon Mar 15 15:12:53 1999 Yasuhiro Fukuma <yasuf@big.or.jp>
+
+ * lib/mkmf.rb: install program relative path check.
+
+Mon Mar 15 14:05:25 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (rb_reg_s_new): 2nd argument is now option.
+ Regexp::EXTENDED can be specified.
+
+Fri Mar 12 10:47:49 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_index): str.index("") should always match at
+ offset point.
+
+ * string.c (rb_str_upto): can specify end point exclusion.
+
+ * string.c (rb_str_index): negative offset.
+
+ * regex.c (re_match): begline should not match at the point
+ between a newline and end-of-string. endline neither.
+
+ * regex.c (re_compile_pattern): context_indep_anchors .
+
+ * parse.y (parse_regx): need not to push backslashes before
+ escaped characters.
+
+ * eval.c (rb_thread_join): re-raises exception within target.
+
+Fri Mar 12 01:09:36 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * ext/readline/readline.c (readline_s_vi_editing_mode): wrong
+ number of arguments.
+
+Fri Mar 12 02:12:50 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * pack.c (PACK_ITEM_ADJUST): "a".unpack("C3") => [97, nil, nil]
+
+Thu Mar 11 18:23:50 1999 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * ext/socket/socket.c (Init_socket): UDPsocket was omitted.
+
+Thu Mar 11 16:43:30 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * pack.c (PACK_LENGTH_ADJUST): push fixed number of items per
+ template to result array.
+
+ * pack.c (pack_unpack): I/N/C etc. push nil in the array for "".
+
+Tue Mar 9 00:19:21 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (ruby_unsetenv): use ruby_setenv(name, 0).
+
+ * hash.c (env_delete): ditto.
+
+ * string.c (rb_str_upto): do not check `beg<end' to generate
+ strings for the pattern like "a".upto("#a").
+
+ * range.c (range_each): treat strings as special case.
+
+ * range.c (range_each): no longer use upto for generic cases.
+
+Sun Mar 7 14:21:32 1999 IKARASHI Akira <ikarashi@itlb.te.noda.sut.ac.jp>
+
+ * string.c (rb_str_index): wrong end point calculation.
+
+Sat Mar 6 02:19:12 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (match_index): MatchingData#index(n) added.
+
+ * array.c (rb_ary_subseq): ary[n..-1] returns an sub-array unless
+ n is too small negative index.
+
+ * re.c (rb_reg_match_method): Regexp#match(str) added.
+
+ * array.c (rb_ary_indexes): understands ranges as indexes.
+
+ * re.c (match_size): MatchingData#size added.
+
+Fri Mar 5 01:04:57 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (rb_ary_fill): modified for range.
+
+ * array.c (rb_ary_aset): a[n..m] revisited.
+
+Thu Mar 4 14:23:29 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_subseq): a[n..m] revisited.
+
+ * parse.y (method_call): allow Const::method{}.
+
+ * array.c (rb_ary_replace_method): should replace original array.
+
+Thu Mar 4 02:30:22 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * configure.in: remove --disable-thread, thread feature is no
+ longer optional.
+
+Thu Mar 4 00:32:17 1999 Yasuhiro Fukuma <yasuf@big.or.jp>
+
+ * parse.y (read_escape): wrong arguments for scan_oct,scan_hex.
+
+Wed Mar 3 11:51:53 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/socket/socket.c (Init_socket): rename class names as
+ TCPsocket -> TCPSocket etc.
+
+Tue Mar 2 19:46:42 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * configure.in (LDSHARED): use gcc -Wl,-G for solaris with gcc.
+
+Tue Mar 2 17:04:19 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): backslashes do not concatenate comment lines
+ anymore.
+
+Mon Mar 1 14:05:12 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_call0): adjust argv for optional arguments. super
+ without arguments emit superclass method with the value from
+ optional arguments. enabled as experiment.
+
+Sun Feb 28 14:04:07 1999 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * parse.y (nextc): backslash at the eof cause infinite loop
+
+Sun Feb 28 11:01:26 1999 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * time.c (make_time_t): month range check added.
+
+Sat Feb 27 02:36:05 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (Init_Regexp): add escape as alias of quote.
+
+ * re.c (rb_reg_s_quote): char-code can be specified now.
+
+Fri Feb 26 18:45:36 1999 Yasuhiro Fukuma <yasuf@big.or.jp>
+
+ * eval.c (error_print): bug for error message with newlines.
+
+Fri Feb 26 12:00:04 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (make_time_t): future check modified to allow 1969-12-31
+ at certain timezone.
+
+ * time.c (time_arg): year >= 1000 should be past.
+
+ * version.c (Init_version): constant RELEASE_DATE added.
+
+Fri Feb 26 01:08:30 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_substr): returns nil for out-of-range access.
+
+ * array.c (rb_ary_subseq): returns nil for out-of-range access.
+
+ * array.c (rb_ary_store): negative index message has changed.
+
+ * string.c (rb_str_aset): reallocation needed.
+
+ * string.c (rb_str_aset): allow char append to the string.
+
+Thu Feb 25 23:30:17 1999 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * time.c (time_load): tm_year should be packed in 17 bits, not 18.
+
+Thu Feb 25 12:50:25 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * missing/dup2.c: replaced by public domain version.
+
+ * time.c (make_time_t): add `future check' in loops.
+
+ * object.c (rb_num2dbl): forbid implicit conversion from nil, or
+ strings. thus `Time.now + str' should raise error.
+
+ * object.c (rb_Float): convert nil into 0.0.
+
+ * object.c (rb_Integer): conversion method improved.
+
+Thu Feb 25 03:27:50 1999 Shugo Maeda <shugo@netlab.co.jp>
+
+ * eval.c (rb_call): should handle T_ICLASS properly.
+
+Thu Feb 25 00:04:00 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * error.c (Init_Exception): global function Exception() removed.
+
+ * variable.c (rb_class2name): returns "nil"/"true"/"false" for them.
+
+ * time.c (time_dump): time marshaling format compressed size from
+ 11 bytes to 8 bytes. thanx to tadf@kt.rim.or.jp.
+
+ * eval.c (rb_obj_call_init): should specify arguments explicitly.
+
+Wed Feb 24 15:43:28 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): comment concatenation requires preceding space
+ before backslash at the end of line.
+
+ * io.c (rb_f_pipe): global pipe is obsolete now.
+
+ * object.c (Init_Object): remove true.to_i, false.to_i.
+
+Tue Feb 23 14:21:41 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): warn if identifier! immediately followed by `='.
+
+Tue Feb 23 12:32:41 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * eval.c (rb_load): tilde expansion moved to find_file.
+
+ * eval.c (find_file): tilde expansion added.
+
+Tue Feb 23 10:50:20 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (require_method): require can handle multiple fnames.
+
+ * hash.c (rb_hash_foreach_iter): hash key may be nil.
+
+Mon Feb 22 17:44:02 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): should not pop failure point on success for
+ non-greedy matches.
+
+ * io.c (Init_IO): remove global_functions getc, readchar, ungetc,
+ seek, tell, rewind.
+
+Sat Feb 20 22:54:26 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * numeric.c (rb_num2long): no implicit conversion from boolean.
+
+Sat Feb 20 09:58:42 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * numeric.c (flo_to_s): portable Infinity and NaN support.
+
+Sat Feb 20 07:13:31 1999 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * io.c (rb_file_sysopen): forgot to initialize a local variable.
+
+Fri Feb 19 23:05:07 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_subseq): range check changed.
+
+ * marshal.c: increment MARSHAL_MINOR for Time format change.
+
+ * time.c (time_old_load): support old marshal format.
+
+ * time.c (time_load): changed for new format Y/M/D/h/m/s/usec.
+
+ * time.c (time_dump): marshal dump format has changed.
+
+Fri Feb 19 00:25:57 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (time_arg): should reject "sep\0" and such.
+
+ * time.c (time_plus): Time#+ should not receive Time object
+ operand.
+
+ * string.c (rb_str_substr): negative length raises exception now.
+
+ * array.c (beg_len): if end == -1, it points end of the array.
+
+ * array.c (rb_ary_subseq): negative length raises exception now.
+
+Thu Feb 18 20:57:04 1999 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * time.c (rb_strftime): strftime() may return 0 on success too.
+
+ * time.c (time_strftime): `\0' within format string should not be
+ omitted in the result.
+
+ * time.c (rb_strftime): zero length format.
+
+ * time.c (time_to_a): yday start with 1 now.
+
+ * time.c (time_zone): support for long timezone name.
+
+ * time.c (time_yday): yday start with 1 now.
+
+ * time.c (time_minus): minus calculation was wrong.
+
+ * time.c (time_minus): sec, usec should be at least `long', maybe
+ they should be `time_t'.
+
+ * time.c (time_plus): addition with float was wrong.
+
+ * time.c (time_to_s): support for long timezone name.
+
+ * time.c (time_gm_or_local): too far future check moved.
+
+ * time.c (time_arg): treat 2 digit year as 69-99 => 1969-1999,
+ 00-68 => 2000-2068
+
+Thu Feb 18 03:56:47 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * missing/fnmatch.c: moved to missing directory.
+
+Wed Feb 17 16:22:26 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * struct.c (rb_struct_alloc): actual initialization now be done in
+ `initialize'.
+
+Wed Feb 17 09:47:15 1999 okabe katsuyuki <hgc02147@nifty.ne.jp>
+
+ * regex.c (re_search): use mbclen() instead of ismbchar().
+
+ * re.c (rb_reg_s_quote): should handle mbchars properly.
+
+Wed Feb 17 01:25:26 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): stop comment concatenation by backslash follows
+ after >= 0x80 char. may cause problem with Latin chars.
+
+ * eval.c (error_print): exception in rb_obj_as_string() caused
+ SEGV. protect it by PUSH_TAG/POP_TAG.
+
+ * error.c (exc_exception): `Exception#exception' should return self.
+
+Wed Feb 17 01:12:22 1999 Hirotaka Ichikawa <hirotaka.ichikawa@tosmec.toshiba.co.jp>
+
+ * configure.in: BeOS patch.
+
+Tue Feb 16 14:25:00 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): should reallocate mbc space for
+ character class unless current_mbctype is ASCII.
+
+Mon Feb 15 15:48:30 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * configure.in: specify `-Wl,-E' only for GNU ld.
+
+Mon Feb 15 11:43:22 1999 GOTO Kentaro <gotoken@math.sci.hokudai.ac.jp>
+
+ * array.c (rb_inspecting_p): should return Qfalse.
+
+Sun Feb 14 22:36:40 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * sprintf.c (rb_f_sprintf): `%G' was omitted.
+
+Sun Feb 14 12:47:48 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * numeric.c (Init_Numeric): allow divide by zero on FreeBSD.
+
+ * numeric.c (Init_Numeric): FloatDomainError added.
+
+ * configure.in (AC_REPLACE_FUNCS): add checks for functions
+ isinf, isnan, and finite.
+
+Sat Feb 13 01:24:16 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_create_0): should protect th->thread.
+
+Fri Feb 12 16:16:47 1999 Yasuhiro Fukuma <yasuf@big.or.jp>
+
+ * string.c (rb_str_inspect): wrong mbc position.
+
+Fri Feb 12 16:21:17 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_fd_close):
+
+ * io.c (rb_io_fptr_close): tell scheduler that fd is closed.
+
+ * io.c (rb_io_reopen): ditto.
+
+ * io.c (READ_CHECK): check if closed after thread context switch.
+
+ * ext/socket/socket.c (bsock_close_read): do not check
+ the return value from shutdown(2).
+
+ * ext/socket/socket.c (bsock_close_write): ditto.
+
+ * ext/socket/socket.c (sock_new): need to dup(fd) for close_read
+ and close_write.
+
+ * parse.y (here_document): handle newlines within #{}.
+
+ * regex.h: should replace symbols for ruby.
+
+Fri Feb 12 00:46:28 1999 Shugo Maeda <shugo@netlab.co.jp>
+
+ * marshal.c (r_object): should update the method name in message.
+
+ * marshal.c (w_object): limit should be converted into Fixnum.
+
+Wed Feb 10 15:20:03 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): empty pattern should not cause infinite
+ pattern match loop.
+
+ * regex.c (re_compile_pattern): RE_OPTIMIZE_ANCHOR for /.*/, not
+ for /(.|\n)/.
+
+ * numeric.c (fix_pow): `fixnum**nil' should raise TypeError.
+
+ * bignum.c (rb_big_pow): need to normalize results.
+
+Wed Feb 10 01:42:41 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * numeric.c (fix_pow): `(5**1).type' should be Integer.
+
+Tue Feb 9 01:22:49 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): do not ignore newlines in mbchars.
+
+ * io.c (rb_file_s_open): mode can be specified by flags like
+ open(2), e.g. File::open(path, File::CREAT|File::WRONLY).
+
+ * io.c (rb_f_open): bit-wise mode flags for pipes
+
+ * io.c (Init_IO): bit flags for open.
+
+Sat Feb 6 22:56:21 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_sub_bang): should not overwrite match data by
+ regexp match within the block.
+
+ * string.c (rb_str_gsub_bang): ditto.
+
+Sat Feb 6 03:06:17 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (match_getter): accessing $~ without matching caused SEGV.
+
+Fri Feb 5 22:11:08 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * parse.y (yylex): binary literal support, like 0b01001.
+
+ * parse.y (yylex): octal numbers can contain `_'s.
+
+ * parse.y (yylex): warns if non-octal number follows immediately
+ after octal literal.
+
+ * parse.y (yylex): now need at least one digit after prefix such
+ as 0x, or 0b.
+
+ * bignum.c (rb_str2inum): recognize binary numbers like 0b0101.
+
+Fri Feb 5 03:26:56 1999 Yasuhiro Fukuma <yasuf@big.or.jp>
+
+ * ruby.c (proc_options): -e without program prints error.
+
+Fri Feb 5 00:01:50 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (terms): needed to clear heredoc_end.
+
+ * numeric.c (flo_div): allow float division by zero.
+
+Thu Feb 4 11:56:24 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * missing/strtod.c: for compatibility.
+
+ * configure.in (strtod): add strtod compatible check.
+
+ * numeric.c (rb_num2long): missing/vsnprintf.c does not support
+ floating points.
+
+ * numeric.c (flo_to_s): ditto.
+
+Wed Feb 3 23:02:12 1999 Yoshida Masato <yoshidam@yoshidam.net>
+
+ * regex.c (re_compile_pattern): use ismbchar() to get next char.
+
+ * regex.c (re_search): wrong mbchar shift.
+
+ * re.c (rb_reg_search): needed to reset $KCODE after match.
+
+ * regex.c (re_compile_fastmap): mbchars should match with \w.
+
+Wed Feb 3 22:35:12 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * parse.y (yylex): too big float raise warning, not error.
+
+Tue Feb 2 23:41:42 1999 Yoshida Masato <yoshidam@yoshidam.net>
+
+ * regex.c (re_match): wrong boundary.
+
+ * regex.c (IS_A_LETTER): re_mbctab[c] may not be 1 for mbc.
+
+ * regex.c (re_search): mbchar support for shifting ranges.
+
+ * regex.c (MBC2WC): wrong conversion.
+
+Wed Feb 3 15:03:16 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (parse_regx): need to escape parens if terminators are
+ not any kind of parenthesis.
+
+ * parse.y (parse_qstring): ditto.
+
+ * parse.y (parse_string): ditto.
+
+Tue Feb 2 17:11:26 1999 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * string.c (rb_str_gsub_bang): too small realloc condition.
+
+Mon Feb 1 10:01:17 1999 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * parse.y (yylex): range check for the float literal.
+
+Sat Jan 30 18:34:16 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (usage): -h option to show brief command description.
+
+Sat Jan 30 08:45:16 1999 IKARASHI Akira <ikarashi@itlb.te.noda.sut.ac.jp>
+
+ * lib/cgi-lib.rb: cookie support added.
+
+Sat Jan 30 13:38:24 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): mbchars should match with \w
+ within character class. Was matching with \W.
+
+ * regex.c (re_match): \w should match with multi byte characters,
+ not its first byte.
+
+Sat Jan 30 10:06:41 1999 Yoshida Masato <yoshidam@yoshidam.net>
+
+ * re.c (rb_reg_s_new): UTF-8 flag handle (/u, /U).
+
+ * re.c (rb_kcode): $KCODE handle for UTF-8.
+
+Sat Jan 30 01:51:16 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (rb_ary_delete_if): RTEST() missing.
+
+ * hash.c (delete_if_i): ditto.
+
+ * enum.c (Init_Enumerable): select (=find_all), detect (=find)
+ added as aliases.
+
+Fri Jan 29 21:32:19 1999 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * hash.c (rb_f_setenv): SEGV caused by small typo.
+
+Fri Jan 29 00:15:58 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * lib/parsedate.rb (parsedate): support date format like
+ 23-Feb-93, which is required by HTTP/1.1.
+
+ * variable.c (find_class_path): avoid calling rb_iv_set().
+
+ * eval.c (backtrace): do not need to modify $SAFE internally.
+
+ * variable.c (classname): inline __classid__ access.
+
+ * eval.c (THREAD_ALLOC): needed to initialize wrapper.
+
+ * lib/ftools.rb (makedirs): allows slash at the end of the path.
+
+ * numeric.c (rb_fix_induced_from): ensure result to be Fixnum.
+
+Thu Jan 28 17:31:43 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * numeric.c (flo_to_s): float format changed to "%16.10g".
+
+Thu Jan 28 02:13:11 1999 Yoshinori Toki <toki@freedom.ne.jp>
+
+ * array.c (rb_ary_store): expand allocated buffer by 3/2.
+
+Wed Jan 27 17:50:02 1999 Kazuhiro HIWADA <hiwada@kuee.kyoto-u.ac.jp>
+
+ * bignum.c (dbl2big): raised error if double is too big to cast
+ into long. check added.
+
+Wed Jan 27 03:16:18 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (rb_mod_const_at): can't list constants of the
+ untainted objects in safe mode.
+
+ * class.c (method_list): can't list methods of untainted objects
+ in safe mode.
+
+Tue Jan 26 02:40:41 1999 GOTO Kentaro <gotoken@math.sci.hokudai.ac.jp>
+
+ * prec.c: Precision support for numbers.
+
+Thu Jan 21 19:08:14 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_f_raise): calls `exception' method, not `new'.
+
+ * error.c (exc_exception): renamed from `new'.
+
+Wed Jan 20 03:39:48 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yycompile): rb_in_compile renamed to ruby_in_compile.
+
+ * ruby.c (load_file): define DATA if __END__ appeared in script.
+
+Tue Jan 19 14:57:51 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (here_document): need to protect lex_lastline.
+
+ * parse.y (yylex): disable %//, %'', %``.
+
+Tue Jan 19 05:01:16 1999 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * array.c (beg_len): round range value too much.
+
+Mon Jan 18 13:02:27 1999 Kuroda Jun <jkuro@dwe.co.jp>
+
+ * hash.c (env_keys): strchr() may return NULL.
+
+Mon Jan 18 17:51:47 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * instruby.rb (wdir): install libruby.a in archdir.
+
+ * lib/ftools.rb (install): removes file before installing.
+
+Mon Jan 18 16:55:31 1999 MAEDA shugo <shugo@aianet.ne.jp>
+
+ * eval.c (rb_callcc): experimental continuation support.
+
+Sun Jan 17 19:45:37 1999 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * pack.c (pack_pack): nil packing caused SEGV.
+
+Sat Jan 16 13:18:03 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_concat): character (fixnum) can be append to
+ strings
+
+ * array.c (rb_ary_unshift): unshift returns array.
+
+Sat Jan 16 01:39:19 1999 Yoshida Masato <yoshidam@tau.bekkoame.ne.jp>
+
+ * string.c (rb_str_split_method): UTF-8 support.
+
+ * regex.c: UTF-8 support.
+
+Thu Jan 14 00:42:55 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_gsub_bang): forget to add offset for null match.
+
+ * eval.c (rb_thread_local_aset): can't modify in tainted mode.
+
+ * hash.c (env_each_key): avoid generating temporary array.
+
+Wed Jan 13 23:58:50 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (rb_f_setenv): name and value can be tainted.
+
+Wed Jan 6 02:42:08 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (Init_Bignum): forgot to define Bignum#===.
+
+ * gc.c (gc_sweep): if add_heap() is called during GC, objects on
+ allocated heap page(s) are not marked, should not be recycled.
+
+ * gc.c (gc_sweep): should refer latest freelist.
+
+ * gc.c (id2ref): modified to support performance patch.
+
+ * object.c (rb_obj_id): performance patch (no bignum for id).
+
+Tue Jan 5 01:56:18 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * config.guess: merge up-to-date from autoconf 2.12.
+
+ * array.c (rb_ary_join): avoid calling rb_protect_inspect() till
+ it is really needed.
+
+ * object.c (rb_obj_inspect): show detailed information for the
+ instance variables (infinite loop can avoid now).
+
+ * struct.c (rb_struct_inspect): avoid infinite loop.
+
+Sun Jan 3 01:37:58 1999 Takao KAWAMURA <kawamura@ike.tottori-u.ac.jp>
+
+ * misc/ruby-mode.el (ruby-end-of-defun): moved too much.
+
+ * misc/ruby-mode.el (ruby-mode-variables): set paragraph-separator
+ for the mode.
+
+ * misc/ruby-mode.el: proper font-lock for `def' and `nil' etc.
+
+Sat Jan 2 17:09:06 1999 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_jump_tag): new api to invoke JUMP_TAG. tag values
+ can obtained from rb_eval_string_protect()/rb_load_protect().
+
+ * eval.c (rb_rescue): now catches all exceptions but SystemExit.
+
+ * eval.c (rb_eval_string_protect): eval string with protection.
+
+ * eval.c (rb_load_protect): load file with protection.
+
+ * io.c (rb_io_puts): avoid infinite loop for cyclic arrays.
+
+ * eval.c (rb_thread_local_aref): thread local hash tables.
+
+ * object.c (rb_equal): check exact equal before calling `=='.
+
+Thu Dec 31 22:28:53 1998 MAEDA shugo <shugo@aianet.ne.jp>
+
+ * eval.c (rb_f_require): feature names should be provided with
+ DLEXT extension.
+
+ * marshal.c (Init_marshal): need to provide `marshal.so'.
+
+Wed Dec 30 02:29:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (classname): do not call rb_ivar_set().
+
+ * eval.c (ruby_run): finalizers were called too early.
+
+Fri Dec 25 12:19:30 1998 Fukuda Masaki <fukuda@wni.co.jp>
+
+ * gc.c (rb_gc_mark): should not return on FL_EXIVAR.
+
+Fri Dec 25 11:56:51 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * gc.c (gc_mark): proper scanning for temporary region.
+
+ * eval.c (TMP_ALLOC): protection for C_ALLOCA was broken.
+
+Thu Dec 24 18:26:04 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * development version 1.3 released.
+
+Thu Dec 24 00:17:00 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_load): top self should be set properly.
+
+ * variable.c (classname): check __classpath__ if it is defined.
+
+ * variable.c (classname): invalid warning at -v with static linked
+ ruby interpreter.
+
+ * eval.c (is_defined): modified for expr::Const support.
+
+ * eval.c (rb_eval): invoke method expr::Const if expr is not class
+ nor module.
+
+ * parse.y (primary): enable expr::identifier as method
+ invocation.
+
+Wed Dec 23 03:04:36 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): avoid too many loop pops for (?:..).
+
+Tue Dec 22 18:01:08 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental version 1.1d1 released.
+
+Mon Dec 21 01:33:03 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (TMP_PROTECT): add volatile to ensure GC protection.
+
+ * string.c (rb_str_gsub_bang): calculate buffer size properly.
+
+ * parse.y (lex_get_str): needed to return Qnil at EOS.
+
+ * eval.c (find_file): check policy modified, raise exception
+ immediately for tainted load_path.
+
+ * hash.c (rb_f_setenv): do not depend on setenv() nor putenv().
+
+Thu Dec 17 06:29:23 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/tk/tkutil.c (tk_s_new): use rb_obj_instance_eval(), instead
+ of rb_yield_0().
+
+ * eval.c (rb_f_require): forgot to call find_file in some cases.
+
+ * eval.c (rb_f_require): `require "feature.so"' to load dynamic
+ libraries. old `require "feature.o"' is still OK.
+
+ * eval.c (rb_eval): yield without value dumped core.
+
+Wed Dec 16 16:28:31 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental version 1.1d0 (pre1.2) released.
+
+Wed Dec 16 10:43:34 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_search): bound check before calling re_match().
+
+Tue Dec 15 13:59:01 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * error.c (exc_to_s): returns class name for unset mesg.
+
+ * error.c (exc_initialize): do not initialize @mesg by "".
+
+ * parse.y (nextc): __END__ should handle CR+LF newlines.
+
+Wed Dec 9 13:37:12 1998 MAEDA shugo <shugo@aianet.ne.jp>
+
+ * pack.c (encodes): use buffering for B-encoding.
+
+ * pack.c (pack_pack): Q-encoding by 'M'.
+
+Tue Dec 8 14:10:00 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (generic_ivar_get): any object can have instance
+ variables now. great improvement.
+
+ * variable.c (rb_name_class): do not set __classpath__ by default,
+ use __classid__ instead.
+
+Mon Dec 7 22:08:22 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.h (struct RFile): IO objects can have instance variables now.
+
+ * parse.y (primary): allows `def obj::foo; .. end'.
+
+Mon Dec 7 18:24:50 1998 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * ruby.c (set_arg0): $0 support for HP-UX.
+
+Mon Dec 7 01:30:28 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * dln.c (dln_strerror): better error messages on win32.
+
+Sat Dec 5 23:27:23 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (here_document): indentable here-doc delimiter by
+ `<<-'. Proposed by Clemens <c.hintze@gmx.net>. Thanks.
+
+Thu Dec 3 16:50:17 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/extmk.rb.in (realclean): trouble on install.
+
+Sun Nov 29 22:25:39 1998 Takaaki Tateishi <ttate@jaist.ac.jp>
+
+ * process.c (f_exec): check number of argument.
+
+Thu Nov 26 17:27:30 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c9 released.
+
+Wed Nov 25 13:07:12 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_dup): do not copy additional data (STR_NO_ORIG).
+
+ * parse.y (yycompile): reduce known memory leak (hard to remove).
+
+Wed Nov 25 03:41:21 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * st.c (st_init_table_with_size): round size up to prime number.
+
+Sat Nov 21 23:27:23 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (rb_hash_aset): reduce copying key strings.
+
+ * gc.c (looks_pointerp): declare as inline function if possible.
+
+ * st.c (PTR_NOT_EQUAL): compare hash values first before calling
+ comparing function.
+
+ * st.c (ADD_DIRECT): save hash value in entries to reduce hash
+ calculation.
+
+ * string.c (rb_str_gsub_bang): avoid rb_scan_args() to speed-up.
+
+ * string.c (rb_str_sub_bang): ditto.
+
+Sat Nov 21 18:44:06 1998 Masaki Fukushima <fukusima@goto.info.waseda.ac.jp>
+
+ * time.c (time_s_now): had memory leak.
+
+ * ext/md5/md5init.c (md5_new): had memory leak.
+
+ * ext/md5/md5init.c (md5_clone): ditto.
+
+Fri Nov 20 23:23:23 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * lib/delegate.rb: do not propagate hash and eql?.
+
+Thu Nov 19 01:40:52 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sample/ruby-mode.el (ruby-expr-beg): failed to find reserved
+ word boundary.
+
+ * eval.c (rb_eval): avoid calling `concat' method. calls
+ rb_ary_concat() directly for efficiency.
+
+ * eval.c (rb_eval): actual rest arguments extended arrays too much.
+
+Wed Nov 18 14:30:24 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * class.c (rb_define_global_function): global functions now be
+ module function of the Kernel.
+
+Wed Nov 18 10:48:09 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (read_all): SEGV on large files.
+
+Tue Nov 17 18:11:20 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c8 released.
+
+Tue Nov 17 16:58:47 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (arg): assignment to attribute name start with capital
+ should be allowed.
+
+ * eval.c (thread_alloc): needed to mark terminated threads too.
+
+Tue Nov 17 12:33:48 1998 Motoyuki Kasahara <m-kasahr@sra.co.jp>
+
+ * ext/extmk.rb.in (create_makefile): Set `libdir' to `@libdir@',
+ Set `pkglibdir' to `$libdir/$(RUBY_INSTALL_NAME)'.
+
+Tue Nov 17 10:30:46 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sprintf.c (f_sprintf): %l%%c -> %%l%c
+
+Tue Nov 17 01:08:50 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (ret_args): distinguish `a' and `*a' for the arguments
+ of yield and return.
+
+ * eval.c (rb_eval): flip3 should work like sed.
+
+ * eval.c (rb_eval): flip{2,3} now have independent state for each
+ scope to work fine with thread.
+
+Mon Nov 16 23:26:29 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (primary): exec else clause if no exception raised.
+
+Sun Nov 15 15:44:07 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * ext/extmk.rb.in (install): bug in target.
+
+Sat Nov 14 11:02:05 1998 Motoyuki Kasahara <m-kasahr@sra.co.jp>
+
+ * Makefile.in (install): Give the argument `$(DESTDIR)' to
+ `instruby.rb'.
+
+ * instruby.rb: Recognize ARG[0] as `destdir'.
+
+ * instruby.rb: Give the argument `destdir' to `extmk.rb'.
+
+ * ext/extmk.rb.in: Recognize ARG[1] as `$destdir'.
+
+ * instruby.rb: Create the installation directories (bindir, libdir,
+ archdir, pkglibdir, archdir, and mandir) under `destdir', and
+ install all files under there.
+
+ * ext/extmk.rb.in: Likewise.
+
+Sat Nov 14 10:56:55 1998 Motoyuki Kasahara <m-kasahr@sra.co.jp>
+
+ * instruby.rb: Add the variable `pkglibdir'.
+
+ * instruby.rb: Set the variable `libdir' to `$(libdir)', not
+ `$(libdir)/$(ruby_install_name)'. `libruby.so' and `libruby.so.LIB'
+ are installed at `libdir'.
+
+ * instruby.rb: Set the variable `archdir' to `$(pkglibdir)/$(arch)'.
+
+Fri Nov 13 19:43:29 1998 KIMURA Koichi <kbk@kt.rim.or.jp>
+
+ * missing/nt.c (SafeFree): wrong free offset.
+
+Thu Nov 12 20:11:53 1998 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * sample/ruby-mode.el: wrong highlight.
+
+ * parse.y (parse_regx): newline in regexp was ignored.
+
+Wed Nov 11 10:54:57 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (here_document): <<'FOO' should not escape anything.
+
+ * parse.y (here_document): bare << here-doc available, even though
+ it's deprecated.
+
+ * file.c (rb_file_s_readlink): return value should be tainted.
+
+ * ext/etc/etc.c (setup_passwd): information (eg. GCOS name) should
+ be tainted (modified at Perl Conference).
+
+Tue Nov 10 00:22:11 1998 EGUCHI Osamu <eguchi@shizuokanet.ne.jp>
+
+ * configure.in: elf support 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
+ split 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 variables can be accessed within right side
+ expression in assignment, notably in blocks.
+
+Wed Oct 14 00:18:33 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (Init_Array): Array#=== is now for equal check, not
+ inclusion check.
+
+ * parse.y (when_args): `when a, *b' style new syntax for array
+ expansion in `case'.
+
+Tue Oct 13 14:30:32 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (rb_obj_untaint): taint marks can be unset.
+
+ * eval.c (rb_eval): taint propagation for embedded strings.
+
+Mon Oct 12 13:27:15 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_call0): check stack depth more frequently.
+
+Mon Oct 12 08:08:30 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_p): can print even in secure mode.
+
+Sun Oct 11 22:50:13 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (rb_const_set): taint check for modification.
+
+ * variable.c (rb_ivar_set): taint check for modification.
+
+ * string.c (rb_str_modify): taint check for modification.
+
+ * hash.c (rb_hash_modify): taint check for modification.
+
+ * array.c (rb_ary_modify): taint check for modification.
+
+ * ruby.h (FL_TAINT): taint for all objects, not only strings.
+
+Fri Oct 9 17:01:14 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (read_all): read() returns "" at immediate EOF.
+
+ * io.c (io_read): read(nil) read all until EOF.
+
+Thu Oct 8 13:32:13 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * time.c (time_dump): marshal can dump Time object now.
+
+ * marshal.c (Init_marshal): rename marshal methods `_dump_to' to
+ `_dump', `_load_from' to `_load'.
+
+ * parse.y (rb_intern): "+=".intern generates proper symbol.
+
+Mon Oct 5 18:31:53 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c6 released.
+
+Fri Oct 2 14:22:33 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_search): `/\s*(--)$/ =~ "- --"' did not match,
+ because of wrong optimize condition.
+
+Mon Oct 1 01:55:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (rb_intern): should not raise exceptions.
+
+ * parse.y (yylex): symbol like `:foo?=' should not be allowed.
+
+ * ext/extmk.rb.in: makes *.a for static link modules.
+
+Wed Sep 30 14:13:06 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_start): supports making a subclass of the
+ Thread class.
+
+Tue Sep 29 17:46:01 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_thread_join): join is now an instance method.
+
+Fri Sep 25 12:01:19 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): `@foo!' should be an error.
+
+Thu Sep 24 14:55:06 1998 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * ext/etc/etc.c (Init_etc): wrong field definition.
+
+Thu Sep 17 17:09:05 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (io_reopen): was creating FILE* for wrong fd.
+
+Tue Sep 15 05:28:11 1998 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * regex.c (re_compile_pattern): forgot to fixup for the pattern
+ like (?=(A)|(B)).
+
+Tue Sep 15 01:06:08 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (rb_io_gets_internal): do not set $_ by default, only
+ gets/readline set the variable.
+
+ * eval.c (rb_f_load): load toplevel class is set to anonymous
+ module if safe_level >= 5, to encapsulate modification.
+
+ * eval.c (rb_f_load): set frame properly.
+
+ * string.c (rb_str_each_line): do not set $_.
+
+Mon Sep 14 14:42:27 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): beginning and end of the string, do not
+ automatically match `\b'.
+
+ * string.c (scan_once): consume at least on character.
+
+ * regex.c (re_search): wrong behavior for negative range.
+
+Sat Sep 12 21:21:26 1998 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * regex.c (re_search): range value should be maintained.
+
+Thu Sep 10 10:55:00 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (backref_error): yyerror does not understand formats.
+
+Tue Sep 8 18:05:33 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c5 released.
+
+Tue Sep 8 10:03:39 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_each_line): wrong line splitting with newline at
+ top of the string.
+
+ * string.c: non bang methods return copied string.
+
+ * eval.c (f_END): needed to initialize frame->argc;
+
+Fri Sep 4 11:27:40 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (bigadd): proper sign combination.
+
+ * regex.c (re_search): wrong return value for \A.
+
+Thu Sep 3 14:08:14 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c4 released.
+
+Tue Sep 1 10:47:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (slow_search): do not compare llen and blen. llen may
+ be longer than blen, if little contains 0xff.
+
+ * regex.c (mbctab_euc): set 0x8e as multibyte character.
+
+ * string.c (str_inspect): mask character for octal output.
+
+Mon Aug 31 15:32:41 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_search): use calculated offset if exactn is the
+ first opcode in the compiled regexp.
+
+ * regex.c (bm_search): use Boyer-Moore search for simple search.
+
+ * regex.c (must_instr): wrong length check if pattern includes
+ byte escape by 0xff.
+
+ * regex.c (re_compile_pattern): need not to check current_mbctype.
+
+Sat Aug 29 16:31:40 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_check_safe_str): avoid calling rb_id2name() in normal
+ cases to speed-up.
+
+ * eval.c (thread_raise): do not save context of terminated thread.
+
+ * regex.c (re_compile_pattern): mask \nnn over 256.
+
+Sat Aug 29 02:09:46 1998 Koji Arai <JCA02266@nifty.ne.jp>
+
+ * sprintf.c (f_sprintf): wrong buffer size check.
+
+Fri Aug 28 01:57:04 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): accepts (?ix-ix) and (?ix-ix:...).
+
+Fri Aug 28 12:25:33 1998 Hiroshi Igarashi <igarashi@ueda.info.waseda.ac.jp>
+
+ * ruby.c (ruby_require_modules): load modules in appearing order.
+
+Fri Aug 28 01:57:04 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): accepts (?ix-ix) and (?ix-ix:...).
+
+Thu Aug 27 12:54:28 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c3 released.
+
+Wed Aug 26 14:40:56 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_eval): check whether ruby_class is properly set,
+ before accessing it.
+
+ * eval.c (rb_obj_instance_eval): ruby_class should be Qnil for
+ special objects like Fixnums.
+
+ * ext/tkutil/tkutil.c (Init_tkutil): removes calls to
+ rb_yield_0(). used instance_eval() instead in the tk.rb.
+
+Wed Aug 26 11:47:00 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): pop non-greedy stack elements on success.
+
+Wed Aug 26 09:25:35 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * ruby.h: add #define environ for cygwin32.
+
+Tue Aug 25 08:57:41 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (rb_ary_sort_bang): temporarily freeze sorting array.
+
+Mon Aug 24 18:46:44 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * dln.c (dln_find_1): path check was too strict.
+
+Mon Aug 24 15:28:11 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * parse.y (f_arglist): opt_nl added after f_args.
+
+Fri Aug 21 01:06:01 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/socket/socket.c: grand renaming on socket.c.
+
+ * ext/socket/socket.c (inet_aton): supply inet_aton for those
+ systems that do not have it.
+
+ * ext/socket/socket.c (setipaddr): use inet_aton instead of
+ inet_addr.
+
+ * ext/socket/socket.c (tcp_s_gethostbyname): new method: works
+ like Socket.gethostbyname but returning array contains ip-addrs
+ as octet decimal string format like "127.0.0.1".
+
+ * ext/socket/socket.c (mkhostent): return format changed to
+ [host, aliases, type, ipaddr..] as documented.
+
+Wed Aug 19 00:31:09 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (io_ctl): forgot to place TRAP_END at right position.
+
+Fri Aug 14 11:01:47 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (call_trace_func): save __FILE__, __LINE__ before
+ executing trace_func, since trace function should not corrupt
+ line number information.
+
+Thu Aug 13 15:09:02 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (ary_s_new): was marking unallocated region on GC.
+
+Tue Aug 11 11:57:35 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c2 released.
+
+Mon Aug 10 14:05:30 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * process.c (f_system): removed fflush(stdin).
+
+Fri Aug 7 17:44:44 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * error.c (err_snprintf): replace sprintf for fixed sized buffer,
+ with snprintf to avoid buffer over-run. For systems which does
+ dot provide snprintf, missing/snprintf.c added.
+
+Wed Aug 5 00:47:35 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (rb_reg_search): recycle match object.
+
+Mon Aug 3 09:17:55 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (rb_str_gsub_bang): do not allocate temporary string.
+
+ * string.c (rb_str_sub_bang): use inline replace.
+
+Wed Jul 29 00:36:08 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (hash_s_new): the default value can be specified.
+
+ * hash.c (hash_default): method to set the default value.
+
+ * hash.c (hash_aref): now returns the default value.
+
+Tue Jul 28 13:03:25 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (ary_s_new): argument to specify initial value is added.
+
+ * array.c (ary_s_new): specifies size, not capacity.
+
+Mon Jul 27 12:39:34 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_replace): zero fill for expansion gap.
+
+ * regex.c (mbctab_euc): set flags on for 0xA1-0xFE. suggested by
+ <inaba@st.rim.or.jp>.
+
+ * string.c (str_inspect): consider current_mbctype.
+
+Sun Jul 26 15:37:11 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * array.c (ary_s_new): Array.new(1<<30) dumps core.
+
+Fri Jul 24 13:40:19 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c1 released.
+
+Fri Jul 24 02:10:22 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * marshal.c (r_bytes2): allocated buffer size was too short.
+
+ * marshal.c (w_object): saves all options, not only casefold flag.
+
+ * re.c (reg_clone): now copies options properly.
+
+ * re.c (reg_get_kcode): code number was wrong.
+
+Thu Jul 23 13:11:32 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_attr): argument should be symbol or string.
+
+Wed Jul 22 11:59:34 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (calculate_must_string): wrong offset added.
+
+Wed Jul 22 11:59:59 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * st.c (rehash): still had a GC problem. fixed.
+
+Tue Jul 21 13:19:30 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (gc_mark_threads): crashed on GC before thread allocation.
+
+ * st.c (rehash): GC during rehash caused SEGV.
+
+Tue Jul 21 01:25:10 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sprintf.c (f_sprintf): integer formatter totally re-written.
+
+ * sprintf.c (remove_sign_bits): support uppercase hexadecimal.
+
+Sat Jul 18 00:14:13 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sprintf.c (f_sprintf): proper sign position for %X and %O.
+
+Fri Jul 17 14:10:20 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * version 1.1c0 released.
+
+Fri Jul 17 08:01:49 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * process.c (f_exec): Check_SafeStr() added.
+
+ * process.c (f_system): Check_SafeStr() moved before fork().
+
+Thu Jul 16 22:58:48 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (scan_once): substrings to the block should not be
+ tainted. use reg_nth_match(), not str_substr().
+
+ * string.c (str_substr): needed to transfer taint.
+
+Thu Jul 16 16:15:57 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * gc.c (xmalloc): object allocation count added to GC trigger.
+
+ * eval.c (thread_save_context): avoid marking uninitialized stack
+ in thread_mark. GC may be triggered by REALLOC_N().
+
+Wed Jul 15 15:11:57 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_31.
+
+Wed Jul 15 15:05:27 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (thread_create): exit() and abort() in threads now
+ forwarded to main_thread.
+
+Tue Jul 14 14:03:47 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (obj_instance_variables): list names that is not
+ instance variables.
+
+ * gc.c (GC_MALLOC_LIMIT): choose smaller limit value.
+
+Mon Jul 13 12:39:38 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (str2cstr): should not return NULL.
+
+Fri Jul 10 11:51:46 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (gettable): needed to add dyna_in_block() check.
+
+Thu Jul 9 17:38:23 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_30.
+
+Thu Jul 9 16:01:48 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * sprintf.c (fmt_setup): format specifier for long needed.
+
+ * sprintf.c (f_sprintf): ditto.
+
+ * numeric.c (fix2str): ditto.
+
+ * eval.c (thread_create): no more ITIMER_REAL.
+
+ * eval.c (thread_create): thread finalization needed before
+ aborting thread if thread_abort is set.
+
+Wed Jul 8 18:17:33 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (big_pow): abandon power by bignum (too big).
+
+Tue Jul 7 13:58:43 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (rb_catch): add C level catch/throw feature.
+
+Mon Jul 6 15:18:09 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (arg): proper return values for `||=' and `&&='.
+
+Fri Jul 3 16:05:11 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_29.
+
+Fri Jul 3 11:20:46 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * marshal.c (r_byte): byte should not extend sign bit.
+
+ * numeric.c (fix_mul): use FIX2LONG() instead of FIX2INT() for
+ 64bit architectures.
+
+ * marshal.c (r_bytes): remove weird casting between pointer and int.
+
+ * process.c (proc_setsid): new method Process#setsid().
+
+Thu Jul 2 12:49:21 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * marshal.c (w_object): remove `write_bignum' label for 64bit
+ architectures.
+
+ * marshal.c (r_bytes): needs int, not long.
+
+Wed Jul 1 14:21:06 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * numeric.c (flo_plus): should not allow addition with strings.
+
+Wed Jul 1 13:09:01 1998 Keiju ISHITSUKA <keiju@rational.com>
+
+ * numeric.c (num_uminus): wrong coerce direction.
+
+Tue Jun 30 10:13:44 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (f_p): accepts arbitrary number of arguments.
+
+ * eval.c (rb_yield_0): there's some case that iterator_p() returns
+ true even if the_block was not set. check added.
+
+Tue Jun 30 01:05:20 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (BEGIN_CALLARGS): adjust the_block before evaluating the
+ receiver's value and the arguments.
+
+Fri Jun 26 18:02:50 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_28.
+
+Fri Jun 26 11:01:26 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * string.c (str_aset_method): needed to convert to string.
+
+Thu Jun 25 02:05:50 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_search): optimize for `.*' at beginning of the
+ pattern.
+
+ * regex.c (re_search): optimize for character class repeat at
+ beginning of the pattern.
+
+ * regex.c (re_compile_pattern): detect optimization potential for
+ the compiled patterns.
+
+Thu Jun 25 00:02:26 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * re.c (reg_s_new): flag value was wrong.
+
+Wed Jun 24 23:45:06 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_search): wrong anchor handling for reverse search.
+
+Wed Jun 24 02:18:57 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (mlhs): `((a,b)),c = [[1,2]],3' assigns a=1,b=2,c=3.
+
+Tue Jun 23 11:46:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (yylex): `&&=' and `||=' added.
+
+Sat Jun 20 02:53:50 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (assignable): nesting local variables should have higher
+ priority than normal local variables for assignment too.
+
+Fri Jun 19 18:28:19 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_27.
+
+Fri Jun 19 14:34:49 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (assign): support hack for nested multiple assignment.
+
+ * parse.y (mlhs): nested multiple assignment.
+
+ * eval.c (rb_eval): in-block variables now honors static scope.
+
+ * configure.in: RSHIFT check moved to configure.
+
+Thu Jun 18 16:46:04 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_26.
+
+Thu Jun 18 13:37:19 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * file.c (file_s_ftype): uses lstat(2) instead of stat(2).
+
+ * dir.c (dir_s_glob): there can be buffer overrun, check added.
+
+ * eval.c (f_binding): handles in-block variables declared after
+ binding's generation.
+
+ * numeric.c (flo_floor): floor, ceil, round added to Float.
+
+Wed Jun 17 11:20:00 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (gettable): nesting local variables should have higher
+ priority than normal local variables.
+
+Tue Jun 16 12:30:46 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (str2inum): handles `+ddd'.
+
+ * struct.c (make_struct): name parameter can be nil for unnamed
+ structures.
+
+Mon Jun 15 16:30:10 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (class_s_inherited): prohibiting to make subclass of
+ class Class.
+
+ * object.c (module_s_new): support for making subclass of Module.
+
+ * parse.y (yycompile): clear eval_tree before compiling.
+
+Fri Jun 12 17:58:18 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (eval): write back the_dyna_var into the block.
+
+Thu Jun 11 18:19:18 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_25.
+
+ * eval.c (dvar_add_compiling): register dyna_var at compile time.
+
+ * regex.c (re_compile_pattern): RE_DUP_MAX iteration is too big.
+
+Wed Jun 10 15:12:04 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (io_eof): do not block other threads.
+
+ * signal.c (trap): reserve SIGALRM for thread.
+
+ * eval.c (thread_create): use ITIMER_REAL also to avoid system
+ call blocking.
+
+ * io.c (f_syscall): add TRAP_BEG, TRAP_END around system calls.
+
+ * io.c (io_ctl): add TRAP_BEG, TRAP_END around system calls.
+
+ * enum.c (enum_collect): did not collect false values.
+
+ * array.c (ary_new2): forgot to initialize capa field.
+
+Tue Jun 9 18:36:15 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * string.c (str_split_method): split dumped core for "\xff".
+
+Tue Jun 9 16:22:12 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_24.
+
+Tue Jun 9 16:04:07 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * ext/kconv/kconv.c (kconv_guess): more precise decision for EUC,
+ using jless algorithm (3 sequential EUC hiragana characters).
+
+Tue Jun 9 15:12:44 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/kconv/kconv.c (kconv_guess): wrong guess for EUC as SJIS in
+ some cases (0xe0 - 0xef).
+
+ * gc.c (xmalloc): insert size check for big (negative in signed)
+ allocation size.
+
+Tue Jun 9 02:54:51 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * lib/parsedate.rb: wday moved to the last in the return values.
+
+Mon Jun 8 10:40:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * string.c (str_split_method): split dumped core for "\0".
+
+Sat Jun 6 22:50:52 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (calculate_must_string): wrong condition for
+ {start,stop}_nowidth.
+
+ * regex.c (re_match): various features imported from GNU regex.c
+ 0.12, such as nested grouping, avoiding infinite loop with empty
+ match, etc.
+
+ * regex.c (register_info_type): now use union.
+
+ * regex.c (re_search): more precise anchor(^) check.
+
+Wed Jun 3 18:07:54 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (reg_raise): check rb_in_compile, not rb_in_eval.
+
+Mon Jun 1 05:26:06 1998 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * string.c (trnext): casting to signed char* needed.
+
+Tue Jun 2 16:00:12 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/socket/socket.c (udp_addrsetup): error check enhanced.
+
+ * ext/socket/socket.c (sock_s_getservbyaname): use strtoul(), if
+ possible.
+
+Sat May 30 07:10:02 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (reg_prepare_re): no more needless regular expression
+ recompile on casefold conditions.
+
+Thu May 28 18:02:55 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * object.c (nil_plus): no more `+' method for nil.
+
+Wed May 27 17:33:46 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (hash_fetch): new method.
+
+ * regex.c (re_search): check whether translate table is set.
+
+Tue May 26 11:39:50 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_23.
+
+ * parse.y (yylex): no UPLUS/UMINUS for 1st argument if
+ parenthesises are omitted.
+
+Tue May 26 01:09:55 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): (?XI) for turns off the
+ corresponding option.
+
+Mon May 25 12:38:56 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): inline i option (?i).
+
+ * regex.c (re_compile_pattern): inline x option (?x).
+
+ * regex.c (re_compile_pattern): x option for regexp.
+
+ * dir.c (dir_s_open): returns block's evaluated value.
+
+ * io.c (f_open): returns block's evaluated value.
+
+ * ext/curses/curses.c (curses_addstr): nil argument caused SEGV.
+
+Fri May 22 11:52:45 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_compile_pattern): push mark on (?:), so that
+ laststart check for {a,b} can be done.
+
+Thu May 21 17:31:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * regex.c (re_match): wrong match (too non-greedy) for `{a,b}?'.
+
+ * io.c (io_lineno): new method IO#lineno, IO#lineno=.
+
+Wed May 20 06:04:43 1998 MAEDA shugo <shugo@aianet.ne.jp>
+
+ * BeOS patch.
+
+Wed May 20 16:32:19 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * bignum.c (BIGDN): use RSHIFT(), instead of mere `>>'.
+
+Tue May 19 16:36:26 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_22.
+
+Tue May 19 16:31:57 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * parse.y (assignable): specification changed for in-block
+ variable definition.
+
+ * eval.c (dyna_var_asgn): error in in-block variables' compile
+ time definition.
+
+ * parse.y (str_extend): wrong nesting detection.
+
+Tue May 19 09:47:55 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * numeric.c (num2int): re-defined (extensions may use this).
+
+Mon May 18 16:40:50 1998 MAEDA shugo <shugo@aianet.ne.jp>
+
+ * error.c (get_syserr): BeOS support.
+
+ * configure.in: modified for BeOS.
+
+ * string.c (str_dump): do not call isascii().
+
+ * sprintf.c (remove_sign_bits): forgot to initialize end pointer.
+
+ * glob.c: #include <alloca.h> added.
+
+Mon May 18 14:52:21 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_21.
+
+Mon May 18 03:27:57 1998 MAEDA shugo <shugo@aianet.ne.jp>
+
+ * file.c (file_s_expand_path): optional second argument
+ `default_directory' added.
+
+Sat May 16 22:06:52 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * error.c (RAISE_ERROR): wrong error message
+
+Fri May 15 14:43:25 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_20.
+
+Thu May 14 14:44:21 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * sun4 cc patches for intern.h and regex.h.
+
+Thu May 14 14:03:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * random.c (RANDOM_MAX): guessing proper maximum value for random
+ numbers.
+
+ * random.c (f_rand): use drand48 if possible.
+
+Wed May 13 19:05:20 1998 MAEDA shugo <shugo@aianet.ne.jp>
+
+ * BeOS patches for io.c, error.c and config.guess.
+
+Wed May 13 14:56:23 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_19.
+
+ * most of the Mac and BeOS patches merged, except path separators.
+
+ * error.c (err_append): generated SyntaxError was String.
+
+ * ruby.h: xxx2INT, xxx2UINT checks values as int, not long.
+
+ * ruby.h: remove typedef's. INT, UINT, UCHAR, USHORT.
+
+Tue May 12 17:38:00 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_18.
+
+Tue May 12 11:38:08 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * error.c (syserr_errno): returns errno of the SystemCallError.
+
+ * error.c (rb_sys_fail): saves errno in the Exception.
+
+ * error.c (set_syserr): no need to protect syserr_list.
+
+ * error.c (rb_sys_fail): no more bufsize limit.
+
+ * error.c (set_syserr): integer value of errno can be accessed by
+ Errno::EXXX::Errno.
+
+Sun May 10 03:10:33 1998 WATANABE Tetsuya <tetsu@jpn.hp.com>
+
+ * io.c (io_tell etc.): moved from File class to IO class.
+
+Fri May 8 12:26:37 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * pack.c (pack_unpack): should be unsigned int (was signed int).
+
+Thu May 7 16:34:10 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * pack.c (pack_pack): `V', `N' uses newly created NUM2UINT().
+
+ * ruby.h (NUM2UINT): new macro.
+
+ * bignum.c (big2uint): try to convert bignum into UINT.
+
+ * re.c (reg_match): needed to return false for match with nil.
+
+ * gc.c (obj_free): wrong condition to free string.
+
+Wed May 6 21:08:08 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * ruby.c (ruby_process_options): modified for DJGPP.
+
+Wed May 6 15:48:03 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_17.
+
+Wed May 6 01:37:39 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c: remove global variable `errat'.
+
+ * eval.c (rb_longjmp): embed error position information in the
+ exception object.
+
+Sat May 2 12:20:02 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * re.c (reg_search): supports reverse search.
+
+ * string.c (str_index_method): does update $~ etc.
+
+ * eval.c (f_load): needed to clear the_dyna_vars.
+
+ * eval.c (dyna_var_asgn): do not push dyna_var, which is id == 0.
+
+ * error.c (Init_Exception): NotImplementError is no longer
+ StandardError, which is not handled by default rescue.
+
+Fri May 1 00:35:51 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ruby.c (proc_options): `-d' turns on verbose flag too.
+
+ * error.c (exception): last argument may be the superclass of the
+ defining exception(s).
+
+ * io.c (Init_IO): EOFError is now subclass of the IOError.
+
+ * io.c (Init_IO): forgot to define IOError.
+
+ * error.c (Init_Exception): old Exception class renamed to
+ StandardError. Exception now replaces old GlobalExit.
+
+ * error.c (Init_Exception): Exception is now the root of the
+ Global Exits. There's no longer GlobalExit class.
+
+ * util.c (ruby_mktemp): check TMP, TMPDIR first.
+
+Thu Apr 30 01:08:35 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * lib/tk.rb: call 'unknown', if proc not defined.
+
+ * eval.c (handle_rescue): default rescue handles `Exceptional' not
+ only the instance of the `Exception's.
+
+ * eval.c (f_raise): exception can be any object.
+
+ * time.c (time_gm_or_local): call time_gmtime or time_localtime.
+
+ * eval.c (f_raise): raises TypeError if the class which is not a
+ subclass of String is specified (checked in exc_new()).
+
+ * error.c (exc_new): need to check whether invalid class (not a
+ subclass of String) is specified.
+
+Wed Apr 29 21:05:44 1998 WATANABE Hirofumi <eban@os.rim.or.jp>
+
+ * ruby.c (proc_options): option '-e' via tempfile.
+
+Tue Apr 28 15:27:58 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_16.
+
+Tue Apr 28 00:07:38 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (obj_is_proc): type check predicate.
+
+ * eval.c (obj_is_block): ditto.
+
+Mon Apr 27 16:59:17 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * ext/gtk/gtk.c (Init_gtk): use timeout, not idle to avoid
+ consuming CPU too much.
+
+ * lib/tk.rb: use tcltklib#_invoke instead of `_eval'.
+
+Mon Apr 27 16:59:17 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * array.c (ary_sort): use dup, not clone.
+
+Mon Apr 27 13:46:27 1998 Tadahiro Maebashi <maebashi@iij.ad.jp>
+
+ * ext/tcltklib/tcltklib.c (ip_invoke): invoke tcl command
+ directly. need not worry about escaping tcl characters.
+
+Mon Apr 27 12:04:43 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * random.c (f_rand): do not call srand() implicitly.
+
+Fri Apr 24 14:35:45 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_15.
+
+ * parse.y (assignable): dyna_var_asgn actually defines nested
+ local variables in outer context.
+
+ * random.c (f_rand): call srand(), if it has not called yet.
+
+ * random.c (f_srand): use tv_usec as the default seed.
+
+ * eval.c (rb_eval): values of nested local variables should be
+ independent.
+
+ * eval.c (rb_yield_0): local variables wrong nested conditions.
+
+Wed Apr 22 23:27:17 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * io.c (select_get_io): get IO object by `to_io'.
+
+ * io.c (io_to_io): method to retrieve IO object, from delegating
+ object for example.
+
+Wed Apr 22 16:52:37 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_14.
+
+ * string.c (str_modify): check for embedded pointer reference.
+
+ * gc.c (obj_free): ditto.
+
+ * pack.c (pack_pack): p/P template to embed pointers.
+
+Wed Apr 22 00:07:10 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * array.c (ary_rindex): embarrassing typo.
+
+Tue Apr 21 12:31:48 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_13.
+
+ * configure.in (RUBY_LIB): supports --program-{prefix,suffix}.
+
+ * array.c (ary_rindex): new method.
+
+ * io.c (io_binmode): should return self.
+
+Tue Apr 21 08:23:04 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
+
+ * parse.y (here_document): calling parse_string with wrong
+ arguments.
+
+ * struct.c (struct_aset): problem member assignment with name.
+
+Mon Apr 20 14:47:49 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * experimental release 1.1b9_12.
+
+ * time.c (time_arg): args may be string (support for reduced
+ implicit type conversion).
+
+ * lib/base64.rb: changed to use pack/unpack with `m' template.
+
+Mon Apr 20 06:23:20 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * variable.c (mod_remove_const): new method.
+
+Sat Apr 18 03:53:27 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * hash.c (hash_each_with_index): removed. use Enumerable's
+ each_with_index instead.
+
+ * class.c (rb_include_module): check for super modules, since
+ module's included modules may be changed.
+
+Fri Apr 17 21:50:47 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * marshal.c (r_long): r_byte() may return signed byte.
+
+Fri Apr 17 11:58:30 1998 NAGAI Hidetoshi <nagai@dumbo.ai.kyutech.ac.jp>
+
+ * ext/tcltklib/tcltklib.c (lib_mainloop): thread and interrupt check.
+
+Fri Apr 17 11:06:30 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * eval.c (find_file): try to fopen() to check whether file exists.
+
+ * ruby.c (load_file): ditto.
+
+ * struct.c (struct_aset): struct member can be set by member name.
+
+Fri Apr 17 00:47:19 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
+
+ * ext/extmk.rb.in: added m68k-human support
+
+ * file.c (LOCK_SH): defines moved.
+
+ * array.c (ary_flatten_bang): simplified loop.
+
Thu Apr 16 16:52:01 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
* experimental release 1.1b9_11.
@@ -223,7 +8994,7 @@ Tue Mar 31 13:23:58 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
Mon Mar 30 11:12:29 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
- * file.c (f_test): raises exception for unkown command.
+ * file.c (f_test): raises exception for unknown command.
* eval.c (Init_eval): `class_eval': alias to the module_eval.
@@ -255,7 +9026,7 @@ Sat Mar 28 20:40:12 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
Sat Mar 28 16:07:11 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
- * io.c (io_closed): should not cause exception fot closed IO.
+ * io.c (io_closed): should not cause exception for closed IO.
* string.c (str_tr): returned nil for success.
@@ -340,7 +9111,7 @@ Wed Mar 18 17:46:31 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
* ruby.c (load_file): new file object constant DATA. Only
available for the script from the file.
- * regex.c (re_match): forwading failure point popped too much.
+ * regex.c (re_match): forwarding failure point popped too much.
Tue Mar 17 18:23:06 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
@@ -455,7 +9226,7 @@ Fri Mar 6 17:23:07 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
primitive classes (mostly perfect).
* ext/curses/curses.c (curses_finalize): restore original state at
- interpreter temination.
+ interpreter termination.
* ext/curses/curses.c (curses_addstr): forgot to check argument
type (caused SEGV). now uses STR2CSTR() macro.
@@ -499,7 +9270,7 @@ Tue Mar 3 11:21:28 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
Tue Mar 3 08:04:56 1998 Tadayoshi Funaba <tadf@kt.rim.or.jp>
- * struct.c (struct_alloc): imcomplete struct initialization made
+ * struct.c (struct_alloc): incomplete struct initialization made
GC to access unallocated addresses.
Mon Mar 2 16:28:27 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
@@ -669,7 +9440,7 @@ Tue Feb 10 17:29:08 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
* string.c (str_oct): does recognize `0x'.
- * sprintf.c (f_sprintf): use baes 10 for conversion from string to
+ * sprintf.c (f_sprintf): use base 10 for conversion from string to
integer.
Mon Feb 9 14:51:56 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
@@ -870,7 +9641,7 @@ Tue Jan 6 00:27:43 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
Mon Jan 5 16:59:13 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
- * file.c (file_s_basename): removes any extention by ".*".
+ * file.c (file_s_basename): removes any extension by ".*".
Sun Jan 4 19:36:22 1998 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
@@ -1008,8 +9779,8 @@ Fri Dec 12 00:50:25 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
* eval.c (rb_eval): new visibility status `function'.
- * parse.y (yycompile): do not clear eval_tree. thus enable multipe
- command line script by optn `-e'.
+ * parse.y (yycompile): do not clear eval_tree. thus enable multiple
+ command line script by option `-e'.
* eval.c (rb_eval): END execute just once.
@@ -1023,7 +9794,7 @@ Thu Dec 11 13:14:35 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
not exist.
* ext/curses/curses.c: remove CHECK macro for BSD curses.
-
+
Thu Dec 11 12:44:01 1997 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
* pack.c: sun4 cc patch
@@ -1089,7 +9860,7 @@ Mon Dec 1 15:24:41 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
Wed Nov 26 18:18:05 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
- * lib/mkmf.rb: generate Makefile for extention modules out of ruby
+ * lib/mkmf.rb: generate Makefile for extension modules out of ruby
source tree. use like `ruby -r mkmf extconf.rb'.
* numeric.c (fix2str): enlarge buffer to prevent overflow on some
@@ -1150,7 +9921,7 @@ Wed Nov 12 13:44:47 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
Mon Nov 10 11:24:51 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
- * regex.c (re_compile_pattern): non-resitering parens (?:..).
+ * regex.c (re_compile_pattern): non-registering parens (?:..).
* regex.c (re_compile_pattern): new meta character \< (wordbeg)
and \> (wordend).
@@ -1287,7 +10058,7 @@ Fri Oct 3 10:51:10 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
* eval.c (ruby_options): f_require() called too early.
- * eval.c (rb_provide): module extentions should always be `.o'.
+ * eval.c (rb_provide): module extensions should always be `.o'.
Thu Oct 2 11:38:31 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
@@ -1406,7 +10177,7 @@ Tue Sep 16 17:54:25 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
* ruby.c (ruby_prog_init): close stdaux and stdprn for MSDOS.
* ruby.c (ruby_prog_init): should not add path from environment
- variable, if ruby is running under seuid.
+ variable, if ruby is running under setuid.
* process.c (init_ids): check suid check for setuid/seteuid etc.
@@ -1483,18 +10254,18 @@ Mon Sep 1 13:42:48 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
* class.c (rb_define_attr): always defines accessors.
- * eval.c (rb_call): alias occured in the module body caused SEGV.
+ * eval.c (rb_call): alias occurred in the module body caused SEGV.
* parse.y: did not generate here document strings properly.
Mon Sep 1 11:43:57 1997 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp>
-
+
* parse.y (yylex): heredoc dropped an extra character.
Fri Aug 29 11:10:21 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
* class.c (class_instance_methods): same method names should not
- appear more than twice.
+ appear more than once.
* parse.y (yylex): spaces can follow =begin/=end.
@@ -1502,7 +10273,7 @@ Fri Aug 29 11:10:21 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
unnamed fundamental classes, such as Object, String, etc.
* variable.c (rb_name_class): can't name class before String class
- is initilialized.
+ is initialized.
* inits.c (rb_call_inits): unrecognized dependency from GC to
Array.
@@ -1536,7 +10307,7 @@ Wed Aug 27 11:32:42 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
* variable.c (fc_i): some classes/modules does not have iv_tbl.
- * variable.c (find_class_path): avoid inifinite loop.
+ * variable.c (find_class_path): avoid infinite loop.
Tue Aug 26 13:43:47 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
@@ -1553,7 +10324,7 @@ Tue Aug 26 13:43:47 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
* object.c (Init_Object): superclass()'s method argument setting
was wrong again.
- * class.c (mod_anscestors): list superclasses and included modules
+ * class.c (mod_ancestors): list superclasses and included modules
in priority order.
Mon Aug 25 11:53:11 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
@@ -1568,7 +10339,7 @@ Mon Aug 25 11:53:11 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
Sat Aug 23 21:39:05 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
- * parse.y (asignable): remove unnecessary local variable
+ * parse.y (assignable): remove unnecessary local variable
initialize by nil.
Fri Aug 22 14:26:40 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
@@ -1631,9 +10402,9 @@ Sat Aug 16 00:17:44 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
Fri Aug 15 15:49:46 1997 Yukihiro Matsumoto <matz@netlab.co.jp>
* eval.c (call_trace_func): block context switch in the trace
- function.
+ function.
- * eval.c (rb_eval): clear method cache at class extention.
+ * eval.c (rb_eval): clear method cache at class extension.
* object.c (obj_type): returns object's class even if it defines
singleton methods.
diff --git a/MANIFEST b/MANIFEST
index 1d0067a56a..17e8924bb7 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1,4 +1,5 @@
COPYING
+COPYING.LIB
ChangeLog
MANIFEST
Makefile.in
@@ -12,9 +13,7 @@ bignum.c
class.c
compar.c
configure
-configure.bat
configure.in
-config.dj
config.guess
config.sub
defines.h
@@ -27,17 +26,13 @@ env.h
error.c
eval.c
file.c
-fnmatch.c
-fnmatch.h
gc.c
-glob.c
hash.c
inits.c
install-sh
instruby.rb
intern.h
io.c
-io.h
keywords
lex.c
main.c
@@ -48,7 +43,9 @@ node.h
numeric.c
object.c
pack.c
+parse.c
parse.y
+prec.c
process.c
random.c
range.c
@@ -59,8 +56,9 @@ regex.h
ruby.1
ruby.c
ruby.h
+rubyio.h
+rubysig.h
rubytest.rb
-sig.h
signal.c
sprintf.c
st.c
@@ -68,23 +66,30 @@ st.h
string.c
struct.c
time.c
-top.sed
util.h
util.c
variable.c
version.c
version.h
+djgpp/README.djgpp
+djgpp/config.hin
+djgpp/config.sed
+djgpp/configure.bat
+djgpp/mkver.sed
+cygwin/GNUmakefile.in
ext/Setup
ext/Setup.dj
-ext/Setup.nt
+ext/Setup.emx
ext/Setup.x68
-ext/aix_ld.rb
-ext/cygwin32_ld.rb
+ext/aix_mksym.rb
+ext/configsub.rb
ext/extmk.rb.in
-ext/extmk.rb.nt
lib/English.rb
lib/Env.rb
+lib/README
lib/base64.rb
+lib/cgi.rb
+lib/cgi/session.rb
lib/cgi-lib.rb
lib/complex.rb
lib/date.rb
@@ -99,7 +104,22 @@ lib/finalize.rb
lib/ftplib.rb
lib/ftools.rb
lib/getopts.rb
+lib/getoptlong.rb
lib/importenv.rb
+lib/irb/completion.rb
+lib/irb/frame.rb
+lib/irb/input-method.rb
+lib/irb/irb.rb
+lib/irb/loader.rb
+lib/irb/main.rb
+lib/irb/multi-irb.rb
+lib/irb/ruby-lex.rb
+lib/irb/ruby-token.rb
+lib/irb/slex.rb
+lib/irb/version.rb
+lib/irb/workspace-binding-2.rb
+lib/irb/workspace-binding.rb
+lib/irb/xmp.rb
lib/jcode.rb
lib/mailread.rb
lib/mathn.rb
@@ -107,54 +127,72 @@ lib/matrix.rb
lib/mkmf.rb
lib/monitor.rb
lib/mutex_m.rb
+lib/net/ftp.rb
+lib/net/http.rb
+lib/net/imap.rb
+lib/net/pop.rb
+lib/net/protocol.rb
+lib/net/smtp.rb
+lib/net/telnet.rb
lib/observer.rb
+lib/open3.rb
lib/ostruct.rb
lib/parsearg.rb
lib/parsedate.rb
lib/ping.rb
+lib/profile.rb
lib/pstore.rb
lib/rational.rb
+lib/readbytes.rb
lib/shellwords.rb
+lib/singleton.rb
lib/sync.rb
+lib/telnet.rb
lib/tempfile.rb
lib/thread.rb
lib/thwait.rb
-lib/tk.rb
-lib/tkcanvas.rb
-lib/tkclass.rb
-lib/tkdialog.rb
-lib/tkentry.rb
-lib/tkmenubar.rb
-lib/tkscrollbox.rb
-lib/tktext.rb
+lib/timeout.rb
lib/tracer.rb
lib/weakref.rb
+misc/README
+misc/inf-ruby.el
+misc/ruby-mode.el
+misc/rubydb2x.el
+misc/rubydb3x.el
missing/alloca.c
missing/crypt.c
missing/dir.h
missing/dup2.c
missing/file.h
+missing/finite.c
missing/flock.c
+missing/isinf.c
+missing/isnan.c
missing/memcmp.c
missing/memmove.c
missing/mkdir.c
-missing/nt.c
-missing/nt.h
-missing/setenv.c
+missing/os2.c
missing/strcasecmp.c
+missing/strncasecmp.c
missing/strchr.c
missing/strdup.c
missing/strerror.c
missing/strftime.c
missing/strstr.c
+missing/strtod.c
missing/strtol.c
missing/strtoul.c
+missing/vsnprintf.c
missing/x68.c
+sample/README
sample/biorhythm.rb
+sample/cal.rb
sample/cbreak.rb
sample/clnt.rb
sample/dbmtest.rb
sample/dir.rb
+sample/dualstack-fetch.rb
+sample/dualstack-httpd.rb
sample/eval.rb
sample/export.rb
sample/exyacc.rb
@@ -169,48 +207,44 @@ sample/from.rb
sample/fullpath.rb
sample/getopts.test
sample/goodfriday.rb
-sample/inf-ruby.el
+sample/irb.rb
sample/less.rb
sample/list.rb
sample/list2.rb
sample/list3.rb
-sample/mrshtest.rb
+sample/mine.rb
sample/mkproto.rb
sample/mpart.rb
+sample/mrshtest.rb
sample/observ.rb
sample/occur.pl
sample/occur.rb
sample/occur2.rb
sample/philos.rb
sample/pi.rb
-sample/rbc.rb
+sample/rename.rb
sample/rcs.awk
sample/rcs.dat
sample/rcs.rb
sample/regx.rb
-sample/ruby-mode.el
-sample/rubydb2x.el
-sample/rubydb3x.el
sample/sieve.rb
sample/svr.rb
sample/test.rb
sample/time.rb
-sample/tkbiff.rb
-sample/tkbrowse.rb
-sample/tkdialog.rb
-sample/tkfrom.rb
-sample/tkhello.rb
-sample/tkline.rb
-sample/tktimer.rb
sample/trojan.rb
sample/tsvr.rb
sample/uumerge.rb
-win32/Makefile
-win32/config.h
-win32/ntsetup.bat
-win32/ruby.def
-win32/sdbm.c
-win32/sdbm.h
+win32/Makefile.sub
+win32/README.win32
+win32/config.h.in
+win32/config.status.in
+win32/configure.bat
+win32/mkexports.rb
+win32/resource.rb
+win32/setup.mak
+win32/win32.c
+win32/win32.h
+win32/winmain.c
x68/fconvert.c
x68/select.c
x68/_dtos18.c
diff --git a/Makefile.in b/Makefile.in
index d6b80e9f31..37f644d786 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -3,205 +3,275 @@ SHELL = /bin/sh
#### Start of system configuration section. ####
srcdir = @srcdir@
-VPATH = @srcdir@:@srcdir@/missing
+VPATH = $(srcdir):$(srcdir)/missing
CC = @CC@
YACC = @YACC@
PURIFY =
+AUTOCONF = autoconf
@SET_MAKE@
-CFLAGS = @CFLAGS@ -I@srcdir@
+prefix = @prefix@
+CFLAGS = @CFLAGS@
+CPPFLAGS = -I. -I$(srcdir) -I@includedir@
LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@
+XLDFLAGS = @XLDFLAGS@
+EXTLIBS =
LIBS = @LIBS@ $(EXTLIBS)
MISSING = @LIBOBJS@ @ALLOCA@
+LDSHARED = @LIBRUBY_LDSHARED@
+DLDFLAGS = @LIBRUBY_DLDFLAGS@
+SOLIBS = @SOLIBS@
+MAINLIBS = @MAINLIBS@
-binsuffix = @binsuffix@
+RUBY_INSTALL_NAME=@RUBY_INSTALL_NAME@
+RUBY_SO_NAME=@RUBY_SO_NAME@
+EXEEXT = @EXEEXT@
+PROGRAM=$(RUBY_INSTALL_NAME)$(EXEEXT)
#### End of system configuration section. ####
+MAJOR= @MAJOR@
+MINOR= @MINOR@
+TEENY= @TEENY@
-LIBRUBY = libruby.a
+LIBRUBY_A = @LIBRUBY_A@
+LIBRUBY_SO = @LIBRUBY_SO@
+LIBRUBY_ALIASES= @LIBRUBY_ALIASES@
+LIBRUBY = @LIBRUBY@
+LIBRUBYARG = @LIBRUBYARG@
EXTOBJS =
-MAINOBJ = main.o
-
-OBJS = array.o \
- bignum.o \
- class.o \
- compar.o \
- dir.o \
- dln.o \
- enum.o \
- error.o \
- eval.o \
- file.o \
- fnmatch.o \
- gc.o \
- glob.o \
- hash.o \
- inits.o \
- io.o \
- marshal.o \
- math.o \
- numeric.o \
- object.o \
- pack.o \
- parse.o \
- process.o \
- random.o \
- range.o \
- re.o \
- regex.o \
- ruby.o \
- signal.o \
- sprintf.o \
- st.o \
- string.o \
- struct.o \
- time.o \
- util.o \
- variable.o \
- version.o \
+MAINOBJ = main.@OBJEXT@
+
+OBJS = array.@OBJEXT@ \
+ bignum.@OBJEXT@ \
+ class.@OBJEXT@ \
+ compar.@OBJEXT@ \
+ dir.@OBJEXT@ \
+ dln.@OBJEXT@ \
+ enum.@OBJEXT@ \
+ error.@OBJEXT@ \
+ eval.@OBJEXT@ \
+ file.@OBJEXT@ \
+ gc.@OBJEXT@ \
+ hash.@OBJEXT@ \
+ inits.@OBJEXT@ \
+ io.@OBJEXT@ \
+ marshal.@OBJEXT@ \
+ math.@OBJEXT@ \
+ numeric.@OBJEXT@ \
+ object.@OBJEXT@ \
+ pack.@OBJEXT@ \
+ parse.@OBJEXT@ \
+ process.@OBJEXT@ \
+ prec.@OBJEXT@ \
+ random.@OBJEXT@ \
+ range.@OBJEXT@ \
+ re.@OBJEXT@ \
+ regex.@OBJEXT@ \
+ ruby.@OBJEXT@ \
+ signal.@OBJEXT@ \
+ sprintf.@OBJEXT@ \
+ st.@OBJEXT@ \
+ string.@OBJEXT@ \
+ struct.@OBJEXT@ \
+ time.@OBJEXT@ \
+ util.@OBJEXT@ \
+ variable.@OBJEXT@ \
+ version.@OBJEXT@ \
$(MISSING)
-all: miniruby$(binsuffix) rbconfig.rb
- @./miniruby$(binsuffix) -Xext extmk.rb @EXTSTATIC@
+all: miniruby$(EXEEXT) @PREP@ rbconfig.rb $(LIBRUBY)
+ @@MINIRUBY@ -Cext extmk.rb @EXTSTATIC@
-miniruby$(binsuffix): $(OBJS) $(MAINOBJ) dmyext.o
+miniruby$(EXEEXT): config.status $(LIBRUBY_A) $(MAINOBJ) dmyext.@OBJEXT@
@rm -f $@
- $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(OBJS) dmyext.o $(LIBS) -o $@
+ $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) dmyext.@OBJEXT@ $(LIBRUBY_A) $(LIBS) -o $@
-ruby$(binsuffix): $(LIBRUBY) $(MAINOBJ) $(EXTOBJS)
+$(PROGRAM): $(LIBRUBY) $(MAINOBJ) $(EXTOBJS)
@rm -f $@
- $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBY) $(LIBS) -o $@
+ $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINLIBS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) -o $@
-$(LIBRUBY): $(OBJS) dmyext.o
- @AR@ rcu $(LIBRUBY) $(OBJS) dmyext.o
- @-@RANLIB@ $(LIBRUBY) 2> /dev/null || true
+$(LIBRUBY_A): $(OBJS) dmyext.@OBJEXT@
+ @AR@ rcu $@ $(OBJS) dmyext.@OBJEXT@
+ @-@RANLIB@ $@ 2> /dev/null || true
-install: rbconfig.rb
- ./miniruby$(binsuffix) $(srcdir)/instruby.rb
-
-clean:; @rm -f $(OBJS) $(LIBRUBY) $(MAINOBJ) rbconfig.rb
- @rm -f ext/extinit.c ext/extinit.o dmyext.o
- @if test -f ./miniruby$(binsuffix); then \
- ./miniruby$(binsuffix) -Xext extmk.rb clean; \
- fi
-
-realclean: clean
- @rm -f Makefile ext/extmk.rb ext/config.cache
- @rm -f config.cache config.h config.log config.status
- @rm -f parse.c lex.c *~ core *.core gmon.out
- @rm -f ruby$(binsuffix) miniruby$(binsuffix)
-
-test: miniruby$(binsuffix)
- @./miniruby$(binsuffix) $(srcdir)/rubytest.rb
+$(LIBRUBY_SO): $(OBJS) dmyext.@OBJEXT@ miniruby$(EXEEXT)
+ $(LDSHARED) $(DLDFLAGS) $(OBJS) dmyext.@OBJEXT@ $(SOLIBS) -o $@
+ @-@MINIRUBY@ -e 'ARGV.each{|link| File.delete link if File.exist? link; \
+ File.symlink "$(LIBRUBY_SO)", link}' \
+ $(LIBRUBY_ALIASES) || true
-rbconfig.rb: config.status miniruby$(binsuffix)
- @./miniruby$(binsuffix) $(srcdir)/mkconfig.rb rbconfig.rb
-
-.c.o:
+install: rbconfig.rb
+ @MINIRUBY@ $(srcdir)/instruby.rb $(DESTDIR)
+
+clean:; @rm -f $(OBJS) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY_ALIASES) $(MAINOBJ) rbconfig.rb
+ @rm -f ext/extinit.c ext/extinit.@OBJEXT@ dmyext.@OBJEXT@
+ @-@MINIRUBY@ -Cext extmk.rb clean 2> /dev/null || true
+ @rm -f $(PROGRAM) miniruby$(EXEEXT)
+
+distclean: clean
+ @rm -f Makefile ext/extmk.rb config.h
+ @rm -f ext/config.cache config.cache config.log config.status
+ @rm -f *~ core *.core gmon.out y.tab.c y.output ruby.imp
+
+realclean: distclean
+ @rm -f parse.c
+ @rm -f lex.c
+
+test: miniruby$(EXEEXT)
+ @./miniruby$(EXEEXT) $(srcdir)/rubytest.rb
+
+rbconfig.rb: miniruby$(EXEEXT) $(srcdir)/mkconfig.rb config.status
+ @@MINIRUBY@ $(srcdir)/mkconfig.rb rbconfig.rb
+
+fake.rb: miniruby$(EXEEXT)
+ @echo ' \
+ class Object; \
+ remove_const :RUBY_PLATFORM; \
+ RUBY_PLATFORM = "@arch@"; \
+ if defined? PLATFORM; \
+ remove_const :PLATFORM; \
+ PLATFORM = "@arch@"; \
+ end; \
+ CROSS_COMPILING = true; \
+ end \
+ ' > $@
+
+config.status: $(srcdir)/configure
+ $(SHELL) ./config.status --recheck
+
+$(srcdir)/configure: $(srcdir)/configure.in
+ cd $(srcdir) && $(AUTOCONF)
+
+.c.@OBJEXT@:
$(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) $<
mv -f y.tab.c parse.c
-alloca.o: @srcdir@/missing/alloca.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/alloca.c
+parse.@OBJEXT@: parse.c
+
+alloca.@OBJEXT@: $(srcdir)/missing/alloca.c
+ $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/alloca.c
+
+crypt.@OBJEXT@: $(srcdir)/missing/crypt.c
+ $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/crypt.c
+
+dup2.@OBJEXT@: $(srcdir)/missing/dup2.c
+ $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/dup2.c
+
+finite.@OBJEXT@: $(srcdir)/missing/finite.c
+ $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/finite.c
+
+flock.@OBJEXT@: $(srcdir)/missing/flock.c
+ $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/flock.c
+
+isinf.@OBJEXT@: $(srcdir)/missing/isinf.c
+ $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/isinf.c
+
+isnan.@OBJEXT@: $(srcdir)/missing/isnan.c
+ $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/isnan.c
+
+fnmatch.@OBJEXT@: $(srcdir)/missing/fnmatch.c
+ $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/fnmatch.c
-crypt.o: @srcdir@/missing/crypt.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/crypt.c
+memcmp.@OBJEXT@: $(srcdir)/missing/memcmp.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/memcmp.c
-dup2.o: @srcdir@/missing/dup2.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/dup2.c
+memmove.@OBJEXT@: $(srcdir)/missing/memmove.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/memmove.c
-flock.o: @srcdir@/missing/flock.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/flock.c
+mkdir.@OBJEXT@: $(srcdir)/missing/mkdir.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/mkdir.c
-memcmp.o: @srcdir@/missing/memcmp.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/memcmp.c
+vsnprintf.@OBJEXT@: $(srcdir)/missing/vsnprintf.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/vsnprintf.c
-memmove.o: @srcdir@/missing/memmove.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/memmove.c
+strcasecmp.@OBJEXT@: $(srcdir)/missing/strcasecmp.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strcasecmp.c
-mkdir.o: @srcdir@/missing/mkdir.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/mkdir.c
+strncasecmp.@OBJEXT@: $(srcdir)/missing/strncasecmp.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strncasecmp.c
-setenv.o: @srcdir@/missing/setenv.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/setenv.c
+strchr.@OBJEXT@: $(srcdir)/missing/strchr.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strchr.c
-strcasecmp.o: @srcdir@/missing/strcasecmp.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strcasecmp.c
+strerror.@OBJEXT@: $(srcdir)/missing/strerror.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strerror.c
-strchr.o: @srcdir@/missing/strchr.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strchr.c
+strftime.@OBJEXT@: $(srcdir)/missing/strftime.c
+ $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strftime.c
-strdup.o: @srcdir@/missing/strdup.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strdup.c
+strstr.@OBJEXT@: $(srcdir)/missing/strstr.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strstr.c
-strerror.o: @srcdir@/missing/strerror.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strerror.c
+strtod.@OBJEXT@: $(srcdir)/missing/strtod.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strtod.c
-strftime.o: @srcdir@/missing/strftime.c
- $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strftime.c
+strtol.@OBJEXT@: $(srcdir)/missing/strtol.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strtol.c
-strstr.o: @srcdir@/missing/strstr.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strstr.c
+strtoul.@OBJEXT@: $(srcdir)/missing/strtoul.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/strtoul.c
-strtol.o: @srcdir@/missing/strtol.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strtol.c
+x68.@OBJEXT@: $(srcdir)/missing/x68.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/x68.c
-strtoul.o: @srcdir@/missing/strtoul.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strtoul.c
+os2.@OBJEXT@: $(srcdir)/missing/os2.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/os2.c
-nt.o: @srcdir@/missing/nt.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/nt.c
+dl_os2.@OBJEXT@: $(srcdir)/missing/dl_os2.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(srcdir)/missing/dl_os2.c
-x68.o: @srcdir@/missing/x68.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/x68.c
+win32.@OBJEXT@: $(srcdir)/win32/win32.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -I$(srcdir)/missing -c $(srcdir)/win32/win32.c
# Prevent GNU make v3 from overflowing arg limit on SysV.
.NOEXPORT:
###
-parse.o: parse.y ruby.h config.h defines.h intern.h env.h node.h st.h regex.h util.h lex.c
+parse.@OBJEXT@: parse.y ruby.h config.h defines.h intern.h env.h node.h st.h regex.h util.h lex.c
###
-array.o: array.c ruby.h config.h defines.h intern.h
-bignum.o: bignum.c ruby.h config.h defines.h intern.h
-class.o: class.c ruby.h config.h defines.h intern.h node.h st.h
-compar.o: compar.c ruby.h config.h defines.h intern.h
-dir.o: dir.c ruby.h config.h defines.h intern.h
-dln.o: dln.c config.h defines.h dln.h
-dmyext.o: dmyext.c
-enum.o: enum.c ruby.h config.h defines.h intern.h
-error.o: error.c ruby.h config.h defines.h intern.h env.h
-eval.o: eval.c ruby.h config.h defines.h intern.h node.h env.h sig.h st.h dln.h
-file.o: file.c ruby.h config.h defines.h intern.h io.h sig.h
-gc.o: gc.c ruby.h config.h defines.h intern.h sig.h st.h node.h env.h re.h regex.h
-hash.o: hash.c ruby.h config.h defines.h intern.h st.h sig.h
-inits.o: inits.c ruby.h config.h defines.h intern.h
-io.o: io.c ruby.h config.h defines.h intern.h io.h sig.h
-main.o: main.c ruby.h config.h defines.h intern.h
-marshal.o: marshal.c ruby.h config.h defines.h intern.h io.h sig.h st.h
-math.o: math.c ruby.h config.h defines.h intern.h
-numeric.o: numeric.c ruby.h config.h defines.h intern.h
-object.o: object.c ruby.h config.h defines.h intern.h st.h
-pack.o: pack.c ruby.h config.h defines.h intern.h
-process.o: process.c ruby.h config.h defines.h intern.h sig.h st.h
-random.o: random.c ruby.h config.h defines.h intern.h
-range.o: range.c ruby.h config.h defines.h intern.h
-re.o: re.c ruby.h config.h defines.h intern.h re.h regex.h
-ruby.o: ruby.c ruby.h config.h defines.h intern.h re.h regex.h dln.h
-signal.o: signal.c ruby.h config.h defines.h intern.h sig.h
-sprintf.o: sprintf.c ruby.h config.h defines.h intern.h
-st.o: st.c config.h st.h
-string.o: string.c ruby.h config.h defines.h intern.h re.h regex.h
-struct.o: struct.c ruby.h config.h defines.h intern.h
-time.o: time.c ruby.h config.h defines.h intern.h
-util.o: util.c ruby.h config.h defines.h intern.h util.h
-variable.o: variable.c ruby.h config.h defines.h intern.h env.h node.h st.h
-version.o: version.c ruby.h config.h defines.h intern.h version.h
+array.@OBJEXT@: array.c ruby.h config.h defines.h intern.h util.h st.h
+bignum.@OBJEXT@: bignum.c ruby.h config.h defines.h intern.h
+class.@OBJEXT@: class.c ruby.h config.h defines.h intern.h rubysig.h node.h st.h
+compar.@OBJEXT@: compar.c ruby.h config.h defines.h intern.h
+dir.@OBJEXT@: dir.c ruby.h config.h defines.h intern.h
+dln.@OBJEXT@: dln.c config.h defines.h dln.h
+dmyext.@OBJEXT@: dmyext.c
+enum.@OBJEXT@: enum.c ruby.h config.h defines.h intern.h node.h
+error.@OBJEXT@: error.c ruby.h config.h defines.h intern.h env.h version.h
+eval.@OBJEXT@: eval.c ruby.h config.h defines.h intern.h node.h env.h rubysig.h st.h dln.h
+file.@OBJEXT@: file.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h dln.h
+gc.@OBJEXT@: gc.c ruby.h config.h defines.h intern.h rubysig.h st.h node.h env.h re.h regex.h
+hash.@OBJEXT@: hash.c ruby.h config.h defines.h intern.h st.h rubysig.h util.h
+inits.@OBJEXT@: inits.c ruby.h config.h defines.h intern.h
+io.@OBJEXT@: io.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h env.h util.h
+main.@OBJEXT@: main.c ruby.h config.h defines.h intern.h
+marshal.@OBJEXT@: marshal.c ruby.h config.h defines.h intern.h rubyio.h st.h
+prec.@OBJEXT@: prec.c ruby.h config.h defines.h intern.h
+math.@OBJEXT@: math.c ruby.h config.h defines.h intern.h
+numeric.@OBJEXT@: numeric.c ruby.h config.h defines.h intern.h
+object.@OBJEXT@: object.c ruby.h config.h defines.h intern.h st.h
+pack.@OBJEXT@: pack.c ruby.h config.h defines.h intern.h
+process.@OBJEXT@: process.c ruby.h config.h defines.h intern.h rubysig.h st.h
+random.@OBJEXT@: random.c ruby.h config.h defines.h intern.h
+range.@OBJEXT@: range.c ruby.h config.h defines.h intern.h
+re.@OBJEXT@: re.c ruby.h config.h defines.h intern.h re.h regex.h
+regex.@OBJEXT@: regex.c config.h regex.h
+ruby.@OBJEXT@: ruby.c ruby.h config.h defines.h intern.h dln.h node.h util.h
+signal.@OBJEXT@: signal.c ruby.h config.h defines.h intern.h rubysig.h
+sprintf.@OBJEXT@: sprintf.c ruby.h config.h defines.h intern.h
+st.@OBJEXT@: st.c config.h st.h
+string.@OBJEXT@: string.c ruby.h config.h defines.h intern.h re.h regex.h
+struct.@OBJEXT@: struct.c ruby.h config.h defines.h intern.h
+time.@OBJEXT@: time.c ruby.h config.h defines.h intern.h
+util.@OBJEXT@: util.c ruby.h config.h defines.h intern.h util.h
+variable.@OBJEXT@: variable.c ruby.h config.h defines.h intern.h env.h node.h st.h
+version.@OBJEXT@: version.c ruby.h config.h defines.h intern.h version.h
diff --git a/README b/README
index d41fb9f79a..760291d1ba 100644
--- a/README
+++ b/README
@@ -3,7 +3,7 @@
Ruby is the interpreted scripting language for quick and
easy object-oriented programming. It has many features to
process text files and to do system management tasks (as in
-perl). It is simple, straight-forward, and extensible.
+Perl). It is simple, straight-forward, and extensible.
* Features of Ruby
@@ -15,42 +15,69 @@ perl). It is simple, straight-forward, and extensible.
+ Iterators and Closures
+ Garbage Collection
+ Dynamic Loading of Object files(on some architecture)
- + Highly Portable(works on many UNIX machines)
+ + Highly Portable(works on many UNIX machines, and on DOS,
+ Windows, Mac, BeOS etc.)
* How to get Ruby
-The Ruby distribution can be found on
+The Ruby distribution can be found on:
ftp://ftp.netlab.co.jp/pub/lang/ruby/
+You can get it by anonymous CVS. How to check out is:
+
+ $ cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src login
+ (Logging in to anonymous@cvs.ruby-lang.org)
+ CVS password: anonymous
+ $ cvs -z4 -d :pserver:anonymous@cvs.ruby-lang.org:/src checkout ruby
+
+* Mailing list
+
+There is a mailing list to talk about Ruby.
+To subscribe this list, please send the following phrase
+
+ subscribe YourFirstName YourFamilyName
+e.g.
+ subscribe Joseph Smith
+
+in the mail body (not subject) to the address <ruby-talk-ctl@ruby-lang.org>.
+
* How to compile and install
This is what you need to do to compile and install Ruby:
- 1. Run ./configure, which will generate config.h and Makefile.
+ 1. If ./configure does not exist or is older than configure.in,
+ run autoconf to (re)generate configure.
+
+ 2. Run ./configure, which will generate config.h and Makefile.
- 2. Edit defines.h if you need. Probably this step will not need.
+ 3. Edit defines.h if you need. Probably this step will not need.
- 3. Remove comment mark(#) before the module names from ext/Setup, if
- you want to link modules statically.
+ 4. Remove comment mark(#) before the module names from ext/Setup (or
+ add module names if not present), if you want to link modules
+ statically.
- If you want to link all the extension modules, remove comment
- mark from the line "#option nodynamic".
+ If you don't want to compile non static extension modules
+ (probably on architectures which does not allow dynamic loading),
+ remove comment mark from the line "#option nodynamic" in
+ ext/Setup.
- 4. Run make.
+ 5. Run make.
- 5. Optionally, run 'make test' to check that the compiled Ruby
- interpreter works well. If you see the message "test succeeded",
- your Ruby works as it should (hopefully).
+ 6. Optionally, run 'make test' to check whether the compiled Ruby
+ interpreter works well. If you see the message "test succeeded",
+ your ruby works as it should (hopefully).
- 6. Run 'make install'
+ 7. Run 'make install'
-If you fail to compile Ruby, please send the detailed error report with
+ You may have to be a super user to install ruby.
+
+If you fail to compile ruby, please send the detailed error report with
the error log and machine/OS type, to help others.
* Copying
-Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.co.jp>.
+Ruby is copyrighted free software by Yukihiro Matsumoto <matz@zetabits.com>.
You can redistribute it and/or modify it under either the terms of the GPL
(see COPYING file), or the conditions below:
@@ -61,12 +88,13 @@ You can redistribute it and/or modify it under either the terms of the GPL
2. You may modify your copy of the software in any way, provided that
you do at least ONE of the following:
- a) place your modifications in the Public Domain or otherwise make them
- Freely Available, such as by posting said modifications to Usenet
- or an equivalent medium, or by allowing the author to include your
- modifications in the software.
+ a) place your modifications in the Public Domain or otherwise
+ make them Freely Available, such as by posting said
+ modifications to Usenet or an equivalent medium, or by allowing
+ the author to include your modifications in the software.
- b) use the modified software only within your corporation or organization.
+ b) use the modified software only within your corporation or
+ organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided.
@@ -84,17 +112,17 @@ You can redistribute it and/or modify it under either the terms of the GPL
the software.
c) give non-standard executables non-standard names, with
- instructions on where to get the original software
- distribution.
+ instructions on where to get the original software distribution.
d) make other distribution arrangements with the author.
4. You may modify and include the part of the software into any other
software (possibly commercial). But some files in the distribution
are not written by the author, so that they are not under this terms.
- They are gc.c(partly), utils.c(partly), regex.[ch], fnmatch.[ch],
- glob.c, st.[ch] and some files under the ./missing directory. See
- each files for the copying condition.
+
+ They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
+ files under the ./missing directory. See each file for the copying
+ condition.
5. The scripts and library files supplied as input to or produced as
output from the software do not automatically fall under the
@@ -104,21 +132,21 @@ You can redistribute it and/or modify it under either the terms of the GPL
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.
* Ruby home-page
The URL of the Ruby home-page is:
- http://www.netlab.co.jp/ruby/
+ http://www.ruby-lang.org/
* The Author
Feel free to send comments and bug reports to the author. Here is the
author's latest mail address:
- matz@netlab.co.jp
+ matz@zetabits.com
-------------------------------------------------------
created at: Thu Aug 3 11:57:36 JST 1995
diff --git a/README.EXT b/README.EXT
index c2f81d1a7a..f3db6fa45b 100644
--- a/README.EXT
+++ b/README.EXT
@@ -1,27 +1,22 @@
.\" README.EXT - -*- Text -*- created at: Mon Aug 7 16:45:54 JST 1995
-This document explains how to make extention modules for ruby.
+This document explains how to make extension libraries for Ruby.
-1¡¥Basic knowledge
+1. Basic knowledge
In C, variables have types and data do not have types. In contrast,
-ruby variables do not have static type and data themselves have
+Ruby variables do not have static type and data themselves have
types. So, data need to be converted across the languages.
-Data in ruby represented C type `VALUE'. Each VALUE data have its
+Data in Ruby represented C type `VALUE'. Each VALUE data have its
data-type.
-ruby¤Î¥Ç¡¼¥¿¤ÏVALUE¤È¤¤¤¦C¤Î·¿¤Çɽ¸½¤µ¤ì¤Þ¤¹¡¥VALUE·¿¤Î¥Ç¡¼
-¥¿¤Ï¤½¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤ò¼«Ê¬¤ÇÃΤäƤ¤¤Þ¤¹¡¥¤³¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤È
-¤¤¤¦¤Î¤Ï¥Ç¡¼¥¿(¥ª¥Ö¥¸¥§¥¯¥È)¤Î¼ÂºÝ¤Î¹½Â¤¤ò°ÕÌ£¤·¤Æ¤¤¤Æ¡¤ruby
-¤Î¥¯¥é¥¹¤È¤Ï¤Þ¤¿°ã¤Ã¤¿¤â¤Î¤Ç¤¹¡¥
-
To retrieve an C data from the VALUE, you need to:
(1) Identify VALUE's data type
(2) Convert VALUE into C data
-Converting to wrong data type may cause serious promblems.
+Converting to wrong data type may cause serious problems.
1.1 Data-types
@@ -29,7 +24,7 @@ Converting to wrong data type may cause serious promblems.
Ruby interpreter has data-types as below:
T_NIL nil
- T_OBJECT ordinaly object
+ T_OBJECT ordinary object
T_CLASS class
T_MODULE module
T_FLOAT floating point number
@@ -37,17 +32,19 @@ Ruby interpreter has data-types as below:
T_REGEXP regular expression
T_ARRAY array
T_FIXNUM Fixnum(31bit integer)
- T_HASH assosiative array
- T_STRUCT (ruby) structure
+ T_HASH associative array
+ T_STRUCT (Ruby) structure
T_BIGNUM multi precision integer
T_TRUE true
T_FALSE false
T_DATA data
+ T_SYMBOL symbol
Otherwise, there are several other types used internally:
T_ICLASS
T_MATCH
+ T_UNDEF
T_VARMAP
T_SCOPE
T_NODE
@@ -72,7 +69,7 @@ data-types, the code will be like:
break;
default:
/* raise exception */
- Fail("not valid value");
+ rb_raise(rb_eTypeError, "not valid value");
break;
}
@@ -89,471 +86,411 @@ There are faster check-macros for fixnums and nil.
1.3 Convert VALUE into C data
-¥Ç¡¼¥¿¥¿¥¤¥×¤¬T_NIL, T_FALSE, T_TRUE¤Ç¤¢¤ë»þ¡¤¥Ç¡¼¥¿¤Ï¤½¤ì¤¾
-¤ìnil, FALSE, TRUE¤Ç¤¹¡¥¤³¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ï¤Ò¤È
-¤Ä¤º¤Ä¤·¤«Â¸ºß¤·¤Þ¤»¤ó¡¥
+The data for type T_NIL, T_FALSE, T_TRUE are nil, true, false
+respectively. They are singletons for the data type.
+
+The T_FIXNUM data is the 31bit length fixed integer (63bit length on
+some machines), which can be convert to the C integer by using
+FIX2INT() macro. There also be NUM2INT() which converts any Ruby
+numbers into C integer. The NUM2INT() macro includes type check, so
+the exception will be raised if conversion failed.
-¥Ç¡¼¥¿¥¿¥¤¥×¤¬T_FIXNUM¤Î»þ¡¤¤³¤ì¤Ï31bit¤Î¥µ¥¤¥º¤ò»ý¤ÄÀ°¿ô¤Ç
-¤¹¡¥FIXNUM¤òC¤ÎÀ°¿ô¤ËÊÑ´¹¤¹¤ë¤¿¤á¤Ë¤Ï¥Þ¥¯¥í¡ÖFIX2INT()¡×¤ò»È
-¤¤¤Þ¤¹¡¥¤½¤ì¤«¤é¡¤FIXNUM¤Ë¸Â¤é¤ºruby¤Î¥Ç¡¼¥¿¤òÀ°¿ô¤ËÊÑ´¹¤¹¤ë
-¡ÖNUM2INT()¡×¤È¤¤¤¦¥Þ¥¯¥í¤¬¤¢¤ê¤Þ¤¹¡¥¤³¤Î¥Þ¥¯¥í¤Ï¥Ç¡¼¥¿¥¿¥¤
-¥×¤Î¥Á¥§¥Ã¥¯Ìµ¤·¤Ç»È¤¨¤Þ¤¹(À°¿ô¤ËÊÑ´¹¤Ç¤­¤Ê¤¤¾ì¹ç¤Ë¤ÏÎã³°¤¬
-ȯÀ¸¤¹¤ë)¡¥
+Other data types have corresponding C structures, e.g. struct RArray
+for T_ARRAY etc. VALUE of the type which has corresponding structure
+can be cast to retrieve the pointer to the struct. The casting macro
+RXXXX for each data type like RARRAY(obj). see "ruby.h".
-¤½¤ì°Ê³°¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤ÏÂбþ¤¹¤ëC¤Î¹½Â¤ÂΤ¬¤¢¤ê¤Þ¤¹¡¥Âбþ¤¹
-¤ë¹½Â¤ÂΤΤ¢¤ëVALUE¤Ï¤½¤Î¤Þ¤Þ¥­¥ã¥¹¥È(·¿ÊÑ´¹)¤¹¤ì¤Ð¹½Â¤ÂΤÎ
-¥Ý¥¤¥ó¥¿¤ËÊÑ´¹¤Ç¤­¤Þ¤¹¡¥
+For example, `RSTRING(size)->len' is the way to get the size of the
+Ruby String object. The allocated region can be accessed by
+`RSTRING(str)->ptr'. For arrays, `RARRAY(ary)->len' and
+`RARRAY(ary)->ptr' respectively.
-¹½Â¤ÂΤϡÖstruct RXxxxx¡×¤È¤¤¤¦Ì¾Á°¤Çruby.h¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤Þ
-¤¹¡¥Î㤨¤Ðʸ»úÎó¤Ï¡Östruct RString¡×¤Ç¤¹¡¥¼ÂºÝ¤Ë»È¤¦²ÄǽÀ­¤¬
-¤¢¤ë¤Î¤Ïʸ»úÎó¤ÈÇÛÎ󤯤餤¤À¤È»×¤¤¤Þ¤¹¡¥
+Notice: Do not change the value of the structure directly, unless you
+are responsible about the result. It will be the cause of interesting
+bugs.
-ruby.h¤Ç¤Ï¹½Â¤ÂΤإ­¥ã¥¹¥È¤¹¤ë¥Þ¥¯¥í¤â¡ÖRXXXXX()¡×(Á´ÉôÂçʸ
-»ú¤Ë¤·¤¿¤â¤Î)¤È¤¤¤¦Ì¾Á°¤ÇÄ󶡤µ¤ì¤Æ¤¤¤Þ¤¹(Îã: RSTRING())¡¥
+1.4 Convert C data into VALUE
-Î㤨¤Ð¡¤Ê¸»úÎóstr¤ÎŤµ¤òÆÀ¤ë¤¿¤á¤Ë¤Ï¡ÖRSTRING(str)->len¡×¤È
-¤·¡¤Ê¸»úÎóstr¤òchar*¤È¤·¤ÆÆÀ¤ë¤¿¤á¤Ë¤Ï¡ÖRSTRING(str)->ptr¡×
-¤È¤·¤Þ¤¹¡¥ÇÛÎó¤Î¾ì¹ç¤Ë¤Ï¡¤¤½¤ì¤¾¤ì¡ÖRARRAT(str)->len¡×¡¤
-¡ÖRARRAT(str)->ptr¡×¤È¤Ê¤ê¤Þ¤¹¡¥
+To convert C data to the values of Ruby:
-ruby¤Î¹½Â¤ÂΤòľÀÜ¥¢¥¯¥»¥¹¤¹¤ë»þ¤Ëµ¤¤ò¤Ä¤±¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤³
-¤È¤Ï¡¤ÇÛÎó¤äʸ»úÎó¤Î¹½Â¤ÂΤÎÃæ¿È¤Ï»²¾È¤¹¤ë¤À¤±¤Ç¡¤Ä¾ÀÜÊѹ¹¤·
-¤Ê¤¤¤³¤È¤Ç¤¹¡¥Ä¾ÀÜÊѹ¹¤·¤¿¾ì¹ç¡¤¥ª¥Ö¥¸¥§¥¯¥È¤ÎÆâÍÆ¤ÎÀ°¹çÀ­¤¬
-¤È¤ì¤Ê¤¯¤Ê¤Ã¤Æ¡¤»×¤ï¤Ì¥Ð¥°¤Î¸¶°ø¤Ë¤Ê¤ê¤Þ¤¹¡¥
+ * FIXNUM
-1.4 Convert C data into VALUE
+ left shift 1 bit, and turn on LSB.
-VALUE¤Î¼ÂºÝ¤Î¹½Â¤¤Ï
+ * Other pointer values
- * FIXNUM¤Î¾ì¹ç
+ cast to VALUE.
- 1bit±¦¥·¥Õ¥È¤·¤Æ¡¤LSB¤òΩ¤Æ¤ë¡¥
+You can determine whether VALUE is pointer or not, by checking LSB.
- * ¤½¤Î¾¤Î¥Ý¥¤¥ó¥¿¤Î¾ì¹ç
+Notice Ruby does not allow arbitrary pointer value to be VALUE. They
+should be pointers to the structures which Ruby knows. The known
+structures are defined in <ruby.h>.
- ¤½¤Î¤Þ¤ÞVALUE¤Ë¥­¥ã¥¹¥È¤¹¤ë¡¥
+To convert C numbers to Ruby value, use these macros.
-¤È¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥¤è¤Ã¤Æ¡¤LSB¤ò¥Á¥§¥Ã¥¯¤¹¤ì¤ÐVALUE¤¬FIXNUM¤«¤É
-¤¦¤«¤ï¤«¤ë¤ï¤±¤Ç¤¹(¥Ý¥¤¥ó¥¿¤ÎLSB¤¬Î©¤Ã¤Æ¤¤¤Ê¤¤¤³¤È¤ò²¾Äꤷ¤Æ
-¤¤¤ë)¡¥
+ INT2FIX() for integers within 31bits.
+ INT2NUM() for arbitrary sized integer.
-¤Ç¤¹¤«¤é¡¤FIXNUM°Ê³°¤Îruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Î¹½Â¤ÂΤÏñ¤ËVALUE
-¤Ë¥­¥ã¥¹¥È¤¹¤ë¤À¤±¤ÇVALUE¤ËÊÑ´¹½ÐÍè¤Þ¤¹¡¥¤¿¤À¤·¡¤Ç¤°Õ¤Î¹½Â¤
-ÂΤ¬VALUE¤Ë¥­¥ã¥¹¥È½ÐÍè¤ë¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡¥¥­¥ã¥¹¥È¤¹¤ë¤Î
-¤Ïruby¤ÎÃΤäƤ¤¤ë¹½Â¤ÂÎ(ruby.h¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ëstruct RXxxx
-¤Î¤â¤Î)¤À¤±¤Ë¤·¤Æ¤ª¤¤¤Æ¤¯¤À¤µ¤¤¡¥
+INT2NUM() converts integers into Bignums, if it is out of FIXNUM
+range, but bit slower.
-FIXNUM¤Ë´Ø¤·¤Æ¤ÏÊÑ´¹¥Þ¥¯¥í¤ò·Ðͳ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥C¤ÎÀ°¿ô
-¤«¤éVALUE¤ËÊÑ´¹¤¹¤ë¥Þ¥¯¥í¤Ï°Ê²¼¤Î¤â¤Î¤¬¤¢¤ê¤Þ¤¹¡¥É¬Íפ˱þ¤¸
-¤Æ»È¤¤Ê¬¤±¤Æ¤¯¤À¤µ¤¤¡¥
+1.5 Manipulate Ruby data
- INT2FIX() ¤â¤È¤ÎÀ°¿ô¤¬31bit°ÊÆâ¤Ë¼ý¤Þ¤ë»þ
- INT2NUM() Ǥ°Õ¤ÎÀ°¿ô¤«¤éVALUE¤Ø
+As I already told, it is not recommended to modify object's internal
+structure. To manipulate objects, use functions supplied by Ruby
+interpreter. Useful functions are listed below (not all):
-INT2NUM()¤ÏÀ°¿ô¤¬FIXNUM¤ÎÈϰϤ˼ý¤Þ¤é¤Ê¤¤¾ì¹ç¡¤Bignum¤ËÊÑ´¹
-¤·¤Æ¤¯¤ì¤Þ¤¹(¤¬¡¤¾¯¤·ÃÙ¤¤)¡¥
+ String functions
-1.5 Manipulate ruby data
+ rb_str_new(const char *ptr, long len)
-ÀèÄø¤â½Ò¤Ù¤¿Ä̤ꡤruby¤Î¹½Â¤ÂΤò¥¢¥¯¥»¥¹¤¹¤ë»þ¤ËÆâÍÆ¤Î¹¹¿·¤ò
-¹Ô¤¦¤³¤È¤Ï´«¤á¤é¤ì¤Þ¤»¤ó¡¥¤Ç¡¤ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë»þ¤Ë¤Ï
-ruby¤¬ÍѰդ·¤Æ¤¤¤ë´Ø¿ô¤òÍѤ¤¤Æ¤¯¤À¤µ¤¤¡¥
+ Creates a new Ruby string.
-¤³¤³¤Ç¤Ï¤â¤Ã¤È¤â»È¤ï¤ì¤ë¤Ç¤¢¤í¤¦Ê¸»úÎó¤ÈÇÛÎó¤ÎÀ¸À®/Áàºî¤ò¹Ô
-¤¤´Ø¿ô¤ò¤¢¤²¤Þ¤¹(Á´Éô¤Ç¤Ï¤Ê¤¤¤Ç¤¹)¡¥
+ rb_str_new2(const char *ptr)
- String funtions
+ Creates a new Ruby string from C string. This is equivalent to
+ rb_str_new(ptr, strlen(ptr)).
- str_new(char *ptr, int len)
+ rb_tainted_str_new(const char *ptr, long len)
- Creates a new ruby string.
+ Creates a new tainted Ruby string. Strings from external data
+ should be tainted.
- str_new2(char *ptr)
+ rb_tainted_str_new2(const char *ptr)
- Creates a new ruby string from C string. This is equivalent to
- str_new(ptr, strlen(ptr)).
+ Creates a new tainted Ruby string from C string.
- str_cat(VALUE str, char *ptr, int len)
+ rb_str_cat(VALUE str, const char *ptr, long len)
- Appends len bytes data from ptr to the ruby string.
+ Appends len bytes data from ptr to the Ruby string.
Array functions
- ary_new()
+ rb_ary_new()
Creates an array with no element.
- ary_new2(int len)
+ rb_ary_new2(long len)
Creates an array with no element, with allocating internal buffer
for len elements.
- ary_new3(int n, ...)
+ rb_ary_new3(long n, ...)
Creates an n-elements array from arguments.
- ary_new4(int n, VALUE *elts)
+ rb_ary_new4(long n, VALUE *elts)
Creates an n-elements array from C array.
- ary_push(VALUE ary)
- ary_pop(VALUE ary, VALUE val)
- ary_shift(VALUE ary)
- ary_unshift(VALUE ary, VALUE val)
- ary_entry(VALUE ary, int idx)
+ rb_ary_push(VALUE ary, VALUE val)
+ rb_ary_pop(VALUE ary)
+ rb_ary_shift(VALUE ary)
+ rb_ary_unshift(VALUE ary, VALUE val)
Array operations. The first argument to each functions must be an
array. They may dump core if other types given.
-2. Extend ruby with C
+2. Extend Ruby with C
-¸¶ÍýŪ¤Ëruby¤Ç½ñ¤±¤ë¤³¤È¤ÏC¤Ç¤â½ñ¤±¤Þ¤¹¡¥ruby¤½¤Î¤â¤Î¤¬C¤Çµ­
-½Ò¤µ¤ì¤Æ¤¤¤ë¤ó¤Ç¤¹¤«¤é¡¤ÅöÁ³¤È¤¤¤¨¤ÐÅöÁ³¤Ê¤ó¤Ç¤¹¤±¤É¡¥¤³¤³¤Ç
-¤Ïruby¤Î³ÈÄ¥¤Ë»È¤¦¤³¤È¤¬Â¿¤¤¤À¤í¤¦¤Èͽ¬¤µ¤ì¤ëµ¡Ç½¤òÃæ¿´¤Ë¾Ò
-²ð¤·¤Þ¤¹¡¥
+2.1 Add new features to Ruby
-2.1 Add new features to ruby
+You can add new features (classes, methods, etc.) to the Ruby
+interpreter. Ruby provides the API to define things below:
-ruby¤ÇÄ󶡤µ¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤¨¤Ðruby¥¤¥ó¥¿¥×¥ê¥¿¤Ë¿·¤·¤¤µ¡Ç½
-¤òÄɲ乤뤳¤È¤¬¤Ç¤­¤Þ¤¹¡¥ruby¤Ç¤Ï°Ê²¼¤Îµ¡Ç½¤òÄɲä¹¤ë´Ø¿ô¤¬
-Ä󶡤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+ * Classes, Modules
+ * Methods, Singleton Methods
+ * Constants
- * ¥¯¥é¥¹¡¤¥â¥¸¥å¡¼¥ë
- * ¥á¥½¥Ã¥É¡¤ÆÃ°Û¥á¥½¥Ã¥É¤Ê¤É
- * Äê¿ô
+2.1.1 Class/module definition
-¤Ç¤Ï½ç¤Ë¾Ò²ð¤·¤Þ¤¹¡¥
+To define class or module, use functions below:
-2.1.1 Class/module definition
+ VALUE rb_define_class(const char *name, VALUE super)
+ VALUE rb_define_module(const char *name)
-¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¤¿¤á¤Ë¤Ï¡¤°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+These functions return the newly created class or module. You may
+want to save this reference into the variable to use later.
- VALUE rb_define_class(char *name, VALUE super)
- VALUE rb_define_module(char *name)
+To define nested class or module, use functions below:
-¤³¤ì¤é¤Î´Ø¿ô¤Ï¿·¤·¤¯ÄêµÁ¤µ¤ì¤¿¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤òÊÖ¤·¤Þ¤¹¡¥
-¥á¥½¥Ã¥É¤äÄê¿ô¤ÎÄêµÁ¤Ë¤³¤ì¤é¤ÎÃͤ¬É¬ÍפʤΤǡ¤¤Û¤È¤ó¤É¤Î¾ì¹ç
-¤ÏÌá¤êÃͤòÊÑ¿ô¤Ë³ÊǼ¤·¤Æ¤ª¤¯É¬Íפ¬¤¢¤ë¤Ç¤·¤ç¤¦¡¥
+ VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
+ VALUE rb_define_module_under(VALUE outer, const char *name)
2.1.2 Method/singleton method definition
-¥á¥½¥Ã¥É¤äÆÃ°Û¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+To define methods or singleton methods, use functions below:
- void rb_define_method(VALUE class, char *name,
+ void rb_define_method(VALUE klass, const char *name,
VALUE (*func)(), int argc)
- void rb_define_singleton_method(VALUE object, char *name,
- VALUE (*func)(), int argc)
+ void rb_define_singleton_method(VALUE object, const char *name,
+ VALUE (*func)(), int argc)
+The `argc' represents the number of the arguments to the C function,
+which must be less than 17. But I believe you don't need that much. :-)
-ǰ¤Î¤¿¤áÀâÌÀ¤¹¤ë¤È¡ÖÆÃ°Û¥á¥½¥Ã¥É¡×¤È¤Ï¡¤¤½¤ÎÆÃÄê¤Î¥ª¥Ö¥¸¥§¥¯
-¥È¤ËÂФ·¤Æ¤À¤±Í­¸ú¤Ê¥á¥½¥Ã¥É¤Ç¤¹¡¥ruby¤Ç¤Ï¤è¤¯Smalltalk¤Ë¤ª
-¤±¤ë¥¯¥é¥¹¥á¥½¥Ã¥É¤È¤·¤Æ¡¤¥¯¥é¥¹¤ËÂФ¹¤ëÆÃ°Û¥á¥½¥Ã¥É¤¬»È¤ï¤ì
-¤Þ¤¹¡¥
+If `argc' is negative, it specifies calling sequence, not number of
+the arguments.
-¤³¤ì¤é¤Î´Ø¿ô¤Î argc¤È¤¤¤¦°ú¿ô¤ÏC¤Î´Ø¿ô¤ØÅϤµ¤ì¤ë°ú¿ô¤Î¿ô(¤È
-·Á¼°)¤ò·è¤á¤Þ¤¹¡¥argc¤¬Àµ¤Î»þ¤Ï´Ø¿ô¤Ë°ú¤­ÅϤ¹°ú¿ô¤Î¿ô¤ò°ÕÌ£
-¤·¤Þ¤¹¡¥16¸Ä°Ê¾å¤Î°ú¿ô¤Ï»È¤¨¤Þ¤»¤ó(¤¬¡¤Íפê¤Þ¤»¤ó¤è¤Í¡¤¤½¤ó
-¤Ê¤Ë)¡¥
+If argc is -1, the function will be called like:
-argc¤¬Éé¤Î»þ¤Ï°ú¿ô¤Î¿ô¤Ç¤Ï¤Ê¤¯¡¤·Á¼°¤ò»ØÄꤷ¤¿¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
-argc¤¬-1¤Î»þ¤Ï°ú¿ô¤òÇÛÎó¤ËÆþ¤ì¤ÆÅϤµ¤ì¤Þ¤¹¡¥argc¤¬-2¤Î»þ¤Ï°ú
-¿ô¤Ïruby¤ÎÇÛÎó¤È¤·¤ÆÅϤµ¤ì¤Þ¤¹¡¥
+ VALUE func(int argc, VALUE *argv, VALUE obj)
-¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ï¤â¤¦Æó¤Ä¤¢¤ê¤Þ¤¹¡¥¤Ò¤È¤Ä¤Ïprivate¥á
-¥½¥Ã¥É¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ç¡¤°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¤Ç¤¹¡¥
+where argc is the actual number of arguments, argv is the C array of
+the arguments, and obj is the receiver.
- void rb_define_private_method(VALUE class, char *name,
- VALUE (*func)(), int argc)
+if argc is -2, the arguments are passed in Ruby array. The function
+will be called like:
+
+ VALUE func(VALUE obj, VALUE args)
-private¥á¥½¥Ã¥É¤È¤Ï´Ø¿ô·Á¼°¤Ç¤·¤«¸Æ¤Ó½Ð¤¹¤³¤È¤Î½ÐÍè¤Ê¤¤¥á¥½¥Ã
-¥É¤Ç¤¹¡¥
+where obj is the receiver, and args is the Ruby array containing
+actual arguments.
-¤â¤¦¤Ò¤È¤Ä¤Ï¥â¥¸¥å¡¼¥ë´Ø¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¤Ç¤¹¡¥¥â¥¸¥å¡¼¥ë´Ø¿ô
-¤È¤Ï¥â¥¸¥å¡¼¥ë¤ÎÆÃ°Û¥á¥½¥Ã¥É¤Ç¤¢¤ê¡¤Æ±»þ¤Ëprivate¥á¥½¥Ã¥É¤Ç
-¤â¤¢¤ë¤â¤Î¤Ç¤¹¡¥Îã¤ò¤¢¤²¤ë¤ÈMath¥â¥¸¥å¡¼¥ë¤Îsqrt()¤Ê¤É¤¬¤¢¤²
-¤é¤ì¤Þ¤¹¡¥¤³¤Î¥á¥½¥Ã¥É¤Ï
+There're two more functions to define method. One is to define
+private method:
+
+ void rb_define_private_method(VALUE klass, const char *name,
+ VALUE (*func)(), int argc)
+
+The other is to define module function, which is private AND singleton
+method of the module. For example, sqrt is the module function
+defined in Math module. It can be call in the form like:
Math.sqrt(4)
-¤È¤¤¤¦·Á¼°¤Ç¤â
+or
include Math
sqrt(4)
-¤È¤¤¤¦·Á¼°¤Ç¤â»È¤¨¤Þ¤¹¡¥¥â¥¸¥å¡¼¥ë´Ø¿ô¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ï°Ê²¼¤Î
-Ä̤ê¤Ç¤¹¡¥
+To define module function
- void rb_define_module_function(VALUE module, char *name,
+ void rb_define_module_function(VALUE module, const char *name,
VALUE (*func)(), int argc)
-´Ø¿ôŪ¥á¥½¥Ã¥É(Kernel¥â¥¸¥å¡¼¥ë¤Îprivaet method)¤òÄêµÁ¤¹¤ë¤¿
-¤á¤Î´Ø¿ô¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¹¡¥
+Oh, in addition, function-like method, which is private method defined
+in Kernel module, can be defined using:
- void rb_define_global_function(char *name, VALUE (*func)(), int argc)
+ void rb_define_global_function(const char *name, VALUE (*func)(), int argc)
+To define alias to the method,
-2.1.3 Constant definition
+ void rb_define_alias(VALUE module, const char* new, const char* old);
-³ÈÄ¥¥â¥¸¥å¡¼¥ë¤¬É¬ÍפÊÄê¿ô¤Ï¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ¤ª¤¤¤¿Êý¤¬Îɤ¤
-¤Ç¤·¤ç¤¦¡¥Äê¿ô¤òÄêµÁ¤¹¤ë´Ø¿ô¤ÏÆó¤Ä¤¢¤ê¤Þ¤¹¡¥
-
- void rb_define_const(VALUE class, char *name, VALUE val)
- void rb_define_global_const(char *name, VALUE val)
+2.1.3 Constant definition
-Á°¼Ô¤ÏÆÃÄê¤Î¥¯¥é¥¹/¥â¥¸¥å¡¼¥ë¤Ë°¤¹¤ëÄê¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¡¤¸å
-¼Ô¤Ï¥°¥í¡¼¥Ð¥ë¤ÊÄê¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¤Ç¤¹¡¥
+We have 2 functions to define constants:
-2.2 Use ruby features from C
+ void rb_define_const(VALUE klass, const char *name, VALUE val)
+ void rb_define_global_const(const char *name, VALUE val)
-´û¤Ë¡Ø1.5 ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë¡Ù¤Ç°ìÉô¾Ò²ð¤·¤¿¤è¤¦¤Ê´Ø¿ô¤ò
-»È¤¨¤Ð¡¤ruby¤Îµ¡Ç½¤ò¼Â¸½¤·¤Æ¤¤¤ë´Ø¿ô¤òľÀܸƤӽФ¹¤³¤È¤¬½ÐÍè
-¤Þ¤¹¡¥
+The former is to define constant under specified class/module. The
+latter is to define global constant.
-# ¤³¤Î¤è¤¦¤Ê´Ø¿ô¤Î°ìÍ÷ɽ¤Ï¤¤¤Þ¤Î¤È¤³¤í¤¢¤ê¤Þ¤»¤ó¡¥¥½¡¼¥¹¤ò¸«
-# ¤ë¤·¤«¤Ê¤¤¤Ç¤¹¤Í¡¥
+2.2 Use Ruby features from C
-¤½¤ì°Ê³°¤Ë¤âruby¤Îµ¡Ç½¤ò¸Æ¤Ó½Ð¤¹ÊýË¡¤Ï¤¤¤¯¤Ä¤«¤¢¤ê¤Þ¤¹¡¥
+There are several ways to invoke Ruby's features from C code.
-2.2.1 ruby¤Î¥×¥í¥°¥é¥à¤òeval¤¹¤ë
+2.2.1 Evaluate Ruby Program in String
-C¤«¤éruby¤Îµ¡Ç½¤ò¸Æ¤Ó½Ð¤¹¤â¤Ã¤È¤â´Êñ¤ÊÊýË¡¤È¤·¤Æ¡¤Ê¸»úÎó¤Ç
-Í¿¤¨¤é¤ì¤¿ruby¤Î¥×¥í¥°¥é¥à¤òɾ²Á¤¹¤ë´Ø¿ô¤¬¤¢¤ê¤Þ¤¹¡¥
+Easiest way to call Ruby's function from C program is to evaluate the
+string as Ruby program. This function will do the job.
- VALUE rb_eval_string(char *str)
+ VALUE rb_eval_string(const char *str)
-¤³¤Îɾ²Á¤Ï¸½ºß¤Î´Ä¶­¤Ç¹Ô¤ï¤ì¤Þ¤¹¡¥¤Ä¤Þ¤ê¡¤¸½ºß¤Î¥í¡¼¥«¥ëÊÑ¿ô
-¤Ê¤É¤ò¼õ¤±·Ñ¤®¤Þ¤¹¡¥
+Evaluation is done under current context, thus current local variables
+of the innermost method (which is defined by Ruby) can be accessed.
2.2.2 ID or Symbol
-C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤Ëruby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤â¤Ç¤­¤Þ
-¤¹¡¥¤½¤ÎÁ°¤Ë¡¤ruby¥¤¥ó¥¿¥×¥ê¥¿Æâ¤Ç¥á¥½¥Ã¥É¤äÊÑ¿ô̾¤ò»ØÄꤹ¤ë
-»þ¤Ë»È¤ï¤ì¤Æ¤¤¤ëID¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Æ¤ª¤­¤Þ¤·¤ç¤¦¡¥
-
-ID¤È¤ÏÊÑ¿ô̾¡¤¥á¥½¥Ã¥É̾¤òɽ¤¹À°¿ô¤Ç¤¹¡¥ruby¤ÎÃæ¤Ç¤Ï
+You can invoke methods directly, without parsing the string. First I
+need to explain about symbols (which data type is ID). ID is the
+integer number to represent Ruby's identifiers such as variable names.
+It can be accessed from Ruby in the form like:
- :¼±ÊÌ»Ò
+ :Identifier
-¤Ç¥¢¥¯¥»¥¹¤Ç¤­¤Þ¤¹¡¥C¤«¤é¤³¤ÎÀ°¿ô¤òÆÀ¤ë¤¿¤á¤Ë¤Ï´Ø¿ô
+You can get the symbol value from string within C code, by using
- rb_intern(char *name)
+ rb_intern(const char *name)
-¤ò»È¤¤¤Þ¤¹¡¥¤Þ¤¿°ìʸ»ú¤Î±é»»»Ò¤Ï¤½¤Îʸ»ú¥³¡¼¥É¤¬¤½¤Î¤Þ¤Þ¥·¥ó
-¥Ü¥ë¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
+2.2.3 Invoke Ruby method from C
-2.2.3 Invoke ruby method from C
-
-C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤Ëruby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤¿¤á¤Ë¤Ï°Ê²¼
-¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+To invoke methods directly, you can use the function below
VALUE rb_funcall(VALUE recv, ID mid, int argc, ...)
-¤³¤Î´Ø¿ô¤Ï¥ª¥Ö¥¸¥§¥¯¥Èrecv¤Îmid¤Ç»ØÄꤵ¤ì¤ë¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð
-¤·¤Þ¤¹¡¥
+This function invokes the method of the recv, which name is specified
+by the symbol mid.
-2.2.4 ÊÑ¿ô/Äê¿ô¤ò»²¾È/¹¹¿·¤¹¤ë
+2.2.4 Accessing the variables and constants
-C¤«¤é´Ø¿ô¤ò»È¤Ã¤Æ»²¾È¡¦¹¹¿·¤Ç¤­¤ë¤Î¤Ï¡¤¥¯¥é¥¹Äê¿ô¡¤¥¤¥ó¥¹¥¿
-¥ó¥¹ÊÑ¿ô¤Ç¤¹¡¥Âç°èÊÑ¿ô¤Ï°ìÉô¤Î¤â¤Î¤ÏC¤ÎÂç°èÊÑ¿ô¤È¤·¤Æ¥¢¥¯¥»
-¥¹¤Ç¤­¤Þ¤¹¡¥¥í¡¼¥«¥ëÊÑ¿ô¤ò»²¾È¤¹¤ëÊýË¡¤Ï¸ø³«¤·¤Æ¤¤¤Þ¤»¤ó¡¥
+You can access class variables, and instance variables using access
+functions. Also, global variables can be shared between both worlds.
+There's no way to access Ruby's local variables.
-¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ò»²¾È¡¦¹¹¿·¤¹¤ë´Ø¿ô¤Ï°Ê²¼¤ÎÄÌ
-¤ê¤Ç¤¹¡¥
+The functions to access/modify instance variables are below:
VALUE rb_ivar_get(VALUE obj, ID id)
VALUE rb_ivar_set(VALUE obj, ID id, VALUE val)
-id¤Ïrb_intern()¤ÇÆÀ¤é¤ì¤ë¤â¤Î¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
+id must be the symbol, which can be retrieved by rb_intern().
-¥¯¥é¥¹Äê¿ô¤ò»²¾È¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
+To access the constants of the class/module:
VALUE rb_const_get(VALUE obj, ID id)
-¥¯¥é¥¹Äê¿ô¤ò¿·¤·¤¯ÄêµÁ¤¹¤ë¤¿¤á¤Ë¤Ï¡Ø2.1.3 Äê¿ôÄêµÁ¡Ù¤Ç¾Ò²ð¤µ
-¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
-
-3. Informatin sharing between ruby and C
+See 2.1.3 for defining new constant.
-C¸À¸ì¤Èruby¤Î´Ö¤Ç¾ðÊó¤ò¶¦Í­¤¹¤ëÊýË¡¤Ë¤Ä¤¤¤Æ²òÀ⤷¤Þ¤¹¡¥
+3. Information sharing between Ruby and C
-3.1 Ruby constant that C¤«¤é»²¾È¤Ç¤­¤ëruby¤ÎÄê¿ô
+3.1 Ruby constant that C can be accessed from C
-Following ruby constants can be referred from C.
+Following Ruby constants can be referred from C.
- TRUE
- FALSE
+ Qtrue
+ Qfalse
-Boolean values. FALSE is false in the C also (i.e. 0).
+Boolean values. Qfalse is false in the C also (i.e. 0).
Qnil
Ruby nil in C scope.
-3.2 Global variables shared between C and ruby
+3.2 Global variables shared between C and Ruby
-C¤Èruby¤ÇÂç°èÊÑ¿ô¤ò»È¤Ã¤Æ¾ðÊó¤ò¶¦Í­¤Ç¤­¤Þ¤¹¡¥¶¦Í­¤Ç¤­¤ëÂç°è
-ÊÑ¿ô¤Ë¤Ï¤¤¤¯¤Ä¤«¤Î¼ïÎब¤¢¤ê¤Þ¤¹¡¥¤½¤Î¤Ê¤«¤Ç¤â¤Ã¤È¤âÎɤ¯»È¤ï
-¤ì¤ë¤È»×¤ï¤ì¤ë¤Î¤Ïrb_define_variable()¤Ç¤¹¡¥
+Information can be shared between two worlds, using shared global
+variables. To define them, you can use functions listed below:
- void rb_define_variable(char *name, VALUE *var)
+ void rb_define_variable(const char *name, VALUE *var)
-¤³¤Î´Ø¿ô¤Ïruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ëÂç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ¤¹¡¥ÊÑ¿ô̾¤¬
-`$'¤Ç»Ï¤Þ¤é¤Ê¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤Þ¤¹¡¥¤³¤ÎÊÑ¿ô¤ÎÃͤòÊÑ
-¹¹¤¹¤ë¤È¼«Æ°Åª¤Ëruby¤ÎÂбþ¤¹¤ëÊÑ¿ô¤ÎÃͤâÊѤï¤ê¤Þ¤¹¡¥
+This function defines the variable which is shared by the both world.
+The value of the global variable pointed by `var', can be accessed
+through Ruby's global variable named `name'.
-¤Þ¤¿ruby¦¤«¤é¤Ï¹¹¿·¤Ç¤­¤Ê¤¤ÊÑ¿ô¤â¤¢¤ê¤Þ¤¹¡¥¤³¤Îread only¤Î
-ÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ÇÄêµÁ¤·¤Þ¤¹¡¥
+You can define read-only (from Ruby, of course) variable by the
+function below.
- void rb_define_readonly_variable(char *name, VALUE *var)
+ void rb_define_readonly_variable(const char *name, VALUE *var)
-¤³¤ì¤éÊÑ¿ô¤Î¾¤Ëhook¤ò¤Ä¤±¤¿Âç°èÊÑ¿ô¤òÄêµÁ¤Ç¤­¤Þ¤¹¡¥hookÉÕ¤­
-¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤òÍѤ¤¤ÆÄêµÁ¤·¤Þ¤¹¡¥hookÉÕ¤­Âç°èÊÑ¿ô¤Î
-Ãͤλ²¾È¤äÀßÄê¤Ïhook¤Ç¹Ô¤¦É¬Íפ¬¤¢¤ê¤Þ¤¹¡¥
-
- void rb_define_hooked_variable(char *name, VALUE *var,
- VALUE (*getter)(), VALUE (*setter)())
+You can defined hooked variables. The accessor functions (getter and
+setter) are called on access to the hooked variables.
-¤³¤Î´Ø¿ô¤ÏC¤Î´Ø¿ô¤Ë¤è¤Ã¤Æhook¤Î¤Ä¤±¤é¤ì¤¿Âç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ
-¤¹¡¥ÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï´Ø¿ôgetter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì
-¤¿»þ¤Ë¤Ï´Ø¿ôsetter¤¬¸Æ¤Ð¤ì¤ë¡¥hook¤ò»ØÄꤷ¤Ê¤¤¾ì¹ç¤Ïgetter¤ä
-setter¤Ë0¤ò»ØÄꤷ¤Þ¤¹¡¥
+ void rb_define_hooked_variable(constchar *name, VALUE *var,
+ VALUE (*getter)(), void (*setter)())
-# getter¤âsetter¤â0¤Ê¤é¤Ðrb_define_variable()¤ÈƱ¤¸¤Ë¤Ê¤ë¡¥
+If you need to supply either setter or getter, just supply 0 for the
+hook you don't need. If both hooks are 0, rb_define_hooked_variable()
+works just like rb_define_variable().
-¤½¤ì¤«¤é¡¤C¤Î´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ëruby¤ÎÂç°èÊÑ¿ô¤òÄêµÁ¤¹¤ë
-´Ø¿ô¤¬¤¢¤ê¤Þ¤¹¡¥
+ void rb_define_virtual_variable(const char *name,
+ VALUE (*getter)(), void (*setter)())
- void rb_define_virtual_variable(char *name,
- VALUE (*getter)(), VALUE (*setter)())
-
-¤³¤Î´Ø¿ô¤Ë¤è¤Ã¤ÆÄêµÁ¤µ¤ì¤¿ruby¤ÎÂç°èÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï
-getter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì¤Þ¤¹¡¥
+This function defines the Ruby global variable without corresponding C
+variable. The value of the variable will be set/get only by hooks.
The prototypes of the getter and setter functions are as following:
(*getter)(ID id, void *data, struct global_entry* entry);
(*setter)(VALUE val, ID id, void *data, struct global_entry* entry);
-3.3 Encapsulate C data into ruby object
-
-C¤ÎÀ¤³¦¤ÇÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿(¹½Â¤ÂÎ)¤òruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ
-¼è¤ê°·¤¤¤¿¤¤¾ì¹ç¤¬¤¢¤ê¤¨¤Þ¤¹¡¥¤³¤Î¤è¤¦¤Ê¾ì¹ç¤Ë¤Ï¡¤Data¤È¤¤¤¦
-ruby¥ª¥Ö¥¸¥§¥¯¥È¤ËC¤Î¹½Â¤ÂÎ(¤Ø¤Î¥Ý¥¤¥ó¥¿)¤ò¤¯¤ë¤à¤³¤È¤Çruby
-¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ¼è¤ê°·¤¨¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡¥
-
-Data¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Æ¹½Â¤ÂΤòruby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¥«¥×¥»¥ë
-²½¤¹¤ë¤¿¤á¤Ë¤Ï¡¤°Ê²¼¤Î¥Þ¥¯¥í¤ò»È¤¤¤Þ¤¹¡¥
+3.3 Encapsulate C data into Ruby object
- Data_Wrap_Struct(class,mark,free,ptr)
+To wrapping and objectify the C pointer as Ruby object (so called
+DATA), use Data_Wrap_Struct().
-¤³¤Î¥Þ¥¯¥í¤ÎÌá¤êÃͤÏÀ¸À®¤µ¤ì¤¿Data¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¹¡¥
+ Data_Wrap_Struct(klass, mark, free, ptr)
-class¤Ï¤³¤ÎData¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¯¥é¥¹¤Ç¤¹¡¥ptr¤Ï¥«¥×¥»¥ë²½¤¹¤ë
-C¤Î¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤Ç¤¹¡¥mark¤Ï¤³¤Î¹½Â¤ÂΤ¬ruby¤Î¥ª¥Ö¥¸¥§
-¥¯¥È¤Ø¤Î»²¾È¤¬¤¢¤ë»þ¤Ë»È¤¦´Ø¿ô¤Ç¤¹¡¥¤½¤Î¤è¤¦¤Ê»²¾È¤ò´Þ¤Þ¤Ê¤¤
-»þ¤Ë¤Ï0¤ò»ØÄꤷ¤Þ¤¹¡¥
+Data_Wrap_Struct() returns a created DATA object. The klass argument
+is the class for the DATA object. The mark argument is the function
+to mark Ruby objects pointed by this data. The free argument is the
+function to free the pointer allocation. The functions, mark and
+free, will be called from garbage collector.
-# ¤½¤Î¤è¤¦¤Ê»²¾È¤Ï´«¤á¤é¤ì¤Þ¤»¤ó¡¥
+You can allocate and wrap the structure in one step.
-free¤Ï¤³¤Î¹½Â¤ÂΤ¬¤â¤¦ÉÔÍפˤʤä¿»þ¤Ë¸Æ¤Ð¤ì¤ë´Ø¿ô¤Ç¤¹¡¥¤³¤Î
-´Ø¿ô¤¬¥¬¡¼¥Ù¡¼¥¸¥³¥ì¥¯¥¿¤«¤é¸Æ¤Ð¤ì¤Þ¤¹¡¥
+ Data_Make_Struct(klass, type, mark, free, sval)
-C¤Î¹½Â¤ÂΤγäÅö¤ÈData¥ª¥Ö¥¸¥§¥¯¥È¤ÎÀ¸À®¤òƱ»þ¤Ë¹Ô¤¦¥Þ¥¯¥í¤È
-¤·¤Æ°Ê²¼¤Î¤â¤Î¤¬Ä󶡤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+This macro returns an allocated Data object, wrapping the pointer to
+the structure, which is also allocated. This macro works like:
- Data_Make_Struct(class, type, mark, free, sval)
+ (sval = ALLOC(type), Data_Wrap_Struct(klass, mark, free, sval))
-¤³¤Î¥Þ¥¯¥í¤ÎÌá¤êÃͤÏÀ¸À®¤µ¤ì¤¿Data¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¹¡¥
+Arguments, klass, mark, free, works like their counterpart of
+Data_Wrap_Struct(). The pointer to allocated structure will be
+assigned to sval, which should be the pointer to the type specified.
-class, mark, free¤ÏData_Wrap_Struct¤ÈƱ¤¸Æ¯¤­¤ò¤·¤Þ¤¹¡¥type
-¤Ï³ä¤êÅö¤Æ¤ëC¹½Â¤ÂΤη¿¤Ç¤¹¡¥³ä¤êÅö¤Æ¤é¤ì¤¿¹½Â¤ÂΤÏÊÑ¿ôsval
-¤ËÂåÆþ¤µ¤ì¤Þ¤¹¡¥¤³¤ÎÊÑ¿ô¤Î·¿¤Ï (type*) ¤Ç¤¢¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥
-
-Data¥ª¥Ö¥¸¥§¥¯¥È¤«¤é¥Ý¥¤¥ó¥¿¤ò¼è¤ê½Ð¤¹¤Î¤Ï°Ê²¼¤Î¥Þ¥¯¥í¤òÍѤ¤
-¤Þ¤¹¡¥
+To retrieve the C pointer from the Data object, use the macro
+Data_Get_Struct().
Data_Get_Struct(obj, type, sval)
-C¤Î¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤ÏÊÑ¿ôsval¤ËÂåÆþ¤µ¤ì¤Þ¤¹¡¥
+The pointer to the structure will be assigned to the variable sval.
-¤³¤ì¤é¤ÎData¤Î»È¤¤Êý¤Ï¤Á¤ç¤Ã¤Èʬ¤«¤ê¤Ë¤¯¤¤¤Î¤Ç¡¤¸å¤ÇÀâÌÀ¤¹¤ë
-ÎãÂê¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+See example below for detail.
-4¡¥Example - Create dbm module
+4. Example - Creating dbm extension
-¤³¤³¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤È¤ê¤¢¤¨¤º³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ïºî¤ì¤ë¤Ï¤º¤Ç¤¹¡¥
-ruby¤Îext¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤¹¤Ç¤Ë´Þ¤Þ¤ì¤Æ¤¤¤ëdbm¥â¥¸¥å¡¼¥ë¤òÎã¤Ë
-¤·¤ÆÃʳ¬Åª¤ËÀâÌÀ¤·¤Þ¤¹¡¥
+OK, here's the example to make extension library. This is the
+extension to access dbm. The full source is included in ext/
+directory in the Ruby's source tree.
(1) make the directory
% mkdir ext/dbm
-ruby¤òŸ³«¤·¤¿¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¡¤ext¥Ç¥£¥ì¥¯¥È¥ê¤ÎÃæ¤Ë³ÈÄ¥¥â
-¥¸¥å¡¼¥ëÍѤΥǥ£¥ì¥¯¥È¥ê¤òºî¤ê¤Þ¤¹¡¥Ì¾Á°¤ÏŬÅö¤ËÁª¤ó¤Ç¹½¤¤¤Þ
-¤»¤ó¡¥
+Make a directory for the extension library under ext directory.
(2) create MANIFEST file
% cd ext/dbm
% touch MANIFEST
-³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¤Ë¤ÏMANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬
-ɬÍפʤΤǡ¤¤È¤ê¤¢¤¨¤º¶õ¤Î¥Õ¥¡¥¤¥ë¤òºî¤Ã¤Æ¤ª¤­¤Þ¤¹¡¥¸å¤Ç¤³¤Î
-¥Õ¥¡¥¤¥ë¤Ë¤ÏɬÍפʥե¡¥¤¥ë°ìÍ÷¤¬Æþ¤ë¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
-
-MANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤Ï¡¤make¤Î»þ¤Ë¥Ç¥£¥ì¥¯¥È¥ê¤¬³ÈÄ¥¥â¥¸¥å¡¼
-¥ë¤ò´Þ¤ó¤Ç¤¤¤ë¤«¤É¤¦¤«È½Äꤹ¤ë¤¿¤á¤Ë»È¤ï¤ì¤ì¤Æ¤¤¤Þ¤¹¡¥
+There should be MANIFEST file in the directory for the extension
+library. Make empty file now.
(3) design the library
-¤Þ¤¢¡¤ÅöÁ³¤Ê¤ó¤Ç¤¹¤±¤É¡¤¤É¤¦¤¤¤¦µ¡Ç½¤ò¼Â¸½¤¹¤ë¤«¤É¤¦¤«¤Þ¤ºÀß
-·×¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥¤É¤ó¤Ê¥¯¥é¥¹¤ò¤Ä¤¯¤ë¤«¡¤¤½¤Î¥¯¥é¥¹¤Ë¤Ï
-¤É¤ó¤Ê¥á¥½¥Ã¥É¤¬¤¢¤ë¤«¡¤¥¯¥é¥¹¤¬Ä󶡤¹¤ëÄê¿ô¤Ê¤É¤Ë¤Ä¤¤¤ÆÀß·×
-¤·¤Þ¤¹¡¥dbm¥¯¥é¥¹¤Ë¤Ä¤¤¤Æ¤Ïext/dbm.doc¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+You need to design the library features, before making it.
(4) write C code.
-³ÈÄ¥¥â¥¸¥å¡¼¥ëËÜÂΤȤʤëC¸À¸ì¤Î¥½¡¼¥¹¤ò½ñ¤­¤Þ¤¹¡¥C¸À¸ì¤Î¥½¡¼
-¥¹¤¬¤Ò¤È¤Ä¤Î»þ¤Ë¤Ï¡Ö¥â¥¸¥å¡¼¥ë̾.c¡×¤òÁª¤Ö¤ÈÎɤ¤¤Ç¤·¤ç¤¦¡¥C
-¸À¸ì¤Î¥½¡¼¥¹¤¬Ê£¿ô¤Î¾ì¹ç¤Ë¤ÏµÕ¤Ë¡Ö¥â¥¸¥å¡¼¥ë̾.c¡×¤È¤¤¤¦¥Õ¥¡
-¥¤¥ë̾¤ÏÈò¤±¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥¥ª¥Ö¥¸¥§¥¯¥È¥Õ¥¡¥¤¥ë¤È¥â¥¸¥å¡¼
-¥ëÀ¸À®»þ¤ËÃæ´ÖŪ¤ËÀ¸À®¤µ¤ì¤ë¡Ö¥â¥¸¥å¡¼¥ë̾.o¡×¤È¤¤¤¦¥Õ¥¡¥¤¥ë
-¤È¤¬¾×ÆÍ¤¹¤ë¤«¤é¤Ç¤¹¡¥
+You need to write C code for your extension library. If your library
+has only one source file, choosing ``LIBRARY.c'' as a file name is
+preferred. On the other hand, in case your library has plural source
+files, avoid choosing ``LIBRARY.c'' for a file name. It may conflict
+with intermediate file ``LIBRARY.o'' on some platforms.
-ruby¤Ï³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ò¥í¡¼¥É¤¹¤ë»þ¤Ë¡ÖInit_¥â¥¸¥å¡¼¥ë̾¡×¤È
-¤¤¤¦´Ø¿ô¤ò¼«Æ°Åª¤Ë¼Â¹Ô¤·¤Þ¤¹¡¥dbm¥â¥¸¥å¡¼¥ë¤Î¾ì¹ç¡ÖInit_dbm¡×
-¤Ç¤¹¡¥¤³¤Î´Ø¿ô¤ÎÃæ¤Ç¥¯¥é¥¹¡¤¥â¥¸¥å¡¼¥ë¡¤¥á¥½¥Ã¥É¡¤Äê¿ô¤Ê¤É¤Î
-ÄêµÁ¤ò¹Ô¤¤¤Þ¤¹¡¥dbm.c¤«¤é°ìÉô°úÍѤ·¤Þ¤¹¡¥
+Ruby will execute the initializing function named ``Init_LIBRARY'' in
+the library. For example, ``Init_dbm()'' will be executed when loading
+the library.
+
+Here's the example of an initializing function.
--
Init_dbm()
{
- /* DBM¥¯¥é¥¹¤òÄêµÁ¤¹¤ë */
- cDBM = rb_define_class("DBM", cObject);
- /* DBM¤ÏEnumerate¥â¥¸¥å¡¼¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë */
- rb_include_module(cDBM, mEnumerable);
+ /* define DBM class */
+ cDBM = rb_define_class("DBM", rb_cObject);
+ /* DBM includes Enumerate module */
+ rb_include_module(cDBM, rb_mEnumerable);
- /* DBM¥¯¥é¥¹¤Î¥¯¥é¥¹¥á¥½¥Ã¥Éopen(): °ú¿ô¤ÏC¤ÎÇÛÎó¤Ç¼õ¤±¤ë */
+ /* DBM has class method open(): arguments are received as C array */
rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1);
- /* DBM¥¯¥é¥¹¤Î¥á¥½¥Ã¥Éclose(): °ú¿ô¤Ï¤Ê¤· */
+ /* DBM instance method close(): no args */
rb_define_method(cDBM, "close", fdbm_close, 0);
- /* DBM¥¯¥é¥¹¤Î¥á¥½¥Ã¥É[]: °ú¿ô¤Ï1¸Ä */
+ /* DBM instance method []: 1 argument */
rb_define_method(cDBM, "[]", fdbm_fetch, 1);
:
- /* DBM¥Ç¡¼¥¿¤ò³ÊǼ¤¹¤ë¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô̾¤Î¤¿¤á¤ÎID */
- id_dbm = rb_intern("dbm");
}
--
-DBM¥â¥¸¥å¡¼¥ë¤Ïdbm¤Î¥Ç¡¼¥¿¤ÈÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Ë¤Ê¤ë¤Ï¤º¤Ç
-¤¹¤«¤é¡¤C¤ÎÀ¤³¦¤Îdbm¤òruby¤ÎÀ¤³¦¤Ë¼è¤ê¹þ¤àɬÍפ¬¤¢¤ê¤Þ¤¹¡¥
-
-
-dbm.c¤Ç¤ÏData_Make_Struct¤ò°Ê²¼¤Î¤è¤¦¤Ë»È¤Ã¤Æ¤¤¤Þ¤¹¡¥
+The dbm extension wrap dbm struct in C world using Data_Make_Struct.
--
struct dbmdata {
@@ -562,15 +499,13 @@ struct dbmdata {
};
-obj = Data_Make_Struct(class,struct dbmdata,0,free_dbm,dbmp);
+obj = Data_Make_Struct(klass, struct dbmdata, 0, free_dbm, dbmp);
--
-¤³¤³¤Ç¤Ïdbmstruct¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤òData¤Ë¥«¥×¥»¥ë²½¤·¤Æ¤¤
-¤Þ¤¹¡¥DBM*¤òľÀÜ¥«¥×¥»¥ë²½¤·¤Ê¤¤¤Î¤Ïclose()¤·¤¿»þ¤Î½èÍý¤ò¹Í
-¤¨¤Æ¤Î¤³¤È¤Ç¤¹¡¥
+This code wraps dbmdata structure into Ruby object. We avoid wrapping
+DBM* directly, because we want to cache size information.
-Data¥ª¥Ö¥¸¥§¥¯¥È¤«¤édbmstruct¹½Â¤ÂΤΥݥ¤¥ó¥¿¤ò¼è¤ê½Ð¤¹¤¿¤á
-¤Ë°Ê²¼¤Î¥Þ¥¯¥í¤ò»È¤Ã¤Æ¤¤¤Þ¤¹¡¥
+To retrieve dbmdata structure from Ruby object, we define the macro below:
--
#define GetDBM(obj, dbmp) {\
@@ -579,14 +514,11 @@ Data¥ª¥Ö¥¸¥§¥¯¥È¤«¤édbmstruct¹½Â¤ÂΤΥݥ¤¥ó¥¿¤ò¼è¤ê½Ð¤¹¤¿¤á
}
--
-¤Á¤ç¤Ã¤ÈÊ£»¨¤Ê¥Þ¥¯¥í¤Ç¤¹¤¬¡¤Íפ¹¤ë¤Ëdbmdata¹½Â¤ÂΤΥݥ¤¥ó¥¿
-¤Î¼è¤ê½Ð¤·¤È¡¤close¤µ¤ì¤Æ¤¤¤ë¤«¤É¤¦¤«¤Î¥Á¥§¥Ã¥¯¤ò¤Þ¤È¤á¤Æ¤¤
-¤ë¤À¤±¤Ç¤¹¡¥
+This sort of complicated macro do the retrieving and close check for
+the DBM.
-DBM¥¯¥é¥¹¤Ë¤Ï¤¿¤¯¤µ¤ó¥á¥½¥Ã¥É¤¬¤¢¤ê¤Þ¤¹¤¬¡¤Ê¬Îह¤ë¤È3¼ïÎà¤Î
-°ú¿ô¤Î¼õ¤±Êý¤¬¤¢¤ê¤Þ¤¹¡¥¤Ò¤È¤Ä¤Ï°ú¿ô¤Î¿ô¤¬¸ÇÄê¤Î¤â¤Î¤Ç¡¤Îã¤È
-¤·¤Æ¤Ïdelete¥á¥½¥Ã¥É¤¬¤¢¤ê¤Þ¤¹¡¥delete¥á¥½¥Ã¥É¤ò¼ÂÁõ¤·¤Æ¤¤¤ë
-fdbm_delete()¤Ï¤³¤Î¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
+There are three kind of way to receiving method arguments. First, the
+methods with fixed number of arguments receives arguments like this:
--
static VALUE
@@ -597,20 +529,18 @@ fdbm_delete(obj, keystr)
}
--
-°ú¿ô¤Î¿ô¤¬¸ÇÄê¤Î¥¿¥¤¥×¤ÏÂè1°ú¿ô¤¬self¡¤Âè2°ú¿ô°Ê¹ß¤¬¥á¥½¥Ã¥É
-¤Î°ú¿ô¤È¤Ê¤ê¤Þ¤¹¡¥
+The first argument of the C function is the self, the rest are the
+arguments to the method.
-°ú¿ô¤Î¿ô¤¬ÉÔÄê¤Î¤â¤Î¤ÏC¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î¤Èruby¤ÎÇÛÎó¤Ç¼õ¤±
-¤ë¤â¤Î¤È¤¬¤¢¤ê¤Þ¤¹¡¥dbm¥â¥¸¥å¡¼¥ë¤ÎÃæ¤Ç¡¤C¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î
-¤ÏDBM¤Î¥¯¥é¥¹¥á¥½¥Ã¥É¤Ç¤¢¤ëopen()¤Ç¤¹¡¥¤³¤ì¤ò¼ÂÁõ¤·¤Æ¤¤¤ë´Ø
-¿ôfdbm_s_open()¤Ï¤³¤¦¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
+Second, the methods with arbitrary number of arguments receives
+arguments like this:
--
static VALUE
-fdbm_s_open(argc, argv, class)
+fdbm_s_open(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
:
if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
@@ -620,115 +550,116 @@ fdbm_s_open(argc, argv, class)
}
--
-¤³¤Î¥¿¥¤¥×¤Î´Ø¿ô¤ÏÂè1°ú¿ô¤¬Í¿¤¨¤é¤ì¤¿°ú¿ô¤Î¿ô¡¤Âè2°ú¿ô¤¬Í¿¤¨
-¤é¤ì¤¿°ú¿ô¤ÎÆþ¤Ã¤Æ¤¤¤ëÇÛÎó¤Ë¤Ê¤ê¤Þ¤¹¡¥self¤ÏÂè3°ú¿ô¤È¤·¤ÆÍ¿
-¤¨¤é¤ì¤Þ¤¹¡¥
+The first argument is the number of method arguments. the second
+argument is the C array of the method arguments. And the third
+argument is the receiver of the method.
-¤³¤ÎÇÛÎó¤ÇÍ¿¤¨¤é¤ì¤¿°ú¿ô¤ò²òÀϤ¹¤ë¤¿¤á¤Î´Ø¿ô¤¬open()¤Ç¤â»È¤ï
-¤ì¤Æ¤¤¤ërb_scan_args()¤Ç¤¹¡¥Âè3°ú¿ô¤Ë»ØÄꤷ¤¿¥Õ¥©¡¼¥Þ¥Ã¥È¤Ë
-½¾¤¤¡¤Âè4ÊÑ¿ô°Ê¹ß¤Ë»ØÄꤷ¤¿ÊÑ¿ô¤ËÃͤòÂåÆþ¤·¤Æ¤¯¤ì¤Þ¤¹¡¥¤³¤Î
-¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¡¤Âè1ʸ»úÌܤ¬¾Êά¤Ç¤­¤Ê¤¤°ú¿ô¤Î¿ô¡¤Âè2ʸ»úÌܤ¬
-¾Êά¤Ç¤­¤ë°ú¿ô¤Î¿ô¡¤Âè3ʸ»úÌܤ¬Âбþ¤¹¤ëÁê¼ê¤¬Ìµ¤¤¤¢¤Þ¤ê¤Î°ú
-¿ô¤¬¤¢¤ë¤«¤É¤¦¤«¤ò¼¨¤¹"*"¤Ç¤¹¡¥2ʸ»úÌܤÈ3ʸ»úÌܤϾÊά¤Ç¤­¤Þ
-¤¹¡¥dbm.c¤ÎÎã¤Ç¤Ï¡¤¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï"11"¤Ç¤¹¤«¤é¡¤°ú¿ô¤ÏºÇÄã1¤Ä
-¤Ç¡¤2¤Ä¤Þ¤Çµö¤µ¤ì¤ë¤È¤¤¤¦°ÕÌ£¤Ë¤Ê¤ê¤Þ¤¹¡¥¾Êά¤µ¤ì¤Æ¤¤¤ë»þ¤Î
-ÊÑ¿ô¤ÎÃͤÏnil(C¸À¸ì¤Î¥ì¥Ù¥ë¤Ç¤ÏQnil)¤Ë¤Ê¤ê¤Þ¤¹¡¥
+You can use the function rb_scan_args() to check and retrieve the
+arguments. For example "11" means, the method requires at least one
+argument, and at most receives two arguments.
-ruby¤ÎÇÛÎó¤Ç°ú¿ô¤ò¼õ¤±¼è¤ë¤â¤Î¤Ïindexes¤¬¤¢¤ê¤Þ¤¹¡¥¼ÂÁõ¤Ï¤³
-¤¦¤Ç¤¹¡¥
+The methods with arbitrary number of arguments can receives arguments
+by Ruby's array, like this:
--
static VALUE
fdbm_indexes(obj, args)
- VALUE obj;
- struct RArray *args;
+ VALUE obj, args;
{
:
}
--
-Âè1°ú¿ô¤Ïself¡¤Âè2°ú¿ô¤Ïruby¤ÎÇÛÎó¤Ç¤¹¡¥¤³¤³¤Ç¤Ï¥­¥ã¥¹¥È¤ò¸º
-¤é¤¹¤¿¤á struct RArray* ¤Ç¼õ¤±¤Æ¤¤¤Þ¤¹¤¬¡¤VALUE¤Ç¤âƱ¤¸¤³¤È
-¤Ç¤¹¡¥
+The first argument is the receiver, the second one is the Ruby array
+which contains the arguments to the method.
-** Ãí°Õ»ö¹à
+** Notice
-ruby¤È¶¦Í­¤Ï¤·¤Ê¤¤¤¬ruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤ò³ÊǼ¤¹¤ë²ÄǽÀ­¤Î¤¢¤ë
-C¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤Æruby¥¤¥ó¥¿¥×¥ê¥¿¤ËÊÑ¿ô¤Î¸ºß
-¤ò¶µ¤¨¤Æ¤¢¤²¤Æ¤¯¤À¤µ¤¤¡¥¤Ç¤Ê¤¤¤ÈGC¤Ç¥È¥é¥Ö¥ë¤òµ¯¤³¤·¤Þ¤¹¡¥
+GC should know about global variables which refers Ruby's objects, but
+not exported to the Ruby world. You need to protect them by
void rb_global_variable(VALUE *var)
(5) prepare extconf.rb
-¤â¤·¥Ç¥£¥ì¥¯¥È¥ê¤Ë¡Öextconf.rb¡×¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ì¤Ð¡¤
-make»þ¤Ë¼Â¹Ô¤µ¤ì¤Þ¤¹¡¥¤Ê¤±¤ì¤ÐŬÅö¤ËMakefile¤¬À¸À®¤µ¤ì¤Þ¤¹¡¥
+If there exists the file named extconf.rb, it will be executed to
+generate Makefile. If not, compilation scheme try to generate
+Makefile anyway.
+
+The extconf.rb is the file to check compilation condition etc. You
+need to put
+
+ require 'mkmf'
-extconf.rb¤Ï¥â¥¸¥å¡¼¥ë¤Î¥³¥ó¥Ñ¥¤¥ë¤ËɬÍפʾò·ï¤Î¥Á¥§¥Ã¥¯¤Ê¤É
-¤ò¹Ô¤¦¤³¤È¤¬ÌÜŪ¤Ç¤¹¡¥extconf.rb¤ÎÃæ¤Ç¤Ï°Ê²¼¤Îruby´Ø¿ô¤ò»È¤¦
-¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥
+at the top of the file. You can use the functions below to check the
+condition.
- have_library(lib, func): ¥é¥¤¥Ö¥é¥ê¤Î¸ºß¥Á¥§¥Ã¥¯
- have_func(func): ´Ø¿ô¤Î¸ºß¥Á¥§¥Ã¥¯
- have_header(header): ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¥Á¥§¥Ã¥¯
- create_makefile(target): Makefile¤ÎÀ¸À®
+ have_library(lib, func): check whether library containing function exists.
+ have_func(func, header): check whether function exists
+ have_header(header): check whether header file exists
+ create_makefile(target): generate Makefile
-°Ê²¼¤ÎÊÑ¿ô¤ò»È¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥
+The value of variables below will affect Makefile.
- $CFLAGS: ¥³¥ó¥Ñ¥¤¥ë»þ¤ËÄɲÃŪ¤Ë»ØÄꤹ¤ë¥Õ¥é¥°(-I¤Ê¤É)
- $LDFLAGS: ¥ê¥ó¥¯»þ¤ËÄɲÃŪ¤Ë»ØÄꤹ¤ë¥Õ¥é¥°(-L¤Ê¤É)
+ $CFLAGS: included in CFLAGS make variable (such as -I)
+ $LDFLAGS: included in LDFLAGS make variable (such as -L)
-¥â¥¸¥å¡¼¥ë¤ò¥³¥ó¥Ñ¥¤¥ë¤¹¤ë¾ò·ï¤¬Â·¤ï¤Ê¤º¡¤¤½¤Î¥â¥¸¥å¡¼¥ë¤Ï¥³
-¥ó¥Ñ¥¤¥ë¤·¤Ê¤¤»þ¤Ë¤Ïcreate_makefile¤ò¸Æ¤Ð¤Ê¤±¤ì¤ÐMakefile¤Ï
-À¸À®¤µ¤ì¤º¡¤¥³¥ó¥Ñ¥¤¥ë¤â¹Ô¤ï¤ì¤Þ¤»¤ó¡¥
+If compilation condition is not fulfilled, you do not call
+``create_makefile''. Makefile will not generated, compilation will
+not be done.
(6) prepare depend (optional)
-¤â¤·¡¤¥Ç¥£¥ì¥¯¥È¥ê¤Ëdepend¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ì¤Ð¡¤
-Makefile¤¬°Í¸´Ø·¸¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤ì¤Þ¤¹¡¥
+If the file named depend exists, Makefile will include that file to
+check dependency. You can make this file by invoking
- % gcc -MM *.c > depend
+ % gcc -MM *.c > depend
-¤Ê¤É¤Çºî¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤¢¤Ã¤ÆÂ»¤Ï̵¤¤¤Ç¤·¤ç¤¦¡¥
+It's no harm. Prepare it.
-(7) MANIFEST¥Õ¥¡¥¤¥ë¤Ë¥Õ¥¡¥¤¥ë̾¤òÆþ¤ì¤ë
+(7) put file names into MANIFEST (optional)
- % ls > MANIFEST
+ % find * -type f -print > MANIFEST
% vi MANIFEST
-*.o, *~¤Ê¤ÉÉÔɬÍפʥե¡¥¤¥ë°Ê³°¤ÏMANIFEST¤ËÄɲ䷤Ƥª¤­¤Þ¤¹¡¥
-make»þ¤Ë¤ÏMANIFEST¤ÎÆâÍÆ¤Ï»²¾È¤·¤Þ¤»¤ó¤Î¤Ç¡¤¶õ¤Î¤Þ¤Þ¤Ç¤âÌäÂê
-¤Ïµ¯¤­¤Þ¤»¤ó¤¬¡¤¥Ñ¥Ã¥±¡¼¥¸¥ó¥°¤Î»þ¤Ë»²¾È¤¹¤ë¤³¤È¤¬¤¢¤ë¤Î¤È¡¤
-ɬÍפʥե¡¥¤¥ë¤ò¶èÊ̤Ǥ­¤ë¤Î¤Ç¡¤ÍѰդ·¤Æ¤ª¤¤¤¿Êý¤¬Îɤ¤¤Ç¤·¤ç
-¤¦¡¥
+Append file names into MANIFEST. The compilation scheme requires
+MANIFEST only to be exist. But, you'd better take this step to
+distinguish required files.
-(8) make
+(8) generate Makefile
-ruby¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Çmake¤ò¼Â¹Ô¤¹¤ë¤ÈMakefile¤òÀ¸À®¤«¤émake¡¤
-ɬÍפˤè¤Ã¤Æ¤Ï¤½¤Î¥â¥¸¥å¡¼¥ë¤Îruby¤Ø¤Î¥ê¥ó¥¯¤Þ¤Ç¼«Æ°Åª¤Ë¼Â¹Ô
-¤·¤Æ¤¯¤ì¤Þ¤¹¡¥extconf.rb¤ò½ñ¤­´¹¤¨¤ë¤Ê¤É¤·¤ÆMakefile¤ÎºÆÀ¸À®
-¤¬É¬Íפʻþ¤Ï¤Þ¤¿ruby¥Ç¥£¥ì¥¯¥È¥ê¤Çmake¤·¤Æ¤¯¤À¤µ¤¤¡¥
+Try generate Makefile by:
-(9) debug
+ ruby extconf.rb
+
+You don't need this step, if you put extension library under ext
+directory of the ruby source tree. In that case, compilation of the
+interpreter will do this step for you.
+
+(9) make
+
+Type
-¤Þ¤¢¡¤¥Ç¥Ð¥Ã¥°¤·¤Ê¤¤¤Èư¤«¤Ê¤¤¤Ç¤·¤ç¤¦¤Í¡¥ext/Setup¤Ë¥Ç¥£¥ì
-¥¯¥È¥ê̾¤ò½ñ¤¯¤ÈÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë¤Î¤Ç¥Ç¥Ð¥Ã¥¬¤¬»È¤¨¤ë¤è¤¦¤Ë¤Ê
-¤ê¤Þ¤¹¡¥¤½¤Îʬ¥³¥ó¥Ñ¥¤¥ë¤¬ÃÙ¤¯¤Ê¤ê¤Þ¤¹¤±¤É¡¥
+ make
-(10) done, now you have the extension module
+to compile your extension. You don't need this step neither, if you
+put extension library under ext directory of the ruby source tree.
-¸å¤Ï¤³¤Ã¤½¤ê»È¤¦¤Ê¤ê¡¤¹­¤¯¸ø³«¤¹¤ë¤Ê¤ê¡¤Çä¤ë¤Ê¤ê¡¤¤´¼«Í³¤Ë¤ª
-»È¤¤¤¯¤À¤µ¤¤¡¥ruby¤Îºî¼Ô¤Ï³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë´Ø¤·¤Æ°ìÀڤθ¢Íø¤ò
-¼çÄ¥¤·¤Þ¤»¤ó¡¥
+(9) debug
+
+You may need to rb_debug the extension. The extensions can be linked
+statically by adding directory name in the ext/Setup file, so that you
+can inspect the extension with the debugger.
-Appendix A. ruby¤Î¥½¡¼¥¹¥³¡¼¥É¤ÎʬÎà
+(10) done, now you have the extension library
-ruby¤Î¥½¡¼¥¹¤Ï¤¤¤¯¤Ä¤«¤ËʬÎह¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤³¤Î¤¦¤Á¥¯¥é
-¥¹¥é¥¤¥Ö¥é¥ê¤ÎÉôʬ¤Ï´ðËÜŪ¤Ë³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ÈƱ¤¸ºî¤êÊý¤Ë¤Ê¤Ã
-¤Æ¤¤¤Þ¤¹¡¥¤³¤ì¤é¤Î¥½¡¼¥¹¤Ïº£¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤Û¤È¤ó¤ÉÍý²ò¤Ç¤­¤ë¤È
-»×¤¤¤Þ¤¹¡¥
+You can do anything you want with your library. The author of Ruby
+will not claim any restriction about your code depending Ruby API.
+Feel free to use, modify, distribute or sell your program.
-coore ruby language
+Appendix A. Ruby source files overview
+
+ruby language core
class.c
error.c
@@ -741,8 +672,6 @@ coore ruby language
utility functions
dln.c
- fnmatch.c
- glob.c
regex.c
st.c
util.c
@@ -765,9 +694,11 @@ class library
file.c
hash.c
io.c
+ marshal.c
math.c
numeric.c
pack.c
+ prec.c
process.c
random.c
range.c
@@ -778,18 +709,15 @@ class library
struct.c
time.c
-Appendix B. ³ÈÄ¥ÍÑ´Ø¿ô¥ê¥Õ¥¡¥ì¥ó¥¹
-
-C¸À¸ì¤«¤éruby¤Îµ¡Ç½¤òÍøÍѤ¹¤ëAPI¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥
+Appendix B. Ruby extension API reference
-** ·¿
+** Types
VALUE
-ruby¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¸½¤¹¤ë·¿¡¥É¬Íפ˱þ¤¸¤Æ¥­¥ã¥¹¥È¤·¤ÆÍѤ¤¤ë¡¥
-ÁȤ߹þ¤ß·¿¤òɽ¸½¤¹¤ëC¤Î·¿¤Ïruby.h¤Ëµ­½Ò¤·¤Æ¤¢¤ëR¤Ç»Ï¤Þ¤ë¹½Â¤
-ÂΤǤ¢¤ë¡¥VALUE·¿¤ò¤³¤ì¤é¤Ë¥­¥ã¥¹¥È¤¹¤ë¤¿¤á¤ËR¤Ç»Ï¤Þ¤ë¹½Â¤ÂÎ
-̾¤òÁ´¤ÆÂçʸ»ú¤Ë¤·¤¿Ì¾Á°¤Î¥Þ¥¯¥í¤¬ÍѰդµ¤ì¤Æ¤¤¤ë¡¥
+The type for Ruby object. Actual structures are defined in ruby.h,
+such as struct RString, etc. To refer the values in structures, use
+casting macros like RSTRING(obj).
** Variables and constants
@@ -797,268 +725,302 @@ ruby¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¸½¤¹¤ë·¿¡¥É¬Íפ˱þ¤¸¤Æ¥­¥ã¥¹¥È¤·¤ÆÍѤ¤¤ë¡¥
const: nil object
- TRUE
+ Qtrue
-const: TRUE object(default true value)
+const: true object(default true value)
- FALSE
+ Qfalse
-const: FALSE object
+const: false object
-** C¥Ç¡¼¥¿¤Î¥«¥×¥»¥ë²½
+** C pointer wrapping
- Data_Wrap_Struct(VALUE class, void (*mark)(), void (*free)(), void *sval)
+ Data_Wrap_Struct(VALUE klass, void (*mark)(), void (*free)(), void *sval)
-C¤ÎǤ°Õ¤Î¥Ý¥¤¥ó¥¿¤ò¥«¥×¥»¥ë²½¤·¤¿ruby¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡¥¤³
-¤Î¥Ý¥¤¥ó¥¿¤¬ruby¤«¤é¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¯¤Ê¤Ã¤¿»þ¡¤free¤Ç»ØÄꤷ¤¿
-´Ø¿ô¤¬¸Æ¤Ð¤ì¤ë¡¥¤Þ¤¿¡¤¤³¤Î¥Ý¥¤¥ó¥¿¤Î»Ø¤¹¥Ç¡¼¥¿¤¬Â¾¤Îruby¥ª¥Ö
-¥¸¥§¥¯¥È¤ò»Ø¤·¤Æ¤¤¤ë¾ì¹ç¡¤mark¤Ë»ØÄꤹ¤ë´Ø¿ô¤Ç¥Þ¡¼¥¯¤¹¤ëɬÍ×
-¤¬¤¢¤ë¡¥
+Wrap C pointer into Ruby object. If object has references to other
+Ruby object, they should be marked by using mark function during GC
+process. Otherwise, mark should be 0. When this object is no longer
+referred by anywhere, the pointer will be discarded by free function.
- Data_Make_Struct(class, type, mark, free, sval)
+ Data_Make_Struct(klass, type, mark, free, sval)
-type·¿¤Î¥á¥â¥ê¤òmalloc¤·¡¤ÊÑ¿ôsval¤ËÂåÆþ¤·¤¿¸å¡¤¤½¤ì¤ò¥«¥×¥»
-¥ë²½¤·¤¿¥Ç¡¼¥¿¤òÊÖ¤¹¥Þ¥¯¥í¡¥
+This macro allocates memory using malloc(), assigns it to the variable
+sval, and returns the DATA encapsulating the pointer to memory region.
Data_Get_Struct(data, type, sval)
-data¤«¤étype·¿¤Î¥Ý¥¤¥ó¥¿¤ò¼è¤ê½Ð¤·ÊÑ¿ôsval¤ËÂåÆþ¤¹¤ë¥Þ¥¯¥í¡¥
+This macro retrieves the pointer value from DATA, and assigns it to
+the variable sval.
-** ¥¯¥é¥¹/¥â¥¸¥å¡¼¥ëÄêµÁ
+** defining class/module
- VALUE rb_define_class(char *name, VALUE super)
+ VALUE rb_define_class(const char *name, VALUE super)
-super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤ruby¥¯¥é¥¹¤òÄêµÁ¤¹¤ë¡¥
+Defines new Ruby class as subclass of super.
- VALUE rb_define_class_under(VALUE module, char *name, VALUE super)
+ VALUE rb_define_class_under(VALUE module, const char *name, VALUE super)
-super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤ruby¥¯¥é¥¹¤òÄêµÁ¤·¡¤module¤ÎÄê
-¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
+Creates new Ruby class as subclass of super, under the module's
+namespace.
- VALUE rb_define_module(char *name)
+ VALUE rb_define_module(const char *name)
-¿·¤·¤¤ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¡¥
+Defines new Ruby module.
- VALUE rb_define_module_under(VALUE module, char *name, VALUE super)
+ VALUE rb_define_module_under(VALUE module, const char *name, VALUE super)
-¿·¤·¤¤ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤·¡¤module¤ÎÄê¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
+Defines new Ruby module, under the module's namespace.
- void rb_include_module(VALUE class, VALUE module)
+ void rb_include_module(VALUE klass, VALUE module)
-¥â¥¸¥å¡¼¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë¡¥class¤¬¤¹¤Ç¤Ëmodule¤ò¥¤¥ó¥¯¥ë¡¼
-¥É¤·¤Æ¤¤¤ë»þ¤Ë¤Ï²¿¤â¤·¤Ê¤¤(¿½Å¥¤¥ó¥¯¥ë¡¼¥É¤Î¶Ø»ß)¡¥
+Includes module into class. If class already includes it, just
+ignore.
void rb_extend_object(VALUE object, VALUE module)
-¥ª¥Ö¥¸¥§¥¯¥È¤ò¥â¥¸¥å¡¼¥ë(¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥á¥½¥Ã¥É)¤Ç³ÈÄ¥¤¹¤ë¡¥
+Extend the object with module's attribute.
-** Âç°èÊÑ¿ôÄêµÁ
+** Defining Global Variables
- void rb_define_variable(char *name, VALUE *var)
+ void rb_define_variable(const char *name, VALUE *var)
-ruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ë¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô̾¤¬`$'¤Ç»Ï
-¤Þ¤é¤Ê¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤ë¡¥name¤È¤·¤Æruby¤Î¼±Ê̻ҤȤ·
-¤Æµö¤µ¤ì¤Ê¤¤Ê¸»ú(Î㤨¤Ð` ')¤ò´Þ¤à¾ì¹ç¤Ë¤Ïruby¥×¥í¥°¥é¥à¤«¤é
-¤Ï¸«¤¨¤Ê¤¯¤Ê¤ë¡¥
+Defines a global variable which is shared between C and Ruby. If name
+contains the character which is not allowed to be part of the symbol,
+it can't be seen from Ruby programs.
- void rb_define_readonly_variable(char *name, VALUE *var)
+ void rb_define_readonly_variable(const char *name, VALUE *var)
-ruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ëread only¤Î¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥read
-only¤Ç¤¢¤ë¤³¤È°Ê³°¤Ïrb_define_variable()¤ÈƱ¤¸¡¥
+Defines a read-only global variable. Works just like
+rb_define_variable(), except defined variable is read-only.
- void rb_define_virtual_variable(char *name,
- VALUE (*getter)(), VALUE (*setter)())
+ void rb_define_virtual_variable(const char *name,
+ VALUE (*getter)(), VALUE (*setter)())
+
+Defines a virtual variable, whose behavior is defined by pair of C
+functions. The getter function is called when the variable is
+referred. The setter function is called when the value is set to the
+variable. The prototype for getter/setter functions are:
+
+ VALUE getter(ID id)
+ void setter(VALUE val, ID id)
-´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ërubyÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ
-¤Ë¤Ïgetter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì¤ë¡¥
+The getter function must return the value for the access.
- void rb_define_hooked_variable(char *name, VALUE *var,
+ void rb_define_hooked_variable(const char *name, VALUE *var,
VALUE (*getter)(), VALUE (*setter)())
-´Ø¿ô¤Ë¤è¤Ã¤Æhook¤Î¤Ä¤±¤é¤ì¤¿¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô¤¬
-»²¾È¤µ¤ì¤¿»þ¤Ë¤Ïgetter¤¬¡¤´Ø¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter
-¤¬¸Æ¤Ð¤ì¤ë¡¥getter¤äsetter¤Ë0¤ò»ØÄꤷ¤¿»þ¤Ë¤Ïhook¤ò»ØÄꤷ¤Ê
-¤¤¤Î¤ÈƱ¤¸»ö¤Ë¤Ê¤ë¡¥
+Defines hooked variable. It's virtual variable with C variable. The
+getter is called as
+
+ VALUE getter(ID id, VALUE *var)
+
+returning new value. The setter is called as
+
+ void setter(VALUE val, ID id, VALUE *var)
+
+GC requires to mark the C global variables which hold Ruby values.
void rb_global_variable(VALUE *var)
-GC¤Î¤¿¤á¡¤ruby¥×¥í¥°¥é¥à¤«¤é¤Ï¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¤¤¬, ruby¥ª¥Ö¥¸¥§
-¥¯¥È¤ò´Þ¤àÂç°èÊÑ¿ô¤ò¥Þ¡¼¥¯¤¹¤ë¡¥
+Tells GC to protect these variables.
-** ¥¯¥é¥¹Äê¿ô
+** Constant Definition
- void rb_define_const(VALUE class, char *name, VALUE val)
+ void rb_define_const(VALUE klass, const char *name, VALUE val)
-¥¯¥é¥¹Äê¿ô¤òÄêµÁ¤¹¤ë¡¥
+Defines a new constant under the class/module.
- void rb_define_global_const(char *name, VALUE val)
+ void rb_define_global_const(const char *name, VALUE val)
-Âç°èÄê¿ô¤òÄêµÁ¤¹¤ë¡¥
+Defines global constant. This is just work as
rb_define_const(cKernal, name, val)
-¤ÈƱ¤¸°ÕÌ£¡¥
-
-** ¥á¥½¥Ã¥ÉÄêµÁ
+** Method Definition
- rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc)
+ rb_define_method(VALUE klass, const char *name, VALUE (*func)(), int argc)
-¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥argc¤Ïself¤ò½ü¤¯°ú¿ô¤Î¿ô¡¥argc¤¬-1¤Î»þ,
-´Ø¿ô¤Ë¤Ï°ú¿ô¤Î¿ô(self¤ò´Þ¤Þ¤Ê¤¤)¤òÂè1°ú¿ô, °ú¿ô¤ÎÇÛÎó¤òÂè2°ú
-¿ô¤È¤¹¤ë·Á¼°¤ÇÍ¿¤¨¤é¤ì¤ë(Âè3°ú¿ô¤Ïself)¡¥argc¤¬-2¤Î»þ, Âè1°ú
-¿ô¤¬self, Âè2°ú¿ô¤¬args(args¤Ï°ú¿ô¤ò´Þ¤àruby¤ÎÇÛÎó)¤È¤¤¤¦·Á
-¼°¤ÇÍ¿¤¨¤é¤ì¤ë¡¥
+Defines a method for the class. func is the function pointer. argc
+is the number of arguments. if argc is -1, the function will receive
+3 arguments argc, argv, and self. if argc is -2, the function will
+receive 2 arguments, self and args, where args is the Ruby array of
+the method arguments.
- rb_define_private_method(VALUE class, char *name, VALUE (*func)(), int argc)
+ rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(), int argc)
-private¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¡¥
+Defines a private method for the class. Arguments are same as
+rb_define_method().
- rb_define_singleton_method(VALUE class, char *name, VALUE (*func)(), int argc)
+ rb_define_singleton_method(VALUE klass, const char *name, VALUE (*func)(), int argc)
-ÆÃ°Û¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¡¥
+Defines a singleton method. Arguments are same as rb_define_method().
- rb_scan_args(int atgc, VALUE *argv, char *fmt, ...)
+ rb_scan_args(int argc, VALUE *argv, const char *fmt, ...)
-argc,argv·Á¼°¤ÇÍ¿¤¨¤é¤ì¤¿°ú¿ô¤òʬ²ò¤¹¤ë¡¥fmt¤Ïɬ¿Ü°ú¿ô¤Î¿ô,
-Éղðú¿ô¤Î¿ô, »Ä¤ê¤Î°ú¿ô¤¬¤¢¤ë¤«¤ò»ØÄꤹ¤ëʸ»úÎó¤Ç, "¿ô»ú¿ô
-»ú*"¤È¤¤¤¦·Á¼°¤Ç¤¢¤ë¡¥ 2 ÈÖÌܤοô»ú¤È"*"¤Ï¤½¤ì¤¾¤ì¾Êά²Äǽ¤Ç
-¤¢¤ë¡¥É¬¿Ü°ú¿ô¤¬°ì¤Ä¤â¤Ê¤¤¾ì¹ç¤Ï0¤ò»ØÄꤹ¤ë¡¥Âè3°ú¿ô°Ê¹ß¤ÏÊÑ
-¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç, ³ºÅö¤¹¤ëÍ×ÁǤ¬¤½¤ÎÊÑ¿ô¤Ë³ÊǼ¤µ¤ì¤ë¡¥Éղðú
-¿ô¤ËÂбþ¤¹¤ë°ú¿ô¤¬Í¿¤¨¤é¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤ÏÊÑ¿ô¤ËQnil¤¬ÂåÆþ¤µ¤ì
-¤ë¡¥
+Retrieve argument from argc, argv. The fmt is the format string for
+the arguments, such as "12" for 1 non-optional argument, 2 optional
+arguments. If `*' appears at the end of fmt, it means the rest of
+the arguments are assigned to corresponding variable, packed in
+array.
-** ruby¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·
+** Invoking Ruby method
VALUE rb_funcall(VALUE recv, ID mid, int narg, ...)
-¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¡¥Ê¸»úÎ󤫤émid¤òÆÀ¤ë¤¿¤á¤Ë¤Ïrb_intern()¤ò»È¤¦¡¥
+Invokes the method. To retrieve mid from method name, use rb_intern().
VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)
-¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¡¥°ú¿ô¤òargc,argv·Á¼°¤ÇÅϤ¹¡¥
+Invokes method, passing arguments by array of values.
- VALUE rb_eval_string(char *str)
+ VALUE rb_eval_string(const char *str)
-ʸ»úÎó¤òruby¤È¥¹¥¯¥ê¥×¥È¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¡¦¼Â¹Ô¤¹¤ë¡¥
+Compiles and executes the string as Ruby program.
- ID rb_intern(char *name)
+ ID rb_intern(const char *name)
-ʸ»úÎó¤ËÂбþ¤¹¤ëID¤òÊÖ¤¹¡¥
+Returns ID corresponding the name.
char *rb_id2name(ID id)
-ID¤ËÂбþ¤¹¤ëʸ»úÎó¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥
+Returns the name corresponding ID.
+
+ char *rb_class2name(VALUE klass)
+
+Returns the name of the class.
- char *rb_class2name(VALUE class)
+ int rb_respond_to(VALUE object, ID id)
-class¤Î̾Á°¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥class¤¬Ì¾Á°¤ò»ý¤¿¤Ê¤¤»þ¤Ë¤Ï,
-ÁÄÀè¤òÁ̤äÆÌ¾Á°¤ò»ý¤Ä¥¯¥é¥¹¤Î̾Á°¤òÊÖ¤¹¡¥
+Returns true if the object responds to the message specified by id.
-** ¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô
+** Instance Variables
- VALUE rb_iv_get(VALUE obj, char *name)
+ VALUE rb_iv_get(VALUE obj, const char *name)
-obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ÎÃͤòÆÀ¤ë¡¥`@'¤Ç»Ï¤Þ¤é¤Ê¤¤¥¤¥ó¥¹¥¿¥ó¥¹
-ÊÑ¿ô¤Ï ruby¥×¥í¥°¥é¥à¤«¤é¥¢¥¯¥»¥¹¤Ç¤­¤Ê¤¤¡Ö±£¤ì¤¿¡×¥¤¥ó¥¹¥¿
-¥ó¥¹ÊÑ¿ô¤Ë¤Ê¤ë¡¥
+Retrieve the value of the instance variable. If the name is not
+prefixed by `@', that variable shall be inaccessible from Ruby.
- VALUE rb_iv_set(VALUE obj, char *name, VALUE val)
+ VALUE rb_iv_set(VALUE obj, const char *name, VALUE val)
-obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤òval¤Ë¥»¥Ã¥È¤¹¤ë¡¥
+Sets the value of the instance variable.
-** À©¸æ¹½Â¤
+** Control Structure
VALUE rb_iterate(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)
-func2¤ò¥Ö¥í¥Ã¥¯¤È¤·¤ÆÀßÄꤷ, func1¤ò¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ö¡¥
-func1¤Ë¤Ï arg1¤¬°ú¿ô¤È¤·¤ÆÅϤµ¤ì, func2¤Ë¤ÏÂè1°ú¿ô¤Ë¥¤¥Æ¥ì¡¼
-¥¿¤«¤éÍ¿¤¨¤é¤ì¤¿ÃÍ, Âè2°ú¿ô¤Ëarg2¤¬ÅϤµ¤ì¤ë¡¥
+Calls the function func1, supplying func2 as the block. func1 will be
+called with the argument arg1. func2 receives the value from yield as
+the first argument, arg2 as the second argument.
VALUE rb_yield(VALUE val)
-val¤òÃͤȤ·¤Æ¥¤¥Æ¥ì¡¼¥¿¥Ö¥í¥Ã¥¯¤ò¸Æ¤Ó½Ð¤¹¡¥
+Evaluates the block with value val.
VALUE rb_rescue(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)
-´Ø¿ôfunc1¤òarg1¤ò°ú¿ô¤Ë¸Æ¤Ó½Ð¤¹¡¥func1¤Î¼Â¹ÔÃæ¤ËÎã³°¤¬È¯À¸¤·
-¤¿»þ¤Ë¤Ï func2¤òarg2¤ò°ú¿ô¤È¤·¤Æ¸Æ¤Ö¡¥Ìá¤êÃͤÏÎã³°¤¬È¯À¸¤·¤Ê
-¤«¤Ã¤¿»þ¤Ïfunc1¤ÎÌá¤êÃÍ, Îã³°¤¬È¯À¸¤·¤¿»þ¤Ë¤Ïfunc2¤ÎÌá¤êÃͤÇ
-¤¢¤ë¡¥
+Calls the function func1, with arg1 as the argument. If exception
+occurs during func1, it calls func2 with arg2 as the argument. The
+return value of rb_rescue() is the return value from func1 if no
+exception occurs, from func2 otherwise.
VALUE rb_ensure(VALUE (*func1)(), void *arg1, void (*func2)(), void *arg2)
-´Ø¿ôfunc1¤òarg1¤ò°ú¿ô¤È¤·¤Æ¼Â¹Ô¤·, ¼Â¹Ô½ªÎ»¸å(¤¿¤È¤¨Îã³°¤¬È¯
-À¸¤·¤Æ¤â) func2¤òarg2¤ò°ú¿ô¤È¤·¤Æ¼Â¹Ô¤¹¤ë¡¥Ìá¤êÃͤÏfunc1¤ÎÌá
-¤êÃͤǤ¢¤ë(Îã³°¤¬È¯À¸¤·¤¿»þ¤ÏÌá¤é¤Ê¤¤)¡¥
+Calls the function func1 with arg1 as the argument, then calls func2
+with arg2, whenever execution terminated. The return value from
+rb_ensure() is that of func1.
+
+** Exceptions and Errors
+
+ void rb_warn(const char *fmt, ...)
+
+Prints warning message according to the printf-like format.
-** Îã³°¡¦¥¨¥é¡¼
+ void rb_warning(const char *fmt, ...)
- void Warning(char *fmt, ...)
+Prints warning message according to the printf-like format, if
+$VERBOSE is true.
-verbose»þ¤Ëɸ½à¥¨¥é¡¼½ÐÎϤ˷ٹð¾ðÊó¤òɽ¼¨¤¹¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
+ void rb_raise(VALUE exception, const char *fmt, ...)
- void Fail(char *fmt, ...)
+Raises an exception of class exception. The fmt is the format string
+just like printf().
-Îã³°¤òȯÀ¸¤µ¤»¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
+ void rb_fatal(const char *fmt, ...)
- void Fatal(char *fmt, ...)
+Raises fatal error, terminates the interpreter. No exception handling
+will be done for fatal error, but ensure blocks will be executed.
-Ã×̿ŪÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥Ä̾ï¤ÎÎã³°½èÍý¤Ï¹Ô¤Ê¤ï¤ì¤º, ¥¤¥ó¥¿¡¼
-¥×¥ê¥¿¤¬½ªÎ»¤¹¤ë(¤¿¤À¤·ensure¤Ç»ØÄꤵ¤ì¤¿¥³¡¼¥É¤Ï½ªÎ»Á°¤Ë¼Â
-¹Ô¤µ¤ì¤ë)¡¥
+ void rb_bug(const char *fmt, ...)
- void Bug(char *fmt, ...)
+Terminates the interpreter immediately. This function should be
+called under the situation caused by the bug in the interpreter. No
+exception handling nor ensure execution will be done.
-¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ê¤É¥×¥í¥°¥é¥à¤Î¥Ð¥°¤Ç¤·¤«È¯À¸¤¹¤ë¤Ï¤º¤Î¤Ê¤¤¾õ
-¶·¤Î»þ¸Æ¤Ö¡¥¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ï¥³¥¢¥À¥ó¥×¤·Ä¾¤Á¤Ë½ªÎ»¤¹¤ë¡¥Îã³°
-½èÍý¤Ï°ìÀڹԤʤï¤ì¤Ê¤¤¡¥
+** Initialize and Starts the Interpreter
-** ruby¤Î½é´ü²½¡¦¼Â¹Ô
+The embedding API are below (not needed for extension libraries):
-ruby¤ò¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤ËËä¤á¹þ¤à¾ì¹ç¤Ë¤Ï°Ê²¼¤Î¥¤¥ó¥¿¥Õ¥§¡¼¥¹
-¤ò»È¤¦¡¥Ä̾ï¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë¤ÏɬÍפʤ¤¡¥
+ void ruby_init()
- void ruby_init(int argc, char **argv, char **envp)
+Initializes the interpreter.
-ruby¥¤¥ó¥¿¥×¥ê¥¿¤Î½é´ü²½¤ò¹Ô¤Ê¤¦¡¥
+ void ruby_options(int argc, char **argv)
+
+Process command line arguments for the interpreter.
void ruby_run()
-ruby¥¤¥ó¥¿¥×¥ê¥¿¤ò¼Â¹Ô¤¹¤ë¡¥
+Starts execution of the interpreter.
void ruby_script(char *name)
-ruby¤Î¥¹¥¯¥ê¥×¥È̾($0)¤òÀßÄꤹ¤ë¡¥
+Specifies the name of the script ($0).
-Appendix B. extconf.rb¤Ç»È¤¨¤ë´Ø¿ô¤¿¤Á
+Appendix B. Functions Available in extconf.rb
-extconf.rb¤ÎÃæ¤Ç¤ÏÍøÍѲÄǽ¤Ê¥³¥ó¥Ñ¥¤¥ë¾ò·ï¥Á¥§¥Ã¥¯¤Î´Ø¿ô¤Ï°Ê
-²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥
+These functions are available in extconf.rb:
have_library(lib, func)
-´Ø¿ôfunc¤òÄêµÁ¤·¤Æ¤¤¤ë¥é¥¤¥Ö¥é¥êlib¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥é
-¥¤¥Ö¥é¥ê¤¬Â¸ºß¤¹¤ë»þ¡¤TRUE¤òÊÖ¤¹¡¥
+Checks whether library which contains specified function exists.
+Returns true if the library exists.
+
+ find_library(lib, func, path...)
- have_func(func)
+Checks whether library which contains specified function exists in
+path. Returns true if the library exists.
-´Ø¿ôfunc¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥func¤¬É¸½à¤Ç¤Ï¥ê¥ó¥¯¤µ¤ì¤Ê¤¤¥é
-¥¤¥Ö¥é¥êÆâ¤Î¤â¤Î¤Ç¤¢¤ë»þ¤Ë¤ÏÀè¤Ëhave_library¤Ç¤½¤Î¥é¥¤¥Ö¥é¥ê
-¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤ª¤¯»ö¡¥´Ø¿ô¤¬Â¸ºß¤¹¤ë»þTRUE¤òÊÖ¤¹¡¥
+ have_func(func, header)
+
+Checks whether func exists with header. Returns true if the function
+exists. To check functions in the additional library, you need to
+check that library first using have_library().
have_header(header)
-¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ë
-»þTRUE¤òÊÖ¤¹¡¥
+Checks whether header exists. Returns true if the header file exists.
create_makefile(target)
-³ÈÄ¥¥â¥¸¥å¡¼¥ëÍѤÎMakefile¤òÀ¸À®¤¹¤ë¡¥¤³¤Î´Ø¿ô¤ò¸Æ¤Ð¤Ê¤±¤ì¤Ð
-¤½¤Î¥â¥¸¥å¡¼¥ë¤Ï¥³¥ó¥Ñ¥¤¥ë¤µ¤ì¤Ê¤¤¡¥target¤Ï¥â¥¸¥å¡¼¥ë̾¤òɽ
-¤¹¡¥
+Generates the Makefile for the extension library. If you don't invoke
+this method, the compilation will not be done.
+
+ with_config(withval[, default=nil])
+
+Parses the command line options and returns the value specified by
+--with-<withval>.
+
+ dir_config(target[, default_dir])
+ dir_config(target[, default_include, default_lib])
+
+Parses the command line options and adds the directories specified by
+--with-<target>-dir, --with-<target>-include, and/or --with-<target>-lib
+to $CFLAGS and/or $LDFLAGS. --with-<target>-dir=/path is equivalent to
+--with-<target>-include=/path/include --with-<target>-lib=/path/lib.
+Returns an array of the added directories ([include_dir, lib_dir]).
/*
* Local variables:
- * fill-column: 60
+ * fill-column: 70
* end:
*/
diff --git a/README.EXT.jp b/README.EXT.jp
index 197efa32df..07a9e8b39d 100644
--- a/README.EXT.jp
+++ b/README.EXT.jp
@@ -1,18 +1,18 @@
.\" README.EXT - -*- Text -*- created at: Mon Aug 7 16:45:54 JST 1995
-ruby¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Îºî¤êÊý¤òÀâÌÀ¤·¤Þ¤¹¡¥
+Ruby¤Î³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Îºî¤êÊý¤òÀâÌÀ¤·¤Þ¤¹¡¥
1¡¥´ðÁÃÃμ±
C¤ÎÊÑ¿ô¤Ë¤Ï·¿¤¬¤¢¤ê¡¤¥Ç¡¼¥¿¤Ë¤Ï·¿¤¬¤¢¤ê¤Þ¤»¤ó¡¥¤Ç¤¹¤«¤é¡¤¤¿
¤È¤¨¤Ð¥Ý¥¤¥ó¥¿¤òint¤ÎÊÑ¿ô¤ËÂåÆþ¤¹¤ë¤È¡¤¤½¤ÎÃͤÏÀ°¿ô¤È¤·¤Æ¼è
-¤ê°·¤ï¤ì¤Þ¤¹¡¥µÕ¤Ëruby¤ÎÊÑ¿ô¤Ë¤Ï·¿¤¬¤Ê¤¯¡¤¥Ç¡¼¥¿¤Ë·¿¤¬¤¢¤ê¤Þ
-¤¹¡¥¤³¤Î°ã¤¤¤Î¤¿¤á¡¤C¤Èruby¤ÏÁê¸ß¤ËÊÑ´¹¤·¤Ê¤±¤ì¤Ð¡¤¤ª¸ß¤¤¤Î
+¤ê°·¤ï¤ì¤Þ¤¹¡¥µÕ¤ËRuby¤ÎÊÑ¿ô¤Ë¤Ï·¿¤¬¤Ê¤¯¡¤¥Ç¡¼¥¿¤Ë·¿¤¬¤¢¤ê¤Þ
+¤¹¡¥¤³¤Î°ã¤¤¤Î¤¿¤á¡¤C¤ÈRuby¤ÏÁê¸ß¤ËÊÑ´¹¤·¤Ê¤±¤ì¤Ð¡¤¤ª¸ß¤¤¤Î
¥Ç¡¼¥¿¤ò¥¢¥¯¥»¥¹¤Ç¤­¤Þ¤»¤ó¡¥
-ruby¤Î¥Ç¡¼¥¿¤ÏVALUE¤È¤¤¤¦C¤Î·¿¤Çɽ¸½¤µ¤ì¤Þ¤¹¡¥VALUE·¿¤Î¥Ç¡¼
+Ruby¤Î¥Ç¡¼¥¿¤ÏVALUE¤È¤¤¤¦C¤Î·¿¤Çɽ¸½¤µ¤ì¤Þ¤¹¡¥VALUE·¿¤Î¥Ç¡¼
¥¿¤Ï¤½¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤ò¼«Ê¬¤ÇÃΤäƤ¤¤Þ¤¹¡¥¤³¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤È
-¤¤¤¦¤Î¤Ï¥Ç¡¼¥¿(¥ª¥Ö¥¸¥§¥¯¥È)¤Î¼ÂºÝ¤Î¹½Â¤¤ò°ÕÌ£¤·¤Æ¤¤¤Æ¡¤ruby
+¤¤¤¦¤Î¤Ï¥Ç¡¼¥¿(¥ª¥Ö¥¸¥§¥¯¥È)¤Î¼ÂºÝ¤Î¹½Â¤¤ò°ÕÌ£¤·¤Æ¤¤¤Æ¡¤Ruby
¤Î¥¯¥é¥¹¤È¤Ï¤Þ¤¿°ã¤Ã¤¿¤â¤Î¤Ç¤¹¡¥
VALUE¤«¤éC¤Ë¤È¤Ã¤Æ°ÕÌ£¤Î¤¢¤ë¥Ç¡¼¥¿¤ò¼è¤ê½Ð¤¹¤¿¤á¤Ë¤Ï
@@ -25,7 +25,7 @@ VALUE¤«¤éC¤Ë¤È¤Ã¤Æ°ÕÌ£¤Î¤¢¤ë¥Ç¡¼¥¿¤ò¼è¤ê½Ð¤¹¤¿¤á¤Ë¤Ï
1.1 ¥Ç¡¼¥¿¥¿¥¤¥×
-ruby¤Ë¤Ï¥æ¡¼¥¶¤¬»È¤¦²ÄǽÀ­¤Î¤¢¤ë°Ê²¼¤Î¥¿¥¤¥×¤¬¤¢¤ê¤Þ¤¹¡¥
+Ruby¤Ë¤Ï¥æ¡¼¥¶¤¬»È¤¦²ÄǽÀ­¤Î¤¢¤ë°Ê²¼¤Î¥¿¥¤¥×¤¬¤¢¤ê¤Þ¤¹¡¥
T_NIL nil
T_OBJECT Ä̾ï¤Î¥ª¥Ö¥¸¥§¥¯¥È
@@ -37,17 +37,19 @@ ruby¤Ë¤Ï¥æ¡¼¥¶¤¬»È¤¦²ÄǽÀ­¤Î¤¢¤ë°Ê²¼¤Î¥¿¥¤¥×¤¬¤¢¤ê¤Þ¤¹¡¥
T_ARRAY ÇÛÎó
T_FIXNUM Fixnum(31bitĹÀ°¿ô)
T_HASH Ï¢ÁÛÇÛÎó
- T_STRUCT (ruby¤Î)¹½Â¤ÂÎ
+ T_STRUCT (Ruby¤Î)¹½Â¤ÂÎ
T_BIGNUM ¿ÇÜĹÀ°¿ô
T_FILE Æþ½ÐÎÏ
T_TRUE ¿¿
T_FALSE µ¶
T_DATA ¥Ç¡¼¥¿
+ T_SYMBOL ¥·¥ó¥Ü¥ë
¤½¤Î¾¤ËÆâÉô¤ÇÍøÍѤµ¤ì¤Æ¤¤¤ë°Ê²¼¤Î¥¿¥¤¥×¤¬¤¢¤ê¤Þ¤¹¡¥
T_ICLASS
T_MATCH
+ T_UNDEF
T_VARMAP
T_SCOPE
T_NODE
@@ -73,7 +75,7 @@ ruby.h¤Ç¤ÏTYPE()¤È¤¤¤¦¥Þ¥¯¥í¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Æ¡¤VALUE¤Î¥Ç¡¼¥¿
break;
default:
/* Îã³°¤òȯÀ¸¤µ¤»¤ë */
- TypeError("not valid value");
+ rb_raise(rb_eTypeError, "not valid value");
break;
}
@@ -99,7 +101,7 @@ FIXNUM¤ÈNIL¤Ë´Ø¤·¤Æ¤Ï¤è¤ê¹â®¤ÊȽÊÌ¥Þ¥¯¥í¤¬ÍѰդµ¤ì¤Æ¤¤¤Þ¤¹¡¥
¥Ç¡¼¥¿¥¿¥¤¥×¤¬T_FIXNUM¤Î»þ¡¤¤³¤ì¤Ï31bit¤Î¥µ¥¤¥º¤ò»ý¤ÄÀ°¿ô¤Ç
¤¹¡¥FIXNUM¤òC¤ÎÀ°¿ô¤ËÊÑ´¹¤¹¤ë¤¿¤á¤Ë¤Ï¥Þ¥¯¥í¡ÖFIX2INT()¡×¤ò»È
-¤¤¤Þ¤¹¡¥¤½¤ì¤«¤é¡¤FIXNUM¤Ë¸Â¤é¤ºruby¤Î¥Ç¡¼¥¿¤òÀ°¿ô¤ËÊÑ´¹¤¹¤ë
+¤¤¤Þ¤¹¡¥¤½¤ì¤«¤é¡¤FIXNUM¤Ë¸Â¤é¤ºRuby¤Î¥Ç¡¼¥¿¤òÀ°¿ô¤ËÊÑ´¹¤¹¤ë
¡ÖNUM2INT()¡×¤È¤¤¤¦¥Þ¥¯¥í¤¬¤¢¤ê¤Þ¤¹¡¥¤³¤Î¥Þ¥¯¥í¤Ï¥Ç¡¼¥¿¥¿¥¤
¥×¤Î¥Á¥§¥Ã¥¯Ìµ¤·¤Ç»È¤¨¤Þ¤¹(À°¿ô¤ËÊÑ´¹¤Ç¤­¤Ê¤¤¾ì¹ç¤Ë¤ÏÎã³°¤¬
ȯÀ¸¤¹¤ë)¡¥
@@ -120,10 +122,10 @@ ruby.h¤Ç¤Ï¹½Â¤ÂΤإ­¥ã¥¹¥È¤¹¤ë¥Þ¥¯¥í¤â¡ÖRXXXXX()¡×(Á´ÉôÂçʸ
Î㤨¤Ð¡¤Ê¸»úÎóstr¤ÎŤµ¤òÆÀ¤ë¤¿¤á¤Ë¤Ï¡ÖRSTRING(str)->len¡×¤È
¤·¡¤Ê¸»úÎóstr¤òchar*¤È¤·¤ÆÆÀ¤ë¤¿¤á¤Ë¤Ï¡ÖRSTRING(str)->ptr¡×
-¤È¤·¤Þ¤¹¡¥ÇÛÎó¤Î¾ì¹ç¤Ë¤Ï¡¤¤½¤ì¤¾¤ì¡ÖRARRAT(str)->len¡×¡¤
-¡ÖRARRAT(str)->ptr¡×¤È¤Ê¤ê¤Þ¤¹¡¥
+¤È¤·¤Þ¤¹¡¥ÇÛÎó¤Î¾ì¹ç¤Ë¤Ï¡¤¤½¤ì¤¾¤ì¡ÖRARRAY(ary)->len¡×¡¤
+¡ÖRARRAY(ary)->ptr¡×¤È¤Ê¤ê¤Þ¤¹¡¥
-ruby¤Î¹½Â¤ÂΤòľÀÜ¥¢¥¯¥»¥¹¤¹¤ë»þ¤Ëµ¤¤ò¤Ä¤±¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤³
+Ruby¤Î¹½Â¤ÂΤòľÀÜ¥¢¥¯¥»¥¹¤¹¤ë»þ¤Ëµ¤¤ò¤Ä¤±¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤³
¤È¤Ï¡¤ÇÛÎó¤äʸ»úÎó¤Î¹½Â¤ÂΤÎÃæ¿È¤Ï»²¾È¤¹¤ë¤À¤±¤Ç¡¤Ä¾ÀÜÊѹ¹¤·
¤Ê¤¤¤³¤È¤Ç¤¹¡¥Ä¾ÀÜÊѹ¹¤·¤¿¾ì¹ç¡¤¥ª¥Ö¥¸¥§¥¯¥È¤ÎÆâÍÆ¤ÎÀ°¹çÀ­¤¬
¤È¤ì¤Ê¤¯¤Ê¤Ã¤Æ¡¤»×¤ï¤Ì¥Ð¥°¤Î¸¶°ø¤Ë¤Ê¤ê¤Þ¤¹¡¥
@@ -134,7 +136,7 @@ VALUE¤Î¼ÂºÝ¤Î¹½Â¤¤Ï
* FIXNUM¤Î¾ì¹ç
- 1bit±¦¥·¥Õ¥È¤·¤Æ¡¤LSB¤òΩ¤Æ¤ë¡¥
+ 1bitº¸¥·¥Õ¥È¤·¤Æ¡¤LSB¤òΩ¤Æ¤ë¡¥
* ¤½¤Î¾¤Î¥Ý¥¤¥ó¥¿¤Î¾ì¹ç
@@ -144,10 +146,10 @@ VALUE¤Î¼ÂºÝ¤Î¹½Â¤¤Ï
¤¦¤«¤ï¤«¤ë¤ï¤±¤Ç¤¹(¥Ý¥¤¥ó¥¿¤ÎLSB¤¬Î©¤Ã¤Æ¤¤¤Ê¤¤¤³¤È¤ò²¾Äꤷ¤Æ
¤¤¤ë)¡¥
-¤Ç¤¹¤«¤é¡¤FIXNUM°Ê³°¤Îruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Î¹½Â¤ÂΤÏñ¤ËVALUE
+¤Ç¤¹¤«¤é¡¤FIXNUM°Ê³°¤ÎRuby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Î¹½Â¤ÂΤÏñ¤ËVALUE
¤Ë¥­¥ã¥¹¥È¤¹¤ë¤À¤±¤ÇVALUE¤ËÊÑ´¹½ÐÍè¤Þ¤¹¡¥¤¿¤À¤·¡¤Ç¤°Õ¤Î¹½Â¤
ÂΤ¬VALUE¤Ë¥­¥ã¥¹¥È½ÐÍè¤ë¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡¥¥­¥ã¥¹¥È¤¹¤ë¤Î
-¤Ïruby¤ÎÃΤäƤ¤¤ë¹½Â¤ÂÎ(ruby.h¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ëstruct RXxxx
+¤ÏRuby¤ÎÃΤäƤ¤¤ë¹½Â¤ÂÎ(ruby.h¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ëstruct RXxxx
¤Î¤â¤Î)¤À¤±¤Ç¤¹¡¥
FIXNUM¤Ë´Ø¤·¤Æ¤ÏÊÑ´¹¥Þ¥¯¥í¤ò·Ðͳ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥C¤ÎÀ°¿ô
@@ -160,69 +162,78 @@ FIXNUM¤Ë´Ø¤·¤Æ¤ÏÊÑ´¹¥Þ¥¯¥í¤ò·Ðͳ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥C¤ÎÀ°¿ô
INT2NUM()¤ÏÀ°¿ô¤¬FIXNUM¤ÎÈϰϤ˼ý¤Þ¤é¤Ê¤¤¾ì¹ç¡¤Bignum¤ËÊÑ´¹
¤·¤Æ¤¯¤ì¤Þ¤¹(¤¬¡¤¾¯¤·ÃÙ¤¤)¡¥
-1.5 ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë
+1.5 Ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë
-ÀèÄø¤â½Ò¤Ù¤¿Ä̤ꡤruby¤Î¹½Â¤ÂΤò¥¢¥¯¥»¥¹¤¹¤ë»þ¤ËÆâÍÆ¤Î¹¹¿·¤ò
-¹Ô¤¦¤³¤È¤Ï´«¤á¤é¤ì¤Þ¤»¤ó¡¥¤Ç¡¤ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë»þ¤Ë¤Ï
-ruby¤¬ÍѰդ·¤Æ¤¤¤ë´Ø¿ô¤òÍѤ¤¤Æ¤¯¤À¤µ¤¤¡¥
+ÀèÄø¤â½Ò¤Ù¤¿Ä̤ꡤRuby¤Î¹½Â¤ÂΤò¥¢¥¯¥»¥¹¤¹¤ë»þ¤ËÆâÍÆ¤Î¹¹¿·¤ò
+¹Ô¤¦¤³¤È¤Ï´«¤á¤é¤ì¤Þ¤»¤ó¡¥¤Ç¡¤Ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë»þ¤Ë¤Ï
+Ruby¤¬ÍѰդ·¤Æ¤¤¤ë´Ø¿ô¤òÍѤ¤¤Æ¤¯¤À¤µ¤¤¡¥
¤³¤³¤Ç¤Ï¤â¤Ã¤È¤â»È¤ï¤ì¤ë¤Ç¤¢¤í¤¦Ê¸»úÎó¤ÈÇÛÎó¤ÎÀ¸À®/Áàºî¤ò¹Ô
¤¤´Ø¿ô¤ò¤¢¤²¤Þ¤¹(Á´Éô¤Ç¤Ï¤Ê¤¤¤Ç¤¹)¡¥
ʸ»úÎó¤ËÂФ¹¤ë´Ø¿ô
- str_new(char *ptr, int len)
+ rb_str_new(const char *ptr, long len)
- ¿·¤·¤¤ruby¤Îʸ»úÎó¤òÀ¸À®¤¹¤ë¡¥
+ ¿·¤·¤¤Ruby¤Îʸ»úÎó¤òÀ¸À®¤¹¤ë¡¥
- str_new2(char *ptr)
+ rb_str_new2(const char *ptr)
- C¤Îʸ»úÎ󤫤éruby¤Îʸ»úÎó¤òÀ¸À®¤¹¤ë¡¥¤³¤Î´Ø¿ô¤Îµ¡Ç½¤Ï
- str_new(ptr, strlen(ptr))¤ÈƱÅù¤Ç¤¢¤ë¡¥
+ C¤Îʸ»úÎ󤫤éRuby¤Îʸ»úÎó¤òÀ¸À®¤¹¤ë¡¥¤³¤Î´Ø¿ô¤Îµ¡Ç½¤Ï
+ rb_str_new(ptr, strlen(ptr))¤ÈƱÅù¤Ç¤¢¤ë¡¥
- str_cat(VALUE str, char *ptr, int len)
+ rb_tainted_str_new(const char *ptr, long len)
- ruby¤Îʸ»úÎóstr¤Ëlen¥Ð¥¤¥È¤Îʸ»úÎóptr¤òÄɲ乤롥
+ ±øÀ÷¥Þ¡¼¥¯¤¬Éղ䵤줿¿·¤·¤¤Ruby¤Îʸ»úÎó¤òÀ¸À®¤¹¤ë¡¥³°Éô
+ ¤«¤é¤Î¥Ç¡¼¥¿¤Ë´ð¤Å¤¯Ê¸»úÎó¤Ë¤Ï±øÀ÷¥Þ¡¼¥¯¤¬Éղ䵤ì¤ë¤Ù¤­
+ ¤Ç¤¢¤ë¡¥
+
+ rb_tainted_str_new2(const char *ptr)
+
+ C¤Îʸ»úÎ󤫤鱸À÷¥Þ¡¼¥¯¤¬Éղ䵤줿Ruby¤Îʸ»úÎó¤òÀ¸À®¤¹¤ë¡¥
+
+ rb_str_cat(VALUE str, const char *ptr, long len)
+
+ Ruby¤Îʸ»úÎóstr¤Ëlen¥Ð¥¤¥È¤Îʸ»úÎóptr¤òÄɲ乤롥
ÇÛÎó¤ËÂФ¹¤ë´Ø¿ô
- ary_new()
+ rb_ary_new()
Í×ÁǤ¬0¤ÎÇÛÎó¤òÀ¸À®¤¹¤ë¡¥
- ary_new2(int len)
+ rb_ary_new2(long len)
Í×ÁǤ¬0¤ÎÇÛÎó¤òÀ¸À®¤¹¤ë¡¥lenÍ×ÁÇʬ¤ÎÎΰè¤ò¤¢¤é¤«¤¸¤á³ä¤ê
Åö¤Æ¤Æ¤ª¤¯¡¥
- ary_new3(int n, ...)
+ rb_ary_new3(long n, ...)
°ú¿ô¤Ç»ØÄꤷ¤¿nÍ×ÁǤò´Þ¤àÇÛÎó¤òÀ¸À®¤¹¤ë¡¥
- ary_new4(int n, VALUE *elts)
+ rb_ary_new4(long n, VALUE *elts)
ÇÛÎó¤ÇÍ¿¤¨¤¿nÍ×ÁǤÎÇÛÎó¤òÀ¸À®¤¹¤ë¡¥
- ary_push(VALUE ary)
- ary_pop(VALUE ary, VALUE val)
- ary_shift(VALUE ary)
- ary_unshift(VALUE ary, VALUE val)
- ary_entry(VALUE ary, int idx)
+ rb_ary_push(VALUE ary, VALUE val)
+ rb_ary_pop(VALUE ary)
+ rb_ary_shift(VALUE ary)
+ rb_ary_unshift(VALUE ary, VALUE val)
Array¤ÎƱ̾¤Î¥á¥½¥Ã¥É¤ÈƱ¤¸Æ¯¤­¤ò¤¹¤ë´Ø¿ô¡¥Âè1°ú¿ô¤Ïɬ¤º
ÇÛÎó¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡¥
-2¡¥ruby¤Îµ¡Ç½¤ò»È¤¦
+2¡¥Ruby¤Îµ¡Ç½¤ò»È¤¦
-¸¶ÍýŪ¤Ëruby¤Ç½ñ¤±¤ë¤³¤È¤ÏC¤Ç¤â½ñ¤±¤Þ¤¹¡¥ruby¤½¤Î¤â¤Î¤¬C¤Çµ­
+¸¶ÍýŪ¤ËRuby¤Ç½ñ¤±¤ë¤³¤È¤ÏC¤Ç¤â½ñ¤±¤Þ¤¹¡¥Ruby¤½¤Î¤â¤Î¤¬C¤Çµ­
½Ò¤µ¤ì¤Æ¤¤¤ë¤ó¤Ç¤¹¤«¤é¡¤ÅöÁ³¤È¤¤¤¨¤ÐÅöÁ³¤Ê¤ó¤Ç¤¹¤±¤É¡¥¤³¤³¤Ç
-¤Ïruby¤Î³ÈÄ¥¤Ë»È¤¦¤³¤È¤¬Â¿¤¤¤À¤í¤¦¤Èͽ¬¤µ¤ì¤ëµ¡Ç½¤òÃæ¿´¤Ë¾Ò
+¤ÏRuby¤Î³ÈÄ¥¤Ë»È¤¦¤³¤È¤¬Â¿¤¤¤À¤í¤¦¤Èͽ¬¤µ¤ì¤ëµ¡Ç½¤òÃæ¿´¤Ë¾Ò
²ð¤·¤Þ¤¹¡¥
-2.1 ruby¤Ëµ¡Ç½¤òÄɲ乤ë
+2.1 Ruby¤Ëµ¡Ç½¤òÄɲ乤ë
-ruby¤ÇÄ󶡤µ¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤¨¤Ðruby¥¤¥ó¥¿¥×¥ê¥¿¤Ë¿·¤·¤¤µ¡Ç½
-¤òÄɲ乤뤳¤È¤¬¤Ç¤­¤Þ¤¹¡¥ruby¤Ç¤Ï°Ê²¼¤Îµ¡Ç½¤òÄɲä¹¤ë´Ø¿ô¤¬
+Ruby¤ÇÄ󶡤µ¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤¨¤ÐRuby¥¤¥ó¥¿¥×¥ê¥¿¤Ë¿·¤·¤¤µ¡Ç½
+¤òÄɲ乤뤳¤È¤¬¤Ç¤­¤Þ¤¹¡¥Ruby¤Ç¤Ï°Ê²¼¤Îµ¡Ç½¤òÄɲä¹¤ë´Ø¿ô¤¬
Ä󶡤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
* ¥¯¥é¥¹¡¤¥â¥¸¥å¡¼¥ë
@@ -235,8 +246,8 @@ ruby¤ÇÄ󶡤µ¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤¨¤Ðruby¥¤¥ó¥¿¥×¥ê¥¿¤Ë¿·¤·¤¤µ¡Ç½
¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¤¿¤á¤Ë¤Ï¡¤°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
- VALUE rb_define_class(char *name, VALUE super)
- VALUE rb_define_module(char *name)
+ VALUE rb_define_class(const char *name, VALUE super)
+ VALUE rb_define_module(const char *name)
¤³¤ì¤é¤Î´Ø¿ô¤Ï¿·¤·¤¯ÄêµÁ¤µ¤ì¤¿¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤òÊÖ¤·¤Þ¤¹¡¥
¥á¥½¥Ã¥É¤äÄê¿ô¤ÎÄêµÁ¤Ë¤³¤ì¤é¤ÎÃͤ¬É¬ÍפʤΤǡ¤¤Û¤È¤ó¤É¤Î¾ì¹ç
@@ -245,40 +256,40 @@ ruby¤ÇÄ󶡤µ¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤¨¤Ðruby¥¤¥ó¥¿¥×¥ê¥¿¤Ë¿·¤·¤¤µ¡Ç½
¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤ò¾¤Î¥¯¥é¥¹¤ÎÆâÉô¤Ë¥Í¥¹¥È¤·¤ÆÄêµÁ¤¹¤ë»þ¤Ë
¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
- VALUE rb_define_class(VALUE outer, char *name, VALUE super)
- VALUE rb_define_module(VALUE outer, char *name)
+ VALUE rb_define_class_under(VALUE outer, const char *name, VALUE super)
+ VALUE rb_define_module_under(VALUE outer, const char *name)
2.1.2 ¥á¥½¥Ã¥É/ÆÃ°Û¥á¥½¥Ã¥ÉÄêµÁ
¥á¥½¥Ã¥É¤äÆÃ°Û¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
- void rb_define_method(VALUE class, char *name,
+ void rb_define_method(VALUE klass, const char *name,
VALUE (*func)(), int argc)
- void rb_define_singleton_method(VALUE object, char *name,
+ void rb_define_singleton_method(VALUE object, const char *name,
VALUE (*func)(), int argc)
ǰ¤Î¤¿¤áÀâÌÀ¤¹¤ë¤È¡ÖÆÃ°Û¥á¥½¥Ã¥É¡×¤È¤Ï¡¤¤½¤ÎÆÃÄê¤Î¥ª¥Ö¥¸¥§¥¯
-¥È¤ËÂФ·¤Æ¤À¤±Í­¸ú¤Ê¥á¥½¥Ã¥É¤Ç¤¹¡¥ruby¤Ç¤Ï¤è¤¯Smalltalk¤Ë¤ª
+¥È¤ËÂФ·¤Æ¤À¤±Í­¸ú¤Ê¥á¥½¥Ã¥É¤Ç¤¹¡¥Ruby¤Ç¤Ï¤è¤¯Smalltalk¤Ë¤ª
¤±¤ë¥¯¥é¥¹¥á¥½¥Ã¥É¤È¤·¤Æ¡¤¥¯¥é¥¹¤ËÂФ¹¤ëÆÃ°Û¥á¥½¥Ã¥É¤¬»È¤ï¤ì
¤Þ¤¹¡¥
¤³¤ì¤é¤Î´Ø¿ô¤Î argc¤È¤¤¤¦°ú¿ô¤ÏC¤Î´Ø¿ô¤ØÅϤµ¤ì¤ë°ú¿ô¤Î¿ô(¤È
-·Á¼°)¤ò·è¤á¤Þ¤¹¡¥argc¤¬Àµ¤Î»þ¤Ï´Ø¿ô¤Ë°ú¤­ÅϤ¹°ú¿ô¤Î¿ô¤ò°ÕÌ£
-¤·¤Þ¤¹¡¥16¸Ä°Ê¾å¤Î°ú¿ô¤Ï»È¤¨¤Þ¤»¤ó(¤¬¡¤Íפê¤Þ¤»¤ó¤è¤Í¡¤¤½¤ó
-¤Ê¤Ë)¡¥¼ÂºÝ¤Î´Ø¿ô¤Ë¤ÏÀèÆ¬¤Î°ú¿ô¤È¤·¤Æself¤¬Í¿¤¨¤é¤ì¤Þ¤¹¤Î¤Ç¡¤
-»ØÄꤷ¤¿¿ô¤è¤ê1¿¤¤°ú¿ô¤ò»ý¤Ä¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
+·Á¼°)¤ò·è¤á¤Þ¤¹¡¥argc¤¬0°Ê¾å¤Î»þ¤Ï´Ø¿ô¤Ë°ú¤­ÅϤ¹°ú¿ô¤Î¿ô¤ò°Õ
+Ì£¤·¤Þ¤¹¡¥16¸Ä°Ê¾å¤Î°ú¿ô¤Ï»È¤¨¤Þ¤»¤ó(¤¬¡¤Íפê¤Þ¤»¤ó¤è¤Í¡¤¤½
+¤ó¤Ê¤Ë)¡¥¼ÂºÝ¤Î´Ø¿ô¤Ë¤ÏÀèÆ¬¤Î°ú¿ô¤È¤·¤Æself¤¬Í¿¤¨¤é¤ì¤Þ¤¹¤Î
+¤Ç¡¤»ØÄꤷ¤¿¿ô¤è¤ê1¿¤¤°ú¿ô¤ò»ý¤Ä¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
argc¤¬Éé¤Î»þ¤Ï°ú¿ô¤Î¿ô¤Ç¤Ï¤Ê¤¯¡¤·Á¼°¤ò»ØÄꤷ¤¿¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
argc¤¬-1¤Î»þ¤Ï°ú¿ô¤òÇÛÎó¤ËÆþ¤ì¤ÆÅϤµ¤ì¤Þ¤¹¡¥argc¤¬-2¤Î»þ¤Ï°ú
-¿ô¤Ïruby¤ÎÇÛÎó¤È¤·¤ÆÅϤµ¤ì¤Þ¤¹¡¥
+¿ô¤ÏRuby¤ÎÇÛÎó¤È¤·¤ÆÅϤµ¤ì¤Þ¤¹¡¥
¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ï¤â¤¦Æó¤Ä¤¢¤ê¤Þ¤¹¡¥¤Ò¤È¤Ä¤Ïprivate¥á
¥½¥Ã¥É¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ç¡¤°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¤Ç¤¹¡¥
- void rb_define_private_method(VALUE class, char *name,
- VALUE (*func)(), int argc)
+ void rb_define_private_method(VALUE klass, const char *name,
+ VALUE (*func)(), int argc)
private¥á¥½¥Ã¥É¤È¤Ï´Ø¿ô·Á¼°¤Ç¤·¤«¸Æ¤Ó½Ð¤¹¤³¤È¤Î½ÐÍè¤Ê¤¤¥á¥½¥Ã
¥É¤Ç¤¹¡¥
@@ -298,70 +309,73 @@ private¥á¥½¥Ã¥É¤È¤Ï´Ø¿ô·Á¼°¤Ç¤·¤«¸Æ¤Ó½Ð¤¹¤³¤È¤Î½ÐÍè¤Ê¤¤¥á¥½¥Ã
¤È¤¤¤¦·Á¼°¤Ç¤â»È¤¨¤Þ¤¹¡¥¥â¥¸¥å¡¼¥ë´Ø¿ô¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ï°Ê²¼¤Î
Ä̤ê¤Ç¤¹¡¥
- void rb_define_module_function(VALUE module, char *name,
+ void rb_define_module_function(VALUE module, const char *name,
VALUE (*func)(), int argc)
´Ø¿ôŪ¥á¥½¥Ã¥É(Kernel¥â¥¸¥å¡¼¥ë¤Îprivate method)¤òÄêµÁ¤¹¤ë¤¿
¤á¤Î´Ø¿ô¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¹¡¥
- void rb_define_global_function(char *name, VALUE (*func)(), int argc)
+ void rb_define_global_function(const char *name, VALUE (*func)(), int argc)
+
+
+¥á¥½¥Ã¥É¤ÎÊÌ̾¤òÄêµÁ¤¹¤ë¤¿¤á¤Î´Ø¿ô¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¹¡£
+ void rb_define_alias(VALUE module, const char* new, const char* old);
2.1.3 Äê¿ôÄêµÁ
-³ÈÄ¥¥â¥¸¥å¡¼¥ë¤¬É¬ÍפÊÄê¿ô¤Ï¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ¤ª¤¤¤¿Êý¤¬Îɤ¤
+³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤¬É¬ÍפÊÄê¿ô¤Ï¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ¤ª¤¤¤¿Êý¤¬Îɤ¤
¤Ç¤·¤ç¤¦¡¥Äê¿ô¤òÄêµÁ¤¹¤ë´Ø¿ô¤ÏÆó¤Ä¤¢¤ê¤Þ¤¹¡¥
- void rb_define_const(VALUE class, char *name, VALUE val)
- void rb_define_global_const(char *name, VALUE val)
+ void rb_define_const(VALUE klass, const char *name, VALUE val)
+ void rb_define_global_const(const char *name, VALUE val)
Á°¼Ô¤ÏÆÃÄê¤Î¥¯¥é¥¹/¥â¥¸¥å¡¼¥ë¤Ë°¤¹¤ëÄê¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¡¤¸å
¼Ô¤Ï¥°¥í¡¼¥Ð¥ë¤ÊÄê¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¤Ç¤¹¡¥
-2.2 ruby¤Îµ¡Ç½¤òC¤«¤é¸Æ¤Ó½Ð¤¹
+2.2 Ruby¤Îµ¡Ç½¤òC¤«¤é¸Æ¤Ó½Ð¤¹
-´û¤Ë¡Ø1.5 ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë¡Ù¤Ç°ìÉô¾Ò²ð¤·¤¿¤è¤¦¤Ê´Ø¿ô¤ò
-»È¤¨¤Ð¡¤ruby¤Îµ¡Ç½¤ò¼Â¸½¤·¤Æ¤¤¤ë´Ø¿ô¤òľÀܸƤӽФ¹¤³¤È¤¬½ÐÍè
+´û¤Ë¡Ø1.5 Ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë¡Ù¤Ç°ìÉô¾Ò²ð¤·¤¿¤è¤¦¤Ê´Ø¿ô¤ò
+»È¤¨¤Ð¡¤Ruby¤Îµ¡Ç½¤ò¼Â¸½¤·¤Æ¤¤¤ë´Ø¿ô¤òľÀܸƤӽФ¹¤³¤È¤¬½ÐÍè
¤Þ¤¹¡¥
# ¤³¤Î¤è¤¦¤Ê´Ø¿ô¤Î°ìÍ÷ɽ¤Ï¤¤¤Þ¤Î¤È¤³¤í¤¢¤ê¤Þ¤»¤ó¡¥¥½¡¼¥¹¤ò¸«
# ¤ë¤·¤«¤Ê¤¤¤Ç¤¹¤Í¡¥
-¤½¤ì°Ê³°¤Ë¤âruby¤Îµ¡Ç½¤ò¸Æ¤Ó½Ð¤¹ÊýË¡¤Ï¤¤¤¯¤Ä¤«¤¢¤ê¤Þ¤¹¡¥
+¤½¤ì°Ê³°¤Ë¤âRuby¤Îµ¡Ç½¤ò¸Æ¤Ó½Ð¤¹ÊýË¡¤Ï¤¤¤¯¤Ä¤«¤¢¤ê¤Þ¤¹¡¥
-2.2.1 ruby¤Î¥×¥í¥°¥é¥à¤òeval¤¹¤ë
+2.2.1 Ruby¤Î¥×¥í¥°¥é¥à¤òeval¤¹¤ë
-C¤«¤éruby¤Îµ¡Ç½¤ò¸Æ¤Ó½Ð¤¹¤â¤Ã¤È¤â´Êñ¤ÊÊýË¡¤È¤·¤Æ¡¤Ê¸»úÎó¤Ç
-Í¿¤¨¤é¤ì¤¿ruby¤Î¥×¥í¥°¥é¥à¤òɾ²Á¤¹¤ë´Ø¿ô¤¬¤¢¤ê¤Þ¤¹¡¥
+C¤«¤éRuby¤Îµ¡Ç½¤ò¸Æ¤Ó½Ð¤¹¤â¤Ã¤È¤â´Êñ¤ÊÊýË¡¤È¤·¤Æ¡¤Ê¸»úÎó¤Ç
+Í¿¤¨¤é¤ì¤¿Ruby¤Î¥×¥í¥°¥é¥à¤òɾ²Á¤¹¤ë°Ê²¼¤Î´Ø¿ô¤¬¤¢¤ê¤Þ¤¹¡¥
- VALUE rb_eval_string(char *str)
+ VALUE rb_eval_string(const char *str)
¤³¤Îɾ²Á¤Ï¸½ºß¤Î´Ä¶­¤Ç¹Ô¤ï¤ì¤Þ¤¹¡¥¤Ä¤Þ¤ê¡¤¸½ºß¤Î¥í¡¼¥«¥ëÊÑ¿ô
¤Ê¤É¤ò¼õ¤±·Ñ¤®¤Þ¤¹¡¥
2.2.2 ID¤Þ¤¿¤Ï¥·¥ó¥Ü¥ë
-C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤Ëruby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤â¤Ç¤­¤Þ
-¤¹¡¥¤½¤ÎÁ°¤Ë¡¤ruby¥¤¥ó¥¿¥×¥ê¥¿Æâ¤Ç¥á¥½¥Ã¥É¤äÊÑ¿ô̾¤ò»ØÄꤹ¤ë
+C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤ËRuby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤â¤Ç¤­¤Þ
+¤¹¡¥¤½¤ÎÁ°¤Ë¡¤Ruby¥¤¥ó¥¿¥×¥ê¥¿Æâ¤Ç¥á¥½¥Ã¥É¤äÊÑ¿ô̾¤ò»ØÄꤹ¤ë
»þ¤Ë»È¤ï¤ì¤Æ¤¤¤ëID¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Æ¤ª¤­¤Þ¤·¤ç¤¦¡¥
-ID¤È¤ÏÊÑ¿ô̾¡¤¥á¥½¥Ã¥É̾¤òɽ¤¹À°¿ô¤Ç¤¹¡¥ruby¤ÎÃæ¤Ç¤Ï
+ID¤È¤ÏÊÑ¿ô̾¡¤¥á¥½¥Ã¥É̾¤òɽ¤¹À°¿ô¤Ç¤¹¡¥Ruby¤ÎÃæ¤Ç¤Ï
:¼±ÊÌ»Ò
¤Ç¥¢¥¯¥»¥¹¤Ç¤­¤Þ¤¹¡¥C¤«¤é¤³¤ÎÀ°¿ô¤òÆÀ¤ë¤¿¤á¤Ë¤Ï´Ø¿ô
- rb_intern(char *name)
+ rb_intern(const char *name)
-¤ò»È¤¤¤Þ¤¹¡¥¤Þ¤¿°ìʸ»ú¤Î±é»»»Ò¤Ï¤½¤Îʸ»ú¥³¡¼¥É¤¬¤½¤Î¤Þ¤Þ¥·¥ó
-¥Ü¥ë¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥ruby¤«¤é°ú¿ô¤È¤·¤ÆÍ¿¤¨¤é¤ì¤¿¥·¥ó¥Ü¥ë(¤Þ
-¤¿¤Ïʸ»úÎó)¤òID¤ËÊÑ´¹¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+¤ò»È¤¤¤Þ¤¹¡¥Ruby¤«¤é°ú¿ô¤È¤·¤ÆÍ¿¤¨¤é¤ì¤¿¥·¥ó¥Ü¥ë(¤Þ¤¿¤Ïʸ»ú
+Îó)¤òID¤ËÊÑ´¹¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
rb_to_id(VALUE symbol)
-2.2.3 C¤«¤éruby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹
+2.2.3 C¤«¤éRuby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹
-C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤Ëruby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤¿¤á¤Ë¤Ï°Ê²¼
+C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤ËRuby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤¿¤á¤Ë¤Ï°Ê²¼
¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
VALUE rb_funcall(VALUE recv, ID mid, int argc, ...)
@@ -372,13 +386,13 @@ C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤Ëruby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤¿¤á¤Ë¤Ï°Ê²¼
VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)
VALUE rb_apply(VALUE recv, ID mid, VALUE args)
-apply¤Ë¤Ï°ú¿ô¤È¤·¤Æruby¤ÎÇÛÎó¤òÍ¿¤¨¤Þ¤¹¡¥
+apply¤Ë¤Ï°ú¿ô¤È¤·¤ÆRuby¤ÎÇÛÎó¤òÍ¿¤¨¤Þ¤¹¡¥
2.2.4 ÊÑ¿ô/Äê¿ô¤ò»²¾È/¹¹¿·¤¹¤ë
-C¤«¤é´Ø¿ô¤ò»È¤Ã¤Æ»²¾È¡¦¹¹¿·¤Ç¤­¤ë¤Î¤Ï¡¤¥¯¥é¥¹Äê¿ô¡¤¥¤¥ó¥¹¥¿
-¥ó¥¹ÊÑ¿ô¤Ç¤¹¡¥Âç°èÊÑ¿ô¤Ï°ìÉô¤Î¤â¤Î¤ÏC¤ÎÂç°èÊÑ¿ô¤È¤·¤Æ¥¢¥¯¥»
-¥¹¤Ç¤­¤Þ¤¹¡¥¥í¡¼¥«¥ëÊÑ¿ô¤ò»²¾È¤¹¤ëÊýË¡¤Ï¸ø³«¤·¤Æ¤¤¤Þ¤»¤ó¡¥
+C¤«¤é´Ø¿ô¤ò»È¤Ã¤Æ»²¾È¡¦¹¹¿·¤Ç¤­¤ë¤Î¤Ï¡¤Äê¿ô¡¤¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ
+¿ô¤Ç¤¹¡¥Âç°èÊÑ¿ô¤Ï°ìÉô¤Î¤â¤Î¤ÏC¤ÎÂç°èÊÑ¿ô¤È¤·¤Æ¥¢¥¯¥»¥¹¤Ç¤­
+¤Þ¤¹¡¥¥í¡¼¥«¥ëÊÑ¿ô¤ò»²¾È¤¹¤ëÊýË¡¤Ï¸ø³«¤·¤Æ¤¤¤Þ¤»¤ó¡¥
¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ò»²¾È¡¦¹¹¿·¤¹¤ë´Ø¿ô¤Ï°Ê²¼¤ÎÄÌ
¤ê¤Ç¤¹¡¥
@@ -388,53 +402,53 @@ C¤«¤é´Ø¿ô¤ò»È¤Ã¤Æ»²¾È¡¦¹¹¿·¤Ç¤­¤ë¤Î¤Ï¡¤¥¯¥é¥¹Äê¿ô¡¤¥¤¥ó¥¹¥¿
id¤Ïrb_intern()¤ÇÆÀ¤é¤ì¤ë¤â¤Î¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
-¥¯¥é¥¹Äê¿ô¤ò»²¾È¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
+Äê¿ô¤ò»²¾È¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
VALUE rb_const_get(VALUE obj, ID id)
-¥¯¥é¥¹Äê¿ô¤ò¿·¤·¤¯ÄêµÁ¤¹¤ë¤¿¤á¤Ë¤Ï¡Ø2.1.3 Äê¿ôÄêµÁ¡Ù¤Ç¾Ò²ð¤µ
+Äê¿ô¤ò¿·¤·¤¯ÄêµÁ¤¹¤ë¤¿¤á¤Ë¤Ï¡Ø2.1.3 Äê¿ôÄêµÁ¡Ù¤Ç¾Ò²ð¤µ
¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
-3¡¥ruby¤ÈC¤È¤Î¾ðÊó¶¦Í­
+3¡¥Ruby¤ÈC¤È¤Î¾ðÊó¶¦Í­
-C¸À¸ì¤Èruby¤Î´Ö¤Ç¾ðÊó¤ò¶¦Í­¤¹¤ëÊýË¡¤Ë¤Ä¤¤¤Æ²òÀ⤷¤Þ¤¹¡¥
+C¸À¸ì¤ÈRuby¤Î´Ö¤Ç¾ðÊó¤ò¶¦Í­¤¹¤ëÊýË¡¤Ë¤Ä¤¤¤Æ²òÀ⤷¤Þ¤¹¡¥
-3.1 C¤«¤é»²¾È¤Ç¤­¤ëruby¤ÎÄê¿ô
+3.1 C¤«¤é»²¾È¤Ç¤­¤ëRuby¤ÎÄê¿ô
-°Ê²¼¤Îruby¤ÎÄê¿ô¤ÏC¤Î¥ì¥Ù¥ë¤«¤é»²¾È¤Ç¤­¤ë¡¥
+°Ê²¼¤ÎRuby¤ÎÄê¿ô¤ÏC¤Î¥ì¥Ù¥ë¤«¤é»²¾È¤Ç¤­¤Þ¤¹¡¥
- TRUE
- FALSE
+ Qtrue
+ Qfalse
-¿¿µ¶ÃÍ¡¥FALSE¤ÏC¸À¸ì¤Ç¤âµ¶¤È¤ß¤Ê¤µ¤ì¤ë(¤Ä¤Þ¤ê0)¡¥
+ ¿¿µ¶ÃÍ¡¥Qfalse¤ÏC¸À¸ì¤Ç¤âµ¶¤È¤ß¤Ê¤µ¤ì¤Þ¤¹(¤Ä¤Þ¤ê0)¡¥
Qnil
-C¸À¸ì¤«¤é¸«¤¿¡Önil¡×¡¥
+ C¸À¸ì¤«¤é¸«¤¿¡Önil¡×¡¥
-3.2 C¤Èruby¤Ç¶¦Í­¤µ¤ì¤ëÂç°èÊÑ¿ô
+3.2 C¤ÈRuby¤Ç¶¦Í­¤µ¤ì¤ëÂç°èÊÑ¿ô
-C¤Èruby¤ÇÂç°èÊÑ¿ô¤ò»È¤Ã¤Æ¾ðÊó¤ò¶¦Í­¤Ç¤­¤Þ¤¹¡¥¶¦Í­¤Ç¤­¤ëÂç°è
+C¤ÈRuby¤ÇÂç°èÊÑ¿ô¤ò»È¤Ã¤Æ¾ðÊó¤ò¶¦Í­¤Ç¤­¤Þ¤¹¡¥¶¦Í­¤Ç¤­¤ëÂç°è
ÊÑ¿ô¤Ë¤Ï¤¤¤¯¤Ä¤«¤Î¼ïÎब¤¢¤ê¤Þ¤¹¡¥¤½¤Î¤Ê¤«¤Ç¤â¤Ã¤È¤âÎɤ¯»È¤ï
¤ì¤ë¤È»×¤ï¤ì¤ë¤Î¤Ïrb_define_variable()¤Ç¤¹¡¥
- void rb_define_variable(char *name, VALUE *var)
+ void rb_define_variable(const char *name, VALUE *var)
-¤³¤Î´Ø¿ô¤Ïruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ëÂç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ¤¹¡¥ÊÑ¿ô̾¤¬
+¤³¤Î´Ø¿ô¤ÏRuby¤ÈC¤È¤Ç¶¦Í­¤¹¤ëÂç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ¤¹¡¥ÊÑ¿ô̾¤¬
`$'¤Ç»Ï¤Þ¤é¤Ê¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤Þ¤¹¡¥¤³¤ÎÊÑ¿ô¤ÎÃͤòÊÑ
-¹¹¤¹¤ë¤È¼«Æ°Åª¤Ëruby¤ÎÂбþ¤¹¤ëÊÑ¿ô¤ÎÃͤâÊѤï¤ê¤Þ¤¹¡¥
+¹¹¤¹¤ë¤È¼«Æ°Åª¤ËRuby¤ÎÂбþ¤¹¤ëÊÑ¿ô¤ÎÃͤâÊѤï¤ê¤Þ¤¹¡¥
-¤Þ¤¿ruby¦¤«¤é¤Ï¹¹¿·¤Ç¤­¤Ê¤¤ÊÑ¿ô¤â¤¢¤ê¤Þ¤¹¡¥¤³¤Îread only¤Î
+¤Þ¤¿Ruby¦¤«¤é¤Ï¹¹¿·¤Ç¤­¤Ê¤¤ÊÑ¿ô¤â¤¢¤ê¤Þ¤¹¡¥¤³¤Îread only¤Î
ÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ÇÄêµÁ¤·¤Þ¤¹¡¥
- void rb_define_readonly_variable(char *name, VALUE *var)
+ void rb_define_readonly_variable(const char *name, VALUE *var)
¤³¤ì¤éÊÑ¿ô¤Î¾¤Ëhook¤ò¤Ä¤±¤¿Âç°èÊÑ¿ô¤òÄêµÁ¤Ç¤­¤Þ¤¹¡¥hookÉÕ¤­
¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤òÍѤ¤¤ÆÄêµÁ¤·¤Þ¤¹¡¥hookÉÕ¤­Âç°èÊÑ¿ô¤Î
Ãͤλ²¾È¤äÀßÄê¤Ïhook¤Ç¹Ô¤¦É¬Íפ¬¤¢¤ê¤Þ¤¹¡¥
- void rb_define_hooked_variable(char *name, VALUE *var,
- VALUE (*getter)(), VALUE (*setter)())
+ void rb_define_hooked_variable(const char *name, VALUE *var,
+ VALUE (*getter)(), void (*setter)())
¤³¤Î´Ø¿ô¤ÏC¤Î´Ø¿ô¤Ë¤è¤Ã¤Æhook¤Î¤Ä¤±¤é¤ì¤¿Âç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ
¤¹¡¥ÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï´Ø¿ôgetter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì
@@ -443,13 +457,13 @@ setter¤Ë0¤ò»ØÄꤷ¤Þ¤¹¡¥
# getter¤âsetter¤â0¤Ê¤é¤Ðrb_define_variable()¤ÈƱ¤¸¤Ë¤Ê¤ë¡¥
-¤½¤ì¤«¤é¡¤C¤Î´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ëruby¤ÎÂç°èÊÑ¿ô¤òÄêµÁ¤¹¤ë
+¤½¤ì¤«¤é¡¤C¤Î´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ëRuby¤ÎÂç°èÊÑ¿ô¤òÄêµÁ¤¹¤ë
´Ø¿ô¤¬¤¢¤ê¤Þ¤¹¡¥
- void rb_define_virtual_variable(char *name,
- VALUE (*getter)(), VALUE (*setter)())
+ void rb_define_virtual_variable(const char *name,
+ VALUE (*getter)(), void (*setter)())
-¤³¤Î´Ø¿ô¤Ë¤è¤Ã¤ÆÄêµÁ¤µ¤ì¤¿ruby¤ÎÂç°èÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï
+¤³¤Î´Ø¿ô¤Ë¤è¤Ã¤ÆÄêµÁ¤µ¤ì¤¿Ruby¤ÎÂç°èÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï
getter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì¤Þ¤¹¡¥
getter¤Èsetter¤Î»ÅÍͤϰʲ¼¤ÎÄ̤ê¤Ç¤¹¡¥
@@ -457,22 +471,22 @@ getter¤Èsetter¤Î»ÅÍͤϰʲ¼¤ÎÄ̤ê¤Ç¤¹¡¥
(*getter)(ID id, void *data, struct global_entry* entry);
(*setter)(VALUE val, ID id, void *data, struct global_entry* entry);
-3.3 C¤Î¥Ç¡¼¥¿¤òruby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¤¹¤ë
+3.3 C¤Î¥Ç¡¼¥¿¤òRuby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¤¹¤ë
-C¤ÎÀ¤³¦¤ÇÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿(¹½Â¤ÂÎ)¤òruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ
+C¤ÎÀ¤³¦¤ÇÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿(¹½Â¤ÂÎ)¤òRuby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ
¼è¤ê°·¤¤¤¿¤¤¾ì¹ç¤¬¤¢¤ê¤¨¤Þ¤¹¡¥¤³¤Î¤è¤¦¤Ê¾ì¹ç¤Ë¤Ï¡¤Data¤È¤¤¤¦
-ruby¥ª¥Ö¥¸¥§¥¯¥È¤ËC¤Î¹½Â¤ÂÎ(¤Ø¤Î¥Ý¥¤¥ó¥¿)¤ò¤¯¤ë¤à¤³¤È¤Çruby
+Ruby¥ª¥Ö¥¸¥§¥¯¥È¤ËC¤Î¹½Â¤ÂÎ(¤Ø¤Î¥Ý¥¤¥ó¥¿)¤ò¤¯¤ë¤à¤³¤È¤ÇRuby
¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ¼è¤ê°·¤¨¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡¥
-Data¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Æ¹½Â¤ÂΤòruby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¥«¥×¥»¥ë
+Data¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Æ¹½Â¤ÂΤòRuby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¥«¥×¥»¥ë
²½¤¹¤ë¤¿¤á¤Ë¤Ï¡¤°Ê²¼¤Î¥Þ¥¯¥í¤ò»È¤¤¤Þ¤¹¡¥
- Data_Wrap_Struct(class,mark,free,ptr)
+ Data_Wrap_Struct(klass, mark, free, ptr)
¤³¤Î¥Þ¥¯¥í¤ÎÌá¤êÃͤÏÀ¸À®¤µ¤ì¤¿Data¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¹¡¥
-class¤Ï¤³¤ÎData¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¯¥é¥¹¤Ç¤¹¡¥ptr¤Ï¥«¥×¥»¥ë²½¤¹¤ë
-C¤Î¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤Ç¤¹¡¥mark¤Ï¤³¤Î¹½Â¤ÂΤ¬ruby¤Î¥ª¥Ö¥¸¥§
+klass¤Ï¤³¤ÎData¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¯¥é¥¹¤Ç¤¹¡¥ptr¤Ï¥«¥×¥»¥ë²½¤¹¤ë
+C¤Î¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤Ç¤¹¡¥mark¤Ï¤³¤Î¹½Â¤ÂΤ¬Ruby¤Î¥ª¥Ö¥¸¥§
¥¯¥È¤Ø¤Î»²¾È¤¬¤¢¤ë»þ¤Ë»È¤¦´Ø¿ô¤Ç¤¹¡¥¤½¤Î¤è¤¦¤Ê»²¾È¤ò´Þ¤Þ¤Ê¤¤
»þ¤Ë¤Ï0¤ò»ØÄꤷ¤Þ¤¹¡¥
@@ -484,11 +498,11 @@ free¤Ï¤³¤Î¹½Â¤ÂΤ¬¤â¤¦ÉÔÍפˤʤä¿»þ¤Ë¸Æ¤Ð¤ì¤ë´Ø¿ô¤Ç¤¹¡¥¤³¤Î
C¤Î¹½Â¤ÂΤγäÅö¤ÈData¥ª¥Ö¥¸¥§¥¯¥È¤ÎÀ¸À®¤òƱ»þ¤Ë¹Ô¤¦¥Þ¥¯¥í¤È
¤·¤Æ°Ê²¼¤Î¤â¤Î¤¬Ä󶡤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
- Data_Make_Struct(class, type, mark, free, sval)
+ Data_Make_Struct(klass, type, mark, free, sval)
¤³¤Î¥Þ¥¯¥í¤ÎÌá¤êÃͤÏÀ¸À®¤µ¤ì¤¿Data¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¹¡¥
-class, mark, free¤ÏData_Wrap_Struct¤ÈƱ¤¸Æ¯¤­¤ò¤·¤Þ¤¹¡¥type
+klass, mark, free¤ÏData_Wrap_Struct¤ÈƱ¤¸Æ¯¤­¤ò¤·¤Þ¤¹¡¥type
¤Ï³ä¤êÅö¤Æ¤ëC¹½Â¤ÂΤη¿¤Ç¤¹¡¥³ä¤êÅö¤Æ¤é¤ì¤¿¹½Â¤ÂΤÏÊÑ¿ôsval
¤ËÂåÆþ¤µ¤ì¤Þ¤¹¡¥¤³¤ÎÊÑ¿ô¤Î·¿¤Ï (type*) ¤Ç¤¢¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥
@@ -504,18 +518,18 @@ C¤Î¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤ÏÊÑ¿ôsval¤ËÂåÆþ¤µ¤ì¤Þ¤¹¡¥
4¡¥ÎãÂê - dbm¥Ñ¥Ã¥±¡¼¥¸¤òºî¤ë
-¤³¤³¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤È¤ê¤¢¤¨¤º³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ïºî¤ì¤ë¤Ï¤º¤Ç¤¹¡¥
-ruby¤Îext¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤¹¤Ç¤Ë´Þ¤Þ¤ì¤Æ¤¤¤ëdbm¥â¥¸¥å¡¼¥ë¤òÎã¤Ë
+¤³¤³¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤È¤ê¤¢¤¨¤º³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ïºî¤ì¤ë¤Ï¤º¤Ç¤¹¡¥
+Ruby¤Îext¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤¹¤Ç¤Ë´Þ¤Þ¤ì¤Æ¤¤¤ëdbm¥é¥¤¥Ö¥é¥ê¤òÎã¤Ë
¤·¤ÆÃʳ¬Åª¤ËÀâÌÀ¤·¤Þ¤¹¡¥
(1) ¥Ç¥£¥ì¥¯¥È¥ê¤òºî¤ë
% mkdir ext/dbm
-ruby 1.1¤«¤é¤ÏǤ°Õ¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ç¥À¥¤¥Ê¥ß¥Ã¥¯¥é¥¤¥Ö¥é¥ê¤òºî
-¤ë¤³¤È¤¬¤Ç¤­¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤·¤¿¡¥ruby¤ËÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë¾ì¹ç¤Ë
-¤Ïruby¤òŸ³«¤·¤¿¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¡¤ext¥Ç¥£¥ì¥¯¥È¥ê¤ÎÃæ¤Ë³ÈÄ¥
-¥â¥¸¥å¡¼¥ëÍѤΥǥ£¥ì¥¯¥È¥ê¤òºî¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥Ì¾Á°¤ÏŬÅö¤Ë
+Ruby 1.1¤«¤é¤ÏǤ°Õ¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ç¥À¥¤¥Ê¥ß¥Ã¥¯¥é¥¤¥Ö¥é¥ê¤òºî
+¤ë¤³¤È¤¬¤Ç¤­¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤·¤¿¡¥Ruby¤ËÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë¾ì¹ç¤Ë
+¤ÏRuby¤òŸ³«¤·¤¿¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¡¤ext¥Ç¥£¥ì¥¯¥È¥ê¤ÎÃæ¤Ë³ÈÄ¥
+¥é¥¤¥Ö¥é¥êÍѤΥǥ£¥ì¥¯¥È¥ê¤òºî¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥Ì¾Á°¤ÏŬÅö¤Ë
Áª¤ó¤Ç¹½¤¤¤Þ¤»¤ó¡¥
(2) MANIFEST¥Õ¥¡¥¤¥ë¤òºî¤ë
@@ -523,12 +537,12 @@ ruby 1.1¤«¤é¤ÏǤ°Õ¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ç¥À¥¤¥Ê¥ß¥Ã¥¯¥é¥¤¥Ö¥é¥ê¤òºî
% cd ext/dbm
% touch MANIFEST
-³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¤Ë¤ÏMANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬
+³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¤Ë¤ÏMANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬
ɬÍפʤΤǡ¤¤È¤ê¤¢¤¨¤º¶õ¤Î¥Õ¥¡¥¤¥ë¤òºî¤Ã¤Æ¤ª¤­¤Þ¤¹¡¥¸å¤Ç¤³¤Î
¥Õ¥¡¥¤¥ë¤Ë¤ÏɬÍפʥե¡¥¤¥ë°ìÍ÷¤¬Æþ¤ë¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
MANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤Ï¡¤ÀÅŪ¥ê¥ó¥¯¤Îmake¤Î»þ¤Ë¥Ç¥£¥ì¥¯¥È¥ê
-¤¬³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ò´Þ¤ó¤Ç¤¤¤ë¤«¤É¤¦¤«È½Äꤹ¤ë¤¿¤á¤Ë»È¤ï¤ì¤ì¤Æ
+¤¬³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ò´Þ¤ó¤Ç¤¤¤ë¤«¤É¤¦¤«È½Äꤹ¤ë¤¿¤á¤Ë»È¤ï¤ì¤ì¤Æ
¤¤¤Þ¤¹¡¥¥À¥¤¥Ê¥ß¥Ã¥¯¥é¥¤¥Ö¥é¥ê¤òºî¤ë¾ì¹ç¤Ë¤Ïɬ¤º¤·¤âɬÍפǤÏ
¤¢¤ê¤Þ¤»¤ó¡¥
@@ -537,19 +551,19 @@ MANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤Ï¡¤ÀÅŪ¥ê¥ó¥¯¤Îmake¤Î»þ¤Ë¥Ç¥£¥ì¥¯¥È¥ê
¤Þ¤¢¡¤ÅöÁ³¤Ê¤ó¤Ç¤¹¤±¤É¡¤¤É¤¦¤¤¤¦µ¡Ç½¤ò¼Â¸½¤¹¤ë¤«¤É¤¦¤«¤Þ¤ºÀß
·×¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥¤É¤ó¤Ê¥¯¥é¥¹¤ò¤Ä¤¯¤ë¤«¡¤¤½¤Î¥¯¥é¥¹¤Ë¤Ï
¤É¤ó¤Ê¥á¥½¥Ã¥É¤¬¤¢¤ë¤«¡¤¥¯¥é¥¹¤¬Ä󶡤¹¤ëÄê¿ô¤Ê¤É¤Ë¤Ä¤¤¤ÆÀß·×
-¤·¤Þ¤¹¡¥dbm¥¯¥é¥¹¤Ë¤Ä¤¤¤Æ¤Ïext/dbm.doc¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+¤·¤Þ¤¹¡¥
(4) C¥³¡¼¥É¤ò½ñ¤¯
-³ÈÄ¥¥â¥¸¥å¡¼¥ëËÜÂΤȤʤëC¸À¸ì¤Î¥½¡¼¥¹¤ò½ñ¤­¤Þ¤¹¡¥C¸À¸ì¤Î¥½¡¼
-¥¹¤¬¤Ò¤È¤Ä¤Î»þ¤Ë¤Ï¡Ö¥â¥¸¥å¡¼¥ë̾.c¡×¤òÁª¤Ö¤ÈÎɤ¤¤Ç¤·¤ç¤¦¡¥C
-¸À¸ì¤Î¥½¡¼¥¹¤¬Ê£¿ô¤Î¾ì¹ç¤Ë¤ÏµÕ¤Ë¡Ö¥â¥¸¥å¡¼¥ë̾.c¡×¤È¤¤¤¦¥Õ¥¡
+³ÈÄ¥¥é¥¤¥Ö¥é¥êËÜÂΤȤʤëC¸À¸ì¤Î¥½¡¼¥¹¤ò½ñ¤­¤Þ¤¹¡¥C¸À¸ì¤Î¥½¡¼
+¥¹¤¬¤Ò¤È¤Ä¤Î»þ¤Ë¤Ï¡Ö¥é¥¤¥Ö¥é¥ê̾.c¡×¤òÁª¤Ö¤ÈÎɤ¤¤Ç¤·¤ç¤¦¡¥C
+¸À¸ì¤Î¥½¡¼¥¹¤¬Ê£¿ô¤Î¾ì¹ç¤Ë¤ÏµÕ¤Ë¡Ö¥é¥¤¥Ö¥é¥ê̾.c¡×¤È¤¤¤¦¥Õ¥¡
¥¤¥ë̾¤ÏÈò¤±¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥¥ª¥Ö¥¸¥§¥¯¥È¥Õ¥¡¥¤¥ë¤È¥â¥¸¥å¡¼
-¥ëÀ¸À®»þ¤ËÃæ´ÖŪ¤ËÀ¸À®¤µ¤ì¤ë¡Ö¥â¥¸¥å¡¼¥ë̾.o¡×¤È¤¤¤¦¥Õ¥¡¥¤¥ë
+¥ëÀ¸À®»þ¤ËÃæ´ÖŪ¤ËÀ¸À®¤µ¤ì¤ë¡Ö¥é¥¤¥Ö¥é¥ê̾.o¡×¤È¤¤¤¦¥Õ¥¡¥¤¥ë
¤È¤¬¾×ÆÍ¤¹¤ë¤«¤é¤Ç¤¹¡¥
-ruby¤Ï³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ò¥í¡¼¥É¤¹¤ë»þ¤Ë¡ÖInit_¥â¥¸¥å¡¼¥ë̾¡×¤È
-¤¤¤¦´Ø¿ô¤ò¼«Æ°Åª¤Ë¼Â¹Ô¤·¤Þ¤¹¡¥dbm¥â¥¸¥å¡¼¥ë¤Î¾ì¹ç¡ÖInit_dbm¡×
+Ruby¤Ï³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤¹¤ë»þ¤Ë¡ÖInit_¥é¥¤¥Ö¥é¥ê̾¡×¤È
+¤¤¤¦´Ø¿ô¤ò¼«Æ°Åª¤Ë¼Â¹Ô¤·¤Þ¤¹¡¥dbm¥é¥¤¥Ö¥é¥ê¤Î¾ì¹ç¡ÖInit_dbm¡×
¤Ç¤¹¡¥¤³¤Î´Ø¿ô¤ÎÃæ¤Ç¥¯¥é¥¹¡¤¥â¥¸¥å¡¼¥ë¡¤¥á¥½¥Ã¥É¡¤Äê¿ô¤Ê¤É¤Î
ÄêµÁ¤ò¹Ô¤¤¤Þ¤¹¡¥dbm.c¤«¤é°ìÉô°úÍѤ·¤Þ¤¹¡¥
@@ -557,9 +571,9 @@ ruby¤Ï³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ò¥í¡¼¥É¤¹¤ë»þ¤Ë¡ÖInit_¥â¥¸¥å¡¼¥ë̾¡×¤È
Init_dbm()
{
/* DBM¥¯¥é¥¹¤òÄêµÁ¤¹¤ë */
- cDBM = rb_define_class("DBM", cObject);
+ cDBM = rb_define_class("DBM", rb_cObject);
/* DBM¤ÏEnumerate¥â¥¸¥å¡¼¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë */
- rb_include_module(cDBM, mEnumerable);
+ rb_include_module(cDBM, rb_mEnumerable);
/* DBM¥¯¥é¥¹¤Î¥¯¥é¥¹¥á¥½¥Ã¥Éopen(): °ú¿ô¤ÏC¤ÎÇÛÎó¤Ç¼õ¤±¤ë */
rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1);
@@ -575,8 +589,8 @@ Init_dbm()
}
--
-DBM¥â¥¸¥å¡¼¥ë¤Ïdbm¤Î¥Ç¡¼¥¿¤ÈÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Ë¤Ê¤ë¤Ï¤º¤Ç
-¤¹¤«¤é¡¤C¤ÎÀ¤³¦¤Îdbm¤òruby¤ÎÀ¤³¦¤Ë¼è¤ê¹þ¤àɬÍפ¬¤¢¤ê¤Þ¤¹¡¥
+DBM¥é¥¤¥Ö¥é¥ê¤Ïdbm¤Î¥Ç¡¼¥¿¤ÈÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Ë¤Ê¤ë¤Ï¤º¤Ç
+¤¹¤«¤é¡¤C¤ÎÀ¤³¦¤Îdbm¤òRuby¤ÎÀ¤³¦¤Ë¼è¤ê¹þ¤àɬÍפ¬¤¢¤ê¤Þ¤¹¡¥
dbm.c¤Ç¤ÏData_Make_Struct¤ò°Ê²¼¤Î¤è¤¦¤Ë»È¤Ã¤Æ¤¤¤Þ¤¹¡¥
@@ -588,7 +602,7 @@ struct dbmdata {
};
-obj = Data_Make_Struct(class,struct dbmdata,0,free_dbm,dbmp);
+obj = Data_Make_Struct(klass, struct dbmdata, 0, free_dbm, dbmp);
--
¤³¤³¤Ç¤Ïdbmstruct¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤òData¤Ë¥«¥×¥»¥ë²½¤·¤Æ¤¤
@@ -626,17 +640,17 @@ fdbm_delete(obj, keystr)
°ú¿ô¤Î¿ô¤¬¸ÇÄê¤Î¥¿¥¤¥×¤ÏÂè1°ú¿ô¤¬self¡¤Âè2°ú¿ô°Ê¹ß¤¬¥á¥½¥Ã¥É
¤Î°ú¿ô¤È¤Ê¤ê¤Þ¤¹¡¥
-°ú¿ô¤Î¿ô¤¬ÉÔÄê¤Î¤â¤Î¤ÏC¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î¤Èruby¤ÎÇÛÎó¤Ç¼õ¤±
-¤ë¤â¤Î¤È¤¬¤¢¤ê¤Þ¤¹¡¥dbm¥â¥¸¥å¡¼¥ë¤ÎÃæ¤Ç¡¤C¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î
+°ú¿ô¤Î¿ô¤¬ÉÔÄê¤Î¤â¤Î¤ÏC¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î¤ÈRuby¤ÎÇÛÎó¤Ç¼õ¤±
+¤ë¤â¤Î¤È¤¬¤¢¤ê¤Þ¤¹¡¥dbm¥é¥¤¥Ö¥é¥ê¤ÎÃæ¤Ç¡¤C¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î
¤ÏDBM¤Î¥¯¥é¥¹¥á¥½¥Ã¥É¤Ç¤¢¤ëopen()¤Ç¤¹¡¥¤³¤ì¤ò¼ÂÁõ¤·¤Æ¤¤¤ë´Ø
¿ôfdbm_s_open()¤Ï¤³¤¦¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
--
static VALUE
-fdbm_s_open(argc, argv, class)
+fdbm_s_open(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
{
:
if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
@@ -660,27 +674,24 @@ fdbm_s_open(argc, argv, class)
¤Ç¡¤2¤Ä¤Þ¤Çµö¤µ¤ì¤ë¤È¤¤¤¦°ÕÌ£¤Ë¤Ê¤ê¤Þ¤¹¡¥¾Êά¤µ¤ì¤Æ¤¤¤ë»þ¤Î
ÊÑ¿ô¤ÎÃͤÏnil(C¸À¸ì¤Î¥ì¥Ù¥ë¤Ç¤ÏQnil)¤Ë¤Ê¤ê¤Þ¤¹¡¥
-ruby¤ÎÇÛÎó¤Ç°ú¿ô¤ò¼õ¤±¼è¤ë¤â¤Î¤Ïindexes¤¬¤¢¤ê¤Þ¤¹¡¥¼ÂÁõ¤Ï¤³
+Ruby¤ÎÇÛÎó¤Ç°ú¿ô¤ò¼õ¤±¼è¤ë¤â¤Î¤Ïindexes¤¬¤¢¤ê¤Þ¤¹¡¥¼ÂÁõ¤Ï¤³
¤¦¤Ç¤¹¡¥
--
static VALUE
fdbm_indexes(obj, args)
- VALUE obj;
- struct RArray *args;
+ VALUE obj, args;
{
:
}
--
-Âè1°ú¿ô¤Ïself¡¤Âè2°ú¿ô¤Ïruby¤ÎÇÛÎó¤Ç¤¹¡¥¤³¤³¤Ç¤Ï¥­¥ã¥¹¥È¤ò¸º
-¤é¤¹¤¿¤á struct RArray* ¤Ç¼õ¤±¤Æ¤¤¤Þ¤¹¤¬¡¤VALUE¤Ç¤âƱ¤¸¤³¤È
-¤Ç¤¹¡¥
+Âè1°ú¿ô¤Ïself¡¤Âè2°ú¿ô¤ÏRuby¤ÎÇÛÎó¤Ç¤¹¡¥
** Ãí°Õ»ö¹à
-ruby¤È¶¦Í­¤Ï¤·¤Ê¤¤¤¬ruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤ò³ÊǼ¤¹¤ë²ÄǽÀ­¤Î¤¢¤ë
-C¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤Æruby¥¤¥ó¥¿¥×¥ê¥¿¤ËÊÑ¿ô¤Î¸ºß
+Ruby¤È¶¦Í­¤Ï¤·¤Ê¤¤¤¬Ruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤ò³ÊǼ¤¹¤ë²ÄǽÀ­¤Î¤¢¤ë
+C¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤ÆRuby¥¤¥ó¥¿¥×¥ê¥¿¤ËÊÑ¿ô¤Î¸ºß
¤ò¶µ¤¨¤Æ¤¢¤²¤Æ¤¯¤À¤µ¤¤¡¥¤Ç¤Ê¤¤¤ÈGC¤Ç¥È¥é¥Ö¥ë¤òµ¯¤³¤·¤Þ¤¹¡¥
void rb_global_variable(VALUE *var)
@@ -688,12 +699,16 @@ C¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤Æruby¥¤¥ó¥¿¥×¥ê¥¿¤ËÊÑ¿ô¤Î¸ºß
(5) extconf.rb¤òÍѰդ¹¤ë
Makefile¤òºî¤ë¾ì¹ç¤Î¿÷·¿¤Ë¤Ê¤ëextconf.rb¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤òºî¤ê
-¤Þ¤¹¡¥extconf.rb¤Ï¥â¥¸¥å¡¼¥ë¤Î¥³¥ó¥Ñ¥¤¥ë¤ËɬÍפʾò·ï¤Î¥Á¥§¥Ã
-¥¯¤Ê¤É¤ò¹Ô¤¦¤³¤È¤¬ÌÜŪ¤Ç¤¹¡¥extconf.rb¤ÎÃæ¤Ç¤Ï°Ê²¼¤Îruby´Ø¿ô
-¤ò»È¤¦¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥
+¤Þ¤¹¡¥extconf.rb¤Ï¥é¥¤¥Ö¥é¥ê¤Î¥³¥ó¥Ñ¥¤¥ë¤ËɬÍפʾò·ï¤Î¥Á¥§¥Ã
+¥¯¤Ê¤É¤ò¹Ô¤¦¤³¤È¤¬ÌÜŪ¤Ç¤¹¡¥¤Þ¤º¡¤
+
+ require 'mkmf'
+
+¤òextconf.rb¤ÎÀèÆ¬¤ËÃÖ¤­¤Þ¤¹¡¥extconf.rb¤ÎÃæ¤Ç¤Ï°Ê²¼¤ÎRuby´Ø
+¿ô¤ò»È¤¦¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥
have_library(lib, func): ¥é¥¤¥Ö¥é¥ê¤Î¸ºß¥Á¥§¥Ã¥¯
- have_func(func): ´Ø¿ô¤Î¸ºß¥Á¥§¥Ã¥¯
+ have_func(func, header): ´Ø¿ô¤Î¸ºß¥Á¥§¥Ã¥¯
have_header(header): ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¥Á¥§¥Ã¥¯
create_makefile(target): Makefile¤ÎÀ¸À®
@@ -702,28 +717,22 @@ Makefile¤òºî¤ë¾ì¹ç¤Î¿÷·¿¤Ë¤Ê¤ëextconf.rb¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤òºî¤ê
$CFLAGS: ¥³¥ó¥Ñ¥¤¥ë»þ¤ËÄɲÃŪ¤Ë»ØÄꤹ¤ë¥Õ¥é¥°(-I¤Ê¤É)
$LDFLAGS: ¥ê¥ó¥¯»þ¤ËÄɲÃŪ¤Ë»ØÄꤹ¤ë¥Õ¥é¥°(-L¤Ê¤É)
-¥â¥¸¥å¡¼¥ë¤ò¥³¥ó¥Ñ¥¤¥ë¤¹¤ë¾ò·ï¤¬Â·¤ï¤Ê¤º¡¤¤½¤Î¥â¥¸¥å¡¼¥ë¤Ï¥³
-¥ó¥Ñ¥¤¥ë¤·¤Ê¤¤»þ¤Ë¤Ïcreate_makefile¤ò¸Æ¤Ð¤Ê¤±¤ì¤ÐMakefile¤Ï
-À¸À®¤µ¤ì¤º¡¤¥³¥ó¥Ñ¥¤¥ë¤â¹Ô¤ï¤ì¤Þ¤»¤ó¡¥
-
-¥â¥¸¥å¡¼¥ë¤¬ruby 1.1ÀìÍѤǤ¢¤ë¾ì¹ç¤Ë¤Ï
-
- require 'mkmf'
-
-¤òextconf.rb¤ÎÀèÆ¬¤ËÃÖ¤¯¤ÈÊØÍø¤Ç¤·¤ç¤¦¡¥
+¥é¥¤¥Ö¥é¥ê¤ò¥³¥ó¥Ñ¥¤¥ë¤¹¤ë¾ò·ï¤¬Â·¤ï¤º¡¤¤½¤Î¥é¥¤¥Ö¥é¥ê¤ò¥³¥ó
+¥Ñ¥¤¥ë¤·¤Ê¤¤»þ¤Ë¤Ïcreate_makefile¤ò¸Æ¤Ð¤Ê¤±¤ì¤ÐMakefile¤ÏÀ¸
+À®¤µ¤ì¤º¡¤¥³¥ó¥Ñ¥¤¥ë¤â¹Ô¤ï¤ì¤Þ¤»¤ó¡¥
(6) depend¤òÍѰդ¹¤ë
¤â¤·¡¤¥Ç¥£¥ì¥¯¥È¥ê¤Ëdepend¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ì¤Ð¡¤
Makefile¤¬°Í¸´Ø·¸¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤ì¤Þ¤¹¡¥
- % gcc -MM *.c > depend
+ % gcc -MM *.c > depend
¤Ê¤É¤Çºî¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤¢¤Ã¤ÆÂ»¤Ï̵¤¤¤Ç¤·¤ç¤¦¡¥
(7) MANIFEST¥Õ¥¡¥¤¥ë¤Ë¥Õ¥¡¥¤¥ë̾¤òÆþ¤ì¤ë
- % ls > MANIFEST
+ % find * -type f -print > MANIFEST
% vi MANIFEST
*.o, *~¤Ê¤ÉÉÔɬÍפʥե¡¥¤¥ë°Ê³°¤ÏMANIFEST¤ËÄɲ䷤Ƥª¤­¤Þ¤¹¡¥
@@ -745,7 +754,7 @@ Makefile¤ò¼ÂºÝ¤ËÀ¸À®¤¹¤ë¤¿¤á¤Ë¤Ï
¤È¤·¤Æ¤¯¤À¤µ¤¤¡¥
-¥Ç¥£¥ì¥¯¥È¥ê¤òext°Ê²¼¤ËÍѰդ·¤¿¾ì¹ç¤Ë¤ÏrubyÁ´ÂΤÎmake¤Î»þ¤Ë
+¥Ç¥£¥ì¥¯¥È¥ê¤òext°Ê²¼¤ËÍѰդ·¤¿¾ì¹ç¤Ë¤ÏRubyÁ´ÂΤÎmake¤Î»þ¤Ë
¼«Æ°Åª¤ËMakefile¤¬À¸À®¤µ¤ì¤Þ¤¹¤Î¤Ç¡¤¤³¤Î¥¹¥Æ¥Ã¥×¤ÏÉÔÍפǤ¹¡¥
(9) make¤¹¤ë
@@ -753,16 +762,16 @@ Makefile¤ò¼ÂºÝ¤ËÀ¸À®¤¹¤ë¤¿¤á¤Ë¤Ï
ưŪ¥ê¥ó¥¯¥é¥¤¥Ö¥é¥ê¤òÀ¸À®¤¹¤ë¾ì¹ç¤Ë¤Ï¤½¤Î¾ì¤Çmake¤·¤Æ¤¯¤À¤µ
¤¤¡¥É¬ÍפǤ¢¤ì¤Ð make install ¤Ç¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Þ¤¹¡¥
-ext°Ê²¼¤Ë¥Ç¥£¥ì¥¯¥È¥ê¤òÍѰդ·¤¿¾ì¹ç¤Ï¡¤ruby¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ç
+ext°Ê²¼¤Ë¥Ç¥£¥ì¥¯¥È¥ê¤òÍѰդ·¤¿¾ì¹ç¤Ï¡¤Ruby¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ç
make¤ò¼Â¹Ô¤¹¤ë¤ÈMakefile¤òÀ¸À®¤«¤émake¡¤É¬Íפˤè¤Ã¤Æ¤Ï¤½¤Î¥â
-¥¸¥å¡¼¥ë¤Îruby¤Ø¤Î¥ê¥ó¥¯¤Þ¤Ç¼«Æ°Åª¤Ë¼Â¹Ô¤·¤Æ¤¯¤ì¤Þ¤¹¡¥
+¥¸¥å¡¼¥ë¤ÎRuby¤Ø¤Î¥ê¥ó¥¯¤Þ¤Ç¼«Æ°Åª¤Ë¼Â¹Ô¤·¤Æ¤¯¤ì¤Þ¤¹¡¥
extconf.rb¤ò½ñ¤­´¹¤¨¤ë¤Ê¤É¤·¤ÆMakefile¤ÎºÆÀ¸À®¤¬É¬Íפʻþ¤Ï¤Þ
-¤¿ruby¥Ç¥£¥ì¥¯¥È¥ê¤Çmake¤·¤Æ¤¯¤À¤µ¤¤¡¥
+¤¿Ruby¥Ç¥£¥ì¥¯¥È¥ê¤Çmake¤·¤Æ¤¯¤À¤µ¤¤¡¥
-ưŪ¥ê¥ó¥¯¥é¥¤¥Ö¥é¥ê¤Ïmake install¤Çruby¥é¥¤¥Ö¥é¥ê¤Î¥Ç¥£¥ì¥¯
-¥È¥ê¤Î²¼¤Ë¥³¥Ô¡¼¤µ¤ì¤Þ¤¹¡¥¤â¤·¥â¥¸¥å¡¼¥ë¤È¶¨Ä´¤·¤Æ»È¤¦ruby¤Ç
-µ­½Ò¤µ¤ì¤¿¥×¥í¥°¥é¥à¤¬¤¢¤ê¡¤ruby¥é¥¤¥Ö¥é¥ê¤ËÃÖ¤­¤¿¤¤¾ì¹ç¤Ë¤Ï¡¤
-³ÈÄ¥¥â¥¸¥å¡¼¥ëÍѤΥǥ£¥ì¥¯¥È¥ê¤Î²¼¤Ë lib ¤È¤¤¤¦¥Ç¥£¥ì¥¯¥È¥ê
+³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ïmake install¤ÇRuby¥é¥¤¥Ö¥é¥ê¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Î
+²¼¤Ë¥³¥Ô¡¼¤µ¤ì¤Þ¤¹¡¥¤â¤·³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤È¶¨Ä´¤·¤Æ»È¤¦Ruby¤Çµ­
+½Ò¤µ¤ì¤¿¥×¥í¥°¥é¥à¤¬¤¢¤ê¡¤Ruby¥é¥¤¥Ö¥é¥ê¤ËÃÖ¤­¤¿¤¤¾ì¹ç¤Ë¤Ï¡¤
+³ÈÄ¥¥é¥¤¥Ö¥é¥êÍѤΥǥ£¥ì¥¯¥È¥ê¤Î²¼¤Ë lib ¤È¤¤¤¦¥Ç¥£¥ì¥¯¥È¥ê
¤òºî¤ê¡¤¤½¤³¤Ë ³ÈÄ¥»Ò .rb ¤Î¥Õ¥¡¥¤¥ë¤òÃÖ¤¤¤Æ¤ª¤±¤ÐƱ»þ¤Ë¥¤¥ó
¥¹¥È¡¼¥ë¤µ¤ì¤Þ¤¹¡¥
@@ -775,17 +784,17 @@ extconf.rb¤ò½ñ¤­´¹¤¨¤ë¤Ê¤É¤·¤ÆMakefile¤ÎºÆÀ¸À®¤¬É¬Íפʻþ¤Ï¤Þ
(11) ¤Ç¤­¤¢¤¬¤ê
¸å¤Ï¤³¤Ã¤½¤ê»È¤¦¤Ê¤ê¡¤¹­¤¯¸ø³«¤¹¤ë¤Ê¤ê¡¤Çä¤ë¤Ê¤ê¡¤¤´¼«Í³¤Ë¤ª
-»È¤¤¤¯¤À¤µ¤¤¡¥ruby¤Îºî¼Ô¤Ï³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë´Ø¤·¤Æ°ìÀڤθ¢Íø¤ò
+»È¤¤¤¯¤À¤µ¤¤¡¥Ruby¤Îºî¼Ô¤Ï³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ë´Ø¤·¤Æ°ìÀڤθ¢Íø¤ò
¼çÄ¥¤·¤Þ¤»¤ó¡¥
-Appendix A. ruby¤Î¥½¡¼¥¹¥³¡¼¥É¤ÎʬÎà
+Appendix A. Ruby¤Î¥½¡¼¥¹¥³¡¼¥É¤ÎʬÎà
-ruby¤Î¥½¡¼¥¹¤Ï¤¤¤¯¤Ä¤«¤ËʬÎह¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤³¤Î¤¦¤Á¥¯¥é
-¥¹¥é¥¤¥Ö¥é¥ê¤ÎÉôʬ¤Ï´ðËÜŪ¤Ë³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ÈƱ¤¸ºî¤êÊý¤Ë¤Ê¤Ã
+Ruby¤Î¥½¡¼¥¹¤Ï¤¤¤¯¤Ä¤«¤ËʬÎह¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤³¤Î¤¦¤Á¥¯¥é
+¥¹¥é¥¤¥Ö¥é¥ê¤ÎÉôʬ¤Ï´ðËÜŪ¤Ë³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ÈƱ¤¸ºî¤êÊý¤Ë¤Ê¤Ã
¤Æ¤¤¤Þ¤¹¡¥¤³¤ì¤é¤Î¥½¡¼¥¹¤Ïº£¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤Û¤È¤ó¤ÉÍý²ò¤Ç¤­¤ë¤È
»×¤¤¤Þ¤¹¡¥
-ruby¸À¸ì¤Î¥³¥¢
+Ruby¸À¸ì¤Î¥³¥¢
class.c
error.c
@@ -798,13 +807,11 @@ ruby¸À¸ì¤Î¥³¥¢
¥æ¡¼¥Æ¥£¥ê¥Æ¥£´Ø¿ô
dln.c
- fnmatch.c
- glob.c
regex.c
st.c
util.c
-ruby¥³¥Þ¥ó¥É¤Î¼ÂÁõ
+Ruby¥³¥Þ¥ó¥É¤Î¼ÂÁõ
dmyext.c
inits.c
@@ -826,6 +833,7 @@ ruby¥³¥Þ¥ó¥É¤Î¼ÂÁõ
math.c
numeric.c
pack.c
+ prec.c
process.c
random.c
range.c
@@ -838,278 +846,291 @@ ruby¥³¥Þ¥ó¥É¤Î¼ÂÁõ
Appendix B. ³ÈÄ¥ÍÑ´Ø¿ô¥ê¥Õ¥¡¥ì¥ó¥¹
-C¸À¸ì¤«¤éruby¤Îµ¡Ç½¤òÍøÍѤ¹¤ëAPI¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥
+C¸À¸ì¤«¤éRuby¤Îµ¡Ç½¤òÍøÍѤ¹¤ëAPI¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥
** ·¿
- VALUE
+VALUE
-ruby¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¸½¤¹¤ë·¿¡¥É¬Íפ˱þ¤¸¤Æ¥­¥ã¥¹¥È¤·¤ÆÍѤ¤¤ë¡¥
-ÁȤ߹þ¤ß·¿¤òɽ¸½¤¹¤ëC¤Î·¿¤Ïruby.h¤Ëµ­½Ò¤·¤Æ¤¢¤ëR¤Ç»Ï¤Þ¤ë¹½Â¤
-ÂΤǤ¢¤ë¡¥VALUE·¿¤ò¤³¤ì¤é¤Ë¥­¥ã¥¹¥È¤¹¤ë¤¿¤á¤ËR¤Ç»Ï¤Þ¤ë¹½Â¤ÂÎ
-̾¤òÁ´¤ÆÂçʸ»ú¤Ë¤·¤¿Ì¾Á°¤Î¥Þ¥¯¥í¤¬ÍѰդµ¤ì¤Æ¤¤¤ë¡¥
+ Ruby¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¸½¤¹¤ë·¿¡¥É¬Íפ˱þ¤¸¤Æ¥­¥ã¥¹¥È¤·¤ÆÍѤ¤¤ë¡¥
+ ÁȤ߹þ¤ß·¿¤òɽ¸½¤¹¤ëC¤Î·¿¤Ïruby.h¤Ëµ­½Ò¤·¤Æ¤¢¤ëR¤Ç»Ï¤Þ¤ë¹½Â¤
+ ÂΤǤ¢¤ë¡¥VALUE·¿¤ò¤³¤ì¤é¤Ë¥­¥ã¥¹¥È¤¹¤ë¤¿¤á¤ËR¤Ç»Ï¤Þ¤ë¹½Â¤ÂÎ
+ ̾¤òÁ´¤ÆÂçʸ»ú¤Ë¤·¤¿Ì¾Á°¤Î¥Þ¥¯¥í¤¬ÍѰդµ¤ì¤Æ¤¤¤ë¡¥
** ÊÑ¿ô¡¦Äê¿ô
- Qnil
+Qnil
-Äê¿ô: nil¥ª¥Ö¥¸¥§¥¯¥È
+ Äê¿ô: nil¥ª¥Ö¥¸¥§¥¯¥È
- TRUE
+Qtrue
-Äê¿ô: true¥ª¥Ö¥¸¥§¥¯¥È(¿¿¤Î¥Ç¥Õ¥©¥ë¥ÈÃÍ)
+ Äê¿ô: true¥ª¥Ö¥¸¥§¥¯¥È(¿¿¤Î¥Ç¥Õ¥©¥ë¥ÈÃÍ)
- FALSE
+Qfalse
-Äê¿ô: false¥ª¥Ö¥¸¥§¥¯¥È
+ Äê¿ô: false¥ª¥Ö¥¸¥§¥¯¥È
** C¥Ç¡¼¥¿¤Î¥«¥×¥»¥ë²½
- Data_Wrap_Struct(VALUE class, void (*mark)(), void (*free)(), void *sval)
+Data_Wrap_Struct(VALUE klass, void (*mark)(), void (*free)(), void *sval)
-C¤ÎǤ°Õ¤Î¥Ý¥¤¥ó¥¿¤ò¥«¥×¥»¥ë²½¤·¤¿ruby¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡¥¤³
-¤Î¥Ý¥¤¥ó¥¿¤¬ruby¤«¤é¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¯¤Ê¤Ã¤¿»þ¡¤free¤Ç»ØÄꤷ¤¿
-´Ø¿ô¤¬¸Æ¤Ð¤ì¤ë¡¥¤Þ¤¿¡¤¤³¤Î¥Ý¥¤¥ó¥¿¤Î»Ø¤¹¥Ç¡¼¥¿¤¬Â¾¤Îruby¥ª¥Ö
-¥¸¥§¥¯¥È¤ò»Ø¤·¤Æ¤¤¤ë¾ì¹ç¡¤mark¤Ë»ØÄꤹ¤ë´Ø¿ô¤Ç¥Þ¡¼¥¯¤¹¤ëɬÍ×
-¤¬¤¢¤ë¡¥
+ C¤ÎǤ°Õ¤Î¥Ý¥¤¥ó¥¿¤ò¥«¥×¥»¥ë²½¤·¤¿Ruby¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡¥¤³
+ ¤Î¥Ý¥¤¥ó¥¿¤¬Ruby¤«¤é¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¯¤Ê¤Ã¤¿»þ¡¤free¤Ç»ØÄꤷ¤¿
+ ´Ø¿ô¤¬¸Æ¤Ð¤ì¤ë¡¥¤Þ¤¿¡¤¤³¤Î¥Ý¥¤¥ó¥¿¤Î»Ø¤¹¥Ç¡¼¥¿¤¬Â¾¤ÎRuby¥ª¥Ö
+ ¥¸¥§¥¯¥È¤ò»Ø¤·¤Æ¤¤¤ë¾ì¹ç¡¤mark¤Ë»ØÄꤹ¤ë´Ø¿ô¤Ç¥Þ¡¼¥¯¤¹¤ëɬÍ×
+ ¤¬¤¢¤ë¡¥
- Data_Make_Struct(class, type, mark, free, sval)
+Data_Make_Struct(klass, type, mark, free, sval)
-type·¿¤Î¥á¥â¥ê¤òmalloc¤·¡¤ÊÑ¿ôsval¤ËÂåÆþ¤·¤¿¸å¡¤¤½¤ì¤ò¥«¥×¥»
-¥ë²½¤·¤¿¥Ç¡¼¥¿¤òÊÖ¤¹¥Þ¥¯¥í¡¥
+ type·¿¤Î¥á¥â¥ê¤òmalloc¤·¡¤ÊÑ¿ôsval¤ËÂåÆþ¤·¤¿¸å¡¤¤½¤ì¤ò¥«¥×¥»
+ ¥ë²½¤·¤¿¥Ç¡¼¥¿¤òÊÖ¤¹¥Þ¥¯¥í¡¥
- Data_Get_Struct(data, type, sval)
+Data_Get_Struct(data, type, sval)
-data¤«¤étype·¿¤Î¥Ý¥¤¥ó¥¿¤ò¼è¤ê½Ð¤·ÊÑ¿ôsval¤ËÂåÆþ¤¹¤ë¥Þ¥¯¥í¡¥
+ data¤«¤étype·¿¤Î¥Ý¥¤¥ó¥¿¤ò¼è¤ê½Ð¤·ÊÑ¿ôsval¤ËÂåÆþ¤¹¤ë¥Þ¥¯¥í¡¥
** ·¿¥Á¥§¥Ã¥¯
- TYPE(value)
- FIXNUM_P(value)
- NIL_P(value)
- void Check_Type(VALUE value, int type)
- void Check_SafeStr(VALUE value)
+TYPE(value)
+FIXNUM_P(value)
+NIL_P(value)
+void Check_Type(VALUE value, int type)
+void Check_SafeStr(VALUE value)
** ·¿ÊÑ´¹
- FIX2INT(value)
- INT2FIX(i)
- NUM2INT(value)
- INT2NUM(i)
- NUM2DBL(value)
- float_new(f)
- STR2CSTR(value)
- str_new2(s)
+FIX2INT(value)
+INT2FIX(i)
+NUM2INT(value)
+INT2NUM(i)
+NUM2DBL(value)
+rb_float_new(f)
+STR2CSTR(value)
+rb_str_new2(s)
** ¥¯¥é¥¹/¥â¥¸¥å¡¼¥ëÄêµÁ
- VALUE rb_define_class(char *name, VALUE super)
+VALUE rb_define_class(const char *name, VALUE super)
-super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤ruby¥¯¥é¥¹¤òÄêµÁ¤¹¤ë¡¥
+ super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤Ruby¥¯¥é¥¹¤òÄêµÁ¤¹¤ë¡¥
- VALUE rb_define_class_under(VALUE module, char *name, VALUE super)
+VALUE rb_define_class_under(VALUE module, const char *name, VALUE super)
-super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤ruby¥¯¥é¥¹¤òÄêµÁ¤·¡¤module¤ÎÄê
-¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
+ super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤Ruby¥¯¥é¥¹¤òÄêµÁ¤·¡¤module¤Î
+ Äê¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
- VALUE rb_define_module(char *name)
+VALUE rb_define_module(const char *name)
-¿·¤·¤¤ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¡¥
+ ¿·¤·¤¤Ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¡¥
- VALUE rb_define_module_under(VALUE module, char *name, VALUE super)
+VALUE rb_define_module_under(VALUE module, const char *name, VALUE super)
-¿·¤·¤¤ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤·¡¤module¤ÎÄê¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
+ ¿·¤·¤¤Ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤·¡¤module¤ÎÄê¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
- void rb_include_module(VALUE class, VALUE module)
+void rb_include_module(VALUE klass, VALUE module)
-¥â¥¸¥å¡¼¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë¡¥class¤¬¤¹¤Ç¤Ëmodule¤ò¥¤¥ó¥¯¥ë¡¼
-¥É¤·¤Æ¤¤¤ë»þ¤Ë¤Ï²¿¤â¤·¤Ê¤¤(¿½Å¥¤¥ó¥¯¥ë¡¼¥É¤Î¶Ø»ß)¡¥
+ ¥â¥¸¥å¡¼¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë¡¥class¤¬¤¹¤Ç¤Ëmodule¤ò¥¤¥ó¥¯
+ ¥ë¡¼¥É¤·¤Æ¤¤¤ë»þ¤Ë¤Ï²¿¤â¤·¤Ê¤¤(¿½Å¥¤¥ó¥¯¥ë¡¼¥É¤Î¶Ø»ß)¡¥
- void rb_extend_object(VALUE object, VALUE module)
+void rb_extend_object(VALUE object, VALUE module)
-¥ª¥Ö¥¸¥§¥¯¥È¤ò¥â¥¸¥å¡¼¥ë(¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥á¥½¥Ã¥É)¤Ç³ÈÄ¥¤¹¤ë¡¥
+ ¥ª¥Ö¥¸¥§¥¯¥È¤ò¥â¥¸¥å¡¼¥ë(¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥á¥½¥Ã¥É)¤Ç³ÈÄ¥¤¹¤ë¡¥
** Âç°èÊÑ¿ôÄêµÁ
- void rb_define_variable(char *name, VALUE *var)
+void rb_define_variable(const char *name, VALUE *var)
-ruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ë¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô̾¤¬`$'¤Ç»Ï
-¤Þ¤é¤Ê¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤ë¡¥name¤È¤·¤Æruby¤Î¼±Ê̻ҤȤ·
-¤Æµö¤µ¤ì¤Ê¤¤Ê¸»ú(Î㤨¤Ð` ')¤ò´Þ¤à¾ì¹ç¤Ë¤Ïruby¥×¥í¥°¥é¥à¤«¤é
-¤Ï¸«¤¨¤Ê¤¯¤Ê¤ë¡¥
+ Ruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ë¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô̾¤¬`$'¤Ç
+ »Ï¤Þ¤é¤Ê¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤ë¡¥name¤È¤·¤ÆRuby¤Î¼±ÊÌ»Ò
+ ¤È¤·¤Æµö¤µ¤ì¤Ê¤¤Ê¸»ú(Î㤨¤Ð` ')¤ò´Þ¤à¾ì¹ç¤Ë¤ÏRuby¥×¥í¥°¥é
+ ¥à¤«¤é¤Ï¸«¤¨¤Ê¤¯¤Ê¤ë¡¥
- void rb_define_readonly_variable(char *name, VALUE *var)
+void rb_define_readonly_variable(const char *name, VALUE *var)
-ruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ëread only¤Î¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥read
-only¤Ç¤¢¤ë¤³¤È°Ê³°¤Ïrb_define_variable()¤ÈƱ¤¸¡¥
+ Ruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ëread only¤Î¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥
+ read only¤Ç¤¢¤ë¤³¤È°Ê³°¤Ïrb_define_variable()¤ÈƱ¤¸¡¥
- void rb_define_virtual_variable(char *name,
- VALUE (*getter)(), VALUE (*setter)())
+void rb_define_virtual_variable(const char *name,
+ VALUE (*getter)(), void (*setter)())
-´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ërubyÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ
-¤Ë¤Ïgetter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì¤ë¡¥
+ ´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ëRubyÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿
+ »þ¤Ë¤Ïgetter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì
+ ¤ë¡¥
- void rb_define_hooked_variable(char *name, VALUE *var,
- VALUE (*getter)(), VALUE (*setter)())
+void rb_define_hooked_variable(const char *name, VALUE *var,
+ VALUE (*getter)(), void (*setter)())
-´Ø¿ô¤Ë¤è¤Ã¤Æhook¤Î¤Ä¤±¤é¤ì¤¿¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô¤¬
-»²¾È¤µ¤ì¤¿»þ¤Ë¤Ïgetter¤¬¡¤´Ø¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter
-¤¬¸Æ¤Ð¤ì¤ë¡¥getter¤äsetter¤Ë0¤ò»ØÄꤷ¤¿»þ¤Ë¤Ïhook¤ò»ØÄꤷ¤Ê
-¤¤¤Î¤ÈƱ¤¸»ö¤Ë¤Ê¤ë¡¥
+ ´Ø¿ô¤Ë¤è¤Ã¤Æhook¤Î¤Ä¤±¤é¤ì¤¿¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô
+ ¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ïgetter¤¬¡¤´Ø¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ï
+ setter¤¬¸Æ¤Ð¤ì¤ë¡¥getter¤äsetter¤Ë0¤ò»ØÄꤷ¤¿»þ¤Ë¤Ïhook¤ò
+ »ØÄꤷ¤Ê¤¤¤Î¤ÈƱ¤¸»ö¤Ë¤Ê¤ë¡¥
- void rb_global_variable(VALUE *var)
+void rb_global_variable(VALUE *var)
-GC¤Î¤¿¤á¡¤ruby¥×¥í¥°¥é¥à¤«¤é¤Ï¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¤¤¬, ruby¥ª¥Ö¥¸¥§
-¥¯¥È¤ò´Þ¤àÂç°èÊÑ¿ô¤ò¥Þ¡¼¥¯¤¹¤ë¡¥
+ GC¤Î¤¿¤á¡¤Ruby¥×¥í¥°¥é¥à¤«¤é¤Ï¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¤¤¬, Ruby¥ª¥Ö
+ ¥¸¥§¥¯¥È¤ò´Þ¤àÂç°èÊÑ¿ô¤ò¥Þ¡¼¥¯¤¹¤ë¡¥
-** ¥¯¥é¥¹Äê¿ô
+** Äê¿ô
- void rb_define_const(VALUE class, char *name, VALUE val)
+void rb_define_const(VALUE klass, const char *name, VALUE val)
-¥¯¥é¥¹Äê¿ô¤òÄêµÁ¤¹¤ë¡¥
+ Äê¿ô¤òÄêµÁ¤¹¤ë¡¥
- void rb_define_global_const(char *name, VALUE val)
+void rb_define_global_const(const char *name, VALUE val)
-Âç°èÄê¿ô¤òÄêµÁ¤¹¤ë¡¥
+ Âç°èÄê¿ô¤òÄêµÁ¤¹¤ë¡¥
- rb_define_const(cKernal, name, val)
+ rb_define_const(rb_cObject, name, val)
-¤ÈƱ¤¸°ÕÌ£¡¥
+ ¤ÈƱ¤¸°ÕÌ£¡¥
** ¥á¥½¥Ã¥ÉÄêµÁ
- rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc)
+rb_define_method(VALUE klass, const char *name, VALUE (*func)(), int argc)
+
+ ¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥argc¤Ïself¤ò½ü¤¯°ú¿ô¤Î¿ô¡¥argc¤¬-1¤Î»þ,
+ ´Ø¿ô¤Ë¤Ï°ú¿ô¤Î¿ô(self¤ò´Þ¤Þ¤Ê¤¤)¤òÂè1°ú¿ô, °ú¿ô¤ÎÇÛÎó¤òÂè2
+ °ú¿ô¤È¤¹¤ë·Á¼°¤ÇÍ¿¤¨¤é¤ì¤ë(Âè3°ú¿ô¤Ïself)¡¥argc¤¬-2¤Î»þ,
+ Âè1°ú¿ô¤¬self, Âè2°ú¿ô¤¬args(args¤Ï°ú¿ô¤ò´Þ¤àRuby¤ÎÇÛÎó)¤È
+ ¤¤¤¦·Á¼°¤ÇÍ¿¤¨¤é¤ì¤ë¡¥
+
+rb_define_private_method(VALUE klass, const char *name, VALUE (*func)(), int argc)
-¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥argc¤Ïself¤ò½ü¤¯°ú¿ô¤Î¿ô¡¥argc¤¬-1¤Î»þ,
-´Ø¿ô¤Ë¤Ï°ú¿ô¤Î¿ô(self¤ò´Þ¤Þ¤Ê¤¤)¤òÂè1°ú¿ô, °ú¿ô¤ÎÇÛÎó¤òÂè2°ú
-¿ô¤È¤¹¤ë·Á¼°¤ÇÍ¿¤¨¤é¤ì¤ë(Âè3°ú¿ô¤Ïself)¡¥argc¤¬-2¤Î»þ, Âè1°ú
-¿ô¤¬self, Âè2°ú¿ô¤¬args(args¤Ï°ú¿ô¤ò´Þ¤àruby¤ÎÇÛÎó)¤È¤¤¤¦·Á
-¼°¤ÇÍ¿¤¨¤é¤ì¤ë¡¥
+ private¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¡¥
- rb_define_private_method(VALUE class, char *name, VALUE (*func)(), int argc)
+rb_define_singleton_method(VALUE klass, const char *name, VALUE (*func)(), int argc)
-private¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¡¥
+ ÆÃ°Û¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¡¥
- rb_define_singleton_method(VALUE class, char *name, VALUE (*func)(), int argc)
+rb_scan_args(int argc, VALUE *argv, const char *fmt, ...)
-ÆÃ°Û¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¡¥
+ argc, argv·Á¼°¤ÇÍ¿¤¨¤é¤ì¤¿°ú¿ô¤òʬ²ò¤¹¤ë¡¥fmt¤Ïɬ¿Ü°ú¿ô¤Î¿ô,
+ Éղðú¿ô¤Î¿ô, »Ä¤ê¤Î°ú¿ô¤¬¤¢¤ë¤«¤ò»ØÄꤹ¤ëʸ»úÎó¤Ç, "¿ô»ú
+ ¿ô»ú*"¤È¤¤¤¦·Á¼°¤Ç¤¢¤ë¡¥ 2 ÈÖÌܤοô»ú¤È"*"¤Ï¤½¤ì¤¾¤ì¾Êά²Ä
+ ǽ¤Ç¤¢¤ë¡¥É¬¿Ü°ú¿ô¤¬°ì¤Ä¤â¤Ê¤¤¾ì¹ç¤Ï0¤ò»ØÄꤹ¤ë¡¥Âè3°ú¿ô°Ê
+ ¹ß¤ÏÊÑ¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç, ³ºÅö¤¹¤ëÍ×ÁǤ¬¤½¤ÎÊÑ¿ô¤Ë³ÊǼ¤µ¤ì¤ë¡¥
+ Éղðú¿ô¤ËÂбþ¤¹¤ë°ú¿ô¤¬Í¿¤¨¤é¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤ÏÊÑ¿ô¤ËQnil¤¬
+ ÂåÆþ¤µ¤ì¤ë¡¥
- rb_scan_args(int atgc, VALUE *argv, char *fmt, ...)
+** Ruby¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·
-argc,argv·Á¼°¤ÇÍ¿¤¨¤é¤ì¤¿°ú¿ô¤òʬ²ò¤¹¤ë¡¥fmt¤Ïɬ¿Ü°ú¿ô¤Î¿ô,
-Éղðú¿ô¤Î¿ô, »Ä¤ê¤Î°ú¿ô¤¬¤¢¤ë¤«¤ò»ØÄꤹ¤ëʸ»úÎó¤Ç, "¿ô»ú¿ô
-»ú*"¤È¤¤¤¦·Á¼°¤Ç¤¢¤ë¡¥ 2 ÈÖÌܤοô»ú¤È"*"¤Ï¤½¤ì¤¾¤ì¾Êά²Äǽ¤Ç
-¤¢¤ë¡¥É¬¿Ü°ú¿ô¤¬°ì¤Ä¤â¤Ê¤¤¾ì¹ç¤Ï0¤ò»ØÄꤹ¤ë¡¥Âè3°ú¿ô°Ê¹ß¤ÏÊÑ
-¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç, ³ºÅö¤¹¤ëÍ×ÁǤ¬¤½¤ÎÊÑ¿ô¤Ë³ÊǼ¤µ¤ì¤ë¡¥Éղðú
-¿ô¤ËÂбþ¤¹¤ë°ú¿ô¤¬Í¿¤¨¤é¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤ÏÊÑ¿ô¤ËQnil¤¬ÂåÆþ¤µ¤ì
-¤ë¡¥
+VALUE rb_funcall(VALUE recv, ID mid, int narg, ...)
-** ruby¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·
+ ¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¡¥Ê¸»úÎ󤫤émid¤òÆÀ¤ë¤¿¤á¤Ë¤Ïrb_intern()¤ò
+ »È¤¦¡¥
- VALUE rb_funcall(VALUE recv, ID mid, int narg, ...)
+VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)
-¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¡¥Ê¸»úÎ󤫤émid¤òÆÀ¤ë¤¿¤á¤Ë¤Ïrb_intern()¤ò»È¤¦¡¥
+ ¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¡¥°ú¿ô¤òargc, argv·Á¼°¤ÇÅϤ¹¡¥
- VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)
+VALUE rb_eval_string(const char *str)
-¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¡¥°ú¿ô¤òargc,argv·Á¼°¤ÇÅϤ¹¡¥
+ ʸ»úÎó¤òRuby¥¹¥¯¥ê¥×¥È¤È¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¡¦¼Â¹Ô¤¹¤ë¡¥
- VALUE rb_eval_string(char *str)
+ID rb_intern(const char *name)
-ʸ»úÎó¤òruby¤È¥¹¥¯¥ê¥×¥È¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¡¦¼Â¹Ô¤¹¤ë¡¥
+ ʸ»úÎó¤ËÂбþ¤¹¤ëID¤òÊÖ¤¹¡¥
- ID rb_intern(char *name)
+char *rb_id2name(ID id)
-ʸ»úÎó¤ËÂбþ¤¹¤ëID¤òÊÖ¤¹¡¥
+ ID¤ËÂбþ¤¹¤ëʸ»úÎó¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥
- char *rb_id2name(ID id)
+char *rb_class2name(VALUE klass)
-ID¤ËÂбþ¤¹¤ëʸ»úÎó¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥
+ ¥¯¥é¥¹¤Î̾Á°¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥¥¯¥é¥¹¤¬Ì¾Á°¤ò»ý¤¿¤Ê¤¤»þ¤Ë¤Ï,
+ ÁÄÀè¤òÁ̤äÆÌ¾Á°¤ò»ý¤Ä¥¯¥é¥¹¤Î̾Á°¤òÊÖ¤¹¡¥
- char *rb_class2name(VALUE class)
+int rb_respond_to(VALUE obj, ID id)
-class¤Î̾Á°¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥class¤¬Ì¾Á°¤ò»ý¤¿¤Ê¤¤»þ¤Ë¤Ï,
-ÁÄÀè¤òÁ̤äÆÌ¾Á°¤ò»ý¤Ä¥¯¥é¥¹¤Î̾Á°¤òÊÖ¤¹¡¥
+ obj¤¬id¤Ç¼¨¤µ¤ì¤ë¥á¥½¥Ã¥É¤ò»ý¤Ä¤«¤É¤¦¤«¤òÊÖ¤¹¡£
** ¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô
- VALUE rb_iv_get(VALUE obj, char *name)
+VALUE rb_iv_get(VALUE obj, const char *name)
-obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ÎÃͤòÆÀ¤ë¡¥`@'¤Ç»Ï¤Þ¤é¤Ê¤¤¥¤¥ó¥¹¥¿¥ó¥¹
-ÊÑ¿ô¤Ï ruby¥×¥í¥°¥é¥à¤«¤é¥¢¥¯¥»¥¹¤Ç¤­¤Ê¤¤¡Ö±£¤ì¤¿¡×¥¤¥ó¥¹¥¿
-¥ó¥¹ÊÑ¿ô¤Ë¤Ê¤ë¡¥
+ obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ÎÃͤòÆÀ¤ë¡¥`@'¤Ç»Ï¤Þ¤é¤Ê¤¤¥¤¥ó¥¹¥¿¥ó
+ ¥¹ÊÑ¿ô¤Ï Ruby¥×¥í¥°¥é¥à¤«¤é¥¢¥¯¥»¥¹¤Ç¤­¤Ê¤¤¡Ö±£¤ì¤¿¡×¥¤¥ó
+ ¥¹¥¿¥ó¥¹ÊÑ¿ô¤Ë¤Ê¤ë¡¥Äê¿ô¤ÏÂçʸ»ú¤Î̾Á°¤ò»ý¤Ä¥¯¥é¥¹(¤Þ¤¿¤Ï
+ ¥â¥¸¥å¡¼¥ë)¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤È¤·¤Æ¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¡¥
- VALUE rb_iv_set(VALUE obj, char *name, VALUE val)
+VALUE rb_iv_set(VALUE obj, const char *name, VALUE val)
-obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤òval¤Ë¥»¥Ã¥È¤¹¤ë¡¥
+ obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤òval¤Ë¥»¥Ã¥È¤¹¤ë¡¥
** À©¸æ¹½Â¤
- VALUE rb_iterate(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)
+VALUE rb_iterate(VALUE (*func1)(), VALUE arg1, VALUE (*func2)(), VALUE arg2)
-func2¤ò¥Ö¥í¥Ã¥¯¤È¤·¤ÆÀßÄꤷ, func1¤ò¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ö¡¥
-func1¤Ë¤Ï arg1¤¬°ú¿ô¤È¤·¤ÆÅϤµ¤ì, func2¤Ë¤ÏÂè1°ú¿ô¤Ë¥¤¥Æ¥ì¡¼
-¥¿¤«¤éÍ¿¤¨¤é¤ì¤¿ÃÍ, Âè2°ú¿ô¤Ëarg2¤¬ÅϤµ¤ì¤ë¡¥
+ func2¤ò¥Ö¥í¥Ã¥¯¤È¤·¤ÆÀßÄꤷ, func1¤ò¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ö¡¥
+ func1¤Ë¤Ï arg1¤¬°ú¿ô¤È¤·¤ÆÅϤµ¤ì, func2¤Ë¤ÏÂè1°ú¿ô¤Ë¥¤¥Æ¥ì¡¼
+ ¥¿¤«¤éÍ¿¤¨¤é¤ì¤¿ÃÍ, Âè2°ú¿ô¤Ëarg2¤¬ÅϤµ¤ì¤ë¡¥
- VALUE rb_yield(VALUE val)
+VALUE rb_yield(VALUE val)
-val¤òÃͤȤ·¤Æ¥¤¥Æ¥ì¡¼¥¿¥Ö¥í¥Ã¥¯¤ò¸Æ¤Ó½Ð¤¹¡¥
+ val¤òÃͤȤ·¤Æ¥¤¥Æ¥ì¡¼¥¿¥Ö¥í¥Ã¥¯¤ò¸Æ¤Ó½Ð¤¹¡¥
- VALUE rb_rescue(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)
+VALUE rb_rescue(VALUE (*func1)(), VALUE arg1, VALUE (*func2)(), VALUE arg2)
-´Ø¿ôfunc1¤òarg1¤ò°ú¿ô¤Ë¸Æ¤Ó½Ð¤¹¡¥func1¤Î¼Â¹ÔÃæ¤ËÎã³°¤¬È¯À¸¤·
-¤¿»þ¤Ë¤Ï func2¤òarg2¤ò°ú¿ô¤È¤·¤Æ¸Æ¤Ö¡¥Ìá¤êÃͤÏÎã³°¤¬È¯À¸¤·¤Ê
-¤«¤Ã¤¿»þ¤Ïfunc1¤ÎÌá¤êÃÍ, Îã³°¤¬È¯À¸¤·¤¿»þ¤Ë¤Ïfunc2¤ÎÌá¤êÃͤÇ
-¤¢¤ë¡¥
+ ´Ø¿ôfunc1¤òarg1¤ò°ú¿ô¤Ë¸Æ¤Ó½Ð¤¹¡¥func1¤Î¼Â¹ÔÃæ¤ËÎã³°¤¬È¯À¸
+ ¤·¤¿»þ¤Ë¤Ï func2¤òarg2¤ò°ú¿ô¤È¤·¤Æ¸Æ¤Ö¡¥Ìá¤êÃͤÏÎã³°¤¬È¯À¸
+ ¤·¤Ê¤«¤Ã¤¿»þ¤Ïfunc1¤ÎÌá¤êÃÍ, Îã³°¤¬È¯À¸¤·¤¿»þ¤Ë¤Ïfunc2¤ÎÌá
+ ¤êÃͤǤ¢¤ë¡¥
- VALUE rb_ensure(VALUE (*func1)(), void *arg1, void (*func2)(), void *arg2)
+VALUE rb_ensure(VALUE (*func1)(), VALUE arg1, void (*func2)(), VALUE arg2)
-´Ø¿ôfunc1¤òarg1¤ò°ú¿ô¤È¤·¤Æ¼Â¹Ô¤·, ¼Â¹Ô½ªÎ»¸å(¤¿¤È¤¨Îã³°¤¬È¯
-À¸¤·¤Æ¤â) func2¤òarg2¤ò°ú¿ô¤È¤·¤Æ¼Â¹Ô¤¹¤ë¡¥Ìá¤êÃͤÏfunc1¤ÎÌá
-¤êÃͤǤ¢¤ë(Îã³°¤¬È¯À¸¤·¤¿»þ¤ÏÌá¤é¤Ê¤¤)¡¥
+ ´Ø¿ôfunc1¤òarg1¤ò°ú¿ô¤È¤·¤Æ¼Â¹Ô¤·, ¼Â¹Ô½ªÎ»¸å(¤¿¤È¤¨Îã³°¤¬
+ ȯÀ¸¤·¤Æ¤â) func2¤òarg2¤ò°ú¿ô¤È¤·¤Æ¼Â¹Ô¤¹¤ë¡¥Ìá¤êÃͤÏfunc1
+ ¤ÎÌá¤êÃͤǤ¢¤ë(Îã³°¤¬È¯À¸¤·¤¿»þ¤ÏÌá¤é¤Ê¤¤)¡¥
** Îã³°¡¦¥¨¥é¡¼
- void Warning(char *fmt, ...)
+void rb_warning(const char *fmt, ...)
-verbose»þ¤Ëɸ½à¥¨¥é¡¼½ÐÎϤ˷ٹð¾ðÊó¤òɽ¼¨¤¹¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
+ rb_verbose»þ¤Ëɸ½à¥¨¥é¡¼½ÐÎϤ˷ٹð¾ðÊó¤òɽ¼¨¤¹¤ë¡¥°ú¿ô¤Ï
+ printf()¤ÈƱ¤¸¡¥
- void Fail(char *fmt, ...)
+void rb_raise(rb_eRuntimeError, const char *fmt, ...)
-RuntimeErrorÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
+ RuntimeErrorÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
- void Raise(VALUE exception, char *fmt, ...)
+void rb_raise(VALUE exception, const char *fmt, ...)
-exception¤Ç»ØÄꤷ¤¿Îã³°¤òȯÀ¸¤µ¤»¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
+ exception¤Ç»ØÄꤷ¤¿Îã³°¤òȯÀ¸¤µ¤»¤ë¡¥fmt°Ê²¼¤Î°ú¿ô¤Ï
+ printf()¤ÈƱ¤¸¡¥
- void Fatal(char *fmt, ...)
+void rb_fatal(const char *fmt, ...)
-Ã×̿ŪÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥Ä̾ï¤ÎÎã³°½èÍý¤Ï¹Ô¤Ê¤ï¤ì¤º, ¥¤¥ó¥¿¡¼
-¥×¥ê¥¿¤¬½ªÎ»¤¹¤ë(¤¿¤À¤·ensure¤Ç»ØÄꤵ¤ì¤¿¥³¡¼¥É¤Ï½ªÎ»Á°¤Ë¼Â
-¹Ô¤µ¤ì¤ë)¡¥
+ Ã×̿ŪÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥Ä̾ï¤ÎÎã³°½èÍý¤Ï¹Ô¤Ê¤ï¤ì¤º, ¥¤¥ó¥¿¡¼
+ ¥×¥ê¥¿¤¬½ªÎ»¤¹¤ë(¤¿¤À¤·ensure¤Ç»ØÄꤵ¤ì¤¿¥³¡¼¥É¤Ï½ªÎ»Á°¤Ë
+ ¼Â¹Ô¤µ¤ì¤ë)¡¥
- void Bug(char *fmt, ...)
+void rb_bug(const char *fmt, ...)
-¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ê¤É¥×¥í¥°¥é¥à¤Î¥Ð¥°¤Ç¤·¤«È¯À¸¤¹¤ë¤Ï¤º¤Î¤Ê¤¤¾õ
-¶·¤Î»þ¸Æ¤Ö¡¥¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ï¥³¥¢¥À¥ó¥×¤·Ä¾¤Á¤Ë½ªÎ»¤¹¤ë¡¥Îã³°
-½èÍý¤Ï°ìÀڹԤʤï¤ì¤Ê¤¤¡¥
+ ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ê¤É¥×¥í¥°¥é¥à¤Î¥Ð¥°¤Ç¤·¤«È¯À¸¤¹¤ë¤Ï¤º¤Î¤Ê¤¤
+ ¾õ¶·¤Î»þ¸Æ¤Ö¡¥¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ï¥³¥¢¥À¥ó¥×¤·Ä¾¤Á¤Ë½ªÎ»¤¹¤ë¡¥
+ Îã³°½èÍý¤Ï°ìÀڹԤʤï¤ì¤Ê¤¤¡¥
-** ruby¤Î½é´ü²½¡¦¼Â¹Ô
+** Ruby¤Î½é´ü²½¡¦¼Â¹Ô
-ruby¤ò¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤ËËä¤á¹þ¤à¾ì¹ç¤Ë¤Ï°Ê²¼¤Î¥¤¥ó¥¿¥Õ¥§¡¼¥¹
-¤ò»È¤¦¡¥Ä̾ï¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë¤ÏɬÍפʤ¤¡¥
+Ruby¤ò¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤ËËä¤á¹þ¤à¾ì¹ç¤Ë¤Ï°Ê²¼¤Î¥¤¥ó¥¿¥Õ¥§¡¼¥¹
+¤ò»È¤¦¡¥Ä̾ï¤Î³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ë¤ÏɬÍפʤ¤¡¥
- void ruby_init(int argc, char **argv, char **envp)
+void ruby_init()
-ruby¥¤¥ó¥¿¥×¥ê¥¿¤Î½é´ü²½¤ò¹Ô¤Ê¤¦¡¥
+ Ruby¥¤¥ó¥¿¥×¥ê¥¿¤Î½é´ü²½¤ò¹Ô¤Ê¤¦¡¥
- void ruby_run()
+void ruby_options(int argc, char **argv)
-ruby¥¤¥ó¥¿¥×¥ê¥¿¤ò¼Â¹Ô¤¹¤ë¡¥
+ Ruby¥¤¥ó¥¿¥×¥ê¥¿¤Î¥³¥Þ¥ó¥É¥é¥¤¥ó°ú¿ô¤Î½èÍý¤ò¹Ô¤Ê¤¦¡¥
- void ruby_script(char *name)
+void ruby_run()
-ruby¤Î¥¹¥¯¥ê¥×¥È̾($0)¤òÀßÄꤹ¤ë¡¥
+ Ruby¥¤¥ó¥¿¥×¥ê¥¿¤ò¼Â¹Ô¤¹¤ë¡¥
+
+void ruby_script(char *name)
+
+ Ruby¤Î¥¹¥¯¥ê¥×¥È̾($0)¤òÀßÄꤹ¤ë¡¥
Appendix B. extconf.rb¤Ç»È¤¨¤ë´Ø¿ô¤¿¤Á
@@ -1117,27 +1138,47 @@ Appendix B. extconf.rb¤Ç»È¤¨¤ë´Ø¿ô¤¿¤Á
extconf.rb¤ÎÃæ¤Ç¤ÏÍøÍѲÄǽ¤Ê¥³¥ó¥Ñ¥¤¥ë¾ò·ï¥Á¥§¥Ã¥¯¤Î´Ø¿ô¤Ï°Ê
²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥
- have_library(lib, func)
+have_library(lib, func)
+
+ ´Ø¿ôfunc¤òÄêµÁ¤·¤Æ¤¤¤ë¥é¥¤¥Ö¥é¥êlib¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥
+ ¥é¥¤¥Ö¥é¥ê¤¬Â¸ºß¤¹¤ë»þ¡¤true¤òÊÖ¤¹¡¥
+
+find_library(lib, func, path...)
+
+ ´Ø¿ôfunc¤òÄêµÁ¤·¤Æ¤¤¤ë¥é¥¤¥Ö¥é¥êlib¤Î¸ºß¤ò -Lpath ¤òÄɲÃ
+ ¤·¤Ê¤¬¤é¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥é¥¤¥Ö¥é¥ê¤¬¸«ÉÕ¤«¤Ã¤¿»þ¡¤true¤òÊÖ¤¹¡¥
+
+have_func(func, header)
+
+ ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ëheader¤ò¥¤¥ó¥¯¥ë¡¼¥É¤·¤Æ´Ø¿ôfunc¤Î¸ºß¤ò¥Á¥§¥Ã
+ ¥¯¤¹¤ë¡¥func¤¬É¸½à¤Ç¤Ï¥ê¥ó¥¯¤µ¤ì¤Ê¤¤¥é¥¤¥Ö¥é¥êÆâ¤Î¤â¤Î¤Ç¤¢
+ ¤ë»þ¤Ë¤ÏÀè¤Ëhave_library¤Ç¤½¤Î¥é¥¤¥Ö¥é¥ê¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤ª¤¯
+ »ö¡¥´Ø¿ô¤¬Â¸ºß¤¹¤ë»þtrue¤òÊÖ¤¹¡¥
+
+have_header(header)
-´Ø¿ôfunc¤òÄêµÁ¤·¤Æ¤¤¤ë¥é¥¤¥Ö¥é¥êlib¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥é
-¥¤¥Ö¥é¥ê¤¬Â¸ºß¤¹¤ë»þ¡¤TRUE¤òÊÖ¤¹¡¥
+ ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹
+ ¤ë»þtrue¤òÊÖ¤¹¡¥
- have_func(func)
+create_makefile(target)
-´Ø¿ôfunc¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥func¤¬É¸½à¤Ç¤Ï¥ê¥ó¥¯¤µ¤ì¤Ê¤¤¥é
-¥¤¥Ö¥é¥êÆâ¤Î¤â¤Î¤Ç¤¢¤ë»þ¤Ë¤ÏÀè¤Ëhave_library¤Ç¤½¤Î¥é¥¤¥Ö¥é¥ê
-¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤ª¤¯»ö¡¥´Ø¿ô¤¬Â¸ºß¤¹¤ë»þTRUE¤òÊÖ¤¹¡¥
+ ³ÈÄ¥¥é¥¤¥Ö¥é¥êÍѤÎMakefile¤òÀ¸À®¤¹¤ë¡¥¤³¤Î´Ø¿ô¤ò¸Æ¤Ð¤Ê¤±¤ì
+ ¤Ð¤½¤Î¥é¥¤¥Ö¥é¥ê¤Ï¥³¥ó¥Ñ¥¤¥ë¤µ¤ì¤Ê¤¤¡¥target¤Ï¥â¥¸¥å¡¼¥ë̾
+ ¤òɽ¤¹¡¥
- have_header(header)
+with_config(withval[, default=nil])
-¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ë
-»þTRUE¤òÊÖ¤¹¡¥
+ ¥³¥Þ¥ó¥É¥é¥¤¥ó¾å¤Î--with-<withval>¤Ç»ØÄꤵ¤ì¤¿¥ª¥×¥·¥ç¥óÃͤòÆÀ¤ë¡¥
- create_makefile(target)
+dir_config(target[, default_dir])
+dir_config(target[, default_include, default_lib])
-³ÈÄ¥¥â¥¸¥å¡¼¥ëÍѤÎMakefile¤òÀ¸À®¤¹¤ë¡¥¤³¤Î´Ø¿ô¤ò¸Æ¤Ð¤Ê¤±¤ì¤Ð
-¤½¤Î¥â¥¸¥å¡¼¥ë¤Ï¥³¥ó¥Ñ¥¤¥ë¤µ¤ì¤Ê¤¤¡¥target¤Ï¥â¥¸¥å¡¼¥ë̾¤òɽ
-¤¹¡¥
+ ¥³¥Þ¥ó¥É¥é¥¤¥ó¾å¤Î--with-<target>-dir, --with-<target>-include,
+ --with-<target>-lib¤Î¤¤¤º¤ì¤«¤Ç»ØÄꤵ¤ì¤ë¥Ç¥£¥ì¥¯¥È¥ê¤ò
+ $CFLAGS ¤ä $LDFLAGS ¤ËÄɲ乤롥--with-<target>-dir=/path¤Ï
+ --with-<target>-include=/path/include --with-<target>-lib=/path/lib
+ ¤ÈÅù²Á¤Ç¤¢¤ë¡¥Äɲ䵤줿 include ¥Ç¥£¥ì¥¯¥È¥ê¤È lib ¥Ç¥£¥ì¥¯¥È¥ê¤Î
+ ÇÛÎó¤òÊÖ¤¹¡¥ ([include_dir, lib_dir])
/*
* Local variables:
diff --git a/README.jp b/README.jp
index 00822a3658..9af1f15bb5 100644
--- a/README.jp
+++ b/README.jp
@@ -5,12 +5,12 @@ Ruby¤ÏºÇ½é¤«¤é½ã¿è¤Ê¥ª¥Ö¥¸¥§¥¯¥È»Ø¸þ¸À¸ì¤È¤·¤ÆÀ߷פµ¤ì¤Æ¤¤¤Þ
¤¹¤«¤é¡¤¥ª¥Ö¥¸¥§¥¯¥È»Ø¸þ¥×¥í¥°¥é¥ß¥ó¥°¤ò¼ê·Ú¤Ë¹Ô¤¦»ö¤¬½ÐÍè¤Þ
¤¹¡¥¤â¤Á¤í¤óÄ̾ï¤Î¼ê³¤­·¿¤Î¥×¥í¥°¥é¥ß¥ó¥°¤â²Äǽ¤Ç¤¹¡¥
-Ruby¤Ï¥Æ¥­¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ
+Ruby¤Ï¥Æ¥­¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤Perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ
¤Ç¤¹¡¥¤µ¤é¤Ë¥·¥ó¥×¥ë¤Êʸˡ¤È¡¤Îã³°½èÍý¤ä¥¤¥Æ¥ì¡¼¥¿¤Ê¤É¤Îµ¡¹½
¤Ë¤è¤Ã¤Æ¡¤¤è¤êʬ¤«¤ê¤ä¤¹¤¤¥×¥í¥°¥é¥ß¥ó¥°¤¬½ÐÍè¤Þ¤¹¡¥
-* Ruby¤ÎÆÃĹ¡¥
+* Ruby¤ÎÆÃĹ
+ ¥·¥ó¥×¥ë¤Êʸˡ
+ ÉáÄ̤Υª¥Ö¥¸¥§¥¯¥È»Ø¸þµ¡Ç½(¥¯¥é¥¹¡¤¥á¥½¥Ã¥É¥³¡¼¥ë¤Ê¤É)
@@ -20,7 +20,8 @@ Ruby¤Ï¥Æ¥­¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ
+ ¥¤¥Æ¥ì¡¼¥¿¤È¥¯¥í¡¼¥¸¥ã
+ ¥¬¡¼¥Ù¡¼¥¸¥³¥ì¥¯¥¿
+ ¥À¥¤¥Ê¥ß¥Ã¥¯¥í¡¼¥Ç¥£¥ó¥° (¥¢¡¼¥­¥Æ¥¯¥Á¥ã¤Ë¤è¤ë)
- + °Ü¿¢À­¤¬¹â¤¤¡¥Â¿¤¯¤ÎUNIX¾å¤Çư¤¯
+ + °Ü¿¢À­¤¬¹â¤¤¡¥Â¿¤¯¤ÎUNIX¾å¤Çư¤¯¤À¤±¤Ç¤Ê¤¯¡¤DOS¤äWindows¡¤
+ Mac¡¤BeOS¤Ê¤É¤Î¾å¤Ç¤âư¤¯
* Æþ¼êË¡
@@ -31,37 +32,64 @@ Ruby¤Ï¥Æ¥­¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ
ftp://ftp.netlab.co.jp/pub/lang/ruby/
+** CVS¤Ç
+
+ $ cvs -d :pserver:anonymous@cvs.ruby-lang.org:/src login
+ (Logging in to anonymous@cvs.ruby-lang.org)
+ CVS password: anonymous
+ $ cvs -z4 -d :pserver:anonymous@cvs.ruby-lang.org:src checkout ruby
+
* ¥Û¡¼¥à¥Ú¡¼¥¸
- Ruby¤Î¥Û¡¼¥à¥Ú¡¼¥¸¤ÎURL¤Ï
+Ruby¤Î¥Û¡¼¥à¥Ú¡¼¥¸¤ÎURL¤Ï
+
+ http://www.ruby-lang.org/
+
+¤Ç¤¹¡¥
+
- http://www.netlab.co.jp/ruby/jp/
+* ¥á¡¼¥ê¥ó¥°¥ê¥¹¥È
- ¤Ç¤¹¡¥
+Ruby¤Î¥á¡¼¥ê¥ó¥°¥ê¥¹¥È¤¬¤¢¤ê¤Þ¤¹¡£»²²Ã´õ˾¤ÎÊý¤Ï
+ ruby-list-ctl@ruby-lang.org
-* ¥á¥¤¥ê¥ó¥°¥ê¥¹¥È
+¤Þ¤ÇËÜʸ¤Ë
- Ruby¤Ë´Ø¤ï¤ëÏÃÂê¤Î¤¿¤á¤Î¥á¥¤¥ê¥ó¥°¥ê¥¹¥È¤ò³«Àߤ·¤Þ¤·¤¿¡¥¥¢
- ¥É¥ì¥¹¤Ï
+ subscribe YourFirstName YourFamilyName
+
+¤È½ñ¤¤¤ÆÁ÷¤Ã¤Æ²¼¤µ¤¤¡£
- ruby-list@netlab.co.jp
+Ruby³«È¯¼Ô¸þ¤±¥á¡¼¥ê¥ó¥°¥ê¥¹¥È¤â¤¢¤ê¤Þ¤¹¡£¤³¤Á¤é¤Ç¤Ïruby¤Î¥Ð
+¥°¡¢¾­Íè¤Î»ÅÍͳÈÄ¥¤Ê¤É¼ÂÁõ¾å¤ÎÌäÂê¤Ë¤Ä¤¤¤ÆµÄÏÀ¤µ¤ì¤Æ¤¤¤Þ¤¹¡£
+»²²Ã´õ˾¤ÎÊý¤Ï
- ¤Ç¤¹¡¥¤³¤Î¥¢¥É¥ì¥¹¤Ë¥á¥¤¥ë¤òÁ÷¤ì¤Ð¡¤¼«Æ°Åª¤ËÅÐÏ¿¤µ¤ì¤Þ¤¹¡¥
+ ruby-dev-ctl@ruby-lang.org
+
+¤Þ¤Çruby-list¤ÈƱÍͤÎÊýË¡¤Ç¥á¡¼¥ë¤·¤Æ¤¯¤À¤µ¤¤¡£
+
+Ruby³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë¤Ä¤¤¤ÆÏ䷹礦ruby-ext¥á¡¼¥ê¥ó¥°¥ê¥¹¥È¤È
+¿ô³Ø´Ø·¸¤ÎÏÃÂê¤Ë¤Ä¤¤¤ÆÏ䷹礦ruby-math¥á¡¼¥ê¥ó¥°¥ê¥¹¥È¤È
+±Ñ¸ì¤ÇÏ䷹礦ruby-talk¥á¡¼¥ê¥ó¥°¥ê¥¹¥È¤â¤¢¤ê¤Þ¤¹¡£»²²ÃÊýË¡
+¤Ï¤É¤ì¤âƱ¤¸¤Ç¤¹¡£
* ¥³¥ó¥Ñ¥¤¥ë¡¦¥¤¥ó¥¹¥È¡¼¥ë
°Ê²¼¤Î¼ê½ç¤Ç¹Ô¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
- 1. configure¤ò¼Â¹Ô¤·¤ÆMakefile¤Ê¤É¤òÀ¸À®¤¹¤ë
+ 1. ¤â¤·configure¥Õ¥¡¥¤¥ë¤¬¸«¤Ä¤«¤é¤Ê¤¤¡¢¤â¤·¤¯¤Ï
+ configure.in¤è¤ê¸Å¤¤¤è¤¦¤Ê¤é¡¢autoconf¤ò¼Â¹Ô¤·¤Æ
+ ¿·¤·¤¯configure¤òÀ¸À®¤¹¤ë
- 2. (ɬÍפʤé¤Ð)defines.h¤òÊÔ½¸¤¹¤ë
+ 2. configure¤ò¼Â¹Ô¤·¤ÆMakefile¤Ê¤É¤òÀ¸À®¤¹¤ë
+
+ 3. (ɬÍפʤé¤Ð)defines.h¤òÊÔ½¸¤¹¤ë
¿ʬ¡¤É¬Í×̵¤¤¤È»×¤¤¤Þ¤¹¡¥
- 3. (ɬÍפʤé¤Ð)ext/Setup¤ËÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ò
+ 4. (ɬÍפʤé¤Ð)ext/Setup¤ËÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë³ÈÄ¥¥â¥¸¥å¡¼¥ë¤ò
»ØÄꤹ¤ë
ext/Setup¤Ëµ­½Ò¤·¤¿¥â¥¸¥å¡¼¥ë¤ÏÀÅŪ¤Ë¥ê¥ó¥¯¤µ¤ì¤Þ¤¹¡¥
@@ -72,14 +100,16 @@ Ruby¤Ï¥Æ¥­¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ
³ÈÄ¥¥â¥¸¥å¡¼¥ë¤òÍøÍѤ¹¤ë¤¿¤á¤Ë¤Ï¡¤¤¢¤é¤«¤¸¤áÀÅŪ¤Ë¥ê¥ó
¥¯¤·¤Æ¤ª¤¯É¬Íפ¬¤¢¤ê¤Þ¤¹¡¥
- 4. make¤ò¼Â¹Ô¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¤¹¤ë
+ 5. make¤ò¼Â¹Ô¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¤¹¤ë
- 5. make test¤Ç¥Æ¥¹¥È¤ò¹Ô¤¦¡¥
+ 6. make test¤Ç¥Æ¥¹¥È¤ò¹Ô¤¦¡¥
¡Ötest succeeded¡×¤Èɽ¼¨¤µ¤ì¤ì¤ÐÀ®¸ù¤Ç¤¹¡¥¤¿¤À¤·¥Æ¥¹¥È
¤ËÀ®¸ù¤·¤Æ¤â´°àú¤À¤ÈÊݾڤµ¤ì¤Æ¤¤¤ëÌõ¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡¥
- 6. make install
+ 7. make install
+
+ root¤Çºî¶È¤¹¤ëɬÍפ¬¤¢¤ë¤«¤â¤·¤ì¤Þ¤»¤ó¡¥
¤â¤·¡¤¥³¥ó¥Ñ¥¤¥ë»þ¤Ë¥¨¥é¡¼¤¬È¯À¸¤·¤¿¾ì¹ç¤Ë¤Ï¥¨¥é¡¼¤Î¥í¥°¤È¥Þ
¥·¥ó¡¤OS¤Î¼ïÎà¤ò´Þ¤à¤Ç¤­¤ë¤À¤±¾Ü¤·¤¤¥ì¥Ý¡¼¥È¤òºî¼Ô¤ËÁ÷¤Ã¤Æ¤¯
@@ -92,7 +122,7 @@ UNIX¤Ç¤¢¤ì¤Ðconfigure¤¬¤Û¤È¤ó¤É¤Îº¹°Û¤òµÛ¼ý¤·¤Æ¤¯¤ì¤ë¤Ï¤º¤Ç
¤¹¤¬¡¤»×¤ï¤Ì¸«Íî¤È¤·¤¬¤¢¤Ã¤¿¾ì¹ç(¤¢¤ë¤Ë°ã¤¤¤Ê¤¤)¡¤ºî¼Ô¤Ë¤½¤Î
¤³¤È¤ò¥ì¥Ý¡¼¥È¤¹¤ì¤Ð¡¤²ò·è¤Ç¤­¤ë¤«¤âÃΤì¤Þ¤»¤ó¡¥
-¥¢¡¼¥¯¥Æ¥¯¥Á¥ã¤Ë¤â¤Ã¤È¤â°Í¸¤¹¤ë¤Î¤ÏGCÉô¤Ç¤¹¡¥Ruby¤ÎGC¤ÏÂоÝ
+¥¢¡¼¥­¥Æ¥¯¥Á¥ã¤Ë¤â¤Ã¤È¤â°Í¸¤¹¤ë¤Î¤ÏGCÉô¤Ç¤¹¡¥Ruby¤ÎGC¤ÏÂоÝ
¤Î¥¢¡¼¥­¥Æ¥¯¥Á¥ã¤¬setjmp()¤Ë¤è¤Ã¤ÆÁ´¤Æ¤Î¥ì¥¸¥¹¥¿¤ò jmp_buf¤Ë
³ÊǼ¤¹¤ë¤³¤È¤È¡¤jmp_buf¤È¥¹¥¿¥Ã¥¯¤¬32bit¥¢¥é¥¤¥ó¥á¥ó¥È¤µ¤ì¤Æ
¤¤¤ë¤³¤È¤ò²¾Äꤷ¤Æ¤¤¤Þ¤¹¡¥ÆÃ¤ËÁ°¼Ô¤¬À®Î©¤·¤Ê¤¤¾ì¹ç¤ÎÂбþ¤ÏÈó
@@ -110,58 +140,63 @@ UNIX¤Ç¤¢¤ì¤Ðconfigure¤¬¤Û¤È¤ó¤É¤Îº¹°Û¤òµÛ¼ý¤·¤Æ¤¯¤ì¤ë¤Ï¤º¤Ç
* ÇÛÉÛ¾ò·ï
-RUby¤Ï¥Õ¥ê¡¼¥½¥Õ¥È¥¦¥§¥¢¤Ç¤¹¡¥GPL(the GNU General Public
-Licence)¤Þ¤¿¤Ï°Ê²¼¤Ë¼¨¤¹¾ò·ï¤ÇRuby¤òºÆÇÛÉۤǤ­¤Þ¤¹¡¥GPL¤Ë¤Ä
-¤¤¤Æ¤ÏCOPYING¥Õ¥¡¥¤¥ë¤ò»²¾È¤·¤Æ²¼¤µ¤¤¡¥
+ËÜ¥×¥í¥°¥é¥à¤Ï¥Õ¥ê¡¼¥½¥Õ¥È¥¦¥§¥¢¤Ç¤¹¡¥GPL(the GNU General
+Public License)¤Þ¤¿¤Ï°Ê²¼¤Ë¼¨¤¹¾ò·ï¤ÇËÜ¥×¥í¥°¥é¥à¤òºÆÇÛÉÛ¤Ç
+¤­¤Þ¤¹¡¥GPL¤Ë¤Ä¤¤¤Æ¤ÏCOPYING¥Õ¥¡¥¤¥ë¤ò»²¾È¤·¤Æ²¼¤µ¤¤¡¥
1. Ê£À½¤ÏÀ©¸Â¤Ê¤¯¼«Í³¤Ç¤¹¡¥
- 2. °Ê²¼¤Î¾ò·ï¤Î¤¤¤º¤ì¤«¤òËþ¤¿¤¹»þ¤Ë¼ê¸µ¤ÎRuby¤Î¥½¡¼¥¹¤ò¼«
- ͳ¤ËÊѹ¹¤Ç¤­¤Þ¤¹¡¥
+ 2. °Ê²¼¤Î¾ò·ï¤Î¤¤¤º¤ì¤«¤òËþ¤¿¤¹»þ¤ËËÜ¥×¥í¥°¥é¥à¤Î¥½¡¼¥¹¤ò
+ ¼«Í³¤ËÊѹ¹¤Ç¤­¤Þ¤¹¡¥
(a) ¥Í¥Ã¥È¥Ë¥å¡¼¥º¤Ë¥Ý¥¹¥È¤·¤¿¤ê¡¤ºî¼Ô¤ËÊѹ¹¤òÁ÷ÉÕ¤¹¤ë
- ¤Ê¤É¤ÎÊýË¡¤Ç¡¤Êѹ¹¤ò¸ø³«¤¹¤ë
+ ¤Ê¤É¤ÎÊýË¡¤Ç¡¤Êѹ¹¤ò¸ø³«¤¹¤ë¡¥
- (b) Êѹ¹¤·¤¿Ruby¤ò¼«Ê¬¤Î½ê°¤¹¤ëÁÈ¿¥ÆâÉô¤À¤±¤Ç»È¤¦
+ (b) Êѹ¹¤·¤¿ËÜ¥×¥í¥°¥é¥à¤ò¼«Ê¬¤Î½ê°¤¹¤ëÁÈ¿¥ÆâÉô¤À¤±¤Ç
+ »È¤¦¡¥
(c) Êѹ¹ÅÀ¤òÌÀ¼¨¤·¤¿¤¦¤¨¡¤¥½¥Õ¥È¥¦¥§¥¢¤Î̾Á°¤òÊѹ¹¤¹¤ë¡¥
- ¤½¤Î¥½¥Õ¥È¥¦¥§¥¢¤òÇÛÉÛ¤¹¤ë»þ¤Ë¤Ï¤â¤È¤ÎRuby¤âƱ»þ¤Ë
- ÇÛÉÛ¤¹¤ë
+ ¤½¤Î¥½¥Õ¥È¥¦¥§¥¢¤òÇÛÉÛ¤¹¤ë»þ¤Ë¤ÏÊѹ¹Á°¤ÎËÜ¥×¥í¥°¥é
+ ¥à¤âƱ»þ¤ËÇÛÉÛ¤¹¤ë¡¥¤Þ¤¿¤ÏÊѹ¹Á°¤ÎËÜ¥×¥í¥°¥é¥à¤Î¥½¡¼
+ ¥¹¤ÎÆþ¼êË¡¤òÌÀ¼¨¤¹¤ë¡¥
- (d) ¤½¤Î¾¤ÎÊѹ¹¾ò·ï¤òºî¼Ô¤È¹ç°Õ¤¹¤ë
+ (d) ¤½¤Î¾¤ÎÊѹ¹¾ò·ï¤òºî¼Ô¤È¹ç°Õ¤¹¤ë¡¥
- 3. °Ê²¼¤Î¾ò·ï¤Î¤¤¤º¤ì¤«¤òËþ¤¿¤¹»þ¤ËRuby¤ò¥ª¥Ö¥¸¥§¥¯¥È¥³¡¼
- ¥É¤ä¼Â¹Ô·Á¼°¤Ç¤âÇÛÉۤǤ­¤Þ¤¹¡¥
+ 3. °Ê²¼¤Î¾ò·ï¤Î¤¤¤º¤ì¤«¤òËþ¤¿¤¹»þ¤ËËÜ¥×¥í¥°¥é¥à¤ò¥³¥ó¥Ñ¥¤
+ ¥ë¤·¤¿¥ª¥Ö¥¸¥§¥¯¥È¥³¡¼¥É¤ä¼Â¹Ô·Á¼°¤Ç¤âÇÛÉۤǤ­¤Þ¤¹¡¥
- (a) ¥Ð¥¤¥Ê¥ê¤ò¼õ¤±¼è¤Ã¤¿¿Í¤¬¥½¡¼¥¹¤òÆþ¼ê¤Ç¤­¤ë¤è¤¦¤Ë¥½¡¼
- ¥¹¤ÎÆþ¼êË¡¤òÌÀ¼¨¤¹¤ë
+ (a) ¥Ð¥¤¥Ê¥ê¤ò¼õ¤±¼è¤Ã¤¿¿Í¤¬¥½¡¼¥¹¤òÆþ¼ê¤Ç¤­¤ë¤è¤¦¤Ë¡¤
+ ¥½¡¼¥¹¤ÎÆþ¼êË¡¤òÌÀ¼¨¤¹¤ë¡¥
- (b) µ¡³£²ÄÆÉ¤Ê¥½¡¼¥¹¥³¡¼¥É¤òźÉÕ¤¹¤ë
+ (b) µ¡³£²ÄÆÉ¤Ê¥½¡¼¥¹¥³¡¼¥É¤òźÉÕ¤¹¤ë¡¥
- (c) Êѹ¹¤ò¹Ô¤Ã¤¿¥Ð¥¤¥Ê¥ê¤Ï̾Á°¤òÊѹ¹¤·¤¿¤¦¤¨¡¤¥½¡¼¥¹¤Î
- Æþ¼êË¡¤òÌÀ¼¨¤¹¤ë
+ (c) Êѹ¹¤ò¹Ô¤Ã¤¿¥Ð¥¤¥Ê¥ê¤Ï̾Á°¤òÊѹ¹¤·¤¿¤¦¤¨¡¤¥ª¥ê¥¸¥Ê
+ ¥ë¤Î¥½¡¼¥¹¥³¡¼¥É¤ÎÆþ¼êË¡¤òÌÀ¼¨¤¹¤ë¡¥
- (d) ¤½¤Î¾¤ÎÇÛÉÛ¾ò·ï¤òºî¼Ô¤È¹ç°Õ¤¹¤ë
+ (d) ¤½¤Î¾¤ÎÇÛÉÛ¾ò·ï¤òºî¼Ô¤È¹ç°Õ¤¹¤ë¡¥
4. ¾¤Î¥×¥í¥°¥é¥à¤Ø¤Î°úÍѤϤ¤¤«¤Ê¤ëÌÜŪ¤Ç¤¢¤ì¼«Í³¤Ç¤¹¡¥¤¿
- ¤À¤·¡¤Ruby¤Ë´Þ¤Þ¤ì¤ë¾¤Îºî¼Ô¤Ë¤è¤ë¥³¡¼¥É¤Ï¡¤¤½¤ì¤¾¤ì¤Î
- ºî¼Ô¤Î°Õ¸þ¤Ë¤è¤ëÀ©¸Â¤¬²Ã¤¨¤é¤ì¤Þ¤¹¡¥¶ñÂÎŪ¤Ë¤Ïgc.c(°ìÉô)¡¤
- util.c(°ìÉô)¡¤st.[ch]¡¤regex.[ch], fnmatch.[ch], glob.c
- ¤ª¤è¤Ó./missing¥Ç¥£¥ì¥¯¥È¥ê²¼¤Î¥Õ¥¡¥¤¥ë·²¤¬³ºÅö¤·¤Þ¤¹¡¥
+ ¤À¤·¡¤ËÜ¥×¥í¥°¥é¥à¤Ë´Þ¤Þ¤ì¤ë¾¤Îºî¼Ô¤Ë¤è¤ë¥³¡¼¥É¤Ï¡¤¤½
+ ¤ì¤¾¤ì¤Îºî¼Ô¤Î°Õ¸þ¤Ë¤è¤ëÀ©¸Â¤¬²Ã¤¨¤é¤ì¤ë¾ì¹ç¤¬¤¢¤ê¤Þ¤¹¡¥
- 5. Ruby¤Ø¤ÎÆþÎϤȤʤ륹¥¯¥ê¥×¥È¤ª¤è¤Ó¡¤Ruby¤«¤é¤Î½ÐÎϤθ¢
- Íø¤ÏRuby¤Îºî¼Ô¤Ç¤Ï¤Ê¤¯¡¤¤½¤ì¤¾¤ì¤ÎÆþ½ÐÎϤòÀ¸À®¤·¤¿¿Í¤Ë
- °¤·¤Þ¤¹¡¥¤Þ¤¿¡¤Ruby¤ËÁȤ߹þ¤à¤¿¤á¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë¤Ä
- ¤¤¤Æ¤âƱÍͤǤ¹¡¥
+ ¶ñÂÎŪ¤Ë¤Ïgc.c(°ìÉô)¡¤util.c(°ìÉô)¡¤st.[ch]¡¤regex.[ch]
+ ¤ª¤è¤Ó ./missing¥Ç¥£¥ì¥¯¥È¥ê²¼¤Î¥Õ¥¡¥¤¥ë·²¤¬³ºÅö¤·¤Þ¤¹¡¥
+ ¤½¤ì¤¾¤ì¤ÎÇÛÉÛ¾ò·ï¤Ê¤É¤ËÉÕ¤¤¤Æ¤Ï³Æ¥Õ¥¡¥¤¥ë¤ò»²¾È¤·¤Æ¤¯
+ ¤À¤µ¤¤¡¥
- 6. Ruby¤Ï̵ÊݾڤǤ¹¡¥ºî¼Ô¤ÏRuby¤ò¥µ¥Ý¡¼¥È¤¹¤ë°Õ»Ö¤Ï¤¢¤ê¤Þ
- ¤¹¤¬¡¤Ruby¼«¿È¤Î¥Ð¥°¤¢¤ë¤¤¤ÏRuby¥¹¥¯¥ê¥×¥È¤Î¥Ð¥°¤Ê¤É¤«
- ¤éȯÀ¸¤¹¤ë¤¤¤«¤Ê¤ë»³²¤ËÂФ·¤Æ¤âÀÕǤ¤ò»ý¤Á¤Þ¤»¤ó¡¥
+ 5. ËÜ¥×¥í¥°¥é¥à¤Ø¤ÎÆþÎϤȤʤ륹¥¯¥ê¥×¥È¤ª¤è¤Ó¡¤ËÜ¥×¥í¥°¥é
+ ¥à¤«¤é¤Î½ÐÎϤθ¢Íø¤ÏËÜ¥×¥í¥°¥é¥à¤Îºî¼Ô¤Ç¤Ï¤Ê¤¯¡¤¤½¤ì¤¾
+ ¤ì¤ÎÆþ½ÐÎϤòÀ¸À®¤·¤¿¿Í¤Ë°¤·¤Þ¤¹¡¥¤Þ¤¿¡¤ËÜ¥×¥í¥°¥é¥à¤Ë
+ ÁȤ߹þ¤Þ¤ì¤ë¤¿¤á¤Î³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ë¤Ä¤¤¤Æ¤âƱÍͤǤ¹¡¥
+ 6. ËÜ¥×¥í¥°¥é¥à¤Ï̵ÊݾڤǤ¹¡¥ºî¼Ô¤ÏËÜ¥×¥í¥°¥é¥à¤ò¥µ¥Ý¡¼¥È
+ ¤¹¤ë°Õ»Ö¤Ï¤¢¤ê¤Þ¤¹¤¬¡¤¥×¥í¥°¥é¥à¼«¿È¤Î¥Ð¥°¤¢¤ë¤¤¤ÏËÜ¥×
+ ¥í¥°¥é¥à¤Î¼Â¹Ô¤Ê¤É¤«¤éȯÀ¸¤¹¤ë¤¤¤«¤Ê¤ë»³²¤ËÂФ·¤Æ¤âÀÕ
+ Ǥ¤ò»ý¤Á¤Þ¤»¤ó¡¥
* Ãø¼Ô
-¥³¥á¥ó¥È¡¤¥Ð¥°¥ì¥Ý¡¼¥È¤½¤Î¾¤Ï matz@netlab.co.jp ¤Þ¤Ç¡¥
+¥³¥á¥ó¥È¡¤¥Ð¥°¥ì¥Ý¡¼¥È¤½¤Î¾¤Ï matz@zetabits.com ¤Þ¤Ç¡¥
-------------------------------------------------------
created at: Thu Aug 3 11:57:36 JST 1995
Local variables:
diff --git a/ToDo b/ToDo
index 9710c42302..5f67a42b25 100644
--- a/ToDo
+++ b/ToDo
@@ -1,3 +1,129 @@
-* non-blocking open/write for thread
-* package or access control for global variables
-* format
+Language Spec.
+
+- def foo; .. rescue .. end
+- compile time string concatenation, "hello" "world" => "helloworld"
+- rescue modifier; a rescue b => begin a rescue; b end
+- %w(a\ b\ c abc) => ["a b c", "abc"]
+- objectify symbols
+- class variable (prefix @@)
+- rescue RuntimeError => err
+* operator !! for rescue. ???
+* objectify characters
+* ../... outside condition invokes operator method too.
+* ... inside condition turns off just before right condition.???
+* package or access control for global variables??
+* named arguments like foo(nation:="german") or foo(nation: "german").
+* method to retrieve argument information (needs new C API)
+* multiple return values, yield values. maybe incompatible ???
+* cascading method invocation ???
+* def Class#method .. end ??
+* class Foo::Bar<Baz .. end, module Boo::Bar .. end
+* def Foo::Bar::baz() .. end ??
+* I18N (or M17N) script/string/regexp
+* Fixnum 0 as false ????
+* discourage use of symbol variable (e.g. $/, etc.) in manual
+* discourage use of Perlish features by giving warnings.
+* non confusing in-block local variable (is it possible?)
+ + remove scope by block
+ + variables appears within block may have independent values.
+* Regexp: make /o thread safe.
+* decide if begin with rescue or ensure make do..while loop.
+* a +1 to be a+1, not a(+1).
+
+Hacking Interpreter
+
+- use eban's fnmatch
+- RUBYOPT environment variable
+- alias $defout $>
+- retrieve STACK_LEVEL_MAX from users' limit.
+- remove end_proc registered out of require only
+- all object made freezable
+* non-blocking open (e.g. for named pipe) for thread
+* avoid blocking with gethostbyname/gethostbyaddr (use fork ???)
+* objectify interpreters ???
+* remove rb_eval() recursions
+* syntax tree -> bytecode ???
+* scrambled script, or script filter
+* setuid ruby
+* performance tune for in-block (dynamic) local variables.
+* generational GC
+* give warnings to assign magic variables.
+* export rb_io_{addstr,printf,puts,print}
+* autoload should work with threads [ruby-talk:4589]
+* remove stdio dependency from IOs.
+* warn for inconsistent local variable usage (lv m and method m at the same time).
+
+Standard Libraries
+
+- hash[key] = nil does not remove entry; hashes may have nil as the value.
+- hash.fetch(key) raises exception if key is not found.
+- Array#{first,last,at}
+- Dir.glob(pat){|f|...}
+- sprintf/printf's $ to specify argument order
+- Dir.glob("**/*.c") ala zsh
+- Remove Enumerable#{size,length}
+- Array#slice, Array#slice!
+- String#slice, String#slice!
+- Marshal should handle generic instance variables.
+- debugger for thread programming
+- SyntaxError, NameError, LoadError and NotImplementedError are subclasses of
+ ScriptError<Exception, not StandardError.
+- Thread::start gives arguments, not a thread object to the block
+- regexp: (?>..), \G
+- Struct::new([name,]member,...)
+- IO#reopen accepts path as well
+- Kernel#scan
+- call initialize for builtin classes too
+- performance tune for String's non-bang methods.
+- 'w' template for pack/unpack
+- alternative for interator? => block_given?
+- regex - /p (made obsolete), /m (new)
+- consistent /, %, divmod
+- unbound method object
+- integrate final.rb into the core.
+* Enumerable#sort_by for Schwartzian transformation
+* String#scanf(?)
+* Object#fmt(?)
+* Integer#{bin,oct,hex,heX}
+* Time::strptime
+* Integer[num], Float[num]; Fixnum[num]?
+* method to retrieve non-number trailer for to_i/to_f.
+* Stream or Port, abstract superclass of IO ?
+* String#{pred,prev}, String#downto
+* optional stepsize argument for succ()
+* Ruby module -- Ruby::Version, Ruby::Interpreter
+* introduce Boolean class; super of TrueClass, FalseClass
+* Process::waitall [ruby-talk:4557]
+* synchronized method - synchronized{...}, synchronized :foo, :bar
+* move Time::times to Process.
+- Module#define_method which takes a name and a body (block, proc or method).
+* IO#for_fd in general
+* Array#&, Array#| to allow duplication. ???
+- fork_and_kill_other_threads.
+* way to specify immortal (fork endurance) thread;
+* or raise ForkException to every thread but fork caller.
+* Array#fetch
+
+Extension Libraries
+
+- FastCGI ruby
+* ptk.rb pTk wrapper that is compatible to tk.rb
+* Berkeley DB extension
+* BitVector
+
+Ruby Libraries
+
+- net/http.rb
+* add uri.rb
+* urllib.rb, nttplib.rb, etc.
+* format like perl's
+
+Tools
+
+- extension library maker using SWIG
+* freeze or undump to bundle everything
+
+Misc
+
+- publish Ruby books
+- publish Ruby books in English
diff --git a/array.c b/array.c
index d88c333dd2..0b36460dbd 100644
--- a/array.c
+++ b/array.c
@@ -1,4 +1,4 @@
-/************************************************
+/**********************************************************************
array.c -
@@ -6,98 +6,125 @@
$Date$
created at: Fri Aug 6 09:46:12 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-2000 Yukihiro Matsumoto
+ Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ Copyright (C) 2000 Information-technology Promotion Agency, Japan
-************************************************/
+**********************************************************************/
#include "ruby.h"
+#include "util.h"
+#include "st.h"
-
-VALUE cArray;
+VALUE rb_cArray;
#define ARY_DEFAULT_SIZE 16
void
-memclear(mem, size)
+rb_mem_clear(mem, size)
register VALUE *mem;
- register int size;
+ register long size;
{
while (size--) {
*mem++ = Qnil;
}
}
-#define ARY_FREEZE FL_USER1
+static void
+memfill(mem, size, val)
+ register VALUE *mem;
+ register long size;
+ register VALUE val;
+{
+ while (size--) {
+ *mem++ = val;
+ }
+}
+
+#define ARY_TMPLOCK FL_USER1
static void
-ary_modify(ary)
+rb_ary_modify(ary)
VALUE ary;
{
- rb_secure(5);
- if (FL_TEST(ary, ARY_FREEZE)) {
- TypeError("can't modify frozen array");
- }
+ if (OBJ_FROZEN(ary)) rb_error_frozen("array");
+ if (FL_TEST(ary, ARY_TMPLOCK))
+ rb_raise(rb_eTypeError, "can't modify array during sort");
+ if (!OBJ_TAINTED(ary) && rb_safe_level() >= 4)
+ rb_raise(rb_eSecurityError, "Insecure: can't modify array");
}
VALUE
-ary_freeze(ary)
+rb_ary_freeze(ary)
VALUE ary;
{
- FL_SET(ary, ARY_FREEZE);
- return ary;
+ return rb_obj_freeze(ary);
}
static VALUE
-ary_frozen_p(ary)
+rb_ary_frozen_p(ary)
VALUE ary;
{
- if (FL_TEST(ary, ARY_FREEZE))
- return TRUE;
- return FALSE;
+ if (FL_TEST(ary, FL_FREEZE|ARY_TMPLOCK))
+ return Qtrue;
+ return Qfalse;
}
VALUE
-ary_new2(len)
- int len;
+rb_ary_new2(len)
+ long len;
{
NEWOBJ(ary, struct RArray);
- OBJSETUP(ary, cArray, T_ARRAY);
+ OBJSETUP(ary, rb_cArray, T_ARRAY);
+ if (len < 0) {
+ rb_raise(rb_eArgError, "negative array size (or size too big)");
+ }
+ if (len > 0 && len*sizeof(VALUE) <= 0) {
+ rb_raise(rb_eArgError, "array size too big");
+ }
ary->len = 0;
ary->capa = len;
- if (len == 0)
- ary->ptr = 0;
- else {
- ary->ptr = ALLOC_N(VALUE, len);
- memclear(ary->ptr, len);
- }
+ ary->ptr = 0;
+ if (len == 0) len++;
+ ary->ptr = ALLOC_N(VALUE, len);
return (VALUE)ary;
}
VALUE
-ary_new()
+rb_ary_new()
{
- return ary_new2(ARY_DEFAULT_SIZE);
+ return rb_ary_new2(ARY_DEFAULT_SIZE);
}
+#ifdef HAVE_STDARG_PROTOTYPES
+#include <stdarg.h>
+#define va_init_list(a,b) va_start(a,b)
+#else
#include <varargs.h>
+#define va_init_list(a,b) va_start(a)
+#endif
VALUE
-ary_new3(n, va_alist)
- int n;
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_ary_new3(long n, ...)
+#else
+rb_ary_new3(n, va_alist)
+ long n;
va_dcl
+#endif
{
va_list ar;
VALUE ary;
- int i;
+ long i;
if (n < 0) {
- IndexError("Negative number of items(%d)", n);
+ rb_raise(rb_eIndexError, "negative number of items(%d)", n);
}
- ary = ary_new2(n<ARY_DEFAULT_SIZE?ARY_DEFAULT_SIZE:n);
+ ary = rb_ary_new2(n<ARY_DEFAULT_SIZE?ARY_DEFAULT_SIZE:n);
- va_start(ar);
+ va_init_list(ar, n);
for (i=0; i<n; i++) {
RARRAY(ary)->ptr[i] = va_arg(ar, VALUE);
}
@@ -108,31 +135,28 @@ ary_new3(n, va_alist)
}
VALUE
-ary_new4(n, elts)
- int n;
+rb_ary_new4(n, elts)
+ long n;
VALUE *elts;
{
VALUE ary;
- ary = ary_new2(n);
+ ary = rb_ary_new2(n);
if (elts) {
MEMCPY(RARRAY(ary)->ptr, elts, VALUE, n);
}
- else {
- memclear(RARRAY(ary)->ptr, n);
- }
RARRAY(ary)->len = n;
return ary;
}
VALUE
-assoc_new(car, cdr)
+rb_assoc_new(car, cdr)
VALUE car, cdr;
{
VALUE ary;
- ary = ary_new2(2);
+ ary = rb_ary_new2(2);
RARRAY(ary)->ptr[0] = car;
RARRAY(ary)->ptr[1] = cdr;
RARRAY(ary)->len = 2;
@@ -141,27 +165,51 @@ assoc_new(car, cdr)
}
static VALUE
-ary_s_new(argc, argv, klass)
+rb_ary_s_new(argc, argv, klass)
int argc;
VALUE *argv;
VALUE klass;
{
- VALUE size;
- NEWOBJ(ary, struct RArray);
+ VALUE ary = rb_ary_new();
OBJSETUP(ary, klass, T_ARRAY);
+ rb_obj_call_init(ary, argc, argv);
- rb_scan_args(argc, argv, "01", &size);
- ary->len = 0;
- ary->capa = NIL_P(size)?ARY_DEFAULT_SIZE:NUM2INT(size);
- ary->ptr = ALLOC_N(VALUE, ary->capa);
- memclear(ary->ptr, ary->capa);
- obj_call_init((VALUE)ary);
+ return ary;
+}
- return (VALUE)ary;
+static VALUE
+rb_ary_initialize(argc, argv, ary)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+{
+ long len;
+ VALUE size, val;
+
+ if (rb_scan_args(argc, argv, "02", &size, &val) == 0) {
+ return ary;
+ }
+
+ rb_ary_modify(ary);
+ len = NUM2LONG(size);
+ if (len < 0) {
+ rb_raise(rb_eArgError, "negative array size");
+ }
+ if (len > 0 && len*sizeof(VALUE) <= 0) {
+ rb_raise(rb_eArgError, "array size too big");
+ }
+ if (len > RARRAY(ary)->capa) {
+ RARRAY(ary)->capa = len;
+ REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
+ }
+ memfill(RARRAY(ary)->ptr, len, val);
+ RARRAY(ary)->len = len;
+
+ return ary;
}
static VALUE
-ary_s_create(argc, argv, klass)
+rb_ary_s_create(argc, argv, klass)
int argc;
VALUE *argv;
VALUE klass;
@@ -169,8 +217,7 @@ ary_s_create(argc, argv, klass)
NEWOBJ(ary, struct RArray);
OBJSETUP(ary, klass, T_ARRAY);
- ary->len = argc;
- ary->capa = argc;
+ ary->len = ary->capa = 0;
if (argc == 0) {
ary->ptr = 0;
}
@@ -178,27 +225,37 @@ ary_s_create(argc, argv, klass)
ary->ptr = ALLOC_N(VALUE, argc);
MEMCPY(ary->ptr, argv, VALUE, argc);
}
+ ary->len = ary->capa = argc;
return (VALUE)ary;
}
void
-ary_store(ary, idx, val)
+rb_ary_store(ary, idx, val)
VALUE ary;
- int idx;
+ long idx;
VALUE val;
{
- ary_modify(ary);
+ rb_ary_modify(ary);
if (idx < 0) {
- IndexError("negative index for array");
+ idx += RARRAY(ary)->len;
+ if (idx < 0) {
+ rb_raise(rb_eIndexError, "index %d out of array",
+ idx - RARRAY(ary)->len);
+ }
}
if (idx >= RARRAY(ary)->capa) {
- RARRAY(ary)->capa = idx + ARY_DEFAULT_SIZE;
+ long capa_inc = RARRAY(ary)->capa / 2;
+ if (capa_inc < ARY_DEFAULT_SIZE) {
+ capa_inc = ARY_DEFAULT_SIZE;
+ }
+ RARRAY(ary)->capa = idx + capa_inc;
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
}
if (idx > RARRAY(ary)->len) {
- memclear(RARRAY(ary)->ptr+RARRAY(ary)->len, idx-RARRAY(ary)->len+1);
+ rb_mem_clear(RARRAY(ary)->ptr+RARRAY(ary)->len,
+ idx-RARRAY(ary)->len+1);
}
if (idx >= RARRAY(ary)->len) {
@@ -208,30 +265,42 @@ ary_store(ary, idx, val)
}
VALUE
-ary_push(ary, item)
+rb_ary_push(ary, item)
VALUE ary;
VALUE item;
{
- ary_store(ary, RARRAY(ary)->len, item);
+ rb_ary_store(ary, RARRAY(ary)->len, item);
return ary;
}
static VALUE
-ary_push_method(argc, argv, ary)
+rb_ary_push_m(argc, argv, ary)
int argc;
VALUE *argv;
VALUE ary;
{
- while (argc--) {
- ary_store(ary, RARRAY(ary)->len, *argv++);
+ if (argc == 0) {
+ rb_raise(rb_eArgError, "wrong # of arguments(at least 1)");
+ }
+ if (argc > 0) {
+ long len = RARRAY(ary)->len;
+
+ --argc;
+ /* make rooms by copying the last item */
+ rb_ary_store(ary, len + argc, argv[argc]);
+
+ if (argc) { /* if any rest */
+ MEMCPY(RARRAY(ary)->ptr + len, argv, VALUE, argc);
+ }
}
return ary;
}
VALUE
-ary_pop(ary)
+rb_ary_pop(ary)
VALUE ary;
{
+ rb_ary_modify(ary);
if (RARRAY(ary)->len == 0) return Qnil;
if (RARRAY(ary)->len * 10 < RARRAY(ary)->capa && RARRAY(ary)->capa > ARY_DEFAULT_SIZE) {
RARRAY(ary)->capa = RARRAY(ary)->len * 2;
@@ -241,11 +310,12 @@ ary_pop(ary)
}
VALUE
-ary_shift(ary)
+rb_ary_shift(ary)
VALUE ary;
{
VALUE top;
+ rb_ary_modify(ary);
if (RARRAY(ary)->len == 0) return Qnil;
top = RARRAY(ary)->ptr[0];
@@ -262,12 +332,16 @@ ary_shift(ary)
}
VALUE
-ary_unshift(ary, item)
+rb_ary_unshift(ary, item)
VALUE ary, item;
{
- ary_modify(ary);
+ rb_ary_modify(ary);
if (RARRAY(ary)->len >= RARRAY(ary)->capa) {
- RARRAY(ary)->capa+=ARY_DEFAULT_SIZE;
+ long capa_inc = RARRAY(ary)->capa / 2;
+ if (capa_inc < ARY_DEFAULT_SIZE) {
+ capa_inc = ARY_DEFAULT_SIZE;
+ }
+ RARRAY(ary)->capa+=capa_inc;
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
}
@@ -275,13 +349,37 @@ ary_unshift(ary, item)
MEMMOVE(RARRAY(ary)->ptr+1, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
RARRAY(ary)->len++;
- return RARRAY(ary)->ptr[0] = item;
+ RARRAY(ary)->ptr[0] = item;
+
+ return ary;
+}
+
+static VALUE
+rb_ary_unshift_m(argc, argv, ary)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+{
+ if (argc == 0) {
+ rb_raise(rb_eArgError, "wrong # of arguments(at least 1)");
+ }
+ if (argc > 0) {
+ long len = RARRAY(ary)->len;
+
+ /* make rooms by setting the last item */
+ rb_ary_store(ary, len + argc - 1, Qnil);
+
+ /* sliding items */
+ MEMMOVE(RARRAY(ary)->ptr + argc, RARRAY(ary)->ptr, VALUE, len);
+ MEMCPY(RARRAY(ary)->ptr, argv, VALUE, argc);
+ }
+ return ary;
}
VALUE
-ary_entry(ary, offset)
+rb_ary_entry(ary, offset)
VALUE ary;
- int offset;
+ long offset;
{
if (RARRAY(ary)->len == 0) return Qnil;
@@ -296,315 +394,344 @@ ary_entry(ary, offset)
}
static VALUE
-ary_subseq(ary, beg, len)
+rb_ary_subseq(ary, beg, len)
VALUE ary;
- int beg, len;
+ long beg, len;
{
VALUE ary2;
- if (beg < 0) {
- beg = RARRAY(ary)->len + beg;
- if (beg < 0) beg = 0;
- }
- if (len < 0) {
- IndexError("negative length %d", RARRAY(ary)->len);
- }
- if (len == 0) {
- return ary_new2(0);
- }
+ if (beg > RARRAY(ary)->len) return Qnil;
+ if (beg < 0 || len < 0) return Qnil;
+
if (beg + len > RARRAY(ary)->len) {
len = RARRAY(ary)->len - beg;
}
if (len < 0) {
len = 0;
}
+ if (len == 0) return rb_ary_new2(0);
- ary2 = ary_new2(len);
+ ary2 = rb_ary_new2(len);
MEMCPY(RARRAY(ary2)->ptr, RARRAY(ary)->ptr+beg, VALUE, len);
RARRAY(ary2)->len = len;
return ary2;
}
-static VALUE
-beg_len(range, begp, lenp, len)
- VALUE range;
- int *begp, *lenp;
- int len;
-{
- int beg, end;
-
- if (!range_beg_end(range, &beg, &end)) return FALSE;
-
- if ((beg > 0 && end > 0 || beg < 0 && end < 0) && beg > end) {
- IndexError("end smaller than beg [%d..%d]", beg, end);
- }
-
- if (beg < 0) {
- beg = len + beg;
- if (beg < 0) beg = 0;
- }
- *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;
- }
- }
- return TRUE;
-}
-
VALUE
-ary_aref(argc, argv, ary)
+rb_ary_aref(argc, argv, ary)
int argc;
VALUE *argv;
VALUE ary;
{
VALUE arg1, arg2;
- int beg, len;
+ long beg, len;
if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
- beg = NUM2INT(arg1);
- len = NUM2INT(arg2);
- if (len <= 0) {
- return ary_new();
+ beg = NUM2LONG(arg1);
+ len = NUM2LONG(arg2);
+ if (beg < 0) {
+ beg = RARRAY(ary)->len + beg;
}
- return ary_subseq(ary, beg, len);
+ return rb_ary_subseq(ary, beg, len);
}
/* special case - speeding up */
if (FIXNUM_P(arg1)) {
- return ary_entry(ary, FIX2INT(arg1));
+ return rb_ary_entry(ary, FIX2LONG(arg1));
+ }
+ else if (TYPE(arg1) == T_BIGNUM) {
+ rb_raise(rb_eIndexError, "index too big");
}
else {
/* check if idx is Range */
- if (beg_len(arg1, &beg, &len, RARRAY(ary)->len)) {
- return ary_subseq(ary, beg, len);
+ switch (rb_range_beg_len(arg1, &beg, &len, RARRAY(ary)->len, 0)) {
+ case Qfalse:
+ break;
+ case Qnil:
+ return Qnil;
+ default:
+ return rb_ary_subseq(ary, beg, len);
}
}
- if (TYPE(arg1) == T_BIGNUM) {
- IndexError("index too big");
- }
- return ary_entry(ary, NUM2INT(arg1));
+ return rb_ary_entry(ary, NUM2LONG(arg1));
+}
+
+static VALUE
+rb_ary_at(ary, pos)
+ VALUE ary, pos;
+{
+ return rb_ary_entry(ary, NUM2LONG(pos));
+}
+
+static VALUE
+rb_ary_first(ary)
+ VALUE ary;
+{
+ if (RARRAY(ary)->len == 0) return Qnil;
+ return RARRAY(ary)->ptr[0];
}
static VALUE
-ary_index(ary, val)
+rb_ary_last(ary)
+ VALUE ary;
+{
+ if (RARRAY(ary)->len == 0) return Qnil;
+ return RARRAY(ary)->ptr[RARRAY(ary)->len-1];
+}
+
+static VALUE
+rb_ary_index(ary, val)
VALUE ary;
VALUE val;
{
- int i;
+ long i;
for (i=0; i<RARRAY(ary)->len; i++) {
if (rb_equal(RARRAY(ary)->ptr[i], val))
- return INT2FIX(i);
+ return INT2NUM(i);
}
return Qnil;
}
static VALUE
-ary_indexes(argc, argv, ary)
+rb_ary_rindex(ary, val)
+ VALUE ary;
+ VALUE val;
+{
+ long i = RARRAY(ary)->len;
+
+ while (i--) {
+ if (rb_equal(RARRAY(ary)->ptr[i], val))
+ return INT2NUM(i);
+ }
+ return Qnil;
+}
+
+static VALUE
+rb_ary_indexes(argc, argv, ary)
int argc;
VALUE *argv;
VALUE ary;
{
VALUE new_ary;
- int i;
+ long i;
- new_ary = ary_new2(argc);
+ new_ary = rb_ary_new2(argc);
for (i=0; i<argc; i++) {
- ary_store(new_ary, i, ary_entry(ary, NUM2INT(argv[i])));
+ rb_ary_push(new_ary, rb_ary_aref(1, argv+i, ary));
}
return new_ary;
}
static void
-ary_replace(ary, beg, len, rpl)
+rb_ary_replace(ary, beg, len, rpl)
VALUE ary, rpl;
- int beg, len;
+ long beg, len;
{
- ary_modify(ary);
- if (TYPE(rpl) != T_ARRAY) {
- rpl = rb_Array(rpl);
+ long rlen;
+
+ if (len < 0) rb_raise(rb_eIndexError, "negative length %d", len);
+ if (beg < 0) {
+ beg += RARRAY(ary)->len;
}
if (beg < 0) {
- beg = RARRAY(ary)->len + beg;
- if (beg < 0) beg = 0;
+ beg -= RARRAY(ary)->len;
+ rb_raise(rb_eIndexError, "index %d out of array", beg);
}
+ if (beg + len > RARRAY(ary)->len) {
+ len = RARRAY(ary)->len - beg;
+ }
+
+ if (NIL_P(rpl)) {
+ rpl = rb_ary_new2(0);
+ }
+ else if (TYPE(rpl) != T_ARRAY) {
+ rpl = rb_ary_new3(1, rpl);
+ }
+ rlen = RARRAY(rpl)->len;
+
+ rb_ary_modify(ary);
if (beg >= RARRAY(ary)->len) {
- len = beg + RARRAY(rpl)->len;
+ len = beg + rlen;
if (len >= RARRAY(ary)->capa) {
RARRAY(ary)->capa=len;
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
}
- memclear(RARRAY(ary)->ptr+RARRAY(ary)->len, beg-RARRAY(ary)->len);
- MEMCPY(RARRAY(ary)->ptr+beg, RARRAY(rpl)->ptr, VALUE, RARRAY(rpl)->len);
+ rb_mem_clear(RARRAY(ary)->ptr+RARRAY(ary)->len, beg-RARRAY(ary)->len);
+ MEMCPY(RARRAY(ary)->ptr+beg, RARRAY(rpl)->ptr, VALUE, rlen);
RARRAY(ary)->len = len;
}
else {
- int alen;
+ long alen;
if (beg + len > RARRAY(ary)->len) {
len = RARRAY(ary)->len - beg;
}
- if (len < 0) {
- IndexError("negative length %d", RARRAY(ary)->len);
- }
- alen = RARRAY(ary)->len + RARRAY(rpl)->len - len;
+ alen = RARRAY(ary)->len + rlen - len;
if (alen >= RARRAY(ary)->capa) {
RARRAY(ary)->capa=alen;
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
}
if (len != RARRAY(rpl)->len) {
- MEMMOVE(RARRAY(ary)->ptr+beg+RARRAY(rpl)->len, RARRAY(ary)->ptr+beg+len,
+ MEMMOVE(RARRAY(ary)->ptr+beg+rlen, RARRAY(ary)->ptr+beg+len,
VALUE, RARRAY(ary)->len-(beg+len));
RARRAY(ary)->len = alen;
}
- MEMCPY(RARRAY(ary)->ptr+beg, RARRAY(rpl)->ptr, VALUE, RARRAY(rpl)->len);
+ MEMMOVE(RARRAY(ary)->ptr+beg, RARRAY(rpl)->ptr, VALUE, rlen);
}
}
static VALUE
-ary_aset(argc, argv, ary)
+rb_ary_aset(argc, argv, ary)
int argc;
VALUE *argv;
VALUE ary;
{
- VALUE arg1, arg2, arg3;
- int offset;
- int beg, len;
+ long offset, beg, len;
- if (rb_scan_args(argc, argv, "21", &arg1, &arg2, &arg3) == 3) {
- beg = NUM2INT(arg1);
- len = NUM2INT(arg2);
- ary_replace(ary, beg, len, arg3);
- return arg3;
+ if (argc == 3) {
+ rb_ary_replace(ary, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]);
+ return argv[2];
+ }
+ if (argc != 2) {
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)", argc);
}
- else if (FIXNUM_P(arg1)) {
- offset = FIX2INT(arg1);
+ if (FIXNUM_P(argv[0])) {
+ offset = FIX2LONG(argv[0]);
goto fixnum;
}
- else if (beg_len(arg1, &beg, &len, RARRAY(ary)->len)) {
+ else if (rb_range_beg_len(argv[0], &beg, &len, RARRAY(ary)->len, 1)) {
/* check if idx is Range */
- ary_replace(ary, beg, len, arg2);
- return arg2;
+ rb_ary_replace(ary, beg, len, argv[1]);
+ return argv[1];
}
- if (TYPE(arg1) == T_BIGNUM) {
- IndexError("index too big");
+ if (TYPE(argv[0]) == T_BIGNUM) {
+ rb_raise(rb_eIndexError, "index too big");
}
- offset = NUM2INT(arg1);
+ offset = NUM2LONG(argv[0]);
fixnum:
- if (offset < 0) {
- offset = RARRAY(ary)->len + offset;
- }
- ary_store(ary, offset, arg2);
- return arg2;
+ rb_ary_store(ary, offset, argv[1]);
+ return argv[1];
}
VALUE
-ary_each(ary)
+rb_ary_each(ary)
VALUE ary;
{
- int i;
+ long i;
for (i=0; i<RARRAY(ary)->len; i++) {
rb_yield(RARRAY(ary)->ptr[i]);
}
- return Qnil;
+ return ary;
}
static VALUE
-ary_each_index(ary)
+rb_ary_each_index(ary)
VALUE ary;
{
- int i;
+ long i;
for (i=0; i<RARRAY(ary)->len; i++) {
- rb_yield(INT2FIX(i));
+ rb_yield(INT2NUM(i));
}
- return Qnil;
+ return ary;
}
static VALUE
-ary_reverse_each(ary)
+rb_ary_reverse_each(ary)
VALUE ary;
{
- int len = RARRAY(ary)->len;
+ long len = RARRAY(ary)->len;
while (len--) {
rb_yield(RARRAY(ary)->ptr[len]);
}
- return Qnil;
+ return ary;
}
static VALUE
-ary_length(ary)
+rb_ary_length(ary)
VALUE ary;
{
- return INT2FIX(RARRAY(ary)->len);
+ return INT2NUM(RARRAY(ary)->len);
}
static VALUE
-ary_empty_p(ary)
+rb_ary_empty_p(ary)
VALUE ary;
{
if (RARRAY(ary)->len == 0)
- return TRUE;
- return FALSE;
+ return Qtrue;
+ return Qfalse;
}
static VALUE
-ary_clone(ary)
+rb_ary_clone(ary)
VALUE ary;
{
- VALUE ary2 = ary_new2(RARRAY(ary)->len);
+ VALUE clone = rb_ary_new2(RARRAY(ary)->len);
- CLONESETUP(ary2, ary);
- MEMCPY(RARRAY(ary2)->ptr, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
- RARRAY(ary2)->len = RARRAY(ary)->len;
- return ary2;
+ CLONESETUP(clone, ary);
+ MEMCPY(RARRAY(clone)->ptr, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
+ RARRAY(clone)->len = RARRAY(ary)->len;
+ return clone;
}
static VALUE
-ary_dup(ary)
+to_ary(ary)
VALUE ary;
{
- return ary_new4(RARRAY(ary)->len, RARRAY(ary)->ptr);
+ return rb_convert_type(ary, T_ARRAY, "Array", "to_ary");
}
-extern VALUE OFS;
+extern VALUE rb_output_fs;
-VALUE
-ary_join(ary, sep)
+static VALUE
+inspect_join(ary, arg)
VALUE ary;
- VALUE sep;
+ VALUE *arg;
+{
+ return rb_ary_join(arg[0], arg[1]);
+}
+
+VALUE
+rb_ary_join(ary, sep)
+ VALUE ary, sep;
{
- int i;
+ long i;
+ int taint = 0;
VALUE result, tmp;
- if (RARRAY(ary)->len == 0) return str_new(0, 0);
- switch (TYPE(RARRAY(ary)->ptr[0])) {
+ if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
+ if (OBJ_TAINTED(ary)) taint = 1;
+ if (OBJ_TAINTED(sep)) taint = 1;
+
+ tmp = RARRAY(ary)->ptr[0];
+ if (OBJ_TAINTED(tmp)) taint = 1;
+ switch (TYPE(tmp)) {
case T_STRING:
- result = str_dup(RARRAY(ary)->ptr[0]);
+ result = rb_str_dup(tmp);
break;
case T_ARRAY:
- result = ary_join(RARRAY(ary)->ptr[0], sep);
+ if (rb_inspecting_p(tmp)) {
+ result = rb_str_new2("[...]");
+ }
+ else {
+ VALUE args[2];
+
+ args[0] = tmp;
+ args[1] = sep;
+ result = rb_protect_inspect(inspect_join, ary, (VALUE)args);
+ }
break;
default:
- result = obj_as_string(RARRAY(ary)->ptr[0]);
+ result = rb_str_dup(rb_obj_as_string(tmp));
break;
}
@@ -614,21 +741,31 @@ ary_join(ary, sep)
case T_STRING:
break;
case T_ARRAY:
- tmp = ary_join(tmp, sep);
+ if (rb_inspecting_p(tmp)) {
+ tmp = rb_str_new2("[...]");
+ }
+ else {
+ VALUE args[2];
+
+ args[0] = tmp;
+ args[1] = sep;
+ tmp = rb_protect_inspect(inspect_join, ary, (VALUE)args);
+ }
break;
default:
- tmp = obj_as_string(tmp);
+ tmp = rb_obj_as_string(tmp);
}
- if (!NIL_P(sep)) str_cat(result, RSTRING(sep)->ptr, RSTRING(sep)->len);
- str_cat(result, RSTRING(tmp)->ptr, RSTRING(tmp)->len);
- if (str_tainted(tmp)) str_taint(result);
+ if (!NIL_P(sep)) rb_str_append(result, sep);
+ rb_str_append(result, tmp);
+ if (OBJ_TAINTED(tmp)) taint = 1;
}
+ if (taint) OBJ_TAINT(result);
return result;
}
static VALUE
-ary_join_method(argc, argv, ary)
+rb_ary_join_m(argc, argv, ary)
int argc;
VALUE *argv;
VALUE ary;
@@ -636,77 +773,161 @@ ary_join_method(argc, argv, ary)
VALUE sep;
rb_scan_args(argc, argv, "01", &sep);
- if (NIL_P(sep)) sep = OFS;
- if (!NIL_P(sep)) Check_Type(sep, T_STRING);
-
- return ary_join(ary, sep);
+ if (NIL_P(sep)) sep = rb_output_fs;
+ return rb_ary_join(ary, sep);
}
VALUE
-ary_to_s(ary)
+rb_ary_to_s(ary)
VALUE ary;
{
- VALUE str = ary_join(ary, OFS);
- if (NIL_P(str)) return str_new(0, 0);
+ VALUE str;
+
+ if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
+ str = rb_ary_join(ary, rb_output_fs);
+ if (NIL_P(str)) return rb_str_new(0, 0);
return str;
}
+static ID inspect_key;
+
+struct inspect_arg {
+ VALUE (*func)();
+ VALUE arg1, arg2;
+};
+
+VALUE
+inspect_call(arg)
+ struct inspect_arg *arg;
+{
+ return (*arg->func)(arg->arg1, arg->arg2);
+}
+
+static VALUE
+inspect_ensure(obj)
+ VALUE obj;
+{
+ VALUE inspect_tbl;
+
+ inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key);
+ rb_ary_pop(inspect_tbl);
+ return 0;
+}
+
+VALUE
+rb_protect_inspect(func, obj, arg)
+ VALUE (*func)();
+ VALUE obj, arg;
+{
+ struct inspect_arg iarg;
+ VALUE inspect_tbl;
+ VALUE id;
+
+ if (!inspect_key) {
+ inspect_key = rb_intern("__inspect_key__");
+ }
+ inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key);
+ if (NIL_P(inspect_tbl)) {
+ inspect_tbl = rb_ary_new();
+ rb_thread_local_aset(rb_thread_current(), inspect_key, inspect_tbl);
+ }
+ id = rb_obj_id(obj);
+ if (rb_ary_includes(inspect_tbl, id)) {
+ return (*func)(obj, arg);
+ }
+ rb_ary_push(inspect_tbl, id);
+ iarg.func = func;
+ iarg.arg1 = obj;
+ iarg.arg2 = arg;
+
+ return rb_ensure(inspect_call, (VALUE)&iarg, inspect_ensure, obj);
+}
+
+VALUE
+rb_inspecting_p(obj)
+ VALUE obj;
+{
+ VALUE inspect_tbl;
+
+ if (!inspect_key) return Qfalse;
+ inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key);
+ if (NIL_P(inspect_tbl)) return Qfalse;
+ return rb_ary_includes(inspect_tbl, rb_obj_id(obj));
+}
+
static VALUE
-ary_inspect(ary)
+inspect_ary(ary)
VALUE ary;
{
- int i, len;
+ int tainted = OBJ_TAINTED(ary);
+ long i = 0;
VALUE s, str;
- if (RARRAY(ary)->len == 0) return str_new2("[]");
- str = str_new2("[");
- len = 1;
+ str = rb_str_new2("[");
for (i=0; i<RARRAY(ary)->len; i++) {
s = rb_inspect(RARRAY(ary)->ptr[i]);
- if (i > 0) str_cat(str, ", ", 2);
- str_cat(str, RSTRING(s)->ptr, RSTRING(s)->len);
- len += RSTRING(s)->len + 2;
+ tainted = OBJ_TAINTED(s);
+ if (i > 0) rb_str_cat2(str, ", ");
+ rb_str_append(str, s);
}
- str_cat(str, "]", 1);
+ rb_str_cat(str, "]", 1);
+ if (tainted) OBJ_TAINT(str);
return str;
}
static VALUE
-ary_to_a(ary)
+rb_ary_inspect(ary)
+ VALUE ary;
+{
+ if (RARRAY(ary)->len == 0) return rb_str_new2("[]");
+ if (rb_inspecting_p(ary)) return rb_str_new2("[...]");
+ return rb_protect_inspect(inspect_ary, ary, 0);
+}
+
+static VALUE
+rb_ary_to_a(ary)
VALUE ary;
{
return ary;
}
VALUE
-ary_reverse(ary)
+rb_ary_reverse(ary)
VALUE ary;
{
VALUE *p1, *p2;
VALUE tmp;
- if (RARRAY(ary)->len == 0) return ary;
+ if (RARRAY(ary)->len <= 1) return ary;
+ rb_ary_modify(ary);
p1 = RARRAY(ary)->ptr;
p2 = p1 + RARRAY(ary)->len - 1; /* points last item */
while (p1 < p2) {
tmp = *p1;
- *p1 = *p2;
- *p2 = tmp;
- p1++; p2--;
+ *p1++ = *p2;
+ *p2-- = tmp;
}
return ary;
}
static VALUE
-ary_reverse_method(ary)
+rb_ary_reverse_bang(ary)
VALUE ary;
{
- return ary_reverse(ary_clone(ary));
+ if (RARRAY(ary)->len <= 1) return Qnil;
+ return rb_ary_reverse(ary);
+}
+
+static VALUE
+rb_ary_reverse_m(ary)
+ VALUE ary;
+{
+ return rb_ary_reverse(rb_obj_dup(ary));
}
static ID cmp;
@@ -715,7 +936,7 @@ static int
sort_1(a, b)
VALUE *a, *b;
{
- VALUE retval = rb_yield(assoc_new(*a, *b));
+ VALUE retval = rb_yield(rb_assoc_new(*a, *b));
return NUM2INT(retval);
}
@@ -728,42 +949,100 @@ sort_2(a, b)
if (FIXNUM_P(*a)) {
if (FIXNUM_P(*b)) return *a - *b;
}
- else if (TYPE(*a) == T_STRING) {
- if (TYPE(*b) == T_STRING) return str_cmp(*a, *b);
+ else if (TYPE(*a) == T_STRING && TYPE(*b) == T_STRING) {
+ return rb_str_cmp(*a, *b);
}
retval = rb_funcall(*a, cmp, 1, *b);
return NUM2INT(retval);
}
+static VALUE
+sort_internal(ary)
+ VALUE ary;
+{
+ qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE),
+ rb_block_given_p()?sort_1:sort_2);
+ return ary;
+}
+
+static VALUE
+sort_unlock(ary)
+ VALUE ary;
+{
+ FL_UNSET(ary, ARY_TMPLOCK);
+ return ary;
+}
+
VALUE
-ary_sort_bang(ary)
+rb_ary_sort_bang(ary)
VALUE ary;
{
- if (RARRAY(ary)->len == 0) return ary;
+ rb_ary_modify(ary);
+ if (RARRAY(ary)->len <= 1) return Qnil;
- ary_modify(ary);
- qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE),
- iterator_p()?sort_1:sort_2);
+ FL_SET(ary, ARY_TMPLOCK); /* prohibit modification during sort */
+ rb_ensure(sort_internal, ary, sort_unlock, ary);
return ary;
}
VALUE
-ary_sort(ary)
+rb_ary_sort(ary)
+ VALUE ary;
+{
+ ary = rb_obj_dup(ary);
+ rb_ary_sort_bang(ary);
+ return ary;
+}
+
+static VALUE
+rb_ary_collect(ary)
+ VALUE ary;
+{
+ long len, i;
+ VALUE collect;
+
+ if (!rb_block_given_p()) {
+ return rb_obj_dup(ary);
+ }
+
+ len = RARRAY(ary)->len;
+ collect = rb_ary_new2(len);
+ for (i=0; i<len; i++) {
+ rb_ary_push(collect, rb_yield(RARRAY(ary)->ptr[i]));
+ }
+ return collect;
+}
+
+static VALUE
+rb_ary_collect_bang(ary)
+ VALUE ary;
+{
+ long i;
+
+ rb_ary_modify(ary);
+ for (i = 0; i < RARRAY(ary)->len; i++) {
+ RARRAY(ary)->ptr[i] = rb_yield(RARRAY(ary)->ptr[i]);
+ }
+ return ary;
+}
+
+static VALUE
+rb_ary_filter(ary)
VALUE ary;
{
- if (RARRAY(ary)->len == 0) return ary;
- return ary_sort_bang(ary_clone(ary));
+ rb_warn("Array#filter is deprecated; use Array#collect!");
+ return rb_ary_collect_bang(ary);
}
VALUE
-ary_delete(ary, item)
+rb_ary_delete(ary, item)
VALUE ary;
VALUE item;
{
- int i1, i2;
+ long i1, i2;
- ary_modify(ary);
+ rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
if (rb_equal(RARRAY(ary)->ptr[i1], item)) continue;
if (i1 != i2) {
@@ -772,7 +1051,9 @@ ary_delete(ary, item)
i2++;
}
if (RARRAY(ary)->len == i2) {
- if (iterator_p()) rb_yield(item);
+ if (rb_block_given_p()) {
+ return rb_yield(item);
+ }
return Qnil;
}
else {
@@ -783,75 +1064,118 @@ ary_delete(ary, item)
}
VALUE
-ary_delete_at(ary, at)
+rb_ary_delete_at(ary, pos)
VALUE ary;
- VALUE at;
+ long pos;
{
- int i1, i2, pos;
+ long i, len = RARRAY(ary)->len;
VALUE del = Qnil;
- ary_modify(ary);
- pos = NUM2INT(at);
- for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
- if (i1 == pos) {
- del = RARRAY(ary)->ptr[i1];
- continue;
- }
- if (i1 != i2) {
- RARRAY(ary)->ptr[i2] = RARRAY(ary)->ptr[i1];
- }
- i2++;
+ rb_ary_modify(ary);
+ if (pos >= len) return Qnil;
+ if (pos < 0) pos += len;
+ if (pos < 0) return Qnil;
+
+ del = RARRAY(ary)->ptr[pos];
+ for (i = pos + 1; i < len; i++, pos++) {
+ RARRAY(ary)->ptr[pos] = RARRAY(ary)->ptr[i];
}
- RARRAY(ary)->len = i2;
+ RARRAY(ary)->len = pos;
return del;
}
+VALUE
+rb_ary_delete_at_m(ary, pos)
+ VALUE ary, pos;
+{
+ return rb_ary_delete_at(ary, NUM2LONG(pos));
+}
+
+static VALUE
+rb_ary_slice_bang(argc, argv, ary)
+ int argc;
+ VALUE *argv;
+ VALUE ary;
+{
+ VALUE arg1, arg2;
+ long pos, len, i;
+
+ rb_ary_modify(ary);
+ if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
+ pos = NUM2LONG(arg1);
+ len = NUM2LONG(arg2);
+ delete_pos_len:
+ if (pos < 0) {
+ pos = RARRAY(ary)->len + pos;
+ }
+ arg2 = rb_ary_subseq(ary, pos, len);
+ rb_ary_replace(ary, pos, len, Qnil); /* Qnil/rb_ary_new2(0) */
+ return arg2;
+ }
+
+ if (!FIXNUM_P(arg1) && rb_range_beg_len(arg1, &pos, &len, RARRAY(ary)->len, 1)) {
+ goto delete_pos_len;
+ }
+
+ pos = NUM2LONG(arg1);
+ len = RARRAY(ary)->len;
+
+ if (pos >= len) return Qnil;
+ if (pos < 0) pos += len;
+ if (pos < 0) return Qnil;
+
+ arg2 = RARRAY(ary)->ptr[pos];
+ for (i = pos + 1; i < len; i++, pos++) {
+ RARRAY(ary)->ptr[pos] = RARRAY(ary)->ptr[i];
+ }
+ RARRAY(ary)->len = pos;
+
+ return arg2;
+}
+
static VALUE
-ary_delete_if(ary)
+rb_ary_reject_bang(ary)
VALUE ary;
{
- int i1, i2;
+ long i1, i2;
- ary_modify(ary);
+ rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
- if (rb_yield(RARRAY(ary)->ptr[i1])) continue;
+ if (RTEST(rb_yield(RARRAY(ary)->ptr[i1]))) continue;
if (i1 != i2) {
RARRAY(ary)->ptr[i2] = RARRAY(ary)->ptr[i1];
}
i2++;
}
+ if (RARRAY(ary)->len == i2) return Qnil;
RARRAY(ary)->len = i2;
return ary;
}
static VALUE
-ary_filter(ary)
+rb_ary_delete_if(ary)
VALUE ary;
{
- int i;
-
- ary_modify(ary);
- for (i = 0; i < RARRAY(ary)->len; i++) {
- RARRAY(ary)->ptr[i] = rb_yield(RARRAY(ary)->ptr[i]);
- }
+ rb_ary_reject_bang(ary);
return ary;
}
static VALUE
-ary_replace_method(ary, ary2)
+rb_ary_replace_m(ary, ary2)
VALUE ary, ary2;
{
- Check_Type(ary2, T_ARRAY);
- ary_replace(ary, 0, RARRAY(ary2)->len, ary2);
+ ary2 = to_ary(ary2);
+ rb_ary_replace(ary, 0, RARRAY(ary)->len, ary2);
return ary;
}
-static VALUE
-ary_clear(ary)
+VALUE
+rb_ary_clear(ary)
VALUE ary;
{
+ rb_ary_modify(ary);
RARRAY(ary)->len = 0;
if (ARY_DEFAULT_SIZE*3 < RARRAY(ary)->capa) {
RARRAY(ary)->capa = ARY_DEFAULT_SIZE * 2;
@@ -861,32 +1185,36 @@ ary_clear(ary)
}
static VALUE
-ary_fill(argc, argv, ary)
+rb_ary_fill(argc, argv, ary)
int argc;
VALUE *argv;
VALUE ary;
{
VALUE item, arg1, arg2;
- int beg, len, end;
+ long beg, end, len;
VALUE *p, *pend;
rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
- if (NIL_P(arg2) && beg_len(arg1, &beg, &len, RARRAY(ary)->len)) {
- /* beg and len set already */
- }
- else {
- beg = NUM2INT(arg1);
+ switch (argc) {
+ case 1:
+ beg = 0;
+ len = RARRAY(ary)->len - beg;
+ break;
+ case 2:
+ if (rb_range_beg_len(arg1, &beg, &len, RARRAY(ary)->len, 1)) {
+ break;
+ }
+ /* fall through */
+ case 3:
+ beg = NIL_P(arg1)?0:NUM2LONG(arg1);
if (beg < 0) {
beg = RARRAY(ary)->len + beg;
if (beg < 0) beg = 0;
}
- if (!NIL_P(arg2)) {
- len = NUM2INT(arg2);
- }
- else {
- len = RARRAY(ary)->len - beg;
- }
+ len = NIL_P(arg2)?RARRAY(ary)->len - beg:NUM2LONG(arg2);
+ break;
}
+ rb_ary_modify(ary);
end = beg + len;
if (end > RARRAY(ary)->len) {
if (end >= RARRAY(ary)->capa) {
@@ -894,7 +1222,7 @@ ary_fill(argc, argv, ary)
REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa);
}
if (beg > RARRAY(ary)->len) {
- memclear(RARRAY(ary)->ptr+RARRAY(ary)->len, end-RARRAY(ary)->len);
+ rb_mem_clear(RARRAY(ary)->ptr+RARRAY(ary)->len,end-RARRAY(ary)->len);
}
RARRAY(ary)->len = end;
}
@@ -907,16 +1235,13 @@ ary_fill(argc, argv, ary)
}
VALUE
-ary_plus(x, y)
+rb_ary_plus(x, y)
VALUE x, y;
{
VALUE z;
- if (TYPE(y) != T_ARRAY) {
- return ary_plus(x, rb_Array(y));
- }
-
- z = ary_new2(RARRAY(x)->len + RARRAY(y)->len);
+ y = to_ary(y);
+ z = rb_ary_new2(RARRAY(x)->len + RARRAY(y)->len);
MEMCPY(RARRAY(z)->ptr, RARRAY(x)->ptr, VALUE, RARRAY(x)->len);
MEMCPY(RARRAY(z)->ptr+RARRAY(x)->len, RARRAY(y)->ptr, VALUE, RARRAY(y)->len);
RARRAY(z)->len = RARRAY(x)->len + RARRAY(y)->len;
@@ -924,43 +1249,46 @@ ary_plus(x, y)
}
VALUE
-ary_concat(x, y)
+rb_ary_concat(x, y)
VALUE x, y;
{
- VALUE *p, *pend;
+ long xlen = RARRAY(x)->len;
+ long ylen;
- if (TYPE(y) != T_ARRAY) {
- return ary_concat(x, rb_Array(y));
- }
-
- p = RARRAY(y)->ptr;
- pend = p + RARRAY(y)->len;
- while (p < pend) {
- ary_store(x, RARRAY(x)->len, *p);
- p++;
+ y = to_ary(y);
+ ylen = RARRAY(y)->len;
+ if (ylen > 0) {
+ rb_ary_modify(x);
+ if (xlen + ylen > RARRAY(x)->capa) {
+ RARRAY(x)->capa = xlen + ylen;
+ REALLOC_N(RARRAY(x)->ptr, VALUE, RARRAY(x)->capa);
+ }
+ MEMCPY(RARRAY(x)->ptr+xlen, RARRAY(y)->ptr, VALUE, ylen);
+ RARRAY(x)->len = xlen + ylen;
}
return x;
}
static VALUE
-ary_times(ary, times)
+rb_ary_times(ary, times)
VALUE ary;
VALUE times;
{
VALUE ary2;
- int i, len;
+ long i, len;
if (TYPE(times) == T_STRING) {
- return ary_join(ary, times);
+ return rb_ary_join(ary, times);
}
- len = NUM2INT(times) * RARRAY(ary)->len;
- ary2 = ary_new2(len);
- RARRAY(ary2)->len = len;
-
+ len = NUM2LONG(times);
if (len < 0) {
- ArgError("negative argument");
+ rb_raise(rb_eArgError, "negative argument");
}
+ len *= RARRAY(ary)->len;
+
+ ary2 = rb_ary_new2(len);
+ RARRAY(ary2)->len = len;
for (i=0; i<len; i+=RARRAY(ary)->len) {
MEMCPY(RARRAY(ary2)->ptr+i, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len);
@@ -970,7 +1298,7 @@ ary_times(ary, times)
}
VALUE
-ary_assoc(ary, key)
+rb_ary_assoc(ary, key)
VALUE ary;
VALUE key;
{
@@ -979,7 +1307,7 @@ ary_assoc(ary, key)
p = RARRAY(ary)->ptr; pend = p + RARRAY(ary)->len;
while (p < pend) {
if (TYPE(*p) == T_ARRAY
- && RARRAY(*p)->len > 1
+ && RARRAY(*p)->len > 0
&& rb_equal(RARRAY(*p)->ptr[0], key))
return *p;
p++;
@@ -988,7 +1316,7 @@ ary_assoc(ary, key)
}
VALUE
-ary_rassoc(ary, value)
+rb_ary_rassoc(ary, value)
VALUE ary;
VALUE value;
{
@@ -1006,71 +1334,75 @@ ary_rassoc(ary, value)
}
static VALUE
-ary_equal(ary1, ary2)
+rb_ary_equal(ary1, ary2)
VALUE ary1, ary2;
{
- int i;
+ long i;
- if (TYPE(ary2) != T_ARRAY) return FALSE;
- if (RARRAY(ary1)->len != RARRAY(ary2)->len) return FALSE;
+ if (TYPE(ary2) != T_ARRAY) return Qfalse;
+ if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
for (i=0; i<RARRAY(ary1)->len; i++) {
if (!rb_equal(RARRAY(ary1)->ptr[i], RARRAY(ary2)->ptr[i]))
- return FALSE;
+ return Qfalse;
}
- return TRUE;
+ return Qtrue;
}
static VALUE
-ary_eql(ary1, ary2)
+rb_ary_eql(ary1, ary2)
VALUE ary1, ary2;
{
- int i;
+ long i;
- if (TYPE(ary2) != T_ARRAY) return FALSE;
+ if (TYPE(ary2) != T_ARRAY) return Qfalse;
if (RARRAY(ary1)->len != RARRAY(ary2)->len)
- return FALSE;
+ return Qfalse;
for (i=0; i<RARRAY(ary1)->len; i++) {
if (!rb_eql(RARRAY(ary1)->ptr[i], RARRAY(ary2)->ptr[i]))
- return FALSE;
+ return Qfalse;
}
- return TRUE;
+ return Qtrue;
}
static VALUE
-ary_hash(ary)
+rb_ary_hash(ary)
VALUE ary;
{
- int h, i;
+ long i;
+ VALUE n;
+ long h;
h = RARRAY(ary)->len;
for (i=0; i<RARRAY(ary)->len; i++) {
- h ^= rb_hash(RARRAY(ary)->ptr[i]);
+ h = (h<<1) | (h<0 ? 1 : 0);
+ n = rb_hash(RARRAY(ary)->ptr[i]);
+ h ^= NUM2LONG(n);
}
return INT2FIX(h);
}
VALUE
-ary_includes(ary, item)
+rb_ary_includes(ary, item)
VALUE ary;
VALUE item;
{
- int i;
+ long i;
for (i=0; i<RARRAY(ary)->len; i++) {
if (rb_equal(RARRAY(ary)->ptr[i], item)) {
- return TRUE;
+ return Qtrue;
}
}
- return FALSE;
+ return Qfalse;
}
-VALUE
-ary_cmp(ary, ary2)
+static VALUE
+rb_ary_cmp(ary, ary2)
VALUE ary;
VALUE ary2;
{
- int i, len;
+ long i, len;
- Check_Type(ary2, T_ARRAY);
+ ary2 = to_ary(ary2);
len = RARRAY(ary)->len;
if (len > RARRAY(ary2)->len) {
len = RARRAY(ary2)->len;
@@ -1088,111 +1420,130 @@ ary_cmp(ary, ary2)
}
static VALUE
-ary_diff(ary1, ary2)
+rb_ary_diff(ary1, ary2)
VALUE ary1, ary2;
{
VALUE ary3;
- int i;
+ long i;
- Check_Type(ary2, T_ARRAY);
- ary3 = ary_new();
+ ary2 = to_ary(ary2);
+ ary3 = rb_ary_new();
for (i=0; i<RARRAY(ary1)->len; i++) {
- if (ary_includes(ary2, RARRAY(ary1)->ptr[i])) continue;
- if (ary_includes(ary3, RARRAY(ary1)->ptr[i])) continue;
- ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ if (rb_ary_includes(ary2, RARRAY(ary1)->ptr[i])) continue;
+ if (rb_ary_includes(ary3, RARRAY(ary1)->ptr[i])) continue;
+ rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
}
return ary3;
}
static VALUE
-ary_and(ary1, ary2)
+ary_make_hash(ary1, ary2)
VALUE ary1, ary2;
{
- VALUE ary3;
- int i;
+ VALUE hash = rb_hash_new();
+ int i, n;
- Check_Type(ary2, T_ARRAY);
- ary3 = ary_new();
for (i=0; i<RARRAY(ary1)->len; i++) {
- if (ary_includes(ary2, RARRAY(ary1)->ptr[i])
- && !ary_includes(ary3, RARRAY(ary1)->ptr[i])) {
- ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ rb_hash_aset(hash, RARRAY(ary1)->ptr[i], Qtrue);
+ }
+ if (ary2) {
+ for (i=0; i<RARRAY(ary2)->len; i++) {
+ rb_hash_aset(hash, RARRAY(ary2)->ptr[i], Qtrue);
}
}
- return ary3;
+ return hash;
}
static VALUE
-ary_or(ary1, ary2)
+rb_ary_and(ary1, ary2)
VALUE ary1, ary2;
{
- VALUE ary3;
- int i;
+ VALUE hash;
+ VALUE ary3 = rb_ary_new();
+ long i;
- if (TYPE(ary2) != T_ARRAY) {
- if (ary_includes(ary1, ary2)) return ary1;
- else return ary_plus(ary1, ary2);
+ ary2 = to_ary(ary2);
+ hash = ary_make_hash(ary2, 0);
+
+ for (i=0; i<RARRAY(ary1)->len; i++) {
+ VALUE v = RARRAY(ary1)->ptr[i];
+ if (st_delete(RHASH(hash)->tbl, &v, 0)) {
+ rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ }
}
- ary3 = ary_new();
+ return ary3;
+}
+
+static VALUE
+rb_ary_or(ary1, ary2)
+ VALUE ary1, ary2;
+{
+ VALUE hash;
+ VALUE ary3 = rb_ary_new();
+ VALUE v;
+ long i;
+
+ ary2 = to_ary(ary2);
+ hash = ary_make_hash(ary1, ary2);
+
for (i=0; i<RARRAY(ary1)->len; i++) {
- if (!ary_includes(ary3, RARRAY(ary1)->ptr[i]))
- ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ v = RARRAY(ary1)->ptr[i];
+ if (st_delete(RHASH(hash)->tbl, &v, 0)) {
+ rb_ary_push(ary3, RARRAY(ary1)->ptr[i]);
+ }
}
for (i=0; i<RARRAY(ary2)->len; i++) {
- if (!ary_includes(ary3, RARRAY(ary2)->ptr[i]))
- ary_push(ary3, RARRAY(ary2)->ptr[i]);
+ v = RARRAY(ary2)->ptr[i];
+ if (st_delete(RHASH(hash)->tbl, &v, 0)) {
+ rb_ary_push(ary3, RARRAY(ary2)->ptr[i]);
+ }
}
+
return ary3;
}
static VALUE
-ary_uniq_bang(ary)
+rb_ary_uniq_bang(ary)
VALUE ary;
{
- VALUE *p, *q, *t, *end;
- VALUE v;
- int i;
+ VALUE hash = ary_make_hash(ary, 0);
+ VALUE *p, *q, *end;
- ary_modify(ary);
- p = RARRAY(ary)->ptr;
- end = p + RARRAY(ary)->len;
+ if (RARRAY(ary)->len == RHASH(hash)->tbl->num_entries) {
+ return Qnil;
+ }
+ rb_ary_modify(ary);
+ p = q = RARRAY(ary)->ptr;
+ end = p + RARRAY(ary)->len;
while (p < end) {
- v = *p++;
- q = t = p;
- while (q < end) {
- if (rb_equal(*q, v)) q++;
- else *t++ = *q++;
+ VALUE v = *p++;
+ if (st_delete(RHASH(hash)->tbl, &v, 0)) {
+ *q++ = *(p-1);
}
- end = t;
- }
- if (RARRAY(ary)->len == (end - RARRAY(ary)->ptr)) {
- return Qnil;
}
-
- RARRAY(ary)->len = (end - RARRAY(ary)->ptr);
+ RARRAY(ary)->len = (q - RARRAY(ary)->ptr);
return ary;
}
static VALUE
-ary_uniq(ary)
+rb_ary_uniq(ary)
VALUE ary;
{
- VALUE v = ary_uniq_bang(ary_clone(ary));
-
- if (NIL_P(v)) return ary;
- return v;
+ ary = rb_obj_dup(ary);
+ rb_ary_uniq_bang(ary);
+ return ary;
}
static VALUE
-ary_compact_bang(ary)
+rb_ary_compact_bang(ary)
VALUE ary;
{
VALUE *p, *t, *end;
- ary_modify(ary);
+ rb_ary_modify(ary);
p = t = RARRAY(ary)->ptr;
end = p + RARRAY(ary)->len;
while (t < end) {
@@ -1209,20 +1560,19 @@ ary_compact_bang(ary)
}
static VALUE
-ary_compact(ary)
+rb_ary_compact(ary)
VALUE ary;
{
- VALUE v = ary_compact_bang(ary_clone(ary));
-
- if (NIL_P(v)) return ary;
- return v;
+ ary = rb_obj_dup(ary);
+ rb_ary_compact_bang(ary);
+ return ary;
}
static VALUE
-ary_nitems(ary)
+rb_ary_nitems(ary)
VALUE ary;
{
- int n = 0;
+ long n = 0;
VALUE *p, *pend;
p = RARRAY(ary)->ptr;
@@ -1231,120 +1581,152 @@ ary_nitems(ary)
if (!NIL_P(*p)) n++;
p++;
}
- return INT2FIX(n);
+ return INT2NUM(n);
+}
+
+static int
+flatten(ary, idx, ary2, memo)
+ VALUE ary;
+ long idx;
+ VALUE ary2, memo;
+{
+ VALUE id;
+ long i = idx;
+ long n, lim = idx + RARRAY(ary2)->len;
+
+ id = rb_obj_id(ary2);
+ if (rb_ary_includes(memo, id)) {
+ rb_raise(rb_eArgError, "tried to flatten recursive array");
+ }
+ rb_ary_push(memo, id);
+ rb_ary_replace(ary, idx, 1, ary2);
+ while (i < lim) {
+ if (TYPE(RARRAY(ary)->ptr[i]) == T_ARRAY) {
+ n = flatten(ary, i, RARRAY(ary)->ptr[i], memo);
+ i += n; lim += n;
+ }
+ i++;
+ }
+ rb_ary_pop(memo);
+
+ return lim - idx - 1; /* returns number of increased items */
}
static VALUE
-ary_flatten_bang(ary)
+rb_ary_flatten_bang(ary)
VALUE ary;
{
- int i;
+ long i = 0;
int mod = 0;
+ VALUE memo = Qnil;
- ary_modify(ary);
- for (;;) {
- int lmod = 0;
+ rb_ary_modify(ary);
+ while (i<RARRAY(ary)->len) {
+ VALUE ary2 = RARRAY(ary)->ptr[i];
- for (i=0; i<RARRAY(ary)->len; i++) {
- if (TYPE(RARRAY(ary)->ptr[i]) == T_ARRAY) {
- VALUE ary2 = RARRAY(ary)->ptr[i];
-
- ary_replace(ary, i, RARRAY(ary2)->len, ary2);
- i += RARRAY(ary2)->len - 1;
- lmod++;
+ if (TYPE(ary2) == T_ARRAY) {
+ if (NIL_P(memo)) {
+ memo = rb_ary_new();
}
+ i += flatten(ary, i, ary2, memo);
+ mod = 1;
}
- if (lmod == 0) break;
- mod = lmod;
+ i++;
}
-
if (mod == 0) return Qnil;
return ary;
}
static VALUE
-ary_flatten(ary)
+rb_ary_flatten(ary)
VALUE ary;
{
- VALUE v = ary_flatten_bang(ary_clone(ary));
-
- if (NIL_P(v)) return ary;
- return v;
+ ary = rb_obj_dup(ary);
+ rb_ary_flatten_bang(ary);
+ return ary;
}
-extern VALUE mEnumerable;
-
void
Init_Array()
{
- cArray = rb_define_class("Array", cObject);
- rb_include_module(cArray, mEnumerable);
-
- rb_define_singleton_method(cArray, "new", ary_s_new, -1);
- rb_define_singleton_method(cArray, "[]", ary_s_create, -1);
- rb_define_method(cArray, "to_s", ary_to_s, 0);
- rb_define_method(cArray, "inspect", ary_inspect, 0);
- rb_define_method(cArray, "to_a", ary_to_a, 0);
-
- rb_define_method(cArray, "freeze", ary_freeze, 0);
- rb_define_method(cArray, "frozen?", ary_frozen_p, 0);
-
- rb_define_method(cArray, "==", ary_equal, 1);
- rb_define_method(cArray, "eql?", ary_eql, 1);
- rb_define_method(cArray, "hash", ary_hash, 0);
-
- rb_define_method(cArray, "[]", ary_aref, -1);
- rb_define_method(cArray, "[]=", ary_aset, -1);
- rb_define_method(cArray, "concat", ary_concat, 1);
- rb_define_method(cArray, "<<", ary_push, 1);
- rb_define_method(cArray, "push", ary_push_method, -1);
- rb_define_method(cArray, "pop", ary_pop, 0);
- rb_define_method(cArray, "shift", ary_shift, 0);
- rb_define_method(cArray, "unshift", ary_unshift, 1);
- rb_define_method(cArray, "each", ary_each, 0);
- rb_define_method(cArray, "each_index", ary_each_index, 0);
- rb_define_method(cArray, "reverse_each", ary_reverse_each, 0);
- rb_define_method(cArray, "length", ary_length, 0);
- rb_define_alias(cArray, "size", "length");
- rb_define_method(cArray, "empty?", ary_empty_p, 0);
- rb_define_method(cArray, "index", ary_index, 1);
- rb_define_method(cArray, "indexes", ary_indexes, -1);
- rb_define_method(cArray, "indices", ary_indexes, -1);
- rb_define_method(cArray, "clone", ary_clone, 0);
- rb_define_method(cArray, "dup", ary_dup, 0);
- rb_define_method(cArray, "join", ary_join_method, -1);
- rb_define_method(cArray, "reverse", ary_reverse_method, 0);
- rb_define_method(cArray, "reverse!", ary_reverse, 0);
- rb_define_method(cArray, "sort", ary_sort, 0);
- rb_define_method(cArray, "sort!", ary_sort_bang, 0);
- rb_define_method(cArray, "delete", ary_delete, 1);
- rb_define_method(cArray, "delete_at", ary_delete_at, 1);
- rb_define_method(cArray, "delete_if", ary_delete_if, 0);
- rb_define_method(cArray, "filter", ary_filter, 0);
- rb_define_method(cArray, "replace", ary_replace_method, 1);
- rb_define_method(cArray, "clear", ary_clear, 0);
- rb_define_method(cArray, "fill", ary_fill, -1);
- rb_define_method(cArray, "include?", ary_includes, 1);
- rb_define_method(cArray, "===", ary_includes, 1);
- rb_define_method(cArray, "<=>", ary_cmp, 1);
-
- rb_define_method(cArray, "assoc", ary_assoc, 1);
- rb_define_method(cArray, "rassoc", ary_rassoc, 1);
-
- rb_define_method(cArray, "+", ary_plus, 1);
- rb_define_method(cArray, "*", ary_times, 1);
-
- rb_define_method(cArray, "-", ary_diff, 1);
- rb_define_method(cArray, "&", ary_and, 1);
- rb_define_method(cArray, "|", ary_or, 1);
-
- rb_define_method(cArray, "uniq", ary_uniq, 0);
- rb_define_method(cArray, "uniq!", ary_uniq_bang, 0);
- rb_define_method(cArray, "compact", ary_compact, 0);
- rb_define_method(cArray, "compact!", ary_compact_bang, 0);
- rb_define_method(cArray, "flatten", ary_flatten, 0);
- rb_define_method(cArray, "flatten!", ary_flatten_bang, 0);
- rb_define_method(cArray, "nitems", ary_nitems, 0);
+ rb_cArray = rb_define_class("Array", rb_cObject);
+ rb_include_module(rb_cArray, rb_mEnumerable);
+
+ rb_define_singleton_method(rb_cArray, "new", rb_ary_s_new, -1);
+ rb_define_singleton_method(rb_cArray, "[]", rb_ary_s_create, -1);
+ rb_define_method(rb_cArray, "initialize", rb_ary_initialize, -1);
+ rb_define_method(rb_cArray, "to_s", rb_ary_to_s, 0);
+ rb_define_method(rb_cArray, "inspect", rb_ary_inspect, 0);
+ rb_define_method(rb_cArray, "to_a", rb_ary_to_a, 0);
+ rb_define_method(rb_cArray, "to_ary", rb_ary_to_a, 0);
+ rb_define_method(rb_cArray, "frozen?", rb_ary_frozen_p, 0);
+
+ rb_define_method(rb_cArray, "==", rb_ary_equal, 1);
+ rb_define_method(rb_cArray, "eql?", rb_ary_eql, 1);
+ rb_define_method(rb_cArray, "hash", rb_ary_hash, 0);
+ rb_define_method(rb_cArray, "===", rb_ary_equal, 1);
+
+ rb_define_method(rb_cArray, "[]", rb_ary_aref, -1);
+ rb_define_method(rb_cArray, "[]=", rb_ary_aset, -1);
+ rb_define_method(rb_cArray, "at", rb_ary_at, 1);
+ rb_define_method(rb_cArray, "first", rb_ary_first, 0);
+ rb_define_method(rb_cArray, "last", rb_ary_last, 0);
+ rb_define_method(rb_cArray, "concat", rb_ary_concat, 1);
+ rb_define_method(rb_cArray, "<<", rb_ary_push, 1);
+ rb_define_method(rb_cArray, "push", rb_ary_push_m, -1);
+ rb_define_method(rb_cArray, "pop", rb_ary_pop, 0);
+ rb_define_method(rb_cArray, "shift", rb_ary_shift, 0);
+ rb_define_method(rb_cArray, "unshift", rb_ary_unshift_m, -1);
+ rb_define_method(rb_cArray, "each", rb_ary_each, 0);
+ rb_define_method(rb_cArray, "each_index", rb_ary_each_index, 0);
+ rb_define_method(rb_cArray, "reverse_each", rb_ary_reverse_each, 0);
+ rb_define_method(rb_cArray, "length", rb_ary_length, 0);
+ rb_define_alias(rb_cArray, "size", "length");
+ rb_define_method(rb_cArray, "empty?", rb_ary_empty_p, 0);
+ rb_define_method(rb_cArray, "index", rb_ary_index, 1);
+ rb_define_method(rb_cArray, "rindex", rb_ary_rindex, 1);
+ rb_define_method(rb_cArray, "indexes", rb_ary_indexes, -1);
+ rb_define_method(rb_cArray, "indices", rb_ary_indexes, -1);
+ rb_define_method(rb_cArray, "clone", rb_ary_clone, 0);
+ rb_define_method(rb_cArray, "join", rb_ary_join_m, -1);
+ rb_define_method(rb_cArray, "reverse", rb_ary_reverse_m, 0);
+ rb_define_method(rb_cArray, "reverse!", rb_ary_reverse_bang, 0);
+ rb_define_method(rb_cArray, "sort", rb_ary_sort, 0);
+ rb_define_method(rb_cArray, "sort!", rb_ary_sort_bang, 0);
+ rb_define_method(rb_cArray, "collect", rb_ary_collect, 0);
+ rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
+ rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
+ rb_define_method(rb_cArray, "filter", rb_ary_filter, 0);
+ rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
+ rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at_m, 1);
+ rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
+ rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);
+ rb_define_method(rb_cArray, "replace", rb_ary_replace_m, 1);
+ rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
+ rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);
+ rb_define_method(rb_cArray, "include?", rb_ary_includes, 1);
+ rb_define_method(rb_cArray, "<=>", rb_ary_cmp, 1);
+
+ rb_define_method(rb_cArray, "slice", rb_ary_aref, -1);
+ rb_define_method(rb_cArray, "slice!", rb_ary_slice_bang, -1);
+
+ rb_define_method(rb_cArray, "assoc", rb_ary_assoc, 1);
+ rb_define_method(rb_cArray, "rassoc", rb_ary_rassoc, 1);
+
+ rb_define_method(rb_cArray, "+", rb_ary_plus, 1);
+ rb_define_method(rb_cArray, "*", rb_ary_times, 1);
+
+ rb_define_method(rb_cArray, "-", rb_ary_diff, 1);
+ rb_define_method(rb_cArray, "&", rb_ary_and, 1);
+ rb_define_method(rb_cArray, "|", rb_ary_or, 1);
+
+ rb_define_method(rb_cArray, "uniq", rb_ary_uniq, 0);
+ rb_define_method(rb_cArray, "uniq!", rb_ary_uniq_bang, 0);
+ rb_define_method(rb_cArray, "compact", rb_ary_compact, 0);
+ rb_define_method(rb_cArray, "compact!", rb_ary_compact_bang, 0);
+ rb_define_method(rb_cArray, "flatten", rb_ary_flatten, 0);
+ rb_define_method(rb_cArray, "flatten!", rb_ary_flatten_bang, 0);
+ rb_define_method(rb_cArray, "nitems", rb_ary_nitems, 0);
cmp = rb_intern("<=>");
}
diff --git a/bignum.c b/bignum.c
index ac84ae410c..3159d143c7 100644
--- a/bignum.c
+++ b/bignum.c
@@ -1,4 +1,4 @@
-/************************************************
+/**********************************************************************
bignum.c -
@@ -6,70 +6,89 @@
$Date$
created at: Fri Jun 10 00:48:55 JST 1994
-************************************************/
+ Copyright (C) 1993-2000 Yukihiro Matsumoto
+
+**********************************************************************/
#include "ruby.h"
-#include <ctype.h>
#include <math.h>
+#include <ctype.h>
-extern VALUE cInteger;
-VALUE cBignum;
+VALUE rb_cBignum;
-#define BDIGITS(x) RBIGNUM(x)->digits
-#define BITSPERDIG (sizeof(USHORT)*CHAR_BIT)
-#define BIGRAD (1L << BITSPERDIG)
-#define DIGSPERINT ((UINT)(sizeof(INT)/sizeof(USHORT)))
-#define BIGUP(x) ((UINT)(x) << BITSPERDIG)
-#define BIGDN(x) ((x) >> BITSPERDIG)
-#define BIGLO(x) ((x) & (BIGRAD-1))
+#if defined __MINGW32__
+#define USHORT _USHORT
+#endif
+
+#if SIZEOF_INT*2 <= SIZEOF_LONG_LONG
+typedef unsigned int BDIGIT;
+typedef unsigned long long BDIGIT_DBL;
+typedef long long BDIGIT_DBL_SIGNED;
+#elif SIZEOF_INT*2 <= SIZEOF___INT64
+typedef unsigned int BDIGIT;
+typedef unsigned __int64 BDIGIT_DBL;
+typedef __int64 BDIGIT_DBL_SIGNED;
+#else
+typedef unsigned short BDIGIT;
+typedef unsigned long BDIGIT_DBL;
+typedef long BDIGIT_DBL_SIGNED;
+#endif
+
+#define BDIGITS(x) ((BDIGIT*)RBIGNUM(x)->digits)
+#define BITSPERDIG (sizeof(BDIGIT)*CHAR_BIT)
+#define BIGRAD ((BDIGIT_DBL)1 << BITSPERDIG)
+#define DIGSPERLONG ((unsigned int)(sizeof(long)/sizeof(BDIGIT)))
+#define BIGUP(x) ((BDIGIT_DBL)(x) << BITSPERDIG)
+#define BIGDN(x) RSHIFT(x,BITSPERDIG)
+#define BIGLO(x) ((BDIGIT)((x) & (BIGRAD-1)))
static VALUE
bignew_1(klass, len, sign)
VALUE klass;
- UINT len;
+ long len;
char sign;
{
NEWOBJ(big, struct RBignum);
OBJSETUP(big, klass, T_BIGNUM);
big->sign = sign;
big->len = len;
- BDIGITS(big) = ALLOC_N(USHORT, len);
+ big->digits = ALLOC_N(BDIGIT, len);
return (VALUE)big;
}
-#define bignew(len,sign) bignew_1(cBignum,len,sign)
+#define bignew(len,sign) bignew_1(rb_cBignum,len,sign)
VALUE
-big_clone(x)
+rb_big_clone(x)
VALUE x;
{
VALUE z = bignew_1(CLASS_OF(x), RBIGNUM(x)->len, RBIGNUM(x)->sign);
- MEMCPY(BDIGITS(z), BDIGITS(x), USHORT, RBIGNUM(x)->len);
+ MEMCPY(BDIGITS(z), BDIGITS(x), BDIGIT, RBIGNUM(x)->len);
return z;
}
void
-big_2comp(x) /* get 2's complement */
+rb_big_2comp(x) /* get 2's complement */
VALUE x;
{
- UINT i = RBIGNUM(x)->len;
- USHORT *ds = BDIGITS(x);
- long num;
+ long i = RBIGNUM(x)->len;
+ BDIGIT *ds = BDIGITS(x);
+ BDIGIT_DBL num;
while (i--) ds[i] = ~ds[i];
i = 0; num = 1;
do {
- num += (long)ds[i];
+ num += ds[i];
ds[i++] = BIGLO(num);
num = BIGDN(num);
} while (i < RBIGNUM(x)->len);
if (ds[0] == 1 || ds[0] == 0) {
- for (i=1;i<RBIGNUM(x)->len;i++) {
+ for (i=1; i<RBIGNUM(x)->len; i++) {
if (ds[i] != 0) return;
}
- REALLOC_N(BDIGITS(x), USHORT, RBIGNUM(x)->len++);
+ REALLOC_N(RBIGNUM(x)->digits, BDIGIT, RBIGNUM(x)->len++);
ds = BDIGITS(x);
ds[RBIGNUM(x)->len-1] = 1;
}
@@ -79,68 +98,71 @@ static VALUE
bignorm(x)
VALUE x;
{
- UINT len = RBIGNUM(x)->len;
- USHORT *ds = BDIGITS(x);
-
- while (len-- && !ds[len]) ;
- RBIGNUM(x)->len = ++len;
-
- if (len*sizeof(USHORT) < sizeof(VALUE) ||
- (len*sizeof(USHORT) == sizeof(VALUE) &&
- ds[sizeof(VALUE)/sizeof(USHORT)-1] <= 0x3fff)) {
- long num = 0;
- while (len--) {
- num = BIGUP(num) + ds[len];
- }
- if (RBIGNUM(x)->sign) {
- if (POSFIXABLE(num)) return INT2FIX(num);
+ if (!FIXNUM_P(x)) {
+ long len = RBIGNUM(x)->len;
+ BDIGIT *ds = BDIGITS(x);
+
+ while (len-- && !ds[len]) ;
+ RBIGNUM(x)->len = ++len;
+
+ if (len*sizeof(BDIGIT) <= sizeof(VALUE)) {
+ long num = 0;
+ while (len--) {
+ num = BIGUP(num) + ds[len];
+ }
+ if (num >= 0) {
+ if (RBIGNUM(x)->sign) {
+ if (POSFIXABLE(num)) return INT2FIX(num);
+ }
+ else if (NEGFIXABLE(-(long)num)) return INT2FIX(-(long)num);
+ }
}
- else if (NEGFIXABLE(-num)) return INT2FIX(-num);
}
return x;
}
VALUE
-big_norm(x)
+rb_big_norm(x)
VALUE x;
{
- return bignorm(RBIGNUM(x));
+ return bignorm(x);
}
VALUE
-uint2big(n)
- UINT n;
+rb_uint2big(n)
+ unsigned long n;
{
- UINT i = 0;
- USHORT *digits;
+ BDIGIT_DBL num = n;
+ long i = 0;
+ BDIGIT *digits;
VALUE big;
i = 0;
- big = bignew(DIGSPERINT, 1);
+ big = bignew(DIGSPERLONG, 1);
digits = BDIGITS(big);
- while (i < DIGSPERINT) {
- digits[i++] = BIGLO(n);
- n = BIGDN(n);
+ while (i < DIGSPERLONG) {
+ digits[i++] = BIGLO(num);
+ num = BIGDN(num);
}
- i = DIGSPERINT;
+ i = DIGSPERLONG;
while (i-- && !digits[i]) ;
RBIGNUM(big)->len = i+1;
return big;
}
VALUE
-int2big(n)
- INT n;
+rb_int2big(n)
+ long n;
{
- INT neg = 0;
+ long neg = 0;
VALUE big;
if (n < 0) {
n = -n;
neg = 1;
}
- big = uint2big(n);
+ big = rb_uint2big(n);
if (neg) {
RBIGNUM(big)->sign = 0;
}
@@ -148,100 +170,139 @@ int2big(n)
}
VALUE
-uint2inum(n)
- UINT n;
+rb_uint2inum(n)
+ unsigned long n;
{
if (POSFIXABLE(n)) return INT2FIX(n);
- return uint2big(n);
+ return rb_uint2big(n);
}
VALUE
-int2inum(n)
- INT n;
+rb_int2inum(n)
+ long n;
{
if (FIXABLE(n)) return INT2FIX(n);
- return int2big(n);
+ return rb_int2big(n);
}
VALUE
-str2inum(str, base)
- UCHAR *str;
+rb_cstr2inum(str, base)
+ const char *str;
int base;
{
+ const char *s = str;
+ char *end;
+ int badcheck = (base==0)?1:0;
char sign = 1, c;
- unsigned long num;
- UINT len, blen = 1, i;
+ BDIGIT_DBL num;
+ long len, blen = 1;
+ long i;
VALUE z;
- USHORT *zds;
+ BDIGIT *zds;
+
+ while (*str && ISSPACE(*str)) str++;
- while (isspace(*str)) str++;
- if (*str == '-') {
+ if (str[0] == '+') {
+ str++;
+ }
+ else if (str[0] == '-') {
str++;
sign = 0;
}
+ if (str[0] == '+' || str[0] == '-') {
+ if (badcheck) goto bad;
+ return INT2FIX(0);
+ }
if (base == 0) {
- if (*str == '0') {
- str++;
- if (*str == 'x' || *str == 'X') {
- str++;
+ if (str[0] == '0') {
+ if (str[1] == 'x' || str[1] == 'X') {
base = 16;
}
+ else if (str[1] == 'b' || str[1] == 'B') {
+ base = 2;
+ }
else {
base = 8;
}
- if (*str == '\0') return INT2FIX(0);
}
else {
base = 10;
}
}
if (base == 8) {
- while (str[0] == '0') str++;
+ while (*str == '0') str++;
+ if (!*str) return INT2FIX(0);
+ while (*str == '_') str++;
len = 3*strlen(str)*sizeof(char);
}
- else { /* base == 10 or 16 */
+ else { /* base == 10, 2 or 16 */
if (base == 16 && str[0] == '0' && (str[1] == 'x'||str[1] == 'X')) {
str += 2;
}
- while (str[0] == '0') str++;
+ if (base == 2 && str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
+ str += 2;
+ }
+ while (*str && *str == '0') str++;
+ if (!*str) str--;
len = 4*strlen(str)*sizeof(char);
}
if (len <= (sizeof(VALUE)*CHAR_BIT)) {
- UINT val = strtoul((char*)str, 0, base);
+ unsigned long val = strtoul((char*)str, &end, base);
+
+ if (*end == '_') goto bigparse;
+ if (badcheck) {
+ if (end == str) goto bad; /* no number */
+ while (*end && ISSPACE(*end)) end++;
+ if (*end) { /* trailing garbage */
+ bad:
+ rb_raise(rb_eArgError, "invalid value for Integer: \"%s\"", s);
+ }
+ }
if (POSFIXABLE(val)) {
if (sign) return INT2FIX(val);
else {
- INT result = -(INT)val;
+ long result = -(long)val;
return INT2FIX(result);
}
}
else {
- VALUE big = uint2big(val);
+ VALUE big = rb_uint2big(val);
RBIGNUM(big)->sign = sign;
return big;
}
}
+ bigparse:
len = (len/BITSPERDIG)+1;
+ if (badcheck && *str == '_') goto bad;
z = bignew(len, sign);
zds = BDIGITS(z);
for (i=len;i--;) zds[i]=0;
while (c = *str++) {
switch (c) {
+ case '8': case '9':
+ if (base == 8) {
+ c = base;
+ break;
+ }
case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
+ case '5': case '6': case '7':
c = c - '0';
break;
case 'a': case 'b': case 'c':
case 'd': case 'e': case 'f':
- c = c - 'a' + 10;
+ if (base != 16) c = base;
+ else c = c - 'a' + 10;
break;
case 'A': case 'B': case 'C':
case 'D': case 'E': case 'F':
- c = c - 'A' + 10;
+ if (base != 16) c = base;
+ else c = c - 'A' + 10;
break;
+ case '_':
+ continue;
default:
c = base;
break;
@@ -251,7 +312,7 @@ str2inum(str, base)
num = c;
for (;;) {
while (i<blen) {
- num += zds[i]*base;
+ num += (BDIGIT_DBL)zds[i]*base;
zds[i++] = BIGLO(num);
num = BIGDN(num);
}
@@ -262,66 +323,98 @@ str2inum(str, base)
break;
}
}
+ if (badcheck) {
+ str--;
+ if (s+1 < str && str[-1] == '_') goto bad;
+ if (ISSPACE(c)) {
+ while (*str && ISSPACE(*str)) str++;
+ }
+ if (*str) goto bad;
+ }
+
return bignorm(z);
}
+VALUE
+rb_str2inum(str, base)
+ VALUE str;
+ int base;
+{
+ char *s;
+ int len;
+
+ s = rb_str2cstr(str, &len);
+ if (s[len]) { /* no sentinel somehow */
+ char *p = ALLOCA_N(char, len+1);
+
+ MEMCPY(p, s, char, len);
+ p[len] = '\0';
+ s = p;
+ }
+ if (len != strlen(s)) {
+ rb_raise(rb_eArgError, "string for Integer contains null byte");
+ }
+ return rb_cstr2inum(s, base);
+}
+
static char hexmap[] = "0123456789abcdef";
VALUE
-big2str(x, base)
+rb_big2str(x, base)
VALUE x;
int base;
{
- VALUE t;
- USHORT *ds;
- UINT i, j, hbase;
+ volatile VALUE t;
+ BDIGIT *ds;
+ long i, j, hbase;
VALUE ss;
- UCHAR *s, c;
+ char *s, c;
if (FIXNUM_P(x)) {
- return fix2str(x, base);
+ return rb_fix2str(x, base);
}
i = RBIGNUM(x)->len;
- if (i == 0) return str_new2("0");
+ if (i == 0) return rb_str_new2("0");
if (base == 10) {
- j = (sizeof(USHORT)/sizeof(char)*CHAR_BIT*i*241L)/800+2;
+ j = (sizeof(BDIGIT)/sizeof(char)*CHAR_BIT*i*241L)/800+2;
hbase = 10000;
}
else if (base == 16) {
- j = (sizeof(USHORT)/sizeof(char)*CHAR_BIT*i)/4+2;
+ j = (sizeof(BDIGIT)/sizeof(char)*CHAR_BIT*i)/4+2;
hbase = 0x10000;
}
else if (base == 8) {
- j = (sizeof(USHORT)/sizeof(char)*CHAR_BIT*i)+2;
+ j = (sizeof(BDIGIT)/sizeof(char)*CHAR_BIT*i)+2;
hbase = 010000;
}
else if (base == 2) {
- j = (sizeof(USHORT)*CHAR_BIT*i)+2;
+ j = (sizeof(BDIGIT)*CHAR_BIT*i)+2;
hbase = 020;
}
else {
j = 0;
hbase = 0;
- Fail("bignum cannot treat base %d", base);
+ rb_raise(rb_eArgError, "bignum cannot treat base %d", base);
}
- t = big_clone(x);
+ t = rb_big_clone(x);
ds = BDIGITS(t);
- ss = str_new(0, j);
+ ss = rb_str_new(0, j);
s = RSTRING(ss)->ptr;
s[0] = RBIGNUM(x)->sign ? '+' : '-';
while (i && j) {
- int k = i;
- unsigned long num = 0;
+ long k = i;
+ BDIGIT_DBL num = 0;
+
while (k--) {
num = BIGUP(num) + ds[k];
- ds[k] = num / hbase;
+ ds[k] = (BDIGIT)(num / hbase);
num %= hbase;
}
if (ds[i-1] == 0) i--;
k = 4;
while (k--) {
- c = num % base;
+ c = (char)(num % base);
s[--j] = hexmap[(int)c];
num /= base;
if (i == 0 && num == 0) break;
@@ -336,53 +429,73 @@ big2str(x, base)
}
static VALUE
-big_to_s(x)
+rb_big_to_s(x)
VALUE x;
{
- return big2str(x, 10);
+ return rb_big2str(x, 10);
}
-INT
-big2int(x)
+static unsigned long
+big2ulong(x, type)
VALUE x;
+ char *type;
{
- UINT num;
- UINT len = RBIGNUM(x)->len;
- USHORT *ds;
+ long len = RBIGNUM(x)->len;
+ BDIGIT_DBL num;
+ BDIGIT *ds;
- if (len > sizeof(INT)/sizeof(USHORT))
- ArgError("bignum too big to convert into `int'");
+ if (len > sizeof(long)/sizeof(BDIGIT))
+ rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type);
ds = BDIGITS(x);
num = 0;
while (len--) {
num = BIGUP(num);
num += ds[len];
}
- if ((INT)num < 0) {
- ArgError("bignum too big to convert into `int'");
- }
+ return num;
+}
+
+unsigned long
+rb_big2ulong(x)
+ VALUE x;
+{
+ unsigned long num = big2ulong(x, "unsigned long");
+
if (!RBIGNUM(x)->sign) return -num;
return num;
}
-VALUE
-big_to_i(x)
+long
+rb_big2long(x)
VALUE x;
{
- return bignorm(x);
+ unsigned long num = big2ulong(x, "int");
+
+ if ((long)num < 0 && (RBIGNUM(x)->sign || (long)num != LONG_MIN)) {
+ rb_raise(rb_eRangeError, "bignum too big to convert into `int'");
+ }
+ if (!RBIGNUM(x)->sign) return -(long)num;
+ return num;
}
-VALUE
+static VALUE
dbl2big(d)
double d;
{
- UINT i = 0;
- long c;
- USHORT *digits;
+ long i = 0;
+ BDIGIT c;
+ BDIGIT *digits;
VALUE z;
double u = (d < 0)?-d:d;
- while (0 != (long)u) {
+ if (isinf(d)) {
+ rb_raise(rb_eFloatDomainError, d < 0 ? "-Infinity" : "Infinity");
+ }
+ if (isnan(d)) {
+ rb_raise(rb_eFloatDomainError, "NaN");
+ }
+
+ while (!POSFIXABLE(u) || 0 != (long)u) {
u /= (double)(BIGRAD);
i++;
}
@@ -390,21 +503,28 @@ dbl2big(d)
digits = BDIGITS(z);
while (i--) {
u *= BIGRAD;
- c = (long)u;
+ c = (BDIGIT)u;
u -= c;
digits[i] = c;
}
- return bignorm(z);
+ return z;
+}
+
+VALUE
+rb_dbl2big(d)
+ double d;
+{
+ return bignorm(dbl2big(d));
}
double
-big2dbl(x)
+rb_big2dbl(x)
VALUE x;
{
double d = 0.0;
- UINT i = RBIGNUM(x)->len;
- USHORT *ds = BDIGITS(x);
+ long i = RBIGNUM(x)->len;
+ BDIGIT *ds = BDIGITS(x);
while (i--) {
d = ds[i] + BIGRAD*d;
@@ -413,29 +533,33 @@ big2dbl(x)
return d;
}
-VALUE
-big_to_f(x)
+static VALUE
+rb_big_to_f(x)
VALUE x;
{
- return float_new(big2dbl(x));
+ return rb_float_new(rb_big2dbl(x));
}
static VALUE
-big_cmp(x, y)
+rb_big_cmp(x, y)
VALUE x, y;
{
- int xlen = RBIGNUM(x)->len;
+ long xlen = RBIGNUM(x)->len;
switch (TYPE(y)) {
case T_FIXNUM:
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
break;
case T_BIGNUM:
break;
+ case T_FLOAT:
+ y = dbl2big(RFLOAT(y)->value);
+ break;
+
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
if (RBIGNUM(x)->sign > RBIGNUM(y)->sign) return INT2FIX(1);
@@ -453,18 +577,32 @@ big_cmp(x, y)
}
static VALUE
-big_eq(x, y)
+rb_big_eq(x, y)
VALUE x, y;
{
- if (big_cmp(x, y) == INT2FIX(0)) return TRUE;
- return FALSE;
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ y = rb_int2big(FIX2LONG(y));
+ break;
+ case T_BIGNUM:
+ break;
+ case T_FLOAT:
+ y = dbl2big(RFLOAT(y)->value);
+ break;
+ default:
+ return Qfalse;
+ }
+ if (RBIGNUM(x)->sign != RBIGNUM(y)->sign) return Qfalse;
+ if (RBIGNUM(x)->len != RBIGNUM(y)->len) return Qfalse;
+ if (MEMCMP(BDIGITS(x),BDIGITS(y),BDIGIT,RBIGNUM(y)->len) != 0) return Qfalse;
+ return Qtrue;
}
static VALUE
-big_uminus(x)
+rb_big_uminus(x)
VALUE x;
{
- VALUE z = big_clone(x);
+ VALUE z = rb_big_clone(x);
RBIGNUM(z)->sign = !RBIGNUM(x)->sign;
@@ -472,16 +610,16 @@ big_uminus(x)
}
static VALUE
-big_neg(x)
+rb_big_neg(x)
VALUE x;
{
- VALUE z = big_clone(x);
- UINT i = RBIGNUM(x)->len;
- USHORT *ds = BDIGITS(z);
+ VALUE z = rb_big_clone(x);
+ long i = RBIGNUM(x)->len;
+ BDIGIT *ds = BDIGITS(z);
- if (!RBIGNUM(x)->sign) big_2comp(z);
+ if (!RBIGNUM(x)->sign) rb_big_2comp(z);
while (i--) ds[i] = ~ds[i];
- if (RBIGNUM(x)->sign) big_2comp(z);
+ if (RBIGNUM(x)->sign) rb_big_2comp(z);
RBIGNUM(z)->sign = !RBIGNUM(z)->sign;
return bignorm(z);
@@ -492,9 +630,9 @@ bigsub(x, y)
VALUE x, y;
{
VALUE z = 0;
- USHORT *zds;
- long num;
- UINT i;
+ BDIGIT *zds;
+ BDIGIT_DBL_SIGNED num;
+ long i;
i = RBIGNUM(x)->len;
/* if x is larger than y, swap */
@@ -518,7 +656,7 @@ bigsub(x, y)
zds = BDIGITS(z);
for (i = 0, num = 0; i < RBIGNUM(y)->len; i++) {
- num += (long)BDIGITS(x)[i] - BDIGITS(y)[i];
+ num += (BDIGIT_DBL_SIGNED)BDIGITS(x)[i] - BDIGITS(y)[i];
zds[i] = BIGLO(num);
num = BIGDN(num);
}
@@ -532,7 +670,7 @@ bigsub(x, y)
i++;
}
- return bignorm(z);
+ return z;
}
static VALUE
@@ -541,11 +679,12 @@ bigadd(x, y, sign)
char sign;
{
VALUE z;
- long num;
- UINT i, len;
+ BDIGIT_DBL num;
+ long i, len;
- if (RBIGNUM(x)->sign == (RBIGNUM(y)->sign ^ sign)) {
- if (RBIGNUM(y)->sign == sign) return bigsub(y, x);
+ sign = (sign == RBIGNUM(y)->sign);
+ if (RBIGNUM(x)->sign != sign) {
+ if (sign) return bigsub(y, x);
return bigsub(x, y);
}
@@ -556,11 +695,11 @@ bigadd(x, y, sign)
else {
len = RBIGNUM(y)->len + 1;
}
- z = bignew(len, sign==RBIGNUM(y)->sign);
+ z = bignew(len, sign);
len = RBIGNUM(x)->len;
for (i = 0, num = 0; i < len; i++) {
- num += (long)(BDIGITS(x)[i] + BDIGITS(y)[i]);
+ num += (BDIGIT_DBL)BDIGITS(x)[i] + BDIGITS(y)[i];
BDIGITS(z)[i] = BIGLO(num);
num = BIGDN(num);
}
@@ -574,72 +713,72 @@ bigadd(x, y, sign)
BDIGITS(z)[i] = BDIGITS(y)[i];
i++;
}
- BDIGITS(z)[i] = num;
+ BDIGITS(z)[i] = (BDIGIT)num;
- return bignorm(z);
+ return z;
}
VALUE
-big_plus(x, y)
+rb_big_plus(x, y)
VALUE x, y;
{
switch (TYPE(y)) {
case T_FIXNUM:
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
/* fall through */
case T_BIGNUM:
- return bigadd(x, y, 1);
+ return bignorm(bigadd(x, y, 1));
case T_FLOAT:
- return float_new(big2dbl(x) + RFLOAT(y)->value);
+ return rb_float_new(rb_big2dbl(x) + RFLOAT(y)->value);
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
}
VALUE
-big_minus(x, y)
+rb_big_minus(x, y)
VALUE x, y;
{
switch (TYPE(y)) {
case T_FIXNUM:
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
/* fall through */
case T_BIGNUM:
- return bigadd(x, y, 0);
+ return bignorm(bigadd(x, y, 0));
case T_FLOAT:
- return float_new(big2dbl(x) - RFLOAT(y)->value);
+ return rb_float_new(rb_big2dbl(x) - RFLOAT(y)->value);
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
}
VALUE
-big_mul(x, y)
+rb_big_mul(x, y)
VALUE x, y;
{
- UINT i = 0, j;
- unsigned long n = 0;
+ long i, j;
+ BDIGIT_DBL n = 0;
VALUE z;
- USHORT *zds;
+ BDIGIT *zds;
- if (FIXNUM_P(x)) x = int2big(FIX2INT(x));
+ if (FIXNUM_P(x)) x = rb_int2big(FIX2LONG(x));
switch (TYPE(y)) {
case T_FIXNUM:
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
break;
case T_BIGNUM:
break;
case T_FLOAT:
- return float_new(big2dbl(x) * RFLOAT(y)->value);
+ return rb_float_new(rb_big2dbl(x) * RFLOAT(y)->value);
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
j = RBIGNUM(x)->len + RBIGNUM(y)->len + 1;
@@ -647,11 +786,11 @@ big_mul(x, y)
zds = BDIGITS(z);
while (j--) zds[j] = 0;
for (i = 0; i < RBIGNUM(x)->len; i++) {
- unsigned long dd = BDIGITS(x)[i];
+ BDIGIT_DBL dd = BDIGITS(x)[i];
if (dd == 0) continue;
n = 0;
for (j = 0; j < RBIGNUM(y)->len; j++) {
- int ee = n + dd * BDIGITS(y)[j];
+ BDIGIT_DBL ee = n + (BDIGIT_DBL)dd * BDIGITS(y)[j];
n = zds[i + j] + ee;
if (ee) zds[i + j] = BIGLO(n);
n = BIGDN(n);
@@ -665,93 +804,102 @@ big_mul(x, y)
}
static void
-bigdivmod(x, y, div, mod, modulo)
+bigdivrem(x, y, divp, modp)
VALUE x, y;
- VALUE *div, *mod;
- int modulo;
+ VALUE *divp, *modp;
{
- UINT nx = RBIGNUM(x)->len, ny = RBIGNUM(y)->len, i, j;
+ long nx = RBIGNUM(x)->len, ny = RBIGNUM(y)->len;
+ long i, j;
VALUE yy, z;
- USHORT *xds, *yds, *zds, *tds;
- unsigned long t2;
- long num;
- USHORT dd, q;
+ BDIGIT *xds, *yds, *zds, *tds;
+ BDIGIT_DBL t2;
+ BDIGIT_DBL_SIGNED num;
+ BDIGIT dd, q;
yds = BDIGITS(y);
- if (ny == 0 && yds[0] == 0) num_zerodiv();
+ if (ny == 0 && yds[0] == 0) rb_num_zerodiv();
if (nx < ny || nx == ny && BDIGITS(x)[nx - 1] < BDIGITS(y)[ny - 1]) {
- if (div) *div = INT2FIX(0);
- if (mod) *mod = bignorm(x);
+ if (divp) *divp = rb_int2big(0);
+ if (modp) *modp = x;
return;
}
xds = BDIGITS(x);
if (ny == 1) {
dd = yds[0];
- z = big_clone(x);
+ z = rb_big_clone(x);
zds = BDIGITS(z);
t2 = 0; i = nx;
while (i--) {
t2 = BIGUP(t2) + zds[i];
- zds[i] = t2 / dd;
+ zds[i] = (BDIGIT)(t2 / dd);
t2 %= dd;
}
- if (div) *div = bignorm(z);
- if (mod) {
- if (!RBIGNUM(y)->sign) t2 = -t2;
- *mod = INT2FIX(t2);
+ RBIGNUM(z)->sign = RBIGNUM(x)->sign==RBIGNUM(y)->sign;
+ if (modp) {
+ *modp = rb_uint2big((unsigned long)t2);
+ RBIGNUM(*modp)->sign = RBIGNUM(x)->sign;
}
+ if (divp) *divp = z;
return;
}
z = bignew(nx==ny?nx+2:nx+1, RBIGNUM(x)->sign==RBIGNUM(y)->sign);
zds = BDIGITS(z);
if (nx==ny) zds[nx+1] = 0;
while (!yds[ny-1]) ny--;
- if ((dd = BIGRAD/(int)(yds[ny-1]+1)) != 1) {
- yy = big_clone(y);
+
+ dd = 0;
+ q = yds[ny-1];
+ while ((q & (1<<(BITSPERDIG-1))) == 0) {
+ q <<= 1;
+ dd++;
+ }
+ if (dd) {
+ yy = rb_big_clone(y);
tds = BDIGITS(yy);
j = 0;
- num = 0;
+ t2 = 0;
while (j<ny) {
- num += (unsigned long)yds[j]*dd;
- tds[j++] = BIGLO(num);
- num = BIGDN(num);
+ t2 += (BDIGIT_DBL)yds[j]<<dd;
+ tds[j++] = BIGLO(t2);
+ t2 = BIGDN(t2);
}
yds = tds;
j = 0;
- num = 0;
+ t2 = 0;
while (j<nx) {
- num += (unsigned long)xds[j]*dd;
- zds[j++] = BIGLO(num);
- num = BIGDN(num);
+ t2 += (BDIGIT_DBL)xds[j]<<dd;
+ zds[j++] = BIGLO(t2);
+ t2 = BIGDN(t2);
}
- zds[j] = num;
+ zds[j] = (BDIGIT)t2;
}
else {
zds[nx] = 0;
j = nx;
while (j--) zds[j] = xds[j];
}
+
j = nx==ny?nx+1:nx;
do {
if (zds[j] == yds[ny-1]) q = BIGRAD-1;
- else q = (BIGUP(zds[j]) + zds[j-1])/yds[ny-1];
+ else q = (BDIGIT)((BIGUP(zds[j]) + zds[j-1])/yds[ny-1]);
if (q) {
i = 0; num = 0; t2 = 0;
do { /* multiply and subtract */
- int ee;
- t2 += (unsigned long)yds[i] * q;
+ BDIGIT_DBL ee;
+ t2 += (BDIGIT_DBL)yds[i] * q;
ee = num - BIGLO(t2);
- num = zds[j - ny + i] + ee;
+ num = (BDIGIT_DBL)zds[j - ny + i] + ee;
if (ee) zds[j - ny + i] = BIGLO(num);
num = BIGDN(num);
t2 = BIGDN(t2);
} while (++i < ny);
- num += zds[j - ny + i] - t2; /* borrow from high digit; don't update */
+ num += zds[j - ny + i] - t2;/* borrow from high digit; don't update */
while (num) { /* "add back" required */
i = 0; num = 0; q--;
do {
- int ee = num + yds[i];
- num = (long) zds[j - ny + i] + ee;
+ BDIGIT_DBL ee = num + yds[i];
+ num = (BDIGIT_DBL)zds[j - ny + i] + ee;
if (ee) zds[j - ny + i] = BIGLO(num);
num = BIGDN(num);
} while (++i < ny);
@@ -760,139 +908,147 @@ bigdivmod(x, y, div, mod, modulo)
}
zds[j] = q;
} while (--j >= ny);
- if (div) { /* move quotient down in z */
- *div = big_clone(z);
- zds = BDIGITS(*div);
+ if (divp) { /* move quotient down in z */
+ *divp = rb_big_clone(z);
+ zds = BDIGITS(*divp);
j = (nx==ny ? nx+2 : nx+1) - ny;
for (i = 0;i < j;i++) zds[i] = zds[i+ny];
- RBIGNUM(*div)->len = i;
- *div = bignorm(*div);
+ RBIGNUM(*divp)->len = i;
}
- if (mod) { /* just normalize remainder */
- *mod = big_clone(z);
+ if (modp) { /* just normalize remainder */
+ *modp = rb_big_clone(z);
+ zds = BDIGITS(*modp);
+ while (ny-- && !zds[ny]); ++ny;
if (dd) {
- zds = BDIGITS(*mod);
t2 = 0; i = ny;
while(i--) {
- t2 = BIGUP(t2) + zds[i];
- zds[i] = t2 / dd;
- t2 %= dd;
- }
- }
- RBIGNUM(*mod)->len = ny;
- RBIGNUM(*mod)->sign = RBIGNUM(x)->sign;
- if (modulo && RBIGNUM(x)->sign != RBIGNUM(y)->sign) {
- int len = ny;
- zds = BDIGITS(*mod);
- while (len-- && !zds[len]);
- if (len > 0) {
- *mod = bigadd(*mod, y, 1);
- return;
+ t2 = (t2 | zds[i]) >> dd;
+ q = zds[i];
+ zds[i] = BIGLO(t2);
+ t2 = BIGUP(q);
}
}
- *mod = bignorm(*mod);
+ RBIGNUM(*modp)->len = ny;
+ RBIGNUM(*modp)->sign = RBIGNUM(x)->sign;
+ }
+}
+
+static void
+bigdivmod(x, y, divp, modp)
+ VALUE x, y;
+ VALUE *divp, *modp;
+{
+ VALUE mod;
+
+ bigdivrem(x, y, divp, &mod);
+ if (RBIGNUM(x)->sign != RBIGNUM(y)->sign && RBIGNUM(mod)->len > 0) {
+ if (divp) *divp = bigadd(*divp, rb_int2big(1), 0);
+ if (modp) *modp = bigadd(mod, y, 1);
+ }
+ else {
+ if (divp) *divp = *divp;
+ if (modp) *modp = mod;
}
}
static VALUE
-big_div(x, y)
+rb_big_div(x, y)
VALUE x, y;
{
VALUE z;
switch (TYPE(y)) {
case T_FIXNUM:
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
break;
case T_BIGNUM:
break;
case T_FLOAT:
- return float_new(big2dbl(x) / RFLOAT(y)->value);
+ return rb_float_new(rb_big2dbl(x) / RFLOAT(y)->value);
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
- bigdivmod(x, y, &z, 0, 0);
+ bigdivmod(x, y, &z, 0);
- return z;
+ return bignorm(z);
}
static VALUE
-big_modulo(x, y, modulo)
+rb_big_modulo(x, y)
VALUE x, y;
- int modulo;
{
VALUE z;
switch (TYPE(y)) {
case T_FIXNUM:
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
break;
case T_BIGNUM:
break;
- case T_FLOAT:
- y = dbl2big(RFLOAT(y)->value);
- break;
-
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
- bigdivmod(x, y, 0, &z, modulo);
+ bigdivmod(x, y, 0, &z);
- return z;
+ return bignorm(z);
}
static VALUE
-big_mod(x, y)
+rb_big_remainder(x, y)
VALUE x, y;
{
- return big_modulo(x, y, 1);
-}
+ VALUE z;
-static VALUE
-big_remainder(x, y)
- VALUE x, y;
-{
- return big_modulo(x, y, 0);
+ switch (TYPE(y)) {
+ case T_FIXNUM:
+ y = rb_int2big(FIX2LONG(y));
+ break;
+
+ case T_BIGNUM:
+ break;
+
+ default:
+ return rb_num_coerce_bin(x, y);
+ }
+ bigdivrem(x, y, 0, &z);
+
+ return bignorm(z);
}
-static VALUE
-big_divmod(x, y)
+VALUE
+rb_big_divmod(x, y)
VALUE x, y;
{
VALUE div, mod;
switch (TYPE(y)) {
case T_FIXNUM:
- y = int2big(FIX2INT(y));
- break;
-
- case T_FLOAT:
- y = dbl2big(RFLOAT(y)->value);
+ y = rb_int2big(FIX2LONG(y));
break;
case T_BIGNUM:
break;
default:
- return num_coerce_bin(x, y);
+ return rb_num_coerce_bin(x, y);
}
- bigdivmod(x, y, &div, &mod, 1);
+ bigdivmod(x, y, &div, &mod);
- return assoc_new(div, mod);;
+ return rb_assoc_new(bignorm(div), bignorm(mod));
}
VALUE
-big_pow(x, y)
+rb_big_pow(x, y)
VALUE x, y;
{
double d;
- VALUE z;
+ long yy;
if (y == INT2FIX(0)) return INT2FIX(1);
switch (TYPE(y)) {
@@ -901,57 +1057,60 @@ big_pow(x, y)
break;
case T_BIGNUM:
- if (RBIGNUM(y)->sign) goto pos_big;
- d = big2dbl(y);
+ rb_warn("in a**b, b may be too big");
+ d = rb_big2dbl(y);
break;
case T_FIXNUM:
- if (FIX2INT(y) > 0) goto pos_big;
- d = (double)FIX2INT(y);
+ yy = NUM2LONG(y);
+ if (yy > 0) {
+ VALUE z;
+
+ z = x;
+ for (;;) {
+ yy = yy - 1;
+ if (yy == 0) break;
+ while (yy % 2 == 0) {
+ yy = yy / 2;
+ x = rb_big_mul(x, x);
+ }
+ z = rb_big_mul(z, x);
+ }
+ if (!FIXNUM_P(z)) z = bignorm(z);
+ return z;
+ }
+ d = (double)yy;
break;
default:
- return num_coerce_bin(x, y);
- }
- return float_new(pow(big2dbl(x), d));
-
- pos_big:
- z = x;
- for (;;) {
- y = rb_funcall(y, '-', 1, INT2FIX(1));
- if (y == INT2FIX(0)) break;
- while (rb_funcall(y, '%', 1, INT2FIX(2)) == INT2FIX(0)) {
- y = rb_funcall(y, '/', 1, INT2FIX(2));
- x = big_mul(x, x);
- }
- z = big_mul(z, x);
+ return rb_num_coerce_bin(x, y);
}
- return z;
+ return rb_float_new(pow(rb_big2dbl(x), d));
}
VALUE
-big_and(x, y)
+rb_big_and(x, y)
VALUE x, y;
{
VALUE z;
- USHORT *ds1, *ds2, *zds;
- UINT i, l1, l2;
+ BDIGIT *ds1, *ds2, *zds;
+ long i, l1, l2;
char sign;
if (FIXNUM_P(y)) {
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
}
else {
Check_Type(y, T_BIGNUM);
}
if (!RBIGNUM(y)->sign) {
- y = big_clone(y);
- big_2comp(y);
+ y = rb_big_clone(y);
+ rb_big_2comp(y);
}
if (!RBIGNUM(x)->sign) {
- x = big_clone(x);
- big_2comp(x);
+ x = rb_big_clone(x);
+ rb_big_2comp(x);
}
if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
l1 = RBIGNUM(y)->len;
@@ -967,7 +1126,7 @@ big_and(x, y)
ds2 = BDIGITS(y);
sign = RBIGNUM(x)->sign;
}
- z = bignew(l2, RBIGNUM(x)->sign && RBIGNUM(y)->sign);
+ z = bignew(l2, RBIGNUM(x)->sign || RBIGNUM(y)->sign);
zds = BDIGITS(z);
for (i=0; i<l1; i++) {
@@ -976,33 +1135,33 @@ big_and(x, y)
for (; i<l2; i++) {
zds[i] = sign?0:ds2[i];
}
- if (!RBIGNUM(z)->sign) big_2comp(z);
+ if (!RBIGNUM(z)->sign) rb_big_2comp(z);
return bignorm(z);
}
VALUE
-big_or(x, y)
+rb_big_or(x, y)
VALUE x, y;
{
VALUE z;
- USHORT *ds1, *ds2, *zds;
- UINT i, l1, l2;
+ BDIGIT *ds1, *ds2, *zds;
+ long i, l1, l2;
char sign;
if (FIXNUM_P(y)) {
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
}
else {
Check_Type(y, T_BIGNUM);
}
if (!RBIGNUM(y)->sign) {
- y = big_clone(y);
- big_2comp(y);
+ y = rb_big_clone(y);
+ rb_big_2comp(y);
}
if (!RBIGNUM(x)->sign) {
- x = big_clone(x);
- big_2comp(x);
+ x = rb_big_clone(x);
+ rb_big_2comp(x);
}
if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
l1 = RBIGNUM(y)->len;
@@ -1018,7 +1177,7 @@ big_or(x, y)
ds2 = BDIGITS(y);
sign = RBIGNUM(x)->sign;
}
- z = bignew(l2, RBIGNUM(x)->sign || RBIGNUM(y)->sign);
+ z = bignew(l2, RBIGNUM(x)->sign && RBIGNUM(y)->sign);
zds = BDIGITS(z);
for (i=0; i<l1; i++) {
@@ -1027,34 +1186,34 @@ big_or(x, y)
for (; i<l2; i++) {
zds[i] = sign?ds2[i]:(BIGRAD-1);
}
- if (!RBIGNUM(z)->sign) big_2comp(z);
+ if (!RBIGNUM(z)->sign) rb_big_2comp(z);
return bignorm(z);
}
VALUE
-big_xor(x, y)
+rb_big_xor(x, y)
VALUE x, y;
{
VALUE z;
- USHORT *ds1, *ds2, *zds;
- UINT i, l1, l2;
+ BDIGIT *ds1, *ds2, *zds;
+ long i, l1, l2;
char sign;
if (FIXNUM_P(y)) {
- y = int2big(FIX2INT(y));
+ y = rb_int2big(FIX2LONG(y));
}
else {
Check_Type(y, T_BIGNUM);
}
if (!RBIGNUM(y)->sign) {
- y = big_clone(y);
- big_2comp(y);
+ y = rb_big_clone(y);
+ rb_big_2comp(y);
}
if (!RBIGNUM(x)->sign) {
- x = big_clone(x);
- big_2comp(x);
+ x = rb_big_clone(x);
+ rb_big_2comp(x);
}
if (RBIGNUM(x)->len > RBIGNUM(y)->len) {
l1 = RBIGNUM(y)->len;
@@ -1081,35 +1240,35 @@ big_xor(x, y)
for (; i<l2; i++) {
zds[i] = sign?ds2[i]:~ds2[i];
}
- if (!RBIGNUM(z)->sign) big_2comp(z);
+ if (!RBIGNUM(z)->sign) rb_big_2comp(z);
return bignorm(z);
}
-static VALUE big_rshift();
+static VALUE rb_big_rshift _((VALUE,VALUE));
VALUE
-big_lshift(x, y)
+rb_big_lshift(x, y)
VALUE x, y;
{
- USHORT *xds, *zds;
+ BDIGIT *xds, *zds;
int shift = NUM2INT(y);
- UINT s1 = shift/BITSPERDIG;
- UINT s2 = shift%BITSPERDIG;
+ int s1 = shift/BITSPERDIG;
+ int s2 = shift%BITSPERDIG;
VALUE z;
- unsigned long num = 0;
- UINT len, i;
+ BDIGIT_DBL num = 0;
+ long len, i;
- if (shift < 0) return big_rshift(x, INT2FIX(-shift));
- xds = BDIGITS(x);
+ if (shift < 0) return rb_big_rshift(x, INT2FIX(-shift));
len = RBIGNUM(x)->len;
z = bignew(len+s1+1, RBIGNUM(x)->sign);
zds = BDIGITS(z);
for (i=0; i<s1; i++) {
*zds++ = 0;
}
+ xds = BDIGITS(x);
for (i=0; i<len; i++) {
- num = num | *xds++<<s2;
+ num = num | (BDIGIT_DBL)*xds++<<s2;
*zds++ = BIGLO(num);
num = BIGDN(num);
}
@@ -1118,19 +1277,19 @@ big_lshift(x, y)
}
static VALUE
-big_rshift(x, y)
+rb_big_rshift(x, y)
VALUE x, y;
{
- USHORT *xds, *zds;
+ BDIGIT *xds, *zds;
int shift = NUM2INT(y);
- UINT s1 = shift/BITSPERDIG;
- UINT s2 = shift%BITSPERDIG;
+ int s1 = shift/BITSPERDIG;
+ int s2 = shift%BITSPERDIG;
VALUE z;
- unsigned long num = 0;
- UINT i = RBIGNUM(x)->len;
- UINT j;
+ BDIGIT_DBL num = 0;
+ long i = RBIGNUM(x)->len;
+ long j;
- if (shift < 0) return big_lshift(x, INT2FIX(-shift));
+ if (shift < 0) return rb_big_lshift(x, INT2FIX(-shift));
if (s1 > RBIGNUM(x)->len) {
if (RBIGNUM(x)->sign)
return INT2FIX(0);
@@ -1150,12 +1309,12 @@ big_rshift(x, y)
}
static VALUE
-big_aref(x, y)
+rb_big_aref(x, y)
VALUE x, y;
{
- USHORT *xds;
+ BDIGIT *xds;
int shift = NUM2INT(y);
- UINT s1, s2;
+ int s1, s2;
if (shift < 0) return INT2FIX(0);
s1 = shift/BITSPERDIG;
@@ -1163,8 +1322,8 @@ big_aref(x, y)
if (!RBIGNUM(x)->sign) {
if (s1 >= RBIGNUM(x)->len) return INT2FIX(1);
- x = big_clone(x);
- big_2comp(x);
+ x = rb_big_clone(x);
+ rb_big_2comp(x);
}
else {
if (s1 >= RBIGNUM(x)->len) return INT2FIX(0);
@@ -1176,38 +1335,40 @@ big_aref(x, y)
}
static VALUE
-big_hash(x)
+rb_big_hash(x)
VALUE x;
{
- int i, len, key;
- USHORT *digits;
+ long i, len, key;
+ BDIGIT *digits;
- key = 0; digits = BDIGITS(x);
- for (i=0,len=RBIGNUM(x)->len; i<RBIGNUM(x)->len; i++) {
+ key = 0; digits = BDIGITS(x); len = RBIGNUM(x)->len;
+ for (i=0; i<len; i++) {
key ^= *digits++;
}
return INT2FIX(key);
}
static VALUE
-big_coerce(x, y)
+rb_big_coerce(x, y)
VALUE x, y;
{
if (FIXNUM_P(y)) {
- return assoc_new(int2big(FIX2INT(y)), x);
+ return rb_assoc_new(rb_int2big(FIX2LONG(y)), x);
}
else {
- TypeError("can't coerce %s to Bignum", rb_class2name(CLASS_OF(y)));
+ rb_raise(rb_eTypeError, "Can't coerce %s to Bignum",
+ rb_class2name(CLASS_OF(y)));
}
/* not reached */
+ return Qnil;
}
static VALUE
-big_abs(x)
+rb_big_abs(x)
VALUE x;
{
if (!RBIGNUM(x)->sign) {
- x = big_clone(x);
+ x = rb_big_clone(x);
RBIGNUM(x)->sign = 1;
}
return x;
@@ -1218,71 +1379,70 @@ big_abs(x)
*/
VALUE
-big_rand(max)
+rb_big_rand(max, rand)
VALUE max;
+ double rand;
{
- struct RBignum *v;
- int len;
+ VALUE v;
+ long len;
len = RBIGNUM(max)->len;
- v = RBIGNUM(bignew(len,1));
+ v = bignew(len,1);
while (len--) {
-#ifdef HAVE_RANDOM
- BDIGITS(v)[len] = random();
-#else
- BDIGITS(v)[len] = rand();
-#endif
+ BDIGITS(v)[len] = ((BDIGIT)~0) * rand;
}
- return big_mod(v, max);
+ return rb_big_modulo((VALUE)v, max);
}
static VALUE
-big_size(big)
+rb_big_size(big)
VALUE big;
{
- return INT2FIX(RBIGNUM(big)->len*sizeof(USHORT));
+ return INT2FIX(RBIGNUM(big)->len*sizeof(BDIGIT));
}
static VALUE
-big_zero_p(big)
+rb_big_zero_p(big)
VALUE big;
{
- return FALSE;
+ return Qfalse;
}
void
Init_Bignum()
{
- cBignum = rb_define_class("Bignum", cInteger);
-
- rb_undef_method(CLASS_OF(cBignum), "new");
-
- rb_define_method(cBignum, "to_s", big_to_s, 0);
- rb_define_method(cBignum, "coerce", big_coerce, 1);
- rb_define_method(cBignum, "-@", big_uminus, 0);
- rb_define_method(cBignum, "+", big_plus, 1);
- rb_define_method(cBignum, "-", big_minus, 1);
- rb_define_method(cBignum, "*", big_mul, 1);
- rb_define_method(cBignum, "/", big_div, 1);
- rb_define_method(cBignum, "%", big_mod, 1);
- rb_define_method(cBignum, "divmod", big_divmod, 1);
- rb_define_method(cBignum, "**", big_pow, 1);
- rb_define_method(cBignum, "&", big_and, 1);
- rb_define_method(cBignum, "|", big_or, 1);
- rb_define_method(cBignum, "^", big_xor, 1);
- rb_define_method(cBignum, "~", big_neg, 0);
- rb_define_method(cBignum, "<<", big_lshift, 1);
- rb_define_method(cBignum, ">>", big_rshift, 1);
- rb_define_method(cBignum, "[]", big_aref, 1);
-
- rb_define_method(cBignum, "<=>", big_cmp, 1);
- rb_define_method(cBignum, "==", big_eq, 1);
- rb_define_method(cBignum, "eql?", big_eq, 1);
- rb_define_method(cBignum, "hash", big_hash, 0);
- rb_define_method(cBignum, "to_i", big_to_i, 0);
- rb_define_method(cBignum, "to_f", big_to_f, 0);
- rb_define_method(cBignum, "abs", big_abs, 0);
- rb_define_method(cBignum, "size", big_size, 0);
- rb_define_method(cBignum, "zero?", big_zero_p, 0);
+ rb_cBignum = rb_define_class("Bignum", rb_cInteger);
+
+ rb_undef_method(CLASS_OF(rb_cBignum), "new");
+
+ rb_define_method(rb_cBignum, "to_s", rb_big_to_s, 0);
+ rb_define_method(rb_cBignum, "coerce", rb_big_coerce, 1);
+ rb_define_method(rb_cBignum, "-@", rb_big_uminus, 0);
+ rb_define_method(rb_cBignum, "+", rb_big_plus, 1);
+ rb_define_method(rb_cBignum, "-", rb_big_minus, 1);
+ rb_define_method(rb_cBignum, "*", rb_big_mul, 1);
+ rb_define_method(rb_cBignum, "/", rb_big_div, 1);
+ rb_define_method(rb_cBignum, "%", rb_big_modulo, 1);
+ rb_define_method(rb_cBignum, "divmod", rb_big_divmod, 1);
+ rb_define_method(rb_cBignum, "modulo", rb_big_modulo, 1);
+ rb_define_method(rb_cBignum, "remainder", rb_big_remainder, 1);
+ rb_define_method(rb_cBignum, "**", rb_big_pow, 1);
+ rb_define_method(rb_cBignum, "&", rb_big_and, 1);
+ rb_define_method(rb_cBignum, "|", rb_big_or, 1);
+ rb_define_method(rb_cBignum, "^", rb_big_xor, 1);
+ rb_define_method(rb_cBignum, "~", rb_big_neg, 0);
+ rb_define_method(rb_cBignum, "<<", rb_big_lshift, 1);
+ rb_define_method(rb_cBignum, ">>", rb_big_rshift, 1);
+ rb_define_method(rb_cBignum, "[]", rb_big_aref, 1);
+
+ rb_define_method(rb_cBignum, "<=>", rb_big_cmp, 1);
+ rb_define_method(rb_cBignum, "==", rb_big_eq, 1);
+ rb_define_method(rb_cBignum, "===", rb_big_eq, 1);
+ rb_define_method(rb_cBignum, "eql?", rb_big_eq, 1);
+ rb_define_method(rb_cBignum, "hash", rb_big_hash, 0);
+ rb_define_method(rb_cBignum, "to_f", rb_big_to_f, 0);
+ rb_define_method(rb_cBignum, "abs", rb_big_abs, 0);
+ rb_define_method(rb_cBignum, "size", rb_big_size, 0);
+ rb_define_method(rb_cBignum, "zero?", rb_big_zero_p, 0);
}
diff --git a/class.c b/class.c
index 40db68beb2..b5caf3082a 100644
--- a/class.c
+++ b/class.c
@@ -1,4 +1,4 @@
-/************************************************
+/**********************************************************************
class.c -
@@ -6,45 +6,33 @@
$Date$
created at: Tue Aug 10 15:05:44 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-2000 Yukihiro Matsumoto
-************************************************/
+**********************************************************************/
#include "ruby.h"
+#include "rubysig.h"
#include "node.h"
#include "st.h"
+#include <ctype.h>
-struct st_table *new_idhash();
extern st_table *rb_class_tbl;
-extern VALUE cClass;
-extern VALUE cModule;
-
VALUE
-class_new(super)
+rb_class_new(super)
VALUE super;
{
NEWOBJ(klass, struct RClass);
- OBJSETUP(klass, cClass, T_CLASS);
+ OBJSETUP(klass, rb_cClass, T_CLASS);
klass->super = super;
klass->iv_tbl = 0;
klass->m_tbl = 0; /* safe GC */
- klass->m_tbl = new_idhash();
+ klass->m_tbl = st_init_numtable();
return (VALUE)klass;
}
-VALUE
-singleton_class_new(super)
- VALUE super;
-{
- VALUE klass = class_new(super);
-
- FL_SET(klass, FL_SINGLETON);
- return klass;
-}
-
static int
clone_method(mid, body, tbl)
ID mid;
@@ -56,7 +44,48 @@ clone_method(mid, body, tbl)
}
VALUE
-singleton_class_clone(klass)
+rb_mod_clone(module)
+ VALUE module;
+{
+ NEWOBJ(clone, struct RClass);
+ CLONESETUP(clone, module);
+
+ clone->super = RCLASS(module)->super;
+ if (RCLASS(module)->iv_tbl) {
+ clone->iv_tbl = st_copy(RCLASS(module)->iv_tbl);
+ }
+ if (RCLASS(module)->m_tbl) {
+ clone->m_tbl = st_init_numtable();
+ st_foreach(RCLASS(module)->m_tbl, clone_method, clone->m_tbl);
+ }
+
+ return (VALUE)clone;
+}
+
+VALUE
+rb_mod_dup(mod)
+ VALUE mod;
+{
+ VALUE dup = rb_mod_clone(mod);
+ OBJSETUP(dup, RBASIC(mod)->klass, BUILTIN_TYPE(mod));
+ if (FL_TEST(mod, FL_SINGLETON)) {
+ FL_SET(dup, FL_SINGLETON);
+ }
+ return dup;
+}
+
+VALUE
+rb_singleton_class_new(super)
+ VALUE super;
+{
+ VALUE klass = rb_class_new(super);
+
+ FL_SET(klass, FL_SINGLETON);
+ return klass;
+}
+
+VALUE
+rb_singleton_class_clone(klass)
VALUE klass;
{
if (!FL_TEST(klass, FL_SINGLETON))
@@ -69,7 +98,10 @@ singleton_class_clone(klass)
clone->super = RCLASS(klass)->super;
clone->iv_tbl = 0;
clone->m_tbl = 0;
- clone->m_tbl = new_idhash();
+ if (RCLASS(klass)->iv_tbl) {
+ clone->iv_tbl = st_copy(RCLASS(klass)->iv_tbl);
+ }
+ clone->m_tbl = st_init_numtable();
st_foreach(RCLASS(klass)->m_tbl, clone_method, clone->m_tbl);
FL_SET(clone, FL_SINGLETON);
return (VALUE)clone;
@@ -77,11 +109,15 @@ singleton_class_clone(klass)
}
void
-singleton_class_attached(klass, obj)
+rb_singleton_class_attached(klass, obj)
VALUE klass, obj;
{
- if (FL_TEST(klass, FL_SINGLETON))
- rb_iv_set(klass, "__attached__", obj);
+ if (FL_TEST(klass, FL_SINGLETON)) {
+ if (!RCLASS(klass)->iv_tbl) {
+ RCLASS(klass)->iv_tbl = st_init_numtable();
+ }
+ st_insert(RCLASS(klass)->iv_tbl, rb_intern("__attached__"), obj);
+ }
}
VALUE
@@ -91,12 +127,12 @@ rb_define_class_id(id, super)
{
VALUE klass;
- if (!super) super = cObject;
- klass = class_new(super);
+ if (!super) super = rb_cObject;
+ klass = rb_class_new(super);
rb_name_class(klass, id);
/* make metaclass */
- RBASIC(klass)->klass = singleton_class_new(RBASIC(super)->klass);
- singleton_class_attached(RBASIC(klass)->klass, klass);
+ RBASIC(klass)->klass = rb_singleton_class_new(RBASIC(super)->klass);
+ rb_singleton_class_attached(RBASIC(klass)->klass, klass);
rb_funcall(super, rb_intern("inherited"), 1, klass);
return klass;
@@ -104,7 +140,7 @@ rb_define_class_id(id, super)
VALUE
rb_define_class(name, super)
- char *name;
+ const char *name;
VALUE super;
{
VALUE klass;
@@ -112,6 +148,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;
@@ -120,7 +157,7 @@ rb_define_class(name, super)
VALUE
rb_define_class_under(outer, name, super)
VALUE outer;
- char *name;
+ const char *name;
VALUE super;
{
VALUE klass;
@@ -135,15 +172,15 @@ rb_define_class_under(outer, name, super)
}
VALUE
-module_new()
+rb_module_new()
{
NEWOBJ(mdl, struct RClass);
- OBJSETUP(mdl, cModule, T_MODULE);
+ OBJSETUP(mdl, rb_cModule, T_MODULE);
mdl->super = 0;
mdl->iv_tbl = 0;
mdl->m_tbl = 0;
- mdl->m_tbl = new_idhash();
+ mdl->m_tbl = st_init_numtable();
return (VALUE)mdl;
}
@@ -152,9 +189,9 @@ VALUE
rb_define_module_id(id)
ID id;
{
- extern st_table *rb_class_tbl;
- VALUE mdl = module_new();
+ VALUE mdl;
+ mdl = rb_module_new();
rb_name_class(mdl, id);
return mdl;
@@ -162,7 +199,7 @@ rb_define_module_id(id)
VALUE
rb_define_module(name)
- char *name;
+ const char *name;
{
VALUE module;
ID id;
@@ -177,7 +214,7 @@ rb_define_module(name)
VALUE
rb_define_module_under(outer, name)
VALUE outer;
- char *name;
+ const char *name;
{
VALUE module;
ID id;
@@ -195,10 +232,13 @@ include_class_new(module, super)
VALUE module, super;
{
NEWOBJ(klass, struct RClass);
- OBJSETUP(klass, cClass, T_ICLASS);
+ OBJSETUP(klass, rb_cClass, T_ICLASS);
- klass->m_tbl = RCLASS(module)->m_tbl;
+ if (!RCLASS(module)->iv_tbl) {
+ RCLASS(module)->iv_tbl = st_init_numtable();
+ }
klass->iv_tbl = RCLASS(module)->iv_tbl;
+ klass->m_tbl = RCLASS(module)->m_tbl;
klass->super = super;
if (TYPE(module) == T_ICLASS) {
RBASIC(klass)->klass = RBASIC(module)->klass;
@@ -215,65 +255,74 @@ rb_include_module(klass, module)
VALUE klass, module;
{
VALUE p;
+ int changed = 0;
+ rb_frozen_class_p(klass);
+ if (!OBJ_TAINTED(klass)) {
+ rb_secure(4);
+ }
if (NIL_P(module)) return;
+ if (klass == module) return;
switch (TYPE(module)) {
case T_MODULE:
case T_CLASS:
+ case T_ICLASS:
break;
default:
Check_Type(module, T_MODULE);
}
- if (klass == module) return;
- rb_clear_cache();
-
while (module) {
/* ignore if the module included already in superclasses */
for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) {
if (BUILTIN_TYPE(p) == T_ICLASS &&
- RCLASS(p)->m_tbl == RCLASS(module)->m_tbl)
+ RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) {
+ if (RCLASS(module)->super) {
+ rb_include_module(p, RCLASS(module)->super);
+ }
+ if (changed) rb_clear_cache();
return;
+ }
}
-
- RCLASS(klass)->super =
- include_class_new(module, RCLASS(klass)->super);
+ RCLASS(klass)->super = include_class_new(module, RCLASS(klass)->super);
klass = RCLASS(klass)->super;
module = RCLASS(module)->super;
+ changed = 1;
}
+ if (changed) rb_clear_cache();
}
VALUE
-mod_included_modules(mod)
+rb_mod_included_modules(mod)
VALUE mod;
{
- VALUE ary = ary_new();
+ VALUE ary = rb_ary_new();
VALUE p;
for (p = RCLASS(mod)->super; p; p = RCLASS(p)->super) {
if (BUILTIN_TYPE(p) == T_ICLASS) {
- ary_push(ary, RBASIC(p)->klass);
+ rb_ary_push(ary, RBASIC(p)->klass);
}
}
return ary;
}
VALUE
-mod_ancestors(mod)
+rb_mod_ancestors(mod)
VALUE mod;
{
- VALUE ary = ary_new();
+ VALUE ary = rb_ary_new();
VALUE p;
for (p = mod; p; p = RCLASS(p)->super) {
if (FL_TEST(p, FL_SINGLETON))
continue;
if (BUILTIN_TYPE(p) == T_ICLASS) {
- ary_push(ary, RBASIC(p)->klass);
+ rb_ary_push(ary, RBASIC(p)->klass);
}
else {
- ary_push(ary, p);
+ rb_ary_push(ary, p);
}
}
return ary;
@@ -286,18 +335,18 @@ ins_methods_i(key, body, ary)
VALUE ary;
{
if ((body->nd_noex&(NOEX_PRIVATE|NOEX_PROTECTED)) == 0) {
- VALUE name = str_new2(rb_id2name(key));
+ VALUE name = rb_str_new2(rb_id2name(key));
- if (!ary_includes(ary, name)) {
+ if (!rb_ary_includes(ary, name)) {
if (!body->nd_body) {
- ary_push(ary, Qnil);
+ rb_ary_push(ary, Qnil);
}
- ary_push(ary, name);
+ rb_ary_push(ary, name);
}
}
else if (body->nd_body && nd_type(body->nd_body) == NODE_ZSUPER) {
- ary_push(ary, Qnil);
- ary_push(ary, str_new2(rb_id2name(key)));
+ rb_ary_push(ary, Qnil);
+ rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
}
return ST_CONTINUE;
}
@@ -309,19 +358,19 @@ ins_methods_prot_i(key, body, ary)
VALUE ary;
{
if (!body->nd_body) {
- ary_push(ary, Qnil);
- ary_push(ary, str_new2(rb_id2name(key)));
+ rb_ary_push(ary, Qnil);
+ rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
}
else if (body->nd_noex & NOEX_PROTECTED) {
- VALUE name = str_new2(rb_id2name(key));
+ VALUE name = rb_str_new2(rb_id2name(key));
- if (!ary_includes(ary, name)) {
- ary_push(ary, name);
+ if (!rb_ary_includes(ary, name)) {
+ rb_ary_push(ary, name);
}
}
else if (nd_type(body->nd_body) == NODE_ZSUPER) {
- ary_push(ary, Qnil);
- ary_push(ary, str_new2(rb_id2name(key)));
+ rb_ary_push(ary, Qnil);
+ rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
}
return ST_CONTINUE;
}
@@ -333,19 +382,19 @@ ins_methods_priv_i(key, body, ary)
VALUE ary;
{
if (!body->nd_body) {
- ary_push(ary, Qnil);
- ary_push(ary, str_new2(rb_id2name(key)));
+ rb_ary_push(ary, Qnil);
+ rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
}
else if (body->nd_noex & NOEX_PRIVATE) {
- VALUE name = str_new2(rb_id2name(key));
+ VALUE name = rb_str_new2(rb_id2name(key));
- if (!ary_includes(ary, name)) {
- ary_push(ary, name);
+ if (!rb_ary_includes(ary, name)) {
+ rb_ary_push(ary, name);
}
}
else if (nd_type(body->nd_body) == NODE_ZSUPER) {
- ary_push(ary, Qnil);
- ary_push(ary, str_new2(rb_id2name(key)));
+ rb_ary_push(ary, Qnil);
+ rb_ary_push(ary, rb_str_new2(rb_id2name(key)));
}
return ST_CONTINUE;
}
@@ -360,7 +409,7 @@ method_list(mod, option, func)
VALUE klass;
VALUE *p, *q, *pend;
- ary = ary_new();
+ ary = rb_ary_new();
for (klass = mod; klass; klass = RCLASS(klass)->super) {
st_foreach(RCLASS(klass)->m_tbl, func, ary);
if (!option) break;
@@ -378,7 +427,7 @@ method_list(mod, option, func)
}
VALUE
-class_instance_methods(argc, argv, mod)
+rb_class_instance_methods(argc, argv, mod)
int argc;
VALUE *argv;
VALUE mod;
@@ -390,7 +439,7 @@ class_instance_methods(argc, argv, mod)
}
VALUE
-class_protected_instance_methods(argc, argv, mod)
+rb_class_protected_instance_methods(argc, argv, mod)
int argc;
VALUE *argv;
VALUE mod;
@@ -402,7 +451,7 @@ class_protected_instance_methods(argc, argv, mod)
}
VALUE
-class_private_instance_methods(argc, argv, mod)
+rb_class_private_instance_methods(argc, argv, mod)
int argc;
VALUE *argv;
VALUE mod;
@@ -414,14 +463,14 @@ class_private_instance_methods(argc, argv, mod)
}
VALUE
-obj_singleton_methods(obj)
+rb_obj_singleton_methods(obj)
VALUE obj;
{
VALUE ary;
VALUE klass;
VALUE *p, *q, *pend;
- ary = ary_new();
+ ary = rb_ary_new();
klass = CLASS_OF(obj);
while (klass && FL_TEST(klass, FL_SINGLETON)) {
st_foreach(RCLASS(klass)->m_tbl, ins_methods_i, ary);
@@ -453,7 +502,7 @@ rb_define_method_id(klass, name, func, argc)
void
rb_define_method(klass, name, func, argc)
VALUE klass;
- char *name;
+ const char *name;
VALUE (*func)();
int argc;
{
@@ -467,7 +516,7 @@ rb_define_method(klass, name, func, argc)
void
rb_define_protected_method(klass, name, func, argc)
VALUE klass;
- char *name;
+ const char *name;
VALUE (*func)();
int argc;
{
@@ -478,7 +527,7 @@ rb_define_protected_method(klass, name, func, argc)
void
rb_define_private_method(klass, name, func, argc)
VALUE klass;
- char *name;
+ const char *name;
VALUE (*func)();
int argc;
{
@@ -489,30 +538,60 @@ rb_define_private_method(klass, name, func, argc)
void
rb_undef_method(klass, name)
VALUE klass;
- char *name;
+ const char *name;
{
rb_add_method(klass, rb_intern(name), 0, NOEX_UNDEF);
}
+#define SPECIAL_SINGLETON(x,c) if (obj == (x)) {\
+ if (!FL_TEST(c, FL_SINGLETON)) {\
+ c = rb_singleton_class_new(c);\
+ rb_singleton_class_attached(c,obj);\
+ }\
+ return c;\
+}
+
VALUE
rb_singleton_class(obj)
VALUE obj;
{
+ VALUE klass;
+
+ if (FIXNUM_P(obj) || SYMBOL_P(obj)) {
+ rb_raise(rb_eTypeError, "can't define singleton");
+ }
if (rb_special_const_p(obj)) {
- TypeError("cannot define singleton");
+ SPECIAL_SINGLETON(Qnil, rb_cNilClass);
+ SPECIAL_SINGLETON(Qfalse, rb_cFalseClass);
+ SPECIAL_SINGLETON(Qtrue, rb_cTrueClass);
+ rb_bug("unknown immediate %d", obj);
}
+
+ DEFER_INTS;
if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON)) {
- return RBASIC(obj)->klass;
+ klass = RBASIC(obj)->klass;
+ }
+ else {
+ klass = rb_singleton_class_new(RBASIC(obj)->klass);
+ RBASIC(obj)->klass = klass;
+ rb_singleton_class_attached(klass, obj);
}
- RBASIC(obj)->klass = singleton_class_new(RBASIC(obj)->klass);
- singleton_class_attached(RBASIC(obj)->klass, obj);
- return RBASIC(obj)->klass;
+ if (OBJ_TAINTED(obj)) {
+ OBJ_TAINT(klass);
+ }
+ else {
+ FL_UNSET(klass, FL_TAINT);
+ }
+ if (OBJ_FROZEN(obj)) OBJ_FREEZE(klass);
+ ALLOW_INTS;
+
+ return klass;
}
void
rb_define_singleton_method(obj, name, func, argc)
VALUE obj;
- char *name;
+ const char *name;
VALUE (*func)();
int argc;
{
@@ -522,7 +601,7 @@ rb_define_singleton_method(obj, name, func, argc)
void
rb_define_module_function(module, name, func, argc)
VALUE module;
- char *name;
+ const char *name;
VALUE (*func)();
int argc;
{
@@ -530,21 +609,19 @@ rb_define_module_function(module, name, func, argc)
rb_define_singleton_method(module, name, func, argc);
}
-extern VALUE mKernel;
-
void
rb_define_global_function(name, func, argc)
- char *name;
+ const char *name;
VALUE (*func)();
int argc;
{
- rb_define_private_method(mKernel, name, func, argc);
+ rb_define_module_function(rb_mKernel, name, func, argc);
}
void
rb_define_alias(klass, name1, name2)
VALUE klass;
- char *name1, *name2;
+ const char *name1, *name2;
{
rb_alias(klass, rb_intern(name1), rb_intern(name2));
}
@@ -552,42 +629,47 @@ rb_define_alias(klass, name1, name2)
void
rb_define_attr(klass, name, read, write)
VALUE klass;
- char *name;
+ const char *name;
int read, write;
{
- rb_attr(klass, rb_intern(name), read, write, FALSE);
+ rb_attr(klass, rb_intern(name), read, write, Qfalse);
}
+#ifdef HAVE_STDARG_PROTOTYPES
+#include <stdarg.h>
+#define va_init_list(a,b) va_start(a,b)
+#else
#include <varargs.h>
-#include <ctype.h>
+#define va_init_list(a,b) va_start(a)
+#endif
int
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_scan_args(int argc, VALUE *argv, const char *fmt, ...)
+#else
rb_scan_args(argc, argv, fmt, va_alist)
int argc;
VALUE *argv;
- char *fmt;
+ const char *fmt;
va_dcl
+#endif
{
- int n, i;
- char *p = fmt;
+ int n, i = 0;
+ const char *p = fmt;
VALUE *var;
va_list vargs;
- va_start(vargs);
+ va_init_list(vargs, fmt);
- if (*p == '*') {
- var = va_arg(vargs, VALUE*);
- *var = ary_new4(argc, argv);
- return argc;
- }
+ if (*p == '*') goto rest_arg;
- if (isdigit(*p)) {
+ if (ISDIGIT(*p)) {
n = *p - '0';
if (n > argc)
- ArgError("Wrong # of arguments (%d for %d)", argc, n);
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for %d)", argc, n);
for (i=0; i<n; i++) {
var = va_arg(vargs, VALUE*);
- *var = argv[i];
+ if (var) *var = argv[i];
}
p++;
}
@@ -595,42 +677,56 @@ rb_scan_args(argc, argv, fmt, va_alist)
goto error;
}
- if (isdigit(*p)) {
+ if (ISDIGIT(*p)) {
n = i + *p - '0';
for (; i<n; i++) {
var = va_arg(vargs, VALUE*);
if (argc > i) {
- *var = argv[i];
+ if (var) *var = argv[i];
}
else {
- *var = Qnil;
+ if (var) *var = Qnil;
}
}
p++;
}
if(*p == '*') {
+ rest_arg:
var = va_arg(vargs, VALUE*);
if (argc > i) {
- *var = ary_new4(argc-i, argv+i);
+ if (var) *var = rb_ary_new4(argc-i, argv+i);
+ i = argc;
}
else {
- *var = ary_new();
+ if (var) *var = rb_ary_new();
}
+ p++;
}
- else if (*p == '\0') {
- if (argc > i) {
- ArgError("Wrong # of arguments(%d for %d)", argc, i);
+
+ if (*p == '&') {
+ var = va_arg(vargs, VALUE*);
+ if (rb_block_given_p()) {
+ *var = rb_f_lambda();
}
+ else {
+ *var = Qnil;
+ }
+ p++;
}
- else {
+ va_end(vargs);
+
+ if (*p != '\0') {
goto error;
}
- va_end(vargs);
+ if (argc > i) {
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for %d)", argc, i);
+ }
+
return argc;
error:
- Fatal("bad scan arg format: %s", fmt);
+ rb_fatal("bad scan arg format: %s", fmt);
return 0;
}
diff --git a/compar.c b/compar.c
index ce85198873..3cebc30a80 100644
--- a/compar.c
+++ b/compar.c
@@ -1,4 +1,4 @@
-/************************************************
+/**********************************************************************
compar.c -
@@ -6,25 +6,44 @@
$Date$
created at: Thu Aug 26 14:39:48 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-2000 Yukihiro Matsumoto
-************************************************/
+**********************************************************************/
#include "ruby.h"
-VALUE mComparable;
+VALUE rb_mComparable;
static ID cmp;
static VALUE
-cmp_eq(x, y)
- VALUE x, y;
+cmp_eq(a)
+ VALUE *a;
{
- VALUE c = rb_funcall(x, cmp, 1, y);
+ VALUE c = rb_funcall(a[0], cmp, 1, a[1]);
int t = NUM2INT(c);
- if (t == 0) return TRUE;
- return FALSE;
+ if (t == 0) return Qtrue;
+ return Qfalse;
+}
+
+static VALUE
+cmp_failed()
+{
+ return Qfalse;
+}
+
+static VALUE
+cmp_equal(x, y)
+ VALUE x, y;
+{
+ VALUE a[2];
+
+ if (x == y) return Qtrue;
+
+ a[0] = x; a[1] = y;
+ return rb_rescue2(cmp_eq, (VALUE)a, cmp_failed, 0,
+ rb_eStandardError, rb_eNameError, 0);
}
static VALUE
@@ -34,8 +53,8 @@ cmp_gt(x, y)
VALUE c = rb_funcall(x, cmp, 1, y);
int t = NUM2INT(c);
- if (t > 0) return TRUE;
- return FALSE;
+ if (t > 0) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -45,8 +64,8 @@ cmp_ge(x, y)
VALUE c = rb_funcall(x, cmp, 1, y);
int t = NUM2INT(c);
- if (t >= 0) return TRUE;
- return FALSE;
+ if (t >= 0) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -56,8 +75,8 @@ cmp_lt(x, y)
VALUE c = rb_funcall(x, cmp, 1, y);
int t = NUM2INT(c);
- if (t < 0) return TRUE;
- return FALSE;
+ if (t < 0) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -67,8 +86,8 @@ cmp_le(x, y)
VALUE c = rb_funcall(x, cmp, 1, y);
int t = NUM2INT(c);
- if (t <= 0) return TRUE;
- return FALSE;
+ if (t <= 0) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -76,25 +95,25 @@ cmp_between(x, min, max)
VALUE x, min, max;
{
VALUE c = rb_funcall(x, cmp, 1, min);
- int t = NUM2INT(c);
- if (t < 0) return FALSE;
+ long t = NUM2LONG(c);
+ if (t < 0) return Qfalse;
c = rb_funcall(x, cmp, 1, max);
- t = NUM2INT(c);
- if (t > 0) return FALSE;
- return TRUE;
+ t = NUM2LONG(c);
+ if (t > 0) return Qfalse;
+ return Qtrue;
}
void
Init_Comparable()
{
- mComparable = rb_define_module("Comparable");
- rb_define_method(mComparable, "==", cmp_eq, 1);
- rb_define_method(mComparable, ">", cmp_gt, 1);
- rb_define_method(mComparable, ">=", cmp_ge, 1);
- rb_define_method(mComparable, "<", cmp_lt, 1);
- rb_define_method(mComparable, "<=", cmp_le, 1);
- rb_define_method(mComparable, "between?", cmp_between, 2);
+ rb_mComparable = rb_define_module("Comparable");
+ rb_define_method(rb_mComparable, "==", cmp_equal, 1);
+ rb_define_method(rb_mComparable, ">", cmp_gt, 1);
+ rb_define_method(rb_mComparable, ">=", cmp_ge, 1);
+ rb_define_method(rb_mComparable, "<", cmp_lt, 1);
+ rb_define_method(rb_mComparable, "<=", cmp_le, 1);
+ rb_define_method(rb_mComparable, "between?", cmp_between, 2);
cmp = rb_intern("<=>");
}
diff --git a/config.dj b/config.dj
deleted file mode 100644
index 8ad3883380..0000000000
--- a/config.dj
+++ /dev/null
@@ -1,36 +0,0 @@
-#define THREAD 1
-#define HAVE_DIRENT_H 1
-#define HAVE_UNISTD_H 1
-#define HAVE_LIMITS_H 1
-#define HAVE_SYS_FILE_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_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_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 FILE_COUNT _cnt
-#define DLEXT ".so"
-#define RUBY_LIB ";/usr/local/lib/ruby;."
-#define RUBY_ARCHLIB "/usr/local/lib/ruby/i386-djgpp"
-#define RUBY_PLATFORM "i386-djgpp"
diff --git a/config.guess b/config.guess
index 1915100b84..c55635bd7b 100644
--- a/config.guess
+++ b/config.guess
@@ -1,6 +1,7 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright (C) 1992, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999
+# Free Software Foundation, Inc.
#
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -23,6 +24,7 @@
# Written by Per Bothner <bothner@cygnus.com>.
# The master version of this file is at the FSF in /home/gd/gnu/lib.
+# Please send patches to the Autoconf mailing list <autoconf@gnu.org>.
#
# This script attempts to guess a canonical system name similar to
# config.sub. If it succeeds, it prints the system name on stdout, and
@@ -35,6 +37,19 @@
# (but try to keep the structure clean).
#
+# Use $HOST_CC if defined. $CC may point to a cross-compiler
+if test x"$CC_FOR_BUILD" = x; then
+ if test x"$HOST_CC" != x; then
+ CC_FOR_BUILD="$HOST_CC"
+ else
+ if test x"$CC" != x; then
+ CC_FOR_BUILD="$CC"
+ else
+ CC_FOR_BUILD=cc
+ fi
+ fi
+fi
+
# Modified for Human68k by K.Okabe 1997.07.09
# Last change: 1997.07.09
@@ -57,11 +72,15 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
-trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15
+dummy=dummy-$$
+trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15
# Note: order is significant - the case branches are not exclusive.
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:OS/2:*:*)
+ echo "i386-pc-os2_emx"
+ exit 0;;
alpha:OSF1:*:*)
if test $UNAME_RELEASE = "V4.0"; then
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
@@ -70,7 +89,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
- cat <<EOF >dummy.s
+ cat <<EOF >$dummy.s
.globl main
.ent main
main:
@@ -87,9 +106,9 @@ main:
ret \$31,(\$26),1
.end main
EOF
- ${CC-cc} dummy.s -o dummy 2>/dev/null
+ $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
if test "$?" = 0 ; then
- ./dummy
+ ./$dummy
case "$?" in
7)
UNAME_MACHINE="alpha"
@@ -108,8 +127,14 @@ EOF
;;
esac
fi
- rm -f dummy.s dummy
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]`
+ rm -f $dummy.s $dummy
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
exit 0 ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
@@ -123,6 +148,9 @@ EOF
amiga:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
arc64:OpenBSD:*:*)
echo mips64el-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
@@ -150,7 +178,7 @@ EOF
SR2?01:HI-UX/MPP:*:*)
echo hppa1.1-hitachi-hiuxmpp
exit 0;;
- Pyramid*:OSx*:*:*|MIS*:OSx*:*:*)
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
if test "`(/bin/universe) 2>/dev/null`" = att ; then
echo pyramid-pyramid-sysv3
@@ -158,9 +186,12 @@ EOF
echo pyramid-pyramid-bsd
fi
exit 0 ;;
- NILE:*:*:dcosx)
+ NILE*:*:*:dcosx)
echo pyramid-pyramid-svr4
exit 0 ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit 0 ;;
@@ -206,6 +237,32 @@ EOF
atari*:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
sun3*:NetBSD:*:*)
echo m68k-sun-netbsd${UNAME_RELEASE}
exit 0 ;;
@@ -227,6 +284,9 @@ EOF
powerpc:machten:*:*)
echo powerpc-apple-machten${UNAME_RELEASE}
exit 0 ;;
+ macppc:NetBSD:*:*)
+ echo powerpc-apple-netbsd${UNAME_RELEASE}
+ exit 0 ;;
RISC*:Mach:*:*)
echo mips-dec-mach_bsd4.3
exit 0 ;;
@@ -236,12 +296,16 @@ EOF
VAX*:ULTRIX*:*:*)
echo vax-dec-ultrix${UNAME_RELEASE}
exit 0 ;;
- 2020:CLIX:*:*)
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
echo clipper-intergraph-clix${UNAME_RELEASE}
exit 0 ;;
mips:*:*:UMIPS | mips:*:*:RISCos)
- sed 's/^ //' << EOF >dummy.c
- int main (argc, argv) int argc; char **argv; {
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
@@ -256,10 +320,10 @@ EOF
exit (-1);
}
EOF
- ${CC-cc} dummy.c -o dummy \
- && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
- && rm dummy.c dummy && exit 0
- rm -f dummy.c dummy
+ $CC_FOR_BUILD $dummy.c -o $dummy \
+ && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
echo mips-mips-riscos${UNAME_RELEASE}
exit 0 ;;
Night_Hawk:Power_UNIX:*:*)
@@ -311,7 +375,7 @@ EOF
exit 0 ;;
*:AIX:2:3)
if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
- sed 's/^ //' << EOF >dummy.c
+ sed 's/^ //' << EOF >$dummy.c
#include <sys/systemcfg.h>
main()
@@ -322,8 +386,8 @@ EOF
exit(0);
}
EOF
- ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
- rm -f dummy.c dummy
+ $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
echo rs6000-ibm-aix3.2.5
elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
echo rs6000-ibm-aix3.2.4
@@ -332,7 +396,8 @@ EOF
fi
exit 0 ;;
*:AIX:*:4)
- if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | head -1 | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -EHl ${IBM_CPU_ID} | grep POWER >/dev/null 2>&1; then
IBM_ARCH=rs6000
else
IBM_ARCH=powerpc
@@ -365,18 +430,50 @@ EOF
hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
echo m68k-hp-bsd4.4
exit 0 ;;
- 9000/[3478]??:HP-UX:*:*)
+ 9000/[34678]??:HP-UX:*:*)
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
- 9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;;
- 9000/8?? ) HP_ARCH=hppa1.0 ;;
+ 9000/[678][0-9][0-9])
+ sed 's/^ //' << EOF >$dummy.c
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ ($CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy`
+ rm -f $dummy.c $dummy
esac
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
exit 0 ;;
3050*:HI-UX:*:*)
- sed 's/^ //' << EOF >dummy.c
+ sed 's/^ //' << EOF >$dummy.c
#include <unistd.h>
int
main ()
@@ -401,8 +498,8 @@ EOF
exit (0);
}
EOF
- ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0
- rm -f dummy.c dummy
+ $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
echo unknown-hitachi-hiuxwe2
exit 0 ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
@@ -411,6 +508,9 @@ EOF
9000/8??:4.3bsd:*:*)
echo hppa1.0-hp-bsd
exit 0 ;;
+ *9??*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
echo hppa1.1-hp-osf
exit 0 ;;
@@ -427,6 +527,9 @@ EOF
parisc*:Lites*:*:*)
echo hppa1.1-hp-lites
exit 0 ;;
+ hppa*:OpenBSD:*:*)
+ echo hppa-unknown-openbsd
+ exit 0 ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit 0 ;;
@@ -459,11 +562,14 @@ EOF
CRAY*TS:*:*:*)
echo t90-cray-unicos${UNAME_RELEASE}
exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo t3e-cray-unicosmk${UNAME_RELEASE}
+ exit 0 ;;
CRAY-2:*:*:*)
echo cray2-cray-unicos
exit 0 ;;
F300:UNIX_System_V:*:*)
- FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit 0 ;;
@@ -476,10 +582,22 @@ EOF
hp300:OpenBSD:*:*)
echo m68k-unknown-openbsd${UNAME_RELEASE}
exit 0 ;;
- i?86:BSD/386:*:* | *:BSD/OS:*:*)
+ i?86:BSD/386:*:* | i?86:BSD/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
*:FreeBSD:*:*)
+ if test -x /usr/bin/objformat; then
+ if test "elf" = "`/usr/bin/objformat`"; then
+ echo ${UNAME_MACHINE}-unknown-freebsdelf`echo ${UNAME_RELEASE}|sed -e 's/[-_].*//'`
+ exit 0
+ fi
+ fi
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit 0 ;;
*:NetBSD:*:*)
@@ -492,13 +610,22 @@ EOF
echo i386-pc-bow
exit 0 ;;
i*:CYGWIN*:*)
- echo i386-pc-cygwin32
+ echo ${UNAME_MACHINE}-pc-cygwin
exit 0 ;;
i*:MINGW*:*)
- echo i386-pc-mingw32
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i386-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
exit 0 ;;
p*:CYGWIN*:*)
- echo powerpcle-unknown-cygwin32
+ echo powerpcle-unknown-cygwin
exit 0 ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
@@ -507,9 +634,17 @@ EOF
echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
exit 0 ;;
*:Linux:*:*)
+ # uname on the ARM produces all sorts of strangeness, and we need to
+ # filter it out.
+ case "$UNAME_MACHINE" in
+ armv*) UNAME_MACHINE=$UNAME_MACHINE ;;
+ arm* | sa110*) UNAME_MACHINE="arm" ;;
+ esac
+
# The BFD linker knows what the default object file format is, so
- # first see if it will tell us.
- ld_help_string=`ld --help 2>&1`
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ ld_help_string=`cd /; ld --help 2>&1`
ld_supported_emulations=`echo $ld_help_string \
| sed -ne '/supported emulations:/!d
s/[ ][ ]*/ /g
@@ -520,12 +655,42 @@ EOF
i?86linux) echo "${UNAME_MACHINE}-pc-linux-aout" ; exit 0 ;;
i?86coff) echo "${UNAME_MACHINE}-pc-linux-coff" ; exit 0 ;;
sparclinux) echo "${UNAME_MACHINE}-unknown-linux-aout" ; exit 0 ;;
+ armlinux) echo "${UNAME_MACHINE}-unknown-linux-aout" ; exit 0 ;;
m68klinux) echo "${UNAME_MACHINE}-unknown-linux-aout" ; exit 0 ;;
- elf32ppc) echo "powerpc-unknown-linux" ; exit 0 ;;
+ elf32ppc)
+ # Determine Lib Version
+ cat >$dummy.c <<EOF
+#include <features.h>
+#if defined(__GLIBC__)
+extern char __libc_version[];
+extern char __libc_release[];
+#endif
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+#if defined(__GLIBC__)
+ printf("%s %s\n", __libc_version, __libc_release);
+#else
+ printf("unkown\n");
+#endif
+ return 0;
+}
+EOF
+ LIBC=""
+ $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ ./$dummy | grep 1\.99 > /dev/null
+ if test "$?" = 0 ; then
+ LIBC="-libc1"
+ fi
+ fi
+ rm -f $dummy.c $dummy
+ echo powerpc-unknown-linux${LIBC} ; exit 0 ;;
esac
if test "${UNAME_MACHINE}" = "alpha" ; then
- sed 's/^ //' <<EOF >dummy.s
+ sed 's/^ //' <<EOF >$dummy.s
.globl main
.ent main
main:
@@ -543,9 +708,9 @@ EOF
.end main
EOF
LIBC=""
- ${CC-cc} dummy.s -o dummy 2>/dev/null
+ $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
if test "$?" = 0 ; then
- ./dummy
+ ./$dummy
case "$?" in
7)
UNAME_MACHINE="alpha"
@@ -564,20 +729,21 @@ EOF
;;
esac
- objdump --private-headers dummy | \
+ objdump --private-headers $dummy | \
grep ld.so.1 > /dev/null
if test "$?" = 0 ; then
- LIBC="libc1"
+ LIBC="-libc1"
fi
- fi
- rm -f dummy.s dummy
- echo ${UNAME_MACHINE}-unknown-linux-{LIBC} ; exit 0
+ fi
+ rm -f $dummy.s $dummy
+ echo ${UNAME_MACHINE}-unknown-linux${LIBC} ; exit 0
elif test "${UNAME_MACHINE}" = "mips" ; then
- cat >dummy.c <<EOF
-main(argc, argv)
- int argc;
- char *argv[];
-{
+ cat >$dummy.c <<EOF
+#ifdef __cplusplus
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
#ifdef __MIPSEB__
printf ("%s-unknown-linux\n", argv[1]);
#endif
@@ -587,9 +753,17 @@ main(argc, argv)
return 0;
}
EOF
- ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0
- rm -f dummy.c dummy
+ $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
else
+ # Either a pre-BFD a.out linker (linux-oldld)
+ # or one that does not give us useful --help.
+ # GCC wants to distinguish between linux-oldld and linux-aout.
+ # If ld does not provide *any* "supported emulations:"
+ # that means it is oldld.
+ echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:"
+ test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-oldld" && exit 0
+
case "${UNAME_MACHINE}" in
i?86)
VENDOR=pc;
@@ -598,8 +772,32 @@ EOF
VENDOR=unknown;
;;
esac
- echo ${UNAME_MACHINE}-${VENDOR}-linux
- exit 0
+ # Determine whether the default compiler is a.out or elf
+ cat >$dummy.c <<EOF
+#include <features.h>
+#ifdef __cplusplus
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+#ifdef __ELF__
+# ifdef __GLIBC__
+# if __GLIBC__ >= 2
+ printf ("%s-${VENDOR}-linux\n", argv[1]);
+# else
+ printf ("%s-${VENDOR}-linux-libc1\n", argv[1]);
+# endif
+# else
+ printf ("%s-${VENDOR}-linux-libc1\n", argv[1]);
+# endif
+#else
+ printf ("%s-${VENDOR}-linux-aout\n", argv[1]);
+#endif
+ return 0;
+}
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
fi ;;
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions
# are messed up and put the nodename in both sysname and nodename.
@@ -621,6 +819,14 @@ EOF
echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE}
fi
exit 0 ;;
+ i?86:*:5:7*)
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) && UNAME_MACHINE=i586
+ (/bin/uname -X|egrep '^Machine.*Pent.*II' >/dev/null) && UNAME_MACHINE=i686
+ (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) && UNAME_MACHINE=i585
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}${UNAME_VERSION}-sysv${UNAME_RELEASE}
+ exit 0 ;;
i?86:*:3.2:*)
if test -f /usr/options/cb.name; then
UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
@@ -630,11 +836,22 @@ EOF
(/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
(/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
&& UNAME_MACHINE=i586
+ (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
else
echo ${UNAME_MACHINE}-pc-sysv32
fi
exit 0 ;;
+ i?86:UnixWare:*:*)
+ if /bin/uname -X 2>/dev/null >/dev/null ; then
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ fi
+ echo ${UNAME_MACHINE}-unixware-${UNAME_RELEASE}-${UNAME_VERSION}
+ exit 0 ;;
pc:*:*:*)
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i386.
@@ -676,7 +893,7 @@ EOF
mc68030:UNIX_System_V:4.*:*)
echo m68k-atari-sysv4
exit 0 ;;
- i?86:LynxOS:2.*:*)
+ i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
exit 0 ;;
TSUNAMI:LynxOS:2.*:*)
@@ -688,6 +905,9 @@ EOF
SM[BE]S:UNIX_SV:*:*)
echo mips-dde-sysv${UNAME_RELEASE}
exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
RM*:SINIX-*:*:*)
echo mips-sni-sysv4
exit 0 ;;
@@ -715,25 +935,49 @@ EOF
mc68*:A/UX:*:*)
echo m68k-apple-aux${UNAME_RELEASE}
exit 0 ;;
- X680[02346]0:Human68k:*:*)
- echo m68k-sharp-human
- exit 0 ;;
news*:NEWS-OS:*:6*)
echo mips-sony-newsos6
- exit 0 ;;
- R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*)
+ exit 0 ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
- echo mips-nec-sysv${UNAME_RELEASE}
+ echo mips-nec-sysv`echo ${UNAME_RELEASE} | sed -n 's/\([.0-9]*\).*/\1/p'`
else
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit 0 ;;
+ DS/90*:*:*:V20*)
+ echo sparc-fujitsu-uxpds
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ echo `uname -p`-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2
#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
-cat >dummy.c <<EOF
+cat >$dummy.c <<EOF
#ifdef _SEQUENT_
# include <sys/types.h>
# include <sys/utsname.h>
@@ -771,7 +1015,10 @@ main ()
#endif
int version;
version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
- printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
exit (0);
#endif
@@ -831,8 +1078,8 @@ main ()
}
EOF
-${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0
-rm -f dummy.c dummy
+$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0
+rm -f $dummy.c $dummy
# Apollos put the system type in the environment.
diff --git a/config.sub b/config.sub
index d37810352f..1000343616 100644
--- a/config.sub
+++ b/config.sub
@@ -1,6 +1,6 @@
#! /bin/sh
# Configuration validation subroutine script, version 1.1.
-# Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
+# Copyright (C) 1991, 92-97, 1998, 1999 Free Software Foundation, Inc.
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
# can handle that machine. It does not imply ALL GNU software can.
@@ -68,7 +68,7 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
- linux-gnu*)
+ linux*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
@@ -98,11 +98,21 @@ case $os in
os=
basic_machine=$1
;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=vxworks
+ basic_machine=$1
+ ;;
-hiux*)
os=-hiuxwe2
;;
-sco5)
- os=sco3.2v5
+ os=-sco3.2v5
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
-sco4)
@@ -121,6 +131,9 @@ case $os in
os=-sco3.2v2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
-isc)
os=-isc2.2
basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
@@ -150,19 +163,26 @@ case $basic_machine in
# Recognize the basic CPU types without company name.
# Some are omitted here because they have special meanings below.
tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \
- | arme[lb] | pyramid | mn10200 | mn10300 \
- | tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \
- | alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \
- | i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \
- | mips64 | mipsel | mips64el | mips64orion | mips64orionel \
- | mipstx39 | mipstx39el \
- | sparc | sparclet | sparclite | sparc64 | v850)
+ | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \
+ | 580 | i960 | h8300 \
+ | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \
+ | alpha | alphaev[4-7] | alphaev56 | alphapca5[67] \
+ | we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \
+ | 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \
+ | mips64orion | mips64orionel | mipstx39 | mipstx39el \
+ | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \
+ | mips64vr5000 | miprs64vr5000el \
+ | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \
+ | thumb | d10v)
basic_machine=$basic_machine-unknown
;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65)
+ ;;
+
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
- i[3456]86)
+ i[34567]86)
basic_machine=$basic_machine-pc
;;
i[3456]86-TOWNS*)
@@ -174,27 +194,44 @@ case $basic_machine in
exit 1
;;
# Recognize the basic CPU types with company name.
- vax-* | tahoe-* | i[3456]86-* | i860-* | m32r-* | m68k-* | m68000-* \
+ vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \
| m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
- | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \
- | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* \
- | alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \
- | ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \
+ | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \
+ | xmp-* | ymp-* \
+ | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* | hppa2.0n-* \
+ | alpha-* | alphaev[4-7]-* | alphaev56-* | alphapca5[67]-* \
+ | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \
+ | clipper-* | orion-* \
| sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
- | sparc64-* | mips64-* | mipsel-* \
- | mips64el-* | mips64orion-* | mips64orionel-* \
+ | sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \
+ | mips64el-* | mips64orion-* | mips64orionel-* \
+ | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \
| mipstx39-* | mipstx39el-* \
- | f301-*)
+ | f301-* | armv*-* | t3e-* \
+ | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \
+ | thumb-* | v850-* | d30v-* | tic30-* | c30-* )
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
basic_machine=m68000-att
;;
3b*)
basic_machine=we32k-att
;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
alliant | fx80)
basic_machine=fx80-alliant
;;
@@ -224,6 +261,10 @@ case $basic_machine in
basic_machine=m68k-apollo
os=-sysv
;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
aux)
basic_machine=m68k-apple
os=-aux
@@ -300,6 +341,10 @@ case $basic_machine in
encore | umax | mmax)
basic_machine=ns32k-encore
;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
fx2800)
basic_machine=i860-alliant
;;
@@ -318,6 +363,14 @@ case $basic_machine in
basic_machine=h8300-hitachi
os=-hms
;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
harris)
basic_machine=m88k-harris
os=-sysv3
@@ -333,13 +386,30 @@ case $basic_machine in
basic_machine=m68k-hp
os=-hpux
;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
hp9k2[0-9][0-9] | hp9k31[0-9])
basic_machine=m68000-hp
;;
hp9k3[2-9][0-9])
basic_machine=m68k-hp
;;
- hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7)
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
basic_machine=hppa1.1-hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
@@ -348,27 +418,51 @@ case $basic_machine in
hppa-next)
os=-nextstep3
;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
i370-ibm* | ibm*)
basic_machine=i370-ibm
os=-mvs
;;
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
- i[3456]86v32)
+ i[34567]86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
;;
- i[3456]86v4*)
+ i[34567]86v4*)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv4
;;
- i[3456]86v)
+ i[34567]86v)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv
;;
- i[3456]86sol2)
+ i[34567]86sol2)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-solaris2
;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ i386-go32 | go32)
+ basic_machine=i386-unknown
+ os=-go32
+ ;;
+ i386-mingw32 | mingw32)
+ basic_machine=i386-unknown
+ os=-mingw32
+ ;;
iris | iris4d)
basic_machine=mips-sgi
case $os in
@@ -397,6 +491,10 @@ case $basic_machine in
miniframe)
basic_machine=m68000-convergent
;;
+ *mint | *MiNT)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
mipsel*-linux*)
basic_machine=mipsel-unknown
os=-linux
@@ -411,10 +509,30 @@ case $basic_machine in
mips3*)
basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ msdos)
+ basic_machine=i386-unknown
+ os=-msdos
+ ;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ hpcmips*-*)
+ basic_machine=hpcmips-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-corel
+ os=-linux
+ ;;
news | news700 | news800 | news900)
basic_machine=m68k-sony
os=-newsos
@@ -427,6 +545,10 @@ case $basic_machine in
basic_machine=mips-sony
os=-newsos
;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
next | m*-next )
basic_machine=m68k-next
case $os in
@@ -452,9 +574,25 @@ case $basic_machine in
basic_machine=i960-intel
os=-nindy
;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
np1)
basic_machine=np1-gould
;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
pa-hitachi)
basic_machine=hppa1.1-hitachi
os=-hiuxwe2
@@ -472,25 +610,23 @@ case $basic_machine in
pc532 | pc532-*)
basic_machine=ns32k-pc532
;;
- pentium | p5)
- basic_machine=i586-intel
+ pentium | p5 | k5 | k6 | nexen)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86)
+ basic_machine=i686-pc
;;
- pentiumpro | p6)
- basic_machine=i686-intel
+ pentiumii | pentium2)
+ basic_machine=i786-pc
;;
- pentium-* | p5-*)
+ pentium-* | p5-* | k5-* | k6-* | nexen-*)
basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
- pentiumpro-* | p6-*)
+ pentiumpro-* | p6-* | 6x86-*)
basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
- k5)
- # We don't have specific support for AMD's K5 yet, so just call it a Pentium
- basic_machine=i586-amd
- ;;
- nexen)
- # We don't have specific support for Nexgen yet, so just call it a Pentium
- basic_machine=i586-nexgen
+ pentiumii-* | pentium2-*)
+ basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
pn)
basic_machine=pn-gould
@@ -510,12 +646,20 @@ case $basic_machine in
ps2)
basic_machine=i386-ibm
;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
rm[46]00)
basic_machine=mips-siemens
;;
rtpc | rtpc-*)
basic_machine=romp-ibm
;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
sequent)
basic_machine=i386-sequent
;;
@@ -523,6 +667,10 @@ case $basic_machine in
basic_machine=sh-hitachi
os=-hms
;;
+ sparclite-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
sps7)
basic_machine=m68k-bull
os=-sysv2
@@ -530,6 +678,13 @@ case $basic_machine in
spur)
basic_machine=spur-unknown
;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
sun2)
basic_machine=m68000-sun
;;
@@ -574,6 +729,10 @@ case $basic_machine in
basic_machine=i386-sequent
os=-dynix
;;
+ t3e)
+ basic_machine=t3e-cray
+ os=-unicos
+ ;;
tx39)
basic_machine=mipstx39-unknown
;;
@@ -591,6 +750,10 @@ case $basic_machine in
basic_machine=a29k-nyu
os=-sym1
;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
vaxv)
basic_machine=vax-dec
os=-sysv
@@ -614,6 +777,14 @@ case $basic_machine in
basic_machine=a29k-wrs
os=-vxworks
;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
xmp)
basic_machine=xmp-cray
os=-unicos
@@ -621,6 +792,10 @@ case $basic_machine in
xps | xps100)
basic_machine=xps100-honeywell
;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
none)
basic_machine=none-none
os=-none
@@ -628,6 +803,15 @@ case $basic_machine in
# Here we handle the default manufacturer of certain CPU types. It is in
# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
mips)
if [ x$os = x-linux ]; then
basic_machine=mips-unknown
@@ -650,7 +834,7 @@ case $basic_machine in
we32k)
basic_machine=we32k-att
;;
- sparc)
+ sparc | sparcv9)
basic_machine=sparc-sun
;;
cydra)
@@ -662,6 +846,16 @@ case $basic_machine in
orion105)
basic_machine=clipper-highlevel
;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ c4x*)
+ basic_machine=c4x-none
+ os=-coff
+ ;;
*)
echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
exit 1
@@ -676,10 +870,6 @@ case $basic_machine in
*-commodore*)
basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
;;
- human)
- basic_machine=m68k-sharp
- os=-human
- ;;
*)
;;
esac
@@ -705,7 +895,7 @@ case $os in
os=-sysv4.2uw
;;
-gnu/linux*)
- os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ os=`echo $os | sed -e 's|gnu/linux|linux|'`
;;
# First accept the basic system types.
# The portable systems comes first.
@@ -719,13 +909,22 @@ case $os in
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
- | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
- | -cygwin32* | -pe* | -psos* | -moss* | -proelf* \
- | -linux* | -bow*)
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -rhapsody* | -openstep* | -oskit* \
+ | -darwin*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+ | -macos* | -mpw* | -magic* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
-sunos5*)
os=`echo $os | sed -e 's|sunos5|solaris2|'`
;;
@@ -747,6 +946,9 @@ case $os in
-acis*)
os=-aos
;;
+ -386bsd)
+ os=-bsd
+ ;;
-ctix* | -uts*)
os=-sysv
;;
@@ -778,11 +980,26 @@ case $os in
# This must come after -sysvr4.
-sysv*)
;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
-xenix)
os=-xenix
;;
+ -mint* | -MiNT*)
+ os=-mint
+ ;;
+ -uxpds)
+ os=-uxpds
+ ;;
-human)
;;
+ -beos)
+ os=-beos
+ ;;
-none)
;;
*)
@@ -808,6 +1025,9 @@ case $basic_machine in
*-acorn)
os=-riscix1.2
;;
+ arm*-corel)
+ os=-linux
+ ;;
arm*-semi)
os=-aout
;;
@@ -829,15 +1049,36 @@ case $basic_machine in
# default.
# os=-sunos4
;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
*-tti) # must be before sparc entry or we get the wrong os.
os=-sysv3
;;
sparc-* | *-sun)
os=-sunos4.1.1
;;
+ *-be)
+ os=-beos
+ ;;
*-ibm)
os=-aix
;;
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
*-hp)
os=-hpux
;;
@@ -901,6 +1142,18 @@ case $basic_machine in
f301-fujitsu)
os=-uxpv
;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
*)
os=-none
;;
@@ -922,9 +1175,15 @@ case $basic_machine in
-aix*)
vendor=ibm
;;
+ -beos*)
+ vendor=be
+ ;;
-hpux*)
vendor=hp
;;
+ -mpeix*)
+ vendor=hp
+ ;;
-hiux*)
vendor=hitachi
;;
@@ -952,6 +1211,15 @@ case $basic_machine in
-aux*)
vendor=apple
;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -*MiNT)
+ vendor=atari
+ ;;
esac
basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
;;
diff --git a/configure b/configure
deleted file mode 100644
index 50ce61b202..0000000000
--- a/configure
+++ /dev/null
@@ -1,4091 +0,0 @@
-#! /bin/sh
-
-# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.12
-# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
-#
-# This configure script is free software; the Free Software Foundation
-# gives unlimited permission to copy, distribute and modify it.
-
-# Defaults:
-ac_help=
-ac_default_prefix=/usr/local
-# Any additions from configure.in:
-ac_help="$ac_help
---without-gcc never use gcc"
-ac_help="$ac_help
---disable-thread never use user-level thread"
-ac_help="$ac_help
---enable-fat-binary build a NeXT Multi Architecture Binary. "
-ac_help="$ac_help
---with-dln-a-out use dln_a_out if possible"
-ac_help="$ac_help
---with-static-linked-ext link external modules statically"
-
-# Initialize some variables set by options.
-# The variables have the same names as the options, with
-# dashes changed to underlines.
-build=NONE
-cache_file=./config.cache
-exec_prefix=NONE
-host=NONE
-no_create=
-nonopt=NONE
-no_recursion=
-prefix=NONE
-program_prefix=NONE
-program_suffix=NONE
-program_transform_name=s,x,x,
-silent=
-site=
-srcdir=
-target=NONE
-verbose=
-x_includes=NONE
-x_libraries=NONE
-bindir='${exec_prefix}/bin'
-sbindir='${exec_prefix}/sbin'
-libexecdir='${exec_prefix}/libexec'
-datadir='${prefix}/share'
-sysconfdir='${prefix}/etc'
-sharedstatedir='${prefix}/com'
-localstatedir='${prefix}/var'
-libdir='${exec_prefix}/lib'
-includedir='${prefix}/include'
-oldincludedir='/usr/include'
-infodir='${prefix}/info'
-mandir='${prefix}/man'
-
-# Initialize some other variables.
-subdirs=
-MFLAGS= MAKEFLAGS=
-# Maximum number of lines to put in a shell here document.
-ac_max_here_lines=12
-
-ac_prev=
-for ac_option
-do
-
- # If the previous option needs an argument, assign it.
- if test -n "$ac_prev"; then
- eval "$ac_prev=\$ac_option"
- ac_prev=
- continue
- fi
-
- case "$ac_option" in
- -*=*) ac_optarg=`echo "$ac_option" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
- *) ac_optarg= ;;
- esac
-
- # Accept the important Cygnus configure options, so we can diagnose typos.
-
- case "$ac_option" in
-
- -bindir | --bindir | --bindi | --bind | --bin | --bi)
- ac_prev=bindir ;;
- -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
- bindir="$ac_optarg" ;;
-
- -build | --build | --buil | --bui | --bu)
- ac_prev=build ;;
- -build=* | --build=* | --buil=* | --bui=* | --bu=*)
- build="$ac_optarg" ;;
-
- -cache-file | --cache-file | --cache-fil | --cache-fi \
- | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
- ac_prev=cache_file ;;
- -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
- | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
- cache_file="$ac_optarg" ;;
-
- -datadir | --datadir | --datadi | --datad | --data | --dat | --da)
- ac_prev=datadir ;;
- -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \
- | --da=*)
- datadir="$ac_optarg" ;;
-
- -disable-* | --disable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*disable-//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- eval "enable_${ac_feature}=no" ;;
-
- -enable-* | --enable-*)
- ac_feature=`echo $ac_option|sed -e 's/-*enable-//' -e 's/=.*//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_feature| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_feature: invalid feature name" 1>&2; exit 1; }
- fi
- ac_feature=`echo $ac_feature| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
- *) ac_optarg=yes ;;
- esac
- eval "enable_${ac_feature}='$ac_optarg'" ;;
-
- -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
- | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
- | --exec | --exe | --ex)
- ac_prev=exec_prefix ;;
- -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
- | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
- | --exec=* | --exe=* | --ex=*)
- exec_prefix="$ac_optarg" ;;
-
- -gas | --gas | --ga | --g)
- # Obsolete; use --with-gas.
- with_gas=yes ;;
-
- -help | --help | --hel | --he)
- # Omit some internal or obsolete options to make the list less imposing.
- # This message is too long to be a string in the A/UX 3.1 sh.
- cat << EOF
-Usage: configure [options] [host]
-Options: [defaults in brackets after descriptions]
-Configuration:
- --cache-file=FILE cache test results in FILE
- --help print this message
- --no-create do not create output files
- --quiet, --silent do not print \`checking...' messages
- --version print the version of autoconf that created configure
-Directory and file names:
- --prefix=PREFIX install architecture-independent files in PREFIX
- [$ac_default_prefix]
- --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
- [same as prefix]
- --bindir=DIR user executables in DIR [EPREFIX/bin]
- --sbindir=DIR system admin executables in DIR [EPREFIX/sbin]
- --libexecdir=DIR program executables in DIR [EPREFIX/libexec]
- --datadir=DIR read-only architecture-independent data in DIR
- [PREFIX/share]
- --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc]
- --sharedstatedir=DIR modifiable architecture-independent data in DIR
- [PREFIX/com]
- --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var]
- --libdir=DIR object code libraries in DIR [EPREFIX/lib]
- --includedir=DIR C header files in DIR [PREFIX/include]
- --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include]
- --infodir=DIR info documentation in DIR [PREFIX/info]
- --mandir=DIR man documentation in DIR [PREFIX/man]
- --srcdir=DIR find the sources in DIR [configure dir or ..]
- --program-prefix=PREFIX prepend PREFIX to installed program names
- --program-suffix=SUFFIX append SUFFIX to installed program names
- --program-transform-name=PROGRAM
- run sed PROGRAM on installed program names
-EOF
- cat << EOF
-Host type:
- --build=BUILD configure for building on BUILD [BUILD=HOST]
- --host=HOST configure for HOST [guessed]
- --target=TARGET configure for TARGET [TARGET=HOST]
-Features and packages:
- --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
- --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
- --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
- --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
- --x-includes=DIR X include files are in DIR
- --x-libraries=DIR X library files are in DIR
-EOF
- if test -n "$ac_help"; then
- echo "--enable and --with options recognized:$ac_help"
- fi
- exit 0 ;;
-
- -host | --host | --hos | --ho)
- ac_prev=host ;;
- -host=* | --host=* | --hos=* | --ho=*)
- host="$ac_optarg" ;;
-
- -includedir | --includedir | --includedi | --included | --include \
- | --includ | --inclu | --incl | --inc)
- ac_prev=includedir ;;
- -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
- | --includ=* | --inclu=* | --incl=* | --inc=*)
- includedir="$ac_optarg" ;;
-
- -infodir | --infodir | --infodi | --infod | --info | --inf)
- ac_prev=infodir ;;
- -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
- infodir="$ac_optarg" ;;
-
- -libdir | --libdir | --libdi | --libd)
- ac_prev=libdir ;;
- -libdir=* | --libdir=* | --libdi=* | --libd=*)
- libdir="$ac_optarg" ;;
-
- -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
- | --libexe | --libex | --libe)
- ac_prev=libexecdir ;;
- -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
- | --libexe=* | --libex=* | --libe=*)
- libexecdir="$ac_optarg" ;;
-
- -localstatedir | --localstatedir | --localstatedi | --localstated \
- | --localstate | --localstat | --localsta | --localst \
- | --locals | --local | --loca | --loc | --lo)
- ac_prev=localstatedir ;;
- -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
- | --localstate=* | --localstat=* | --localsta=* | --localst=* \
- | --locals=* | --local=* | --loca=* | --loc=* | --lo=*)
- localstatedir="$ac_optarg" ;;
-
- -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
- ac_prev=mandir ;;
- -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
- mandir="$ac_optarg" ;;
-
- -nfp | --nfp | --nf)
- # Obsolete; use --without-fp.
- with_fp=no ;;
-
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c)
- no_create=yes ;;
-
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
- no_recursion=yes ;;
-
- -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
- | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
- | --oldin | --oldi | --old | --ol | --o)
- ac_prev=oldincludedir ;;
- -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
- | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
- | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
- oldincludedir="$ac_optarg" ;;
-
- -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
- ac_prev=prefix ;;
- -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
- prefix="$ac_optarg" ;;
-
- -program-prefix | --program-prefix | --program-prefi | --program-pref \
- | --program-pre | --program-pr | --program-p)
- ac_prev=program_prefix ;;
- -program-prefix=* | --program-prefix=* | --program-prefi=* \
- | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
- program_prefix="$ac_optarg" ;;
-
- -program-suffix | --program-suffix | --program-suffi | --program-suff \
- | --program-suf | --program-su | --program-s)
- ac_prev=program_suffix ;;
- -program-suffix=* | --program-suffix=* | --program-suffi=* \
- | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
- program_suffix="$ac_optarg" ;;
-
- -program-transform-name | --program-transform-name \
- | --program-transform-nam | --program-transform-na \
- | --program-transform-n | --program-transform- \
- | --program-transform | --program-transfor \
- | --program-transfo | --program-transf \
- | --program-trans | --program-tran \
- | --progr-tra | --program-tr | --program-t)
- ac_prev=program_transform_name ;;
- -program-transform-name=* | --program-transform-name=* \
- | --program-transform-nam=* | --program-transform-na=* \
- | --program-transform-n=* | --program-transform-=* \
- | --program-transform=* | --program-transfor=* \
- | --program-transfo=* | --program-transf=* \
- | --program-trans=* | --program-tran=* \
- | --progr-tra=* | --program-tr=* | --program-t=*)
- program_transform_name="$ac_optarg" ;;
-
- -q | -quiet | --quiet | --quie | --qui | --qu | --q \
- | -silent | --silent | --silen | --sile | --sil)
- silent=yes ;;
-
- -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
- ac_prev=sbindir ;;
- -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
- | --sbi=* | --sb=*)
- sbindir="$ac_optarg" ;;
-
- -sharedstatedir | --sharedstatedir | --sharedstatedi \
- | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
- | --sharedst | --shareds | --shared | --share | --shar \
- | --sha | --sh)
- ac_prev=sharedstatedir ;;
- -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
- | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
- | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
- | --sha=* | --sh=*)
- sharedstatedir="$ac_optarg" ;;
-
- -site | --site | --sit)
- ac_prev=site ;;
- -site=* | --site=* | --sit=*)
- site="$ac_optarg" ;;
-
- -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
- ac_prev=srcdir ;;
- -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
- srcdir="$ac_optarg" ;;
-
- -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
- | --syscon | --sysco | --sysc | --sys | --sy)
- ac_prev=sysconfdir ;;
- -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
- | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
- sysconfdir="$ac_optarg" ;;
-
- -target | --target | --targe | --targ | --tar | --ta | --t)
- ac_prev=target ;;
- -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
- target="$ac_optarg" ;;
-
- -v | -verbose | --verbose | --verbos | --verbo | --verb)
- verbose=yes ;;
-
- -version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.12"
- exit 0 ;;
-
- -with-* | --with-*)
- ac_package=`echo $ac_option|sed -e 's/-*with-//' -e 's/=.*//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-_a-zA-Z0-9]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- case "$ac_option" in
- *=*) ;;
- *) ac_optarg=yes ;;
- esac
- eval "with_${ac_package}='$ac_optarg'" ;;
-
- -without-* | --without-*)
- ac_package=`echo $ac_option|sed -e 's/-*without-//'`
- # Reject names that are not valid shell variable names.
- if test -n "`echo $ac_package| sed 's/[-a-zA-Z0-9_]//g'`"; then
- { echo "configure: error: $ac_package: invalid package name" 1>&2; exit 1; }
- fi
- ac_package=`echo $ac_package| sed 's/-/_/g'`
- eval "with_${ac_package}=no" ;;
-
- --x)
- # Obsolete; use --with-x.
- with_x=yes ;;
-
- -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
- | --x-incl | --x-inc | --x-in | --x-i)
- ac_prev=x_includes ;;
- -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
- | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
- x_includes="$ac_optarg" ;;
-
- -x-libraries | --x-libraries | --x-librarie | --x-librari \
- | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
- ac_prev=x_libraries ;;
- -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
- | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
- x_libraries="$ac_optarg" ;;
-
- -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; }
- ;;
-
- *)
- if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then
- echo "configure: warning: $ac_option: invalid host type" 1>&2
- fi
- if test "x$nonopt" != xNONE; then
- { echo "configure: error: can only configure for one host and one target at a time" 1>&2; exit 1; }
- fi
- nonopt="$ac_option"
- ;;
-
- esac
-done
-
-if test -n "$ac_prev"; then
- { echo "configure: error: missing argument to --`echo $ac_prev | sed 's/_/-/g'`" 1>&2; exit 1; }
-fi
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-# File descriptor usage:
-# 0 standard input
-# 1 file creation
-# 2 errors and warnings
-# 3 some systems may open it to /dev/tty
-# 4 used on the Kubota Titan
-# 6 checking for... messages and results
-# 5 compiler messages saved in config.log
-if test "$silent" = yes; then
- exec 6>/dev/null
-else
- exec 6>&1
-fi
-exec 5>./config.log
-
-echo "\
-This file contains any messages produced by compilers while
-running configure, to aid debugging if configure makes a mistake.
-" 1>&5
-
-# Strip out --no-create and --no-recursion so they do not pile up.
-# Also quote any args containing shell metacharacters.
-ac_configure_args=
-for ac_arg
-do
- case "$ac_arg" in
- -no-create | --no-create | --no-creat | --no-crea | --no-cre \
- | --no-cr | --no-c) ;;
- -no-recursion | --no-recursion | --no-recursio | --no-recursi \
- | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) ;;
- *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*)
- ac_configure_args="$ac_configure_args '$ac_arg'" ;;
- *) ac_configure_args="$ac_configure_args $ac_arg" ;;
- esac
-done
-
-# NLS nuisances.
-# Only set these to C if already set. These must not be set unconditionally
-# because not all systems understand e.g. LANG=C (notably SCO).
-# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'!
-# Non-C LC_CTYPE values break the ctype check.
-if test "${LANG+set}" = set; then LANG=C; export LANG; fi
-if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi
-if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi
-if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi
-
-# confdefs.h avoids OS command line length limits that DEFS can exceed.
-rm -rf conftest* confdefs.h
-# AIX cpp loses on an empty file, so make sure it contains at least a newline.
-echo > confdefs.h
-
-# A filename unique to this package, relative to the directory that
-# configure is in, which we can look for to find out if srcdir is correct.
-ac_unique_file=ruby.h
-
-# Find the source files, if location was not specified.
-if test -z "$srcdir"; then
- ac_srcdir_defaulted=yes
- # Try the directory containing this script, then its parent.
- ac_prog=$0
- ac_confdir=`echo $ac_prog|sed 's%/[^/][^/]*$%%'`
- test "x$ac_confdir" = "x$ac_prog" && ac_confdir=.
- srcdir=$ac_confdir
- if test ! -r $srcdir/$ac_unique_file; then
- srcdir=..
- fi
-else
- ac_srcdir_defaulted=no
-fi
-if test ! -r $srcdir/$ac_unique_file; then
- if test "$ac_srcdir_defaulted" = yes; then
- { echo "configure: error: can not find sources in $ac_confdir or .." 1>&2; exit 1; }
- else
- { echo "configure: error: can not find sources in $srcdir" 1>&2; exit 1; }
- fi
-fi
-srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
-
-# Prefer explicitly selected file to automatically selected ones.
-if test -z "$CONFIG_SITE"; then
- if test "x$prefix" != xNONE; then
- CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
- else
- CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
- fi
-fi
-for ac_site_file in $CONFIG_SITE; do
- if test -r "$ac_site_file"; then
- echo "loading site script $ac_site_file"
- . "$ac_site_file"
- fi
-done
-
-if test -r "$cache_file"; then
- echo "loading cache $cache_file"
- . $cache_file
-else
- echo "creating cache $cache_file"
- > $cache_file
-fi
-
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then
- # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu.
- if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then
- ac_n= ac_c='
-' ac_t=' '
- else
- ac_n=-n ac_c= ac_t=
- fi
-else
- ac_n= ac_c='\c' ac_t=
-fi
-
-
-
-# Check whether --with-gcc or --without-gcc was given.
-if test "${with_gcc+set}" = set; then
- withval="$with_gcc"
-
- case $withval in
- no) CC=cc
- without_gcc=yes;;
- yes) CC=gcc
- without_gcc=no;;
- *) CC=$withval
- without_gcc=$withval;;
- esac
-else
- without_gcc=no
-fi
-
-if test ! -z "$ac_cv_prog_CC" -a ! -z "$CC" -a "$CC" != "$ac_cv_prog_CC"
-then
- { echo "configure: error: cached CC is different -- throw away $cache_file
-(it is also a good idea to do 'make clean' before compiling)" 1>&2; exit 1; }
-fi
-
-rb_thread=yes
-# Check whether --enable-thread or --disable-thread was given.
-if test "${enable_thread+set}" = set; then
- enableval="$enable_thread"
-
- rb_thread=$enableval
-
-fi
-
-if test $rb_thread = yes; then
- cat >> confdefs.h <<\EOF
-#define THREAD 1
-EOF
-
-fi
-
-ac_aux_dir=
-for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
- if test -f $ac_dir/install-sh; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install-sh -c"
- break
- elif test -f $ac_dir/install.sh; then
- ac_aux_dir=$ac_dir
- ac_install_sh="$ac_aux_dir/install.sh -c"
- break
- fi
-done
-if test -z "$ac_aux_dir"; then
- { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; }
-fi
-ac_config_guess=$ac_aux_dir/config.guess
-ac_config_sub=$ac_aux_dir/config.sub
-ac_configure=$ac_aux_dir/configure # This should be Cygnus configure.
-
-
-# Make sure we can run config.sub.
-if $ac_config_sub sun4 >/dev/null 2>&1; then :
-else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; }
-fi
-
-echo $ac_n "checking host system type""... $ac_c" 1>&6
-echo "configure:597: checking host system type" >&5
-
-host_alias=$host
-case "$host_alias" in
-NONE)
- case $nonopt in
- NONE)
- if host_alias=`$ac_config_guess`; then :
- else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; }
- fi ;;
- *) host_alias=$nonopt ;;
- esac ;;
-esac
-
-host=`$ac_config_sub $host_alias`
-host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
-host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
-host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
-echo "$ac_t""$host" 1>&6
-
-
-
-fat_binary=no
-# Check whether --enable-fat-binary or --disable-fat-binary was given.
-if test "${enable_fat_binary+set}" = set; then
- enableval="$enable_fat_binary"
- fat_binary=$enableval
-fi
-
-if test "$fat_binary" = yes ; then
-
- echo $ac_n "checking target architecture ""... $ac_c" 1>&6
-echo "configure:629: checking target architecture " >&5
-
- if test "$TARGET_ARCHS" = "" ; then
- if test `/usr/bin/arch` = "m68k" ; then
- TARGET_ARCHS="m68k i486"
- else
- TARGET_ARCHS="m68k `/usr/bin/arch`"
- fi
- fi
- # /usr/lib/arch_tool -archify_list $TARGET_ARCHS
- for archs in $TARGET_ARCHS
- do
- ARCH_FLAG="$ARCH_FLAG -arch $archs "
- echo -n " $archs"
- done
- cat >> confdefs.h <<\EOF
-#define NEXT_FAT_BINARY 1
-EOF
-
- echo "."
-fi
-
-
-if test "$program_transform_name" = s,x,x,; then
- program_transform_name=
-else
- # Double any \ or $. echo might interpret backslashes.
- cat <<\EOF_SED > conftestsed
-s,\\,\\\\,g; s,\$,$$,g
-EOF_SED
- program_transform_name="`echo $program_transform_name|sed -f conftestsed`"
- rm -f conftestsed
-fi
-test "$program_prefix" != NONE &&
- program_transform_name="s,^,${program_prefix},; $program_transform_name"
-# Use a double $ so make ignores it.
-test "$program_suffix" != NONE &&
- program_transform_name="s,\$\$,${program_suffix},; $program_transform_name"
-
-# sed with no file args requires a program.
-test "$program_transform_name" = "" && program_transform_name="s,x,x,"
-
-
-# Extract the first word of "gcc", so it can be a program name with args.
-set dummy gcc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:675: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
- for ac_dir in $PATH; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_CC="gcc"
- break
- fi
- done
- IFS="$ac_save_ifs"
-fi
-fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-if test -z "$CC"; then
- # Extract the first word of "cc", so it can be a program name with args.
-set dummy cc; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:704: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$CC"; then
- ac_cv_prog_CC="$CC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
- ac_prog_rejected=no
- for ac_dir in $PATH; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then
- ac_prog_rejected=yes
- continue
- fi
- ac_cv_prog_CC="cc"
- break
- fi
- done
- IFS="$ac_save_ifs"
-if test $ac_prog_rejected = yes; then
- # We found a bogon in the path, so make sure we never use it.
- set dummy $ac_cv_prog_CC
- shift
- if test $# -gt 0; then
- # We chose a different compiler from the bogus one.
- # However, it has the same basename, so the bogon will be chosen
- # first if we set CC to just the basename; use the full file name.
- shift
- set dummy "$ac_dir/$ac_word" "$@"
- shift
- ac_cv_prog_CC="$@"
- fi
-fi
-fi
-fi
-CC="$ac_cv_prog_CC"
-if test -n "$CC"; then
- echo "$ac_t""$CC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
- test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; }
-fi
-
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:752: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
-
-ac_ext=c
-# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options.
-ac_cpp='$CPP $CPPFLAGS'
-ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5'
-ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5'
-cross_compiling=$ac_cv_prog_cc_cross
-
-cat > conftest.$ac_ext <<EOF
-#line 762 "configure"
-#include "confdefs.h"
-main(){return(0);}
-EOF
-if { (eval echo configure:766: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- ac_cv_prog_cc_works=yes
- # If we can't run a trivial program, we are probably using a cross compiler.
- if (./conftest; exit) 2>/dev/null; then
- ac_cv_prog_cc_cross=no
- else
- ac_cv_prog_cc_cross=yes
- fi
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- ac_cv_prog_cc_works=no
-fi
-rm -fr conftest*
-
-echo "$ac_t""$ac_cv_prog_cc_works" 1>&6
-if test $ac_cv_prog_cc_works = no; then
- { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; }
-fi
-echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6
-echo "configure:786: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
-echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6
-cross_compiling=$ac_cv_prog_cc_cross
-
-echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
-echo "configure:791: checking whether we are using GNU C" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.c <<EOF
-#ifdef __GNUC__
- yes;
-#endif
-EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:800: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
- ac_cv_prog_gcc=yes
-else
- ac_cv_prog_gcc=no
-fi
-fi
-
-echo "$ac_t""$ac_cv_prog_gcc" 1>&6
-
-if test $ac_cv_prog_gcc = yes; then
- GCC=yes
- ac_test_CFLAGS="${CFLAGS+set}"
- ac_save_CFLAGS="$CFLAGS"
- CFLAGS=
- echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:815: checking whether ${CC-cc} accepts -g" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- echo 'void f(){}' > conftest.c
-if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then
- ac_cv_prog_cc_g=yes
-else
- ac_cv_prog_cc_g=no
-fi
-rm -f conftest*
-
-fi
-
-echo "$ac_t""$ac_cv_prog_cc_g" 1>&6
- if test "$ac_test_CFLAGS" = set; then
- CFLAGS="$ac_save_CFLAGS"
- elif test $ac_cv_prog_cc_g = yes; then
- CFLAGS="-g -O2"
- else
- CFLAGS="-O2"
- fi
-else
- GCC=
- test "${CFLAGS+set}" = set || CFLAGS="-g"
-fi
-
-echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:843: checking how to run the C preprocessor" >&5
-# On Suns, sometimes $CPP names a directory.
-if test -n "$CPP" && test -d "$CPP"; then
- CPP=
-fi
-if test -z "$CPP"; then
-if eval "test \"`echo '$''{'ac_cv_prog_CPP'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- # This must be in double quotes, not single quotes, because CPP may get
- # substituted into the Makefile and "${CC-cc}" will confuse make.
- CPP="${CC-cc} -E"
- # On the NeXT, cc -E runs the code through the compiler's parser,
- # not just through cpp.
- cat > conftest.$ac_ext <<EOF
-#line 858 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:864: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
-if test -z "$ac_err"; then
- :
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP="${CC-cc} -E -traditional-cpp"
- cat > conftest.$ac_ext <<EOF
-#line 875 "configure"
-#include "confdefs.h"
-#include <assert.h>
-Syntax Error
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:881: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
-if test -z "$ac_err"; then
- :
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- CPP=/lib/cpp
-fi
-rm -f conftest*
-fi
-rm -f conftest*
- ac_cv_prog_CPP="$CPP"
-fi
- CPP="$ac_cv_prog_CPP"
-else
- ac_cv_prog_CPP="$CPP"
-fi
-echo "$ac_t""$CPP" 1>&6
-
-if test $ac_cv_prog_gcc = yes; then
- echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
-echo "configure:905: checking whether ${CC-cc} needs -traditional" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_gcc_traditional'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_pattern="Autoconf.*'x'"
- cat > conftest.$ac_ext <<EOF
-#line 911 "configure"
-#include "confdefs.h"
-#include <sgtty.h>
-Autoconf TIOCGETP
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "$ac_pattern" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_prog_gcc_traditional=yes
-else
- rm -rf conftest*
- ac_cv_prog_gcc_traditional=no
-fi
-rm -f conftest*
-
-
- if test $ac_cv_prog_gcc_traditional = no; then
- cat > conftest.$ac_ext <<EOF
-#line 929 "configure"
-#include "confdefs.h"
-#include <termio.h>
-Autoconf TCGETA
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "$ac_pattern" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_prog_gcc_traditional=yes
-fi
-rm -f conftest*
-
- fi
-fi
-
-echo "$ac_t""$ac_cv_prog_gcc_traditional" 1>&6
- if test $ac_cv_prog_gcc_traditional = yes; then
- CC="$CC -traditional"
- fi
-fi
-
-for ac_prog in 'bison -y' byacc
-do
-# Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:955: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_YACC'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$YACC"; then
- ac_cv_prog_YACC="$YACC" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
- for ac_dir in $PATH; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_YACC="$ac_prog"
- break
- fi
- done
- IFS="$ac_save_ifs"
-fi
-fi
-YACC="$ac_cv_prog_YACC"
-if test -n "$YACC"; then
- echo "$ac_t""$YACC" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-test -n "$YACC" && break
-done
-test -n "$YACC" || YACC="yacc"
-
-# Extract the first word of "ranlib", so it can be a program name with args.
-set dummy ranlib; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:987: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$RANLIB"; then
- ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
- for ac_dir in $PATH; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_RANLIB="ranlib"
- break
- fi
- done
- IFS="$ac_save_ifs"
- test -z "$ac_cv_prog_RANLIB" && ac_cv_prog_RANLIB=":"
-fi
-fi
-RANLIB="$ac_cv_prog_RANLIB"
-if test -n "$RANLIB"; then
- echo "$ac_t""$RANLIB" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-
-for ac_prog in ar aal
-do
-# Extract the first word of "$ac_prog", so it can be a program name with args.
-set dummy $ac_prog; ac_word=$2
-echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:1019: checking for $ac_word" >&5
-if eval "test \"`echo '$''{'ac_cv_prog_AR'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test -n "$AR"; then
- ac_cv_prog_AR="$AR" # Let the user override the test.
-else
- IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:"
- for ac_dir in $PATH; do
- test -z "$ac_dir" && ac_dir=.
- if test -f $ac_dir/$ac_word; then
- ac_cv_prog_AR="$ac_prog"
- break
- fi
- done
- IFS="$ac_save_ifs"
-fi
-fi
-AR="$ac_cv_prog_AR"
-if test -n "$AR"; then
- echo "$ac_t""$AR" 1>&6
-else
- echo "$ac_t""no" 1>&6
-fi
-
-test -n "$AR" && break
-done
-test -n "$AR" || AR="ar"
-
-# Find a good install program. We prefer a C program (faster),
-# so one script is as good as another. But avoid the broken or
-# incompatible versions:
-# SysV /etc/install, /usr/sbin/install
-# SunOS /usr/etc/install
-# IRIX /sbin/install
-# AIX /bin/install
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# ./install, which can be erroneously created by make from ./install.sh.
-echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:1059: checking for a BSD compatible install" >&5
-if test -z "$INSTALL"; then
-if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:"
- for ac_dir in $PATH; do
- # Account for people who put trailing slashes in PATH elements.
- case "$ac_dir/" in
- /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- for ac_prog in ginstall installbsd scoinst install; do
- if test -f $ac_dir/$ac_prog; then
- if test $ac_prog = install &&
- grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- # OSF/1 installbsd also uses dspmsg, but is usable.
- :
- else
- ac_cv_path_install="$ac_dir/$ac_prog -c"
- break 2
- fi
- fi
- done
- ;;
- esac
- done
- IFS="$ac_save_IFS"
-
-fi
- if test "${ac_cv_path_install+set}" = set; then
- INSTALL="$ac_cv_path_install"
- else
- # As a last resort, use the slow shell script. We don't cache a
- # path for INSTALL within a source directory, because that will
- # break other packages using the cache if that directory is
- # removed, or if the path is relative.
- INSTALL="$ac_install_sh"
- fi
-fi
-echo "$ac_t""$INSTALL" 1>&6
-
-# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
-# It thinks the first close brace ends the variable substitution.
-test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
-
-echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:1109: checking whether ${MAKE-make} sets \${MAKE}" >&5
-set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftestmake <<\EOF
-all:
- @echo 'ac_maketemp="${MAKE}"'
-EOF
-# GNU make sometimes prints "make[1]: Entering...", which would confuse us.
-eval `${MAKE-make} -f conftestmake 2>/dev/null | grep temp=`
-if test -n "$ac_maketemp"; then
- eval ac_cv_prog_make_${ac_make}_set=yes
-else
- eval ac_cv_prog_make_${ac_make}_set=no
-fi
-rm -f conftestmake
-fi
-if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- SET_MAKE=
-else
- echo "$ac_t""no" 1>&6
- SET_MAKE="MAKE=${MAKE-make}"
-fi
-
-
-# checks for UNIX variants that set C preprocessor variables
-ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6
-echo "configure:1139: checking for minix/config.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1144 "configure"
-#include "confdefs.h"
-#include <minix/config.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1149: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- MINIX=yes
-else
- echo "$ac_t""no" 1>&6
-MINIX=
-fi
-
-if test "$MINIX" = yes; then
- cat >> confdefs.h <<\EOF
-#define _POSIX_SOURCE 1
-EOF
-
- cat >> confdefs.h <<\EOF
-#define _POSIX_1_SOURCE 2
-EOF
-
- cat >> confdefs.h <<\EOF
-#define _MINIX 1
-EOF
-
-fi
-
-
-case "$host_os" in
-nextstep*) ;;
-human*) ;;
-*) LIBS="-lm $LIBS";;
-esac
-echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6
-echo "configure:1193: checking for crypt in -lcrypt" >&5
-ac_lib_var=`echo crypt'_'crypt | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-lcrypt $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1201 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char crypt();
-
-int main() {
-crypt()
-; return 0; }
-EOF
-if { (eval echo configure:1212: \"$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
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_lib=HAVE_LIB`echo crypt | sed -e 's/[^a-zA-Z0-9_]/_/g' \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_lib 1
-EOF
-
- LIBS="-lcrypt $LIBS"
-
-else
- echo "$ac_t""no" 1>&6
-fi
-
-echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
-echo "configure:1240: checking for dlopen in -ldl" >&5
-ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-ldl $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1248 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char dlopen();
-
-int main() {
-dlopen()
-; return 0; }
-EOF
-if { (eval echo configure:1259: \"$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
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_lib=HAVE_LIB`echo dl | sed -e 's/[^a-zA-Z0-9_]/_/g' \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_lib 1
-EOF
-
- LIBS="-ldl $LIBS"
-
-else
- echo "$ac_t""no" 1>&6
-fi
- # Dynamic linking for SunOS/Solaris and SYSV
-echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
-echo "configure:1287: checking for shl_load in -ldld" >&5
-ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-ldld $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1295 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char shl_load();
-
-int main() {
-shl_load()
-; return 0; }
-EOF
-if { (eval echo configure:1306: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_lib=HAVE_LIB`echo dld | sed -e 's/[^a-zA-Z0-9_]/_/g' \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_lib 1
-EOF
-
- LIBS="-ldld $LIBS"
-
-else
- echo "$ac_t""no" 1>&6
-fi
- # Dynamic linking for HP-UX
-
-ac_header_dirent=no
-for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h
-do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr that defines DIR""... $ac_c" 1>&6
-echo "configure:1339: checking for $ac_hdr that defines DIR" >&5
-if eval "test \"`echo '$''{'ac_cv_header_dirent_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1344 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <$ac_hdr>
-int main() {
-DIR *dirp = 0;
-; return 0; }
-EOF
-if { (eval echo configure:1352: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- eval "ac_cv_header_dirent_$ac_safe=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_dirent_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_dirent_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
- ac_header_dirent=$ac_hdr; break
-else
- echo "$ac_t""no" 1>&6
-fi
-done
-# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
-if test $ac_header_dirent = dirent.h; then
-echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
-echo "configure:1377: checking for opendir in -ldir" >&5
-ac_lib_var=`echo dir'_'opendir | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-ldir $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1385 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char opendir();
-
-int main() {
-opendir()
-; return 0; }
-EOF
-if { (eval echo configure:1396: \"$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
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- LIBS="$LIBS -ldir"
-else
- echo "$ac_t""no" 1>&6
-fi
-
-else
-echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
-echo "configure:1418: checking for opendir in -lx" >&5
-ac_lib_var=`echo x'_'opendir | sed 'y%./+-%__p_%'`
-if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_save_LIBS="$LIBS"
-LIBS="-lx $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 1426 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char opendir();
-
-int main() {
-opendir()
-; return 0; }
-EOF
-if { (eval echo configure:1437: \"$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
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- LIBS="$LIBS -lx"
-else
- echo "$ac_t""no" 1>&6
-fi
-
-fi
-
-echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:1460: checking for ANSI C header files" >&5
-if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1465 "configure"
-#include "confdefs.h"
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1473: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
-if test -z "$ac_err"; then
- rm -rf conftest*
- ac_cv_header_stdc=yes
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
-cat > conftest.$ac_ext <<EOF
-#line 1490 "configure"
-#include "confdefs.h"
-#include <string.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "memchr" >/dev/null 2>&1; then
- :
-else
- rm -rf conftest*
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
-cat > conftest.$ac_ext <<EOF
-#line 1508 "configure"
-#include "confdefs.h"
-#include <stdlib.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "free" >/dev/null 2>&1; then
- :
-else
- rm -rf conftest*
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
-if test "$cross_compiling" = yes; then
- :
-else
- cat > conftest.$ac_ext <<EOF
-#line 1529 "configure"
-#include "confdefs.h"
-#include <ctype.h>
-#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-#define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int main () { int i; for (i = 0; i < 256; i++)
-if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
-exit (0); }
-
-EOF
-if { (eval echo configure:1540: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- :
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_header_stdc=no
-fi
-rm -fr conftest*
-fi
-
-fi
-fi
-
-echo "$ac_t""$ac_cv_header_stdc" 1>&6
-if test $ac_cv_header_stdc = yes; then
- cat >> confdefs.h <<\EOF
-#define STDC_HEADERS 1
-EOF
-
-fi
-
-for ac_hdr in stdlib.h unistd.h limits.h sys/file.h sys/ioctl.h pwd.h \
- sys/select.h sys/time.h sys/times.h sys/param.h sys/wait.h\
- syscall.h a.out.h string.h utime.h memory.h
-do
-ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1569: checking for $ac_hdr" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1574 "configure"
-#include "confdefs.h"
-#include <$ac_hdr>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1579: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_hdr 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-fi
-done
-
-
-echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
-echo "configure:1607: checking for uid_t in sys/types.h" >&5
-if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1612 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "uid_t" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_type_uid_t=yes
-else
- rm -rf conftest*
- ac_cv_type_uid_t=no
-fi
-rm -f conftest*
-
-fi
-
-echo "$ac_t""$ac_cv_type_uid_t" 1>&6
-if test $ac_cv_type_uid_t = no; then
- cat >> confdefs.h <<\EOF
-#define uid_t int
-EOF
-
- cat >> confdefs.h <<\EOF
-#define gid_t int
-EOF
-
-fi
-
-echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:1641: checking for size_t" >&5
-if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1646 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#if STDC_HEADERS
-#include <stdlib.h>
-#include <stddef.h>
-#endif
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_type_size_t=yes
-else
- rm -rf conftest*
- ac_cv_type_size_t=no
-fi
-rm -f conftest*
-
-fi
-echo "$ac_t""$ac_cv_type_size_t" 1>&6
-if test $ac_cv_type_size_t = no; then
- cat >> confdefs.h <<\EOF
-#define size_t unsigned
-EOF
-
-fi
-
-echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6
-echo "configure:1674: checking for st_blksize in struct stat" >&5
-if eval "test \"`echo '$''{'ac_cv_struct_st_blksize'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1679 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-int main() {
-struct stat s; s.st_blksize;
-; return 0; }
-EOF
-if { (eval echo configure:1687: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_struct_st_blksize=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_struct_st_blksize=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$ac_cv_struct_st_blksize" 1>&6
-if test $ac_cv_struct_st_blksize = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_ST_BLKSIZE 1
-EOF
-
-fi
-
-save_LIBOJBS="$LIBOBJS"
-echo $ac_n "checking for st_blocks in struct stat""... $ac_c" 1>&6
-echo "configure:1709: checking for st_blocks in struct stat" >&5
-if eval "test \"`echo '$''{'ac_cv_struct_st_blocks'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1714 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-int main() {
-struct stat s; s.st_blocks;
-; return 0; }
-EOF
-if { (eval echo configure:1722: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_struct_st_blocks=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_struct_st_blocks=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$ac_cv_struct_st_blocks" 1>&6
-if test $ac_cv_struct_st_blocks = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_ST_BLOCKS 1
-EOF
-
-else
- LIBOBJS="$LIBOBJS fileblocks.o"
-fi
-
-LIBOBJS="$save_LIBOBJS"
-echo $ac_n "checking for st_rdev in struct stat""... $ac_c" 1>&6
-echo "configure:1746: checking for st_rdev in struct stat" >&5
-if eval "test \"`echo '$''{'ac_cv_struct_st_rdev'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 1751 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-int main() {
-struct stat s; s.st_rdev;
-; return 0; }
-EOF
-if { (eval echo configure:1759: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_struct_st_rdev=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_struct_st_rdev=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$ac_cv_struct_st_rdev" 1>&6
-if test $ac_cv_struct_st_rdev = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_ST_RDEV 1
-EOF
-
-fi
-
-
-echo $ac_n "checking size of short""... $ac_c" 1>&6
-echo "configure:1781: checking size of short" >&5
-if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
-else
- cat > conftest.$ac_ext <<EOF
-#line 1789 "configure"
-#include "confdefs.h"
-#include <stdio.h>
-main()
-{
- FILE *f=fopen("conftestval", "w");
- if (!f) exit(1);
- fprintf(f, "%d\n", sizeof(short));
- exit(0);
-}
-EOF
-if { (eval echo configure:1800: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_sizeof_short=`cat conftestval`
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_sizeof_short=0
-fi
-rm -fr conftest*
-fi
-
-fi
-echo "$ac_t""$ac_cv_sizeof_short" 1>&6
-cat >> confdefs.h <<EOF
-#define SIZEOF_SHORT $ac_cv_sizeof_short
-EOF
-
-
-echo $ac_n "checking size of int""... $ac_c" 1>&6
-echo "configure:1820: checking size of int" >&5
-if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
-else
- cat > conftest.$ac_ext <<EOF
-#line 1828 "configure"
-#include "confdefs.h"
-#include <stdio.h>
-main()
-{
- FILE *f=fopen("conftestval", "w");
- if (!f) exit(1);
- fprintf(f, "%d\n", sizeof(int));
- exit(0);
-}
-EOF
-if { (eval echo configure:1839: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_sizeof_int=`cat conftestval`
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_sizeof_int=0
-fi
-rm -fr conftest*
-fi
-
-fi
-echo "$ac_t""$ac_cv_sizeof_int" 1>&6
-cat >> confdefs.h <<EOF
-#define SIZEOF_INT $ac_cv_sizeof_int
-EOF
-
-
-echo $ac_n "checking size of long""... $ac_c" 1>&6
-echo "configure:1859: checking size of long" >&5
-if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
-else
- cat > conftest.$ac_ext <<EOF
-#line 1867 "configure"
-#include "confdefs.h"
-#include <stdio.h>
-main()
-{
- FILE *f=fopen("conftestval", "w");
- if (!f) exit(1);
- fprintf(f, "%d\n", sizeof(long));
- exit(0);
-}
-EOF
-if { (eval echo configure:1878: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_sizeof_long=`cat conftestval`
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_sizeof_long=0
-fi
-rm -fr conftest*
-fi
-
-fi
-echo "$ac_t""$ac_cv_sizeof_long" 1>&6
-cat >> confdefs.h <<EOF
-#define SIZEOF_LONG $ac_cv_sizeof_long
-EOF
-
-
-echo $ac_n "checking size of void*""... $ac_c" 1>&6
-echo "configure:1898: checking size of void*" >&5
-if eval "test \"`echo '$''{'ac_cv_sizeof_voidp'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
-else
- cat > conftest.$ac_ext <<EOF
-#line 1906 "configure"
-#include "confdefs.h"
-#include <stdio.h>
-main()
-{
- FILE *f=fopen("conftestval", "w");
- if (!f) exit(1);
- fprintf(f, "%d\n", sizeof(void*));
- exit(0);
-}
-EOF
-if { (eval echo configure:1917: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_sizeof_voidp=`cat conftestval`
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_sizeof_voidp=0
-fi
-rm -fr conftest*
-fi
-
-fi
-echo "$ac_t""$ac_cv_sizeof_voidp" 1>&6
-cat >> confdefs.h <<EOF
-#define SIZEOF_VOIDP $ac_cv_sizeof_voidp
-EOF
-
-
-
-echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6
-echo "configure:1938: checking type of array argument to getgroups" >&5
-if eval "test \"`echo '$''{'ac_cv_type_getgroups'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- ac_cv_type_getgroups=cross
-else
- cat > conftest.$ac_ext <<EOF
-#line 1946 "configure"
-#include "confdefs.h"
-
-/* Thanks to Mike Rendell for this test. */
-#include <sys/types.h>
-#define NGID 256
-#undef MAX
-#define MAX(x, y) ((x) > (y) ? (x) : (y))
-main()
-{
- gid_t gidset[NGID];
- int i, n;
- union { gid_t gval; long lval; } val;
-
- val.lval = -1;
- for (i = 0; i < NGID; i++)
- gidset[i] = val.gval;
- n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1,
- gidset);
- /* Exit non-zero if getgroups seems to require an array of ints. This
- happens when gid_t is short but getgroups modifies an array of ints. */
- exit ((n > 0 && gidset[n] != val.gval) ? 1 : 0);
-}
-
-EOF
-if { (eval echo configure:1971: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_type_getgroups=gid_t
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_type_getgroups=int
-fi
-rm -fr conftest*
-fi
-
-if test $ac_cv_type_getgroups = cross; then
- cat > conftest.$ac_ext <<EOF
-#line 1985 "configure"
-#include "confdefs.h"
-#include <unistd.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "getgroups.*int.*gid_t" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_type_getgroups=gid_t
-else
- rm -rf conftest*
- ac_cv_type_getgroups=int
-fi
-rm -f conftest*
-
-fi
-fi
-
-echo "$ac_t""$ac_cv_type_getgroups" 1>&6
-cat >> confdefs.h <<EOF
-#define GETGROUPS_T $ac_cv_type_getgroups
-EOF
-
-
-echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:2009: checking return type of signal handlers" >&5
-if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2014 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <signal.h>
-#ifdef signal
-#undef signal
-#endif
-#ifdef __cplusplus
-extern "C" void (*signal (int, void (*)(int)))(int);
-#else
-void (*signal ()) ();
-#endif
-
-int main() {
-int i;
-; return 0; }
-EOF
-if { (eval echo configure:2031: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_type_signal=void
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_type_signal=int
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$ac_cv_type_signal" 1>&6
-cat >> confdefs.h <<EOF
-#define RETSIGTYPE $ac_cv_type_signal
-EOF
-
-
-# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
-# for constant arguments. Useless!
-echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
-echo "configure:2052: checking for working alloca.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_alloca_h'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2057 "configure"
-#include "confdefs.h"
-#include <alloca.h>
-int main() {
-char *p = alloca(2 * sizeof(int));
-; return 0; }
-EOF
-if { (eval echo configure:2064: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- ac_cv_header_alloca_h=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_header_alloca_h=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$ac_cv_header_alloca_h" 1>&6
-if test $ac_cv_header_alloca_h = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_ALLOCA_H 1
-EOF
-
-fi
-
-echo $ac_n "checking for alloca""... $ac_c" 1>&6
-echo "configure:2085: checking for alloca" >&5
-if eval "test \"`echo '$''{'ac_cv_func_alloca_works'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2090 "configure"
-#include "confdefs.h"
-
-#ifdef __GNUC__
-# define alloca __builtin_alloca
-#else
-# if HAVE_ALLOCA_H
-# include <alloca.h>
-# else
-# ifdef _AIX
- #pragma alloca
-# else
-# ifndef alloca /* predefined by HP cc +Olibcalls */
-char *alloca ();
-# endif
-# endif
-# endif
-#endif
-
-int main() {
-char *p = (char *) alloca(1);
-; return 0; }
-EOF
-if { (eval echo configure:2113: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- ac_cv_func_alloca_works=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_func_alloca_works=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$ac_cv_func_alloca_works" 1>&6
-if test $ac_cv_func_alloca_works = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_ALLOCA 1
-EOF
-
-fi
-
-if test $ac_cv_func_alloca_works = no; then
- # The SVR3 libPW and SVR4 libucb both contain incompatible functions
- # that cause trouble. Some versions do not even contain alloca or
- # contain a buggy version. If you still want to use their alloca,
- # use ar to extract alloca.o from them instead of compiling alloca.c.
- ALLOCA=alloca.o
- cat >> confdefs.h <<\EOF
-#define C_ALLOCA 1
-EOF
-
-
-echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
-echo "configure:2145: checking whether alloca needs Cray hooks" >&5
-if eval "test \"`echo '$''{'ac_cv_os_cray'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2150 "configure"
-#include "confdefs.h"
-#if defined(CRAY) && ! defined(CRAY2)
-webecray
-#else
-wenotbecray
-#endif
-
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "webecray" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_os_cray=yes
-else
- rm -rf conftest*
- ac_cv_os_cray=no
-fi
-rm -f conftest*
-
-fi
-
-echo "$ac_t""$ac_cv_os_cray" 1>&6
-if test $ac_cv_os_cray = yes; then
-for ac_func in _getb67 GETB67 getb67; do
- echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2175: checking for $ac_func" >&5
-if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2180 "configure"
-#include "confdefs.h"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-$ac_func();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:2203: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- cat >> confdefs.h <<EOF
-#define CRAY_STACKSEG_END $ac_func
-EOF
-
- break
-else
- echo "$ac_t""no" 1>&6
-fi
-
-done
-fi
-
-echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
-echo "configure:2230: checking stack direction for C alloca" >&5
-if eval "test \"`echo '$''{'ac_cv_c_stack_direction'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- ac_cv_c_stack_direction=0
-else
- cat > conftest.$ac_ext <<EOF
-#line 2238 "configure"
-#include "confdefs.h"
-find_stack_direction ()
-{
- static char *addr = 0;
- auto char dummy;
- if (addr == 0)
- {
- addr = &dummy;
- return find_stack_direction ();
- }
- else
- return (&dummy > addr) ? 1 : -1;
-}
-main ()
-{
- exit (find_stack_direction() < 0);
-}
-EOF
-if { (eval echo configure:2257: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_c_stack_direction=1
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_c_stack_direction=-1
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$ac_cv_c_stack_direction" 1>&6
-cat >> confdefs.h <<EOF
-#define STACK_DIRECTION $ac_cv_c_stack_direction
-EOF
-
-fi
-
-echo $ac_n "checking for pid_t""... $ac_c" 1>&6
-echo "configure:2279: checking for pid_t" >&5
-if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2284 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#if STDC_HEADERS
-#include <stdlib.h>
-#include <stddef.h>
-#endif
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "pid_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_type_pid_t=yes
-else
- rm -rf conftest*
- ac_cv_type_pid_t=no
-fi
-rm -f conftest*
-
-fi
-echo "$ac_t""$ac_cv_type_pid_t" 1>&6
-if test $ac_cv_type_pid_t = no; then
- cat >> confdefs.h <<\EOF
-#define pid_t int
-EOF
-
-fi
-
-ac_safe=`echo "vfork.h" | sed 'y%./+-%__p_%'`
-echo $ac_n "checking for vfork.h""... $ac_c" 1>&6
-echo "configure:2313: checking for vfork.h" >&5
-if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2318 "configure"
-#include "confdefs.h"
-#include <vfork.h>
-EOF
-ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2323: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
-ac_err=`grep -v '^ *+' conftest.out`
-if test -z "$ac_err"; then
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=yes"
-else
- echo "$ac_err" >&5
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_header_$ac_safe=no"
-fi
-rm -f conftest*
-fi
-if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- cat >> confdefs.h <<\EOF
-#define HAVE_VFORK_H 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-fi
-
-echo $ac_n "checking for working vfork""... $ac_c" 1>&6
-echo "configure:2348: checking for working vfork" >&5
-if eval "test \"`echo '$''{'ac_cv_func_vfork_works'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- echo $ac_n "checking for vfork""... $ac_c" 1>&6
-echo "configure:2354: checking for vfork" >&5
-if eval "test \"`echo '$''{'ac_cv_func_vfork'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2359 "configure"
-#include "confdefs.h"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char vfork(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char vfork();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_vfork) || defined (__stub___vfork)
-choke me
-#else
-vfork();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:2382: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- eval "ac_cv_func_vfork=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_vfork=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'vfork`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- :
-else
- echo "$ac_t""no" 1>&6
-fi
-
-else
- cat > conftest.$ac_ext <<EOF
-#line 2403 "configure"
-#include "confdefs.h"
-/* Thanks to Paul Eggert for this test. */
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_VFORK_H
-#include <vfork.h>
-#endif
-/* On some sparc systems, changes by the child to local and incoming
- argument registers are propagated back to the parent.
- The compiler is told about this with #include <vfork.h>,
- but some compilers (e.g. gcc -O) don't grok <vfork.h>.
- Test for this by using a static variable whose address
- is put into a register that is clobbered by the vfork. */
-static
-#ifdef __cplusplus
-sparc_address_test (int arg)
-#else
-sparc_address_test (arg) int arg;
-#endif
-{
- static pid_t child;
- if (!child) {
- child = vfork ();
- if (child < 0) {
- perror ("vfork");
- _exit(2);
- }
- if (!child) {
- arg = getpid();
- write(-1, "", 0);
- _exit (arg);
- }
- }
-}
-main() {
- pid_t parent = getpid ();
- pid_t child;
-
- sparc_address_test ();
-
- child = vfork ();
-
- if (child == 0) {
- /* Here is another test for sparc vfork register problems.
- This test uses lots of local variables, at least
- as many local variables as main has allocated so far
- including compiler temporaries. 4 locals are enough for
- gcc 1.40.3 on a Solaris 4.1.3 sparc, but we use 8 to be safe.
- A buggy compiler should reuse the register of parent
- for one of the local variables, since it will think that
- parent can't possibly be used any more in this routine.
- Assigning to the local variable will thus munge parent
- in the parent process. */
- pid_t
- p = getpid(), p1 = getpid(), p2 = getpid(), p3 = getpid(),
- p4 = getpid(), p5 = getpid(), p6 = getpid(), p7 = getpid();
- /* Convince the compiler that p..p7 are live; otherwise, it might
- use the same hardware register for all 8 local variables. */
- if (p != p1 || p != p2 || p != p3 || p != p4
- || p != p5 || p != p6 || p != p7)
- _exit(1);
-
- /* On some systems (e.g. IRIX 3.3),
- vfork doesn't separate parent from child file descriptors.
- If the child closes a descriptor before it execs or exits,
- this munges the parent's descriptor as well.
- Test for this by closing stdout in the child. */
- _exit(close(fileno(stdout)) != 0);
- } else {
- int status;
- struct stat st;
-
- while (wait(&status) != child)
- ;
- exit(
- /* Was there some problem with vforking? */
- child < 0
-
- /* Did the child fail? (This shouldn't happen.) */
- || status
-
- /* Did the vfork/compiler bug occur? */
- || parent != getpid()
-
- /* Did the file descriptor bug occur? */
- || fstat(fileno(stdout), &st) != 0
- );
- }
-}
-EOF
-if { (eval echo configure:2498: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_func_vfork_works=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_func_vfork_works=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$ac_cv_func_vfork_works" 1>&6
-if test $ac_cv_func_vfork_works = no; then
- cat >> confdefs.h <<\EOF
-#define vfork fork
-EOF
-
-fi
-
-echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
-echo "configure:2521: checking for 8-bit clean memcmp" >&5
-if eval "test \"`echo '$''{'ac_cv_func_memcmp_clean'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- ac_cv_func_memcmp_clean=no
-else
- cat > conftest.$ac_ext <<EOF
-#line 2529 "configure"
-#include "confdefs.h"
-
-main()
-{
- char c0 = 0x40, c1 = 0x80, c2 = 0x81;
- exit(memcmp(&c0, &c2, 1) < 0 && memcmp(&c1, &c2, 1) < 0 ? 0 : 1);
-}
-
-EOF
-if { (eval echo configure:2539: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_func_memcmp_clean=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_func_memcmp_clean=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
-echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6
-test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.o"
-
-for ac_func in dup2 setenv memmove mkdir strcasecmp strerror strftime\
- strchr strstr strtoul strdup crypt flock
-do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2560: 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 2565 "configure"
-#include "confdefs.h"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-$ac_func();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:2588: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-LIBOBJS="$LIBOBJS ${ac_func}.o"
-fi
-done
-
-
-for ac_func in fmod killpg random wait4 waitpid syscall getcwd\
- truncate chsize times utimes fcntl lockf setitimer\
- setruid seteuid setreuid setrgid setegid setregid\
- setpgrp2 getpgid getgroups getpriority\
- dlopen sigprocmask sigaction _setjmp
-do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2621: 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 2626 "configure"
-#include "confdefs.h"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-$ac_func();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:2649: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-fi
-done
-
-if test "$ac_cv_func_strftime" = no; then
- echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
-echo "configure:2675: checking whether struct tm is in sys/time.h or time.h" >&5
-if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2680 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <time.h>
-int main() {
-struct tm *tp; tp->tm_sec;
-; return 0; }
-EOF
-if { (eval echo configure:2688: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_struct_tm=time.h
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_struct_tm=sys/time.h
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$ac_cv_struct_tm" 1>&6
-if test $ac_cv_struct_tm = sys/time.h; then
- cat >> confdefs.h <<\EOF
-#define TM_IN_SYS_TIME 1
-EOF
-
-fi
-
-echo $ac_n "checking for tm_zone in struct tm""... $ac_c" 1>&6
-echo "configure:2709: checking for tm_zone in struct tm" >&5
-if eval "test \"`echo '$''{'ac_cv_struct_tm_zone'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2714 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <$ac_cv_struct_tm>
-int main() {
-struct tm tm; tm.tm_zone;
-; return 0; }
-EOF
-if { (eval echo configure:2722: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_struct_tm_zone=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_struct_tm_zone=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$ac_cv_struct_tm_zone" 1>&6
-if test "$ac_cv_struct_tm_zone" = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_TM_ZONE 1
-EOF
-
-else
- echo $ac_n "checking for tzname""... $ac_c" 1>&6
-echo "configure:2742: checking for tzname" >&5
-if eval "test \"`echo '$''{'ac_cv_var_tzname'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2747 "configure"
-#include "confdefs.h"
-#include <time.h>
-#ifndef tzname /* For SGI. */
-extern char *tzname[]; /* RS6000 and others reject char **tzname. */
-#endif
-int main() {
-atoi(*tzname);
-; return 0; }
-EOF
-if { (eval echo configure:2757: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- ac_cv_var_tzname=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_var_tzname=no
-fi
-rm -f conftest*
-fi
-
-echo "$ac_t""$ac_cv_var_tzname" 1>&6
- if test $ac_cv_var_tzname = yes; then
- cat >> confdefs.h <<\EOF
-#define HAVE_TZNAME 1
-EOF
-
- fi
-fi
-
- cat > conftest.$ac_ext <<EOF
-#line 2779 "configure"
-#include "confdefs.h"
-
-int main() {
-extern int daylight; int i = daylight;
-; return 0; }
-EOF
-if { (eval echo configure:2786: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- cat >> confdefs.h <<\EOF
-#define HAVE_DAYLIGHT 1
-EOF
-
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
-fi
-rm -f conftest*
-fi
-
-if test "$ac_cv_func_sigprocmask" = yes && test "$ac_cv_func_sigaction" = yes; then
- cat >> confdefs.h <<\EOF
-#define POSIX_SIGNAL 1
-EOF
-
-else
- echo $ac_n "checking for BSD signal semantics""... $ac_c" 1>&6
-echo "configure:2806: checking for BSD signal semantics" >&5
- if eval "test \"`echo '$''{'rb_cv_bsd_signal'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
-else
- cat > conftest.$ac_ext <<EOF
-#line 2814 "configure"
-#include "confdefs.h"
-
-#include <stdio.h>
-#include <signal.h>
-
-void
-sig_handler(dummy)
- int dummy;
-{
-}
-
-int
-main()
-{
- signal(SIGINT, sig_handler);
- kill(getpid(), SIGINT);
- kill(getpid(), SIGINT);
- return 0;
-}
-
-EOF
-if { (eval echo configure:2836: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- rb_cv_bsd_signal=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- rb_cv_bsd_signal=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
- echo "$ac_t""$rb_cv_bsd_signal" 1>&6
- if test "$rb_cv_bsd_signal" = yes; then
- cat >> confdefs.h <<\EOF
-#define BSD_SIGNAL 1
-EOF
-
- fi
-fi
-
-if test "$ac_cv_func_setpgrp2" = yes; then
- cat >> confdefs.h <<\EOF
-#define BSD_GETPGRP getpgrp2
-EOF
-
- cat >> confdefs.h <<\EOF
-#define BSD_SETPGRP setpgrp2
-EOF
-
-else
- echo $ac_n "checking whether getpgrp() has arg""... $ac_c" 1>&6
-echo "configure:2870: checking whether getpgrp() has arg" >&5
- if eval "test \"`echo '$''{'rb_cv_bsdgetpgrp'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2875 "configure"
-#include "confdefs.h"
-#include <unistd.h>
-int main() {
-getpgrp(0);
-; return 0; }
-EOF
-if { (eval echo configure:2882: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- rb_cv_bsdgetpgrp=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- rb_cv_bsdgetpgrp=no
-fi
-rm -f conftest*
-fi
-
- echo "$ac_t""$rb_cv_bsdgetpgrp" 1>&6
- if test "$rb_cv_bsdgetpgrp" = yes; then
- cat >> confdefs.h <<\EOF
-#define BSD_GETPGRP getpgrp
-EOF
-
- fi
-
- echo $ac_n "checking whether setpgrp() has args""... $ac_c" 1>&6
-echo "configure:2903: checking whether setpgrp() has args" >&5
- if eval "test \"`echo '$''{'rb_cv_bsdsetpgrp'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 2908 "configure"
-#include "confdefs.h"
-#include <unistd.h>
-int main() {
-setpgrp(1, 1);
-; return 0; }
-EOF
-if { (eval echo configure:2915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- rb_cv_bsdsetpgrp=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- rb_cv_bsdsetpgrp=no
-fi
-rm -f conftest*
-fi
-
- echo "$ac_t""$rb_cv_bsdsetpgrp" 1>&6
- if test "$rb_cv_bsdsetpgrp" = yes; then
- cat >> confdefs.h <<\EOF
-#define BSD_SETPGRP setpgrp
-EOF
-
- fi
-fi
-
-echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-echo "configure:2937: checking whether byte ordering is bigendian" >&5
-if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- ac_cv_c_bigendian=unknown
-# See if sys/param.h defines the BYTE_ORDER macro.
-cat > conftest.$ac_ext <<EOF
-#line 2944 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <sys/param.h>
-int main() {
-
-#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN
- bogus endian macros
-#endif
-; return 0; }
-EOF
-if { (eval echo configure:2955: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- # It does; now see whether it defined to BIG_ENDIAN or not.
-cat > conftest.$ac_ext <<EOF
-#line 2959 "configure"
-#include "confdefs.h"
-#include <sys/types.h>
-#include <sys/param.h>
-int main() {
-
-#if BYTE_ORDER != BIG_ENDIAN
- not big endian
-#endif
-; return 0; }
-EOF
-if { (eval echo configure:2970: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- ac_cv_c_bigendian=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- ac_cv_c_bigendian=no
-fi
-rm -f conftest*
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
-fi
-rm -f conftest*
-if test $ac_cv_c_bigendian = unknown; then
-if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
-else
- cat > conftest.$ac_ext <<EOF
-#line 2990 "configure"
-#include "confdefs.h"
-main () {
- /* Are we little or big endian? From Harbison&Steele. */
- union
- {
- long l;
- char c[sizeof (long)];
- } u;
- u.l = 1;
- exit (u.c[sizeof (long) - 1] == 1);
-}
-EOF
-if { (eval echo configure:3003: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_c_bigendian=no
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_c_bigendian=yes
-fi
-rm -fr conftest*
-fi
-
-fi
-fi
-
-echo "$ac_t""$ac_cv_c_bigendian" 1>&6
-if test $ac_cv_c_bigendian = yes; then
- cat >> confdefs.h <<\EOF
-#define WORDS_BIGENDIAN 1
-EOF
-
-fi
-
-echo $ac_n "checking whether char is unsigned""... $ac_c" 1>&6
-echo "configure:3027: checking whether char is unsigned" >&5
-if eval "test \"`echo '$''{'ac_cv_c_char_unsigned'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$GCC" = yes; then
- # GCC predefines this symbol on systems where it applies.
-cat > conftest.$ac_ext <<EOF
-#line 3034 "configure"
-#include "confdefs.h"
-#ifdef __CHAR_UNSIGNED__
- yes
-#endif
-
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "yes" >/dev/null 2>&1; then
- rm -rf conftest*
- ac_cv_c_char_unsigned=yes
-else
- rm -rf conftest*
- ac_cv_c_char_unsigned=no
-fi
-rm -f conftest*
-
-else
-if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
-else
- cat > conftest.$ac_ext <<EOF
-#line 3056 "configure"
-#include "confdefs.h"
-/* volatile prevents gcc2 from optimizing the test away on sparcs. */
-#if !defined(__STDC__) || __STDC__ != 1
-#define volatile
-#endif
-main() {
- volatile char c = 255; exit(c < 0);
-}
-EOF
-if { (eval echo configure:3066: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- ac_cv_c_char_unsigned=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- ac_cv_c_char_unsigned=no
-fi
-rm -fr conftest*
-fi
-
-fi
-fi
-
-echo "$ac_t""$ac_cv_c_char_unsigned" 1>&6
-if test $ac_cv_c_char_unsigned = yes && test "$GCC" != yes; then
- cat >> confdefs.h <<\EOF
-#define __CHAR_UNSIGNED__ 1
-EOF
-
-fi
-
-
-echo $ac_n "checking count field in FILE structures""... $ac_c" 1>&6
-echo "configure:3091: checking count field in FILE structures" >&5
-if eval "test \"`echo '$''{'rb_cv_fcnt'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- cat > conftest.$ac_ext <<EOF
-#line 3096 "configure"
-#include "confdefs.h"
-#include <stdio.h>
-int main() {
-FILE *f = stdin; f->_cnt = 0;
-; return 0; }
-EOF
-if { (eval echo configure:3103: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- rb_cv_fcnt="_cnt"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
-fi
-rm -f conftest*
-if test "$rb_cv_fcnt" = ""; then
- cat > conftest.$ac_ext <<EOF
-#line 3113 "configure"
-#include "confdefs.h"
-#include <stdio.h>
-int main() {
-FILE *f = stdin; f->__cnt = 0;
-; return 0; }
-EOF
-if { (eval echo configure:3120: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- rb_cv_fcnt="__cnt"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
-fi
-rm -f conftest*
-fi
-if test "$rb_cv_fcnt" = ""; then
- cat > conftest.$ac_ext <<EOF
-#line 3131 "configure"
-#include "confdefs.h"
-#include <stdio.h>
-int main() {
-FILE *f = stdin; f->_r = 0;
-; return 0; }
-EOF
-if { (eval echo configure:3138: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- rb_cv_fcnt="_r"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
-fi
-rm -f conftest*
-fi
-if test "$rb_cv_fcnt" = ""; then
- cat > conftest.$ac_ext <<EOF
-#line 3149 "configure"
-#include "confdefs.h"
-#include <stdio.h>
-int main() {
-FILE *f = stdin; f->readCount = 0;
-; return 0; }
-EOF
-if { (eval echo configure:3156: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- rb_cv_fcnt="readCount"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- rb_cv_fcnt="not found"
-fi
-rm -f conftest*
-fi
-fi
-
-if test "$rb_cv_fcnt" = "not found"; then
- echo "$ac_t""not found(OK if using GNU libc)" 1>&6
-else
- echo "$ac_t""$rb_cv_fcnt" 1>&6
- cat >> confdefs.h <<EOF
-#define FILE_COUNT $rb_cv_fcnt
-EOF
-
-fi
-
-if test "$ac_cv_func_getpwent" = yes; then
- echo $ac_n "checking struct passwd""... $ac_c" 1>&6
-echo "configure:3181: checking struct passwd" >&5
- cat > conftest.$ac_ext <<EOF
-#line 3183 "configure"
-#include "confdefs.h"
-#include <pwd.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "pw_change" >/dev/null 2>&1; then
- rm -rf conftest*
- cat >> confdefs.h <<\EOF
-#define PW_CHANGE 1
-EOF
-
-fi
-rm -f conftest*
-
- cat > conftest.$ac_ext <<EOF
-#line 3198 "configure"
-#include "confdefs.h"
-#include <pwd.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "pw_quota" >/dev/null 2>&1; then
- rm -rf conftest*
- cat >> confdefs.h <<\EOF
-#define PW_QUOTA 1
-EOF
-
-fi
-rm -f conftest*
-
- cat > conftest.$ac_ext <<EOF
-#line 3213 "configure"
-#include "confdefs.h"
-#include <pwd.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "pw_age" >/dev/null 2>&1; then
- rm -rf conftest*
- cat >> confdefs.h <<\EOF
-#define PW_AGE 1
-EOF
-
-fi
-rm -f conftest*
-
- cat > conftest.$ac_ext <<EOF
-#line 3228 "configure"
-#include "confdefs.h"
-#include <pwd.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "pw_class" >/dev/null 2>&1; then
- rm -rf conftest*
- cat >> confdefs.h <<\EOF
-#define PW_CLASS 1
-EOF
-
-fi
-rm -f conftest*
-
- cat > conftest.$ac_ext <<EOF
-#line 3243 "configure"
-#include "confdefs.h"
-#include <pwd.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "pw_comment" >/dev/null 2>&1; then
- rm -rf conftest*
- cat >> confdefs.h <<\EOF
-#define PW_COMMENT 1
-EOF
-
-fi
-rm -f conftest*
-
- cat > conftest.$ac_ext <<EOF
-#line 3258 "configure"
-#include "confdefs.h"
-#include <pwd.h>
-EOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- egrep "pw_expire" >/dev/null 2>&1; then
- rm -rf conftest*
- cat >> confdefs.h <<\EOF
-#define PW_EXPIRE 1
-EOF
-
-fi
-rm -f conftest*
-
- echo "$ac_t""done" 1>&6
-fi
-
-# Check whether --with-dln-a-out or --without-dln-a-out was given.
-if test "${with_dln_a_out+set}" = set; then
- withval="$with_dln_a_out"
-
- case $withval in
- yes) with_dln_a_out=yes;;
- *) with_dln_a_out=no;;
- esac
-else
- with_dln_a_out=no
-fi
-
-
-case "$host_os" in
- linux*)
- echo $ac_n "checking whether ELF binaries are produced""... $ac_c" 1>&6
-echo "configure:3291: checking whether ELF binaries are produced" >&5
- if eval "test \"`echo '$''{'rb_cv_linux_elf'+set}'`\" = set"; then
- echo $ac_n "(cached) $ac_c" 1>&6
-else
- if test "$cross_compiling" = yes; then
- :
-else
- cat > conftest.$ac_ext <<EOF
-#line 3299 "configure"
-#include "confdefs.h"
-
-/* Test for whether ELF binaries are produced */
-#include <fcntl.h>
-#include <stdlib.h>
-main() {
- char buffer[4];
- int i=open("conftest",O_RDONLY);
- if(i==-1)
- exit(1); /* fail */
- if(read(i,&buffer[0],4)<4)
- exit(1); /* fail */
- if(buffer[0] != 127 || buffer[1] != 'E' ||
- buffer[2] != 'L' || buffer[3] != 'F')
- exit(1); /* fail */
- exit(0); /* succeed (yes, it's ELF) */
-}
-
-EOF
-if { (eval echo configure:3319: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- rb_cv_linux_elf=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- rb_cv_linux_elf=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
- echo "$ac_t""$rb_cv_linux_elf" 1>&6
- if test "$rb_cv_linux_elf" = no; then
- with_dln_a_out=yes
- host_os=linux-a.out
- else
- LDFLAGS="-rdynamic"
- fi;;
-esac
-
-
-
-STATIC=
-
-if test "$with_dln_a_out" != yes; then
- rb_cv_dlopen=unknown
- echo $ac_n "checking whether OS depend dynamic link works""... $ac_c" 1>&6
-echo "configure:3349: checking whether OS depend dynamic link works" >&5
- if test "$GCC" = yes; then
- case "$host_os" in
- nextstep*) ;;
- human*) ;;
- *) CCDLFLAGS=-fpic;;
- esac
- else
- case "$host_os" in
- hpux*) CCDLFLAGS='+z';;
- solaris*|irix*) CCDLFLAGS='-K pic' ;;
- sunos*) CCDLFLAGS='-pic' ;;
- esix*|uxpds*) CCDLFLAGS='-Kpic' ;;
- *) CCDLFLAGS='' ;;
- esac
- fi
-
- case "$host_os" in
- hpux*) DLDFLAGS="-E"
- LDSHARED='ld -b'
- LDFLAGS="-Wl,-E"
- rb_cv_dlopen=yes;;
- solaris*) LDSHARED='ld -G'
- rb_cv_dlopen=yes;;
- sunos*) LDSHARED='ld -assert nodefinitions'
- rb_cv_dlopen=yes;;
- irix*) LDSHARED='ld -ignore_unresolved'
- rb_cv_dlopen=yes;;
- sysv4*) LDSHARED='ld -G'
- rb_cv_dlopen=yes;;
- esix*|uxpds*) LDSHARED="ld -G"
- rb_cv_dlopen=yes ;;
- linux*) LDSHARED="gcc -shared"
- rb_cv_dlopen=yes ;;
- freebsd*) LDSHARED="ld -Bshareable"
- rb_cv_dlopen=yes ;;
- netbsd*) LDSHARED="ld -Bshareable"
- rb_cv_dlopen=yes ;;
- openbsd*) LDSHARED="ld -Bshareable"
- rb_cv_dlopen=yes ;;
- nextstep*) LDSHARED='cc -r'
- LDFLAGS="-u libsys_s"
- DLDFLAGS="$ARCH_FLAG"
- rb_cv_dlopen=yes ;;
- aix*) LDSHARED='../../miniruby ../aix_ld.rb $(TARGET)'
- rb_cv_dlopen=yes ;;
- human*) DLDFLAGS=''
- LDSHARED=''
- LDFLAGS='' ;;
- *) LDSHARED='ld' ;;
- esac
- echo "$ac_t""$rb_cv_dlopen" 1>&6
-fi
-
-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:3407: 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 3413 "configure"
-#include "confdefs.h"
-
-#define USE_DLN_A_OUT
-#include "dln.c"
-
-int main() {
-
-; return 0; }
-EOF
-if { (eval echo configure:3423: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- rb_cv_dln_a_out=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- rb_cv_dln_a_out=no
-fi
-rm -f conftest*
-fi
-
- echo "$ac_t""$rb_cv_dln_a_out" 1>&6
- if test "$rb_cv_dln_a_out" = yes; then
- dln_a_out_works=yes
- cat >> confdefs.h <<\EOF
-#define USE_DLN_A_OUT 1
-EOF
-
- fi
- fi
-fi
-
-if test "$dln_a_out_works" = yes; then
- if test "$GCC" = yes; then
- STATIC=-static
- else
- STATIC=-Bstatic
- fi
- DLEXT=o
- cat >> confdefs.h <<\EOF
-#define DLEXT ".o"
-EOF
-
- CCDLFLAGS=
-else
- case "$host_os" in
- hpux*) DLEXT=sl
- cat >> confdefs.h <<\EOF
-#define DLEXT ".sl"
-EOF
-;;
- nextstep*) DLEXT=o
- cat >> confdefs.h <<\EOF
-#define DLEXT ".o"
-EOF
-;;
- *) DLEXT=so
- cat >> confdefs.h <<\EOF
-#define DLEXT ".so"
-EOF
-;;
- esac
-fi
-
-if test "$with_dln_a_out" = yes; then
- STRIP=true
-else
- STRIP=strip
-fi
-
-case "$host_os" in
- linux*)
- STRIP='strip -S -x';;
- nextstep*)
- STRIP='strip -A -n';;
-esac
-
-EXTSTATIC=
-# Check whether --with-static-linked-ext or --without-static-linked-ext was given.
-if test "${with_static_linked_ext+set}" = set; then
- withval="$with_static_linked_ext"
- case $withval in
- yes) STATIC=
- EXTSTATIC=static;;
- *) ;;
- esac
-fi
-
-
-case "$host_os" in
- human*)
- echo $ac_n "checking for _harderr in -lsignal""... $ac_c" 1>&6
-echo "configure:3506: 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
-else
- ac_save_LIBS="$LIBS"
-LIBS="-lsignal $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 3514 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char _harderr();
-
-int main() {
-_harderr()
-; return 0; }
-EOF
-if { (eval echo configure:3525: \"$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
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_lib=HAVE_LIB`echo signal | sed -e 's/[^a-zA-Z0-9_]/_/g' \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_lib 1
-EOF
-
- LIBS="-lsignal $LIBS"
-
-else
- echo "$ac_t""no" 1>&6
-fi
-
- echo $ac_n "checking for hmemset in -lhmem""... $ac_c" 1>&6
-echo "configure:3553: 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
-else
- ac_save_LIBS="$LIBS"
-LIBS="-lhmem $LIBS"
-cat > conftest.$ac_ext <<EOF
-#line 3561 "configure"
-#include "confdefs.h"
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char hmemset();
-
-int main() {
-hmemset()
-; return 0; }
-EOF
-if { (eval echo configure:3572: \"$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
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_lib_$ac_lib_var=no"
-fi
-rm -f conftest*
-LIBS="$ac_save_LIBS"
-
-fi
-if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_lib=HAVE_LIB`echo hmem | sed -e 's/[^a-zA-Z0-9_]/_/g' \
- -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_lib 1
-EOF
-
- LIBS="-lhmem $LIBS"
-
-else
- echo "$ac_t""no" 1>&6
-fi
-
- for ac_func in select
-do
-echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3602: 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 3607 "configure"
-#include "confdefs.h"
-/* System header to define __stub macros and hopefully few prototypes,
- which can conflict with char $ac_func(); below. */
-#include <assert.h>
-/* Override any gcc2 internal prototype to avoid an error. */
-/* We use char because int might match the return type of a gcc2
- builtin and then its argument prototype would still apply. */
-char $ac_func();
-
-int main() {
-
-/* The GNU C library defines this for functions which it implements
- to always fail with ENOSYS. Some functions are actually named
- something starting with __ and the normal name is an alias. */
-#if defined (__stub_$ac_func) || defined (__stub___$ac_func)
-choke me
-#else
-$ac_func();
-#endif
-
-; return 0; }
-EOF
-if { (eval echo configure:3630: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=yes"
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -rf conftest*
- eval "ac_cv_func_$ac_func=no"
-fi
-rm -f conftest*
-fi
-
-if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then
- echo "$ac_t""yes" 1>&6
- ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'`
- cat >> confdefs.h <<EOF
-#define $ac_tr_func 1
-EOF
-
-else
- echo "$ac_t""no" 1>&6
-fi
-done
-
- echo $ac_n "checking whether PD libc _dtos18 fail to convert big number""... $ac_c" 1>&6
-echo "configure:3655: 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
- if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
-else
- cat > conftest.$ac_ext <<EOF
-#line 3663 "configure"
-#include "confdefs.h"
-
-#include <stdio.h>
-main ()
-{
- char buf[256];
- sprintf (buf, "%g", 1e+300);
- exit (strcmp (buf, "1e+300") ? 0 : 1);
-}
-
-EOF
-if { (eval echo configure:3675: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- rb_cv_missing__dtos18=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- rb_cv_missing__dtos18=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
- echo "$ac_t""$rb_cv_missing__dtos18" 1>&6
- if test "$rb_cv_missing__dtos18" = yes; then
- cat >> confdefs.h <<\EOF
-#define MISSING__DTOS18 1
-EOF
-
- fi
- echo $ac_n "checking whether PD libc fconvert fail to round""... $ac_c" 1>&6
-echo "configure:3697: 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
- if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
-else
- cat > conftest.$ac_ext <<EOF
-#line 3705 "configure"
-#include "confdefs.h"
-
-#include <stdio.h>
-#include <math.h>
-main ()
-{
- char buf[256];
- sprintf (buf, "%f", log(exp(1.0)));
- exit (strcmp (buf, "1.000000") ? 0 : 1);
-}
-
-EOF
-if { (eval echo configure:3718: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null
-then
- rb_cv_missing_fconvert=yes
-else
- echo "configure: failed program was:" >&5
- cat conftest.$ac_ext >&5
- rm -fr conftest*
- rb_cv_missing_fconvert=no
-fi
-rm -fr conftest*
-fi
-
-fi
-
- echo "$ac_t""$rb_cv_missing_fconvert" 1>&6
- if test "$rb_cv_missing_fconvert" = yes; then
- cat >> confdefs.h <<\EOF
-#define MISSING_FCONVERT 1
-EOF
-
- fi
- LIBOBJS="$LIBOBJS x68.o"
- CFLAGS="$CFLAGS -fansi-only -cc1-stack=196608 -cpp-stack=2694144"
- binsuffix=.x
- setup=Setup.x68
- ;;
- *)
- binsuffix=
- setup=Setup
- ;;
-esac
-
-
-
-if test "$prefix" = NONE; then
- prefix=$ac_default_prefix
-fi
-
-if test "$fat_binary" = yes ; then
- CFLAGS="$CFLAGS -pipe $ARCH_FLAG"
-fi
-
-cat >> confdefs.h <<EOF
-#define RUBY_LIB "${prefix}/lib/ruby"
-EOF
-
-cat >> confdefs.h <<EOF
-#define RUBY_SITE_LIB "${prefix}/lib/site_ruby"
-EOF
-
-
-if test "$fat_binary" = yes ; then
- arch="fat-${host_os}"
-
- cat >> confdefs.h <<EOF
-#define RUBY_THIN_ARCHLIB "${prefix}/lib/ruby/" __ARCHITECTURE__ "-${host_os}"
-EOF
-
-
- cat >> confdefs.h <<EOF
-#define RUBY_SITE_THIN_ARCHLIB "${prefix}/lib/ruby/" __ARCHITECTURE__ "-${host_os}"
-EOF
-
-
- cat >> confdefs.h <<EOF
-#define RUBY_ARCHLIB "${prefix}/lib/ruby/${arch}"
-EOF
-
- cat >> confdefs.h <<EOF
-#define RUBY_SITE_ARCHLIB "${prefix}/lib/site_ruby/${arch}"
-EOF
-
- cat >> confdefs.h <<EOF
-#define RUBY_PLATFORM __ARCHITECTURE__ "-${host_os}"
-EOF
-
-else
- arch="${host_cpu}-${host_os}"
- cat >> confdefs.h <<EOF
-#define RUBY_ARCHLIB "${prefix}/lib/ruby/${arch}"
-EOF
-
- cat >> confdefs.h <<EOF
-#define RUBY_SITE_ARCHLIB "${prefix}/lib/site_ruby/${arch}"
-EOF
-
- cat >> confdefs.h <<EOF
-#define RUBY_PLATFORM "${arch}"
-EOF
-
-fi
-
-echo "creating config.h"
-cat confdefs.h > config.h
-
-trap '' 1 2 15
-cat > confcache <<\EOF
-# This file is a shell script that caches the results of configure
-# tests run on this system so they can be shared between configure
-# scripts and configure runs. It is not useful on other systems.
-# If it contains results you don't want to keep, you may remove or edit it.
-#
-# By default, configure uses ./config.cache as the cache file,
-# creating it if it does not exist already. You can give configure
-# the --cache-file=FILE option to use a different cache file; that is
-# what configure does when it calls configure scripts in
-# subdirectories, so they share the cache.
-# Giving --cache-file=/dev/null disables caching, for debugging configure.
-# config.status only pays attention to the cache file if you give it the
-# --recheck option to rerun configure.
-#
-EOF
-# The following way of writing the cache mishandles newlines in values,
-# but we know of no workaround that is simple, portable, and efficient.
-# So, don't put newlines in cache variables' values.
-# Ultrix sh set writes to stderr and can't be redirected directly,
-# and sets the high bit in the cache file unless we assign to the vars.
-(set) 2>&1 |
- case `(ac_space=' '; set) 2>&1` in
- *ac_space=\ *)
- # `set' does not quote correctly, so add quotes (double-quote substitution
- # turns \\\\ into \\, and sed turns \\ into \).
- sed -n \
- -e "s/'/'\\\\''/g" \
- -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p"
- ;;
- *)
- # `set' quotes correctly as required by POSIX, so do not add quotes.
- sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p'
- ;;
- esac >> confcache
-if cmp -s $cache_file confcache; then
- :
-else
- if test -w $cache_file; then
- echo "updating cache $cache_file"
- cat confcache > $cache_file
- else
- echo "not updating unwritable cache $cache_file"
- fi
-fi
-rm -f confcache
-
-trap 'rm -fr conftest* confdefs* core core.* *.core $ac_clean_files; exit 1' 1 2 15
-
-test "x$prefix" = xNONE && prefix=$ac_default_prefix
-# Let make expand exec_prefix.
-test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
-
-# Any assignment to VPATH causes Sun make to only execute
-# the first set of double-colon rules, so remove it if not needed.
-# If there is a colon in the path, we need to keep it.
-if test "x$srcdir" = x.; then
- ac_vpsub='/^[ ]*VPATH[ ]*=[^:]*$/d'
-fi
-
-trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15
-
-# Transform confdefs.h into DEFS.
-# Protect against shell expansion while executing Makefile rules.
-# Protect against Makefile macro expansion.
-cat > conftest.defs <<\EOF
-s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g
-s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g
-s%\[%\\&%g
-s%\]%\\&%g
-s%\$%$$%g
-EOF
-DEFS=`sed -f conftest.defs confdefs.h | tr '\012' ' '`
-rm -f conftest.defs
-
-
-# Without the "./", some shells look in PATH for config.status.
-: ${CONFIG_STATUS=./config.status}
-
-echo creating $CONFIG_STATUS
-rm -f $CONFIG_STATUS
-cat > $CONFIG_STATUS <<EOF
-#! /bin/sh
-# Generated automatically by configure.
-# Run this file to recreate the current configuration.
-# This directory was configured as follows,
-# on host `(hostname || uname -n) 2>/dev/null | sed 1q`:
-#
-# $0 $ac_configure_args
-#
-# Compiler output produced by configure, useful for debugging
-# configure, is in ./config.log if it exists.
-
-ac_cs_usage="Usage: $CONFIG_STATUS [--recheck] [--version] [--help]"
-for ac_option
-do
- case "\$ac_option" in
- -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
- echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
- exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
- -version | --version | --versio | --versi | --vers | --ver | --ve | --v)
- echo "$CONFIG_STATUS generated by autoconf version 2.12"
- exit 0 ;;
- -help | --help | --hel | --he | --h)
- echo "\$ac_cs_usage"; exit 0 ;;
- *) echo "\$ac_cs_usage"; exit 1 ;;
- esac
-done
-
-ac_given_srcdir=$srcdir
-ac_given_INSTALL="$INSTALL"
-
-trap 'rm -fr `echo "Makefile ext/extmk.rb" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
-EOF
-cat >> $CONFIG_STATUS <<EOF
-
-# Protect against being on the right side of a sed subst in config.status.
-sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g;
- s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF
-$ac_vpsub
-$extrasub
-s%@CFLAGS@%$CFLAGS%g
-s%@CPPFLAGS@%$CPPFLAGS%g
-s%@CXXFLAGS@%$CXXFLAGS%g
-s%@DEFS@%$DEFS%g
-s%@LDFLAGS@%$LDFLAGS%g
-s%@LIBS@%$LIBS%g
-s%@exec_prefix@%$exec_prefix%g
-s%@prefix@%$prefix%g
-s%@program_transform_name@%$program_transform_name%g
-s%@bindir@%$bindir%g
-s%@sbindir@%$sbindir%g
-s%@libexecdir@%$libexecdir%g
-s%@datadir@%$datadir%g
-s%@sysconfdir@%$sysconfdir%g
-s%@sharedstatedir@%$sharedstatedir%g
-s%@localstatedir@%$localstatedir%g
-s%@libdir@%$libdir%g
-s%@includedir@%$includedir%g
-s%@oldincludedir@%$oldincludedir%g
-s%@infodir@%$infodir%g
-s%@mandir@%$mandir%g
-s%@host@%$host%g
-s%@host_alias@%$host_alias%g
-s%@host_cpu@%$host_cpu%g
-s%@host_vendor@%$host_vendor%g
-s%@host_os@%$host_os%g
-s%@CC@%$CC%g
-s%@CPP@%$CPP%g
-s%@YACC@%$YACC%g
-s%@RANLIB@%$RANLIB%g
-s%@AR@%$AR%g
-s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
-s%@INSTALL_DATA@%$INSTALL_DATA%g
-s%@SET_MAKE@%$SET_MAKE%g
-s%@LIBOBJS@%$LIBOBJS%g
-s%@ALLOCA@%$ALLOCA%g
-s%@DLDFLAGS@%$DLDFLAGS%g
-s%@STATIC@%$STATIC%g
-s%@CCDLFLAGS@%$CCDLFLAGS%g
-s%@LDSHARED@%$LDSHARED%g
-s%@DLEXT@%$DLEXT%g
-s%@STRIP@%$STRIP%g
-s%@EXTSTATIC@%$EXTSTATIC%g
-s%@binsuffix@%$binsuffix%g
-s%@setup@%$setup%g
-s%@arch@%$arch%g
-
-CEOF
-EOF
-
-cat >> $CONFIG_STATUS <<\EOF
-
-# Split the substitutions into bite-sized pieces for seds with
-# small command number limits, like on Digital OSF/1 and HP-UX.
-ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script.
-ac_file=1 # Number of current file.
-ac_beg=1 # First line for current file.
-ac_end=$ac_max_sed_cmds # Line after last line for current file.
-ac_more_lines=:
-ac_sed_cmds=""
-while $ac_more_lines; do
- if test $ac_beg -gt 1; then
- sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file
- else
- sed "${ac_end}q" conftest.subs > conftest.s$ac_file
- fi
- if test ! -s conftest.s$ac_file; then
- ac_more_lines=false
- rm -f conftest.s$ac_file
- else
- if test -z "$ac_sed_cmds"; then
- ac_sed_cmds="sed -f conftest.s$ac_file"
- else
- ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file"
- fi
- ac_file=`expr $ac_file + 1`
- ac_beg=$ac_end
- ac_end=`expr $ac_end + $ac_max_sed_cmds`
- fi
-done
-if test -z "$ac_sed_cmds"; then
- ac_sed_cmds=cat
-fi
-EOF
-
-cat >> $CONFIG_STATUS <<EOF
-
-CONFIG_FILES=\${CONFIG_FILES-"Makefile ext/extmk.rb"}
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
- # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in".
- case "$ac_file" in
- *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'`
- ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;;
- *) ac_file_in="${ac_file}.in" ;;
- esac
-
- # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories.
-
- # Remove last slash and all that follows it. Not all systems have dirname.
- ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'`
- if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then
- # The file is in a subdirectory.
- test ! -d "$ac_dir" && mkdir "$ac_dir"
- ac_dir_suffix="/`echo $ac_dir|sed 's%^\./%%'`"
- # A "../" for each directory in $ac_dir_suffix.
- ac_dots=`echo $ac_dir_suffix|sed 's%/[^/]*%../%g'`
- else
- ac_dir_suffix= ac_dots=
- fi
-
- case "$ac_given_srcdir" in
- .) srcdir=.
- if test -z "$ac_dots"; then top_srcdir=.
- else top_srcdir=`echo $ac_dots|sed 's%/$%%'`; fi ;;
- /*) srcdir="$ac_given_srcdir$ac_dir_suffix"; top_srcdir="$ac_given_srcdir" ;;
- *) # Relative path.
- srcdir="$ac_dots$ac_given_srcdir$ac_dir_suffix"
- top_srcdir="$ac_dots$ac_given_srcdir" ;;
- esac
-
- case "$ac_given_INSTALL" in
- [/$]*) INSTALL="$ac_given_INSTALL" ;;
- *) INSTALL="$ac_dots$ac_given_INSTALL" ;;
- esac
-
- echo creating "$ac_file"
- rm -f "$ac_file"
- configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure."
- case "$ac_file" in
- *Makefile*) ac_comsub="1i\\
-# $configure_input" ;;
- *) ac_comsub= ;;
- esac
-
- ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"`
- sed -e "$ac_comsub
-s%@configure_input@%$configure_input%g
-s%@srcdir@%$srcdir%g
-s%@top_srcdir@%$top_srcdir%g
-s%@INSTALL@%$INSTALL%g
-" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file
-fi; done
-rm -f conftest.s*
-
-EOF
-cat >> $CONFIG_STATUS <<EOF
-
-EOF
-cat >> $CONFIG_STATUS <<\EOF
-
-exit 0
-EOF
-chmod +x $CONFIG_STATUS
-rm -fr confdefs* $ac_clean_files
-test "$no_create" = yes || ${CONFIG_SHELL-/bin/sh} $CONFIG_STATUS || exit 1
-
diff --git a/configure.bat b/configure.bat
deleted file mode 100644
index 35f9d4893d..0000000000
--- a/configure.bat
+++ /dev/null
@@ -1,5 +0,0 @@
-@echo off
-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
diff --git a/configure.in b/configure.in
index dc561b4d78..65a560be28 100644
--- a/configure.in
+++ b/configure.in
@@ -1,6 +1,13 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(ruby.h)
+rb_version=`grep RUBY_VERSION $srcdir/version.h`
+MAJOR=`expr "$rb_version" : '#define RUBY_VERSION "\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*"'`
+MINOR=`expr "$rb_version" : '#define RUBY_VERSION "[0-9][0-9]*\.\([0-9][0-9]*\)\.[0-9][0-9]*"'`
+TEENY=`expr "$rb_version" : '#define RUBY_VERSION "[0-9][0-9]*\.[0-9][0-9]*\.\([0-9][0-9]*\)"'`
+AC_SUBST(MAJOR)
+AC_SUBST(MINOR)
+AC_SUBST(TEENY)
dnl checks for alternative programs
AC_ARG_WITH(gcc, [--without-gcc never use gcc], [
case $withval in
@@ -18,64 +25,230 @@ then
(it is also a good idea to do 'make clean' before compiling))
fi
-dnl checks for thread
-rb_thread=yes
-AC_ARG_ENABLE(thread, [--disable-thread never use user-level thread], [
- rb_thread=$enableval
-])
-if test $rb_thread = yes; then
- AC_DEFINE(THREAD)
-fi
-
AC_CANONICAL_HOST
-
+AC_CANONICAL_TARGET
+AC_CANONICAL_BUILD
dnl checks for fat-binary
fat_binary=no
-AC_ARG_ENABLE( fat-binary,
- [--enable-fat-binary build a NeXT Multi Architecture Binary. ],
- [ fat_binary=$enableval ] )
-if test "$fat_binary" = yes ; then
+AC_ARG_ENABLE(fat-binary,
+ [--enable-fat-binary build a NeXT/Apple Multi Architecture Binary. ],
+ [fat_binary=$enableval])
+ if test "$fat_binary" = yes ; then
- AC_MSG_CHECKING( target architecture )
+ AC_MSG_CHECKING(target architecture)
- if test "$TARGET_ARCHS" = "" ; then
- if test `/usr/bin/arch` = "m68k" ; then
- TARGET_ARCHS="m68k i486"
- else
- TARGET_ARCHS="m68k `/usr/bin/arch`"
- fi
- fi
+ case "$target_os" in
+ rhapsody*)
+ echo -n "MacOS X Server: "
+ if test "$TARGET_ARCHS" = "" ; then
+ TARGET_ARCHS="ppc i386"
+ fi
+ ;;
+ nextstep*|openstep*)
+ echo -n "NeXTSTEP/OPENSTEP: "
+ if test "$TARGET_ARCHS" = "" ; then
+ if test `/usr/bin/arch` = "m68k" ; then
+ TARGET_ARCHS="m68k i486"
+ else # Black and Native one
+ TARGET_ARCHS="m68k `/usr/bin/arch`"
+ fi
+ fi
+ # to ensure AC_HEADER_SYS_WAIT works
+ AC_DEFINE(_POSIX_SOURCE)
+ ;;
+ macos*|darwin*)
+ echo -n "MacOS X (Darwin): "
+ if test "$TARGET_ARCHS" = "" ; then
+ TARGET_ARCHS="ppc i386"
+ fi
+ ;;
+ esac
# /usr/lib/arch_tool -archify_list $TARGET_ARCHS
for archs in $TARGET_ARCHS
do
ARCH_FLAG="$ARCH_FLAG -arch $archs "
echo -n " $archs"
done
- AC_DEFINE( NEXT_FAT_BINARY )
+ AC_DEFINE(NEXT_FAT_BINARY)
echo "."
fi
-
AC_ARG_PROGRAM
dnl Checks for programs.
+
+if test x"${build}" != x"${host}"; then
+ AC_CHECK_TOOL(CC, gcc)
+fi
AC_PROG_CC
AC_PROG_GCC_TRADITIONAL
+
AC_PROG_YACC
-AC_PROG_RANLIB
-AC_SUBST(AR)
+AC_CHECK_TOOL(RANLIB, ranlib, :)
+AC_CHECK_TOOL(AR, ar)
AC_CHECK_PROGS(AR, ar aal, ar)
-AC_PROG_INSTALL
+
+case "$target_os" in
+cygwin*|mingw*)
+ AC_CHECK_TOOL(NM, nm)
+ AC_CHECK_TOOL(DLLWRAP, dllwrap)
+ AC_CHECK_TOOL(AS, as)
+ AC_CHECK_TOOL(DLLTOOL, dlltool)
+ AC_CHECK_TOOL(WINDRES, windres)
+ echo 'main(){}' > conftest.c
+ if $CC -mwin32 -c conftest.c 2> /dev/null; then
+ MWIN32=-mwin32
+ CFLAGS="$CFLAGS $MWIN32"
+ fi
+ ;;
+esac
+AC_SUBST(MWIN32)
+
+AC_PROG_LN_S
AC_PROG_MAKE_SET
# checks for UNIX variants that set C preprocessor variables
+AC_AIX
AC_MINIX
+AC_EXEEXT
+AC_OBJEXT
+
+AC_CHECK_SIZEOF(int, 4)
+AC_CHECK_SIZEOF(short, 2)
+AC_CHECK_SIZEOF(long, 4)
+AC_CHECK_SIZEOF(long long, 0)
+AC_CHECK_SIZEOF(__int64, 0)
+AC_CHECK_SIZEOF(void*, 4)
+AC_CHECK_SIZEOF(float, 4)
+AC_CHECK_SIZEOF(double, 8)
+
+AC_CACHE_CHECK(for prototypes, rb_cv_have_prototypes,
+ [AC_TRY_COMPILE([int foo(int x) { return 0; }], [return foo(10);],
+ rb_cv_have_prototypes=yes,
+ rb_cv_have_prototypes=no)])
+if test "$rb_cv_have_prototypes" = yes; then
+ AC_DEFINE(HAVE_PROTOTYPES)
+fi
+
+AC_CACHE_CHECK(token paste string, rb_cv_tokenpaste,
+ [AC_TRY_COMPILE([#define paste(a,b) a##b],
+ [int xy = 1; return paste(x,y);],
+ rb_cv_tokenpaste=ansi,
+ rb_cv_tokenpaste=knr)])
+if test "$rb_cv_tokenpaste" = ansi; then
+ AC_DEFINE(TOKEN_PASTE(x,y),[x##y])
+else
+ AC_DEFINE(TOKEN_PASTE(x,y),[x/**/y])
+fi
+
+AC_CACHE_CHECK(for variable length prototypes and stdarg.h, rb_cv_stdarg,
+ [AC_TRY_COMPILE([
+#include <stdarg.h>
+int foo(int x, ...) {
+ va_list va;
+ va_start(va, x);
+ va_arg(va, int);
+ va_arg(va, char *);
+ va_arg(va, double);
+ return 0;
+}
+], [return foo(10, "", 3.14);],
+ rb_cv_stdarg=yes,
+ rb_cv_stdarg=no)])
+if test "$rb_cv_stdarg" = yes; then
+ AC_DEFINE(HAVE_STDARG_PROTOTYPES)
+fi
+
+AC_CACHE_CHECK(for gcc attribute noreturn, rb_cv_have_attr_noreturn,
+ [AC_TRY_COMPILE([void exit(int x) __attribute__ ((noreturn));], [],
+ rb_cv_have_attr_noreturn=yes,
+ rb_cv_have_attr_noreturn=no)])
+if test "$rb_cv_have_attr_noreturn" = yes; then
+ AC_DEFINE(HAVE_ATTR_NORETURN)
+fi
+
+dnl wheather link libc_r or not
+AC_ARG_WITH(libc_r,
+ [--with-libc_r link libc_r if possible (FreeBSD only)], [
+ case $withval in
+ yes) with_libc_r=yes;;
+ *) with_libc_r=no;;
+ esac], [with_libc_r=yes])
+
dnl Checks for libraries.
-case "$host_os" in
+case "$target_os" in
nextstep*) ;;
-human*) ;;
+openstep*) ;;
+rhapsody*) ;;
+darwin*) LIBS="-lobjc $LIBS";;
+human*) ac_cv_func_getpgrp_void=yes;;
+beos*) ;;
+cygwin*) rb_cv_have_daylight=no
+ ac_cv_var_tzname=no;;
+mingw*) LIBS="-lwsock32 -lmsvcrt $LIBS"
+ ac_cv_header_a_out_h=no
+ ac_cv_header_pwd_h=no
+ ac_cv_header_utime_h=no
+ ac_cv_header_sys_ioctl_h=no
+ ac_cv_header_sys_param_h=no
+ ac_cv_header_sys_resource_h=no
+ ac_cv_header_sys_select_h=no
+ ac_cv_header_sys_times_h=no
+ ac_cv_func_times=yes;;
+os2_emx*) LIBS="-lm $LIBS"
+ ac_cv_lib_dir_opendir=no;;
+msdosdjgpp*) LIBS="-lm $LIBS"
+ ac_cv_func_getpgrp_void=yes;;
+freebsd*) LIBS="-lm $LIBS"
+ AC_CACHE_CHECK([whether -lxpg4 has to be linked],
+ rb_cv_lib_xpg4_needed,
+ [AC_TRY_CPP([
+#include <osreldate.h>
+#if __FreeBSD_version < 400020 || \
+ (__FreeBSD_version >= 500000 && __FreeBSD_version < 500005)
+#error needs libxpg4
+#endif
+ ],
+ rb_cv_lib_xpg4_needed=no,
+ rb_cv_lib_xpg4_needed=yes,
+ rb_cv_lib_xpg4_needed=yes)])
+ if test "$rb_cv_lib_xpg4_needed" = yes; then
+ AC_CHECK_LIB(xpg4, setlocale)
+ fi
+ if test "$with_libc_r" = yes; then
+ AC_CACHE_CHECK([whether libc_r is supplementary to libc],
+ rb_cv_supplementary_lib_c_r,
+ [AC_TRY_CPP([
+#include <osreldate.h>
+#if 500016 <= __FreeBSD_version
+#error libc_r is supplementary to libc
+#endif
+ ],
+ rb_cv_supplementary_lib_c_r=no,
+ rb_cv_supplementary_lib_c_r=yes,
+ rb_cv_supplementary_lib_c_r=yes)])
+ if test "$rb_cv_supplementary_lib_c_r" = yes; then
+ MAINLIBS="-lc_r $MAINLIBS"
+ else
+ MAINLIBS="-pthread $MAINLIBS"
+ CFLAGS="-D_THREAD_SAFE $CFLAGS"
+ fi
+ fi
+ ;;
+linux*) LIBS="-lm $LIBS"
+ case "$target_cpu" in
+ alpha*)
+ CFLAGS="-mieee $CFLAGS" ;;
+ esac ;;
+osf*) LIBS="-lm $LIBS"
+ case "$target_cpu"::"$without_gcc" in
+ alpha*::no)
+ CFLAGS="-mieee $CFLAGS" ;;
+ alpha*::yes)
+ CFLAGS="-ieee $CFLAGS" ;;
+ esac ;;
*) LIBS="-lm $LIBS";;
esac
AC_CHECK_LIB(crypt, crypt)
@@ -85,9 +258,10 @@ AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX
dnl Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
-AC_CHECK_HEADERS(stdlib.h unistd.h limits.h sys/file.h sys/ioctl.h pwd.h \
- sys/select.h sys/time.h sys/times.h sys/param.h sys/wait.h\
- syscall.h a.out.h string.h utime.h memory.h)
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(stdlib.h string.h unistd.h limits.h sys/file.h sys/ioctl.h\
+ fcntl.h sys/fcntl.h sys/select.h sys/time.h sys/times.h sys/param.h\
+ syscall.h pwd.h a.out.h utime.h memory.h direct.h sys/resource.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_UID_T
@@ -98,35 +272,35 @@ AC_STRUCT_ST_BLOCKS
LIBOBJS="$save_LIBOBJS"
AC_STRUCT_ST_RDEV
-AC_CHECK_SIZEOF(short)
-AC_CHECK_SIZEOF(int)
-AC_CHECK_SIZEOF(long)
-AC_CHECK_SIZEOF(void*)
-
dnl Checks for library functions.
AC_TYPE_GETGROUPS
AC_TYPE_SIGNAL
AC_FUNC_ALLOCA
AC_FUNC_VFORK
AC_FUNC_MEMCMP
-AC_REPLACE_FUNCS(dup2 setenv memmove mkdir strcasecmp strerror strftime\
- strchr strstr strtoul strdup crypt flock)
-AC_CHECK_FUNCS(fmod killpg random wait4 waitpid syscall getcwd\
- truncate chsize times utimes fcntl lockf setitimer\
- setruid seteuid setreuid setrgid setegid setregid\
- setpgrp2 getpgid getgroups getpriority\
- dlopen sigprocmask sigaction _setjmp)
-if test "$ac_cv_func_strftime" = no; then
- AC_STRUCT_TIMEZONE
- AC_TRY_LINK([],
- [extern int daylight; int i = daylight;], AC_DEFINE(HAVE_DAYLIGHT))
+AC_REPLACE_FUNCS(dup2 memmove mkdir strcasecmp strncasecmp strerror strftime\
+ strchr strstr strtoul crypt flock vsnprintf\
+ isinf isnan finite)
+AC_CHECK_FUNCS(fmod killpg drand48 random wait4 waitpid syscall getcwd chroot\
+ truncate chsize times utimes fcntl lockf lstat symlink readlink\
+ setitimer setruid seteuid setreuid setrgid setegid setregid pause\
+ getpgrp setpgrp getpgid setpgid getgroups getpriority getrlimit\
+ dlopen sigprocmask sigaction _setjmp setsid telldir seekdir fchmod)
+AC_STRUCT_TIMEZONE
+AC_CACHE_CHECK(for external int daylight, rb_cv_have_daylight,
+ [AC_TRY_LINK([#include <time.h>
+ int i;],
+ [i = daylight;],
+ rb_cv_have_daylight=yes,
+ rb_cv_have_daylight=no)])
+if test "$rb_cv_have_daylight" = yes; then
+ AC_DEFINE(HAVE_DAYLIGHT)
fi
if test "$ac_cv_func_sigprocmask" = yes && test "$ac_cv_func_sigaction" = yes; then
AC_DEFINE(POSIX_SIGNAL)
else
- AC_MSG_CHECKING(for BSD signal semantics)
- AC_CACHE_VAL(rb_cv_bsd_signal,
+ AC_CACHE_CHECK(for BSD signal semantics, rb_cv_bsd_signal,
[AC_TRY_RUN([
#include <stdio.h>
#include <signal.h>
@@ -147,42 +321,71 @@ main()
}
],
rb_cv_bsd_signal=yes,
+ rb_cv_bsd_signal=no,
rb_cv_bsd_signal=no)])
- AC_MSG_RESULT($rb_cv_bsd_signal)
if test "$rb_cv_bsd_signal" = yes; then
AC_DEFINE(BSD_SIGNAL)
fi
fi
-if test "$ac_cv_func_setpgrp2" = yes; then
- AC_DEFINE(BSD_GETPGRP, getpgrp2)
- AC_DEFINE(BSD_SETPGRP, setpgrp2)
-else
- AC_MSG_CHECKING(whether getpgrp() has arg)
- AC_CACHE_VAL(rb_cv_bsdgetpgrp,
- [AC_TRY_COMPILE([#include <unistd.h>], [getpgrp(0);],
- rb_cv_bsdgetpgrp=yes,
- rb_cv_bsdgetpgrp=no)])
- AC_MSG_RESULT($rb_cv_bsdgetpgrp)
- if test "$rb_cv_bsdgetpgrp" = yes; then
- AC_DEFINE(BSD_GETPGRP, getpgrp)
- fi
+AC_FUNC_GETPGRP
+AC_FUNC_SETPGRP
- AC_MSG_CHECKING(whether setpgrp() has args)
- AC_CACHE_VAL(rb_cv_bsdsetpgrp,
- [AC_TRY_COMPILE([#include <unistd.h>], [setpgrp(1, 1);],
- rb_cv_bsdsetpgrp=yes,
- rb_cv_bsdsetpgrp=no)])
- AC_MSG_RESULT($rb_cv_bsdsetpgrp)
- if test "$rb_cv_bsdsetpgrp" = yes; then
- AC_DEFINE(BSD_SETPGRP, setpgrp)
- fi
-fi
+AC_CACHE_CHECK(for working strtod, rb_cv_func_strtod,
+[AC_TRY_RUN([
+double strtod ();
+int
+main()
+{
+ {
+ /* Some versions of Linux strtod mis-parse strings with leading '+'. */
+ char *string = " +69";
+ char *term;
+ double value;
+ value = strtod(string, &term);
+ if (value != 69 || term != (string + 4))
+ exit(1);
+ }
+
+ {
+ /* Under Solaris 2.4, strtod returns the wrong value for the
+ terminating character under some conditions. */
+ char *string = "NaN";
+ char *term;
+ strtod(string, &term);
+ if (term != string && *(term - 1) == 0)
+ exit(1);
+ }
+ exit(0);
+}
+], rb_cv_func_strtod=yes, rb_cv_func_strtod=no, rb_cv_func_strtod=no)])
+test $rb_cv_func_strtod = no && LIBOBJS="$LIBOBJS strtod.o"
AC_C_BIGENDIAN
-AC_CHAR_UNSIGNED
+AC_C_CONST
+AC_C_CHAR_UNSIGNED
+AC_C_INLINE
-AC_MSG_CHECKING([count field in FILE structures])
+AC_CACHE_CHECK(whether right shift preserve sign bit, rb_cv_rshift_sign,
+ [AC_TRY_RUN([
+int
+main()
+{
+ if (-1==(-1>>1))
+ return 0;
+ return 1;
+}
+],
+ rb_cv_rshift_sign=yes,
+ rb_cv_rshift_sign=no,
+ rb_cv_rshift_sign=yes)])
+if test "$rb_cv_rshift_sign" = yes; then
+ AC_DEFINE(RSHIFT(x,y), ((x)>>(int)y))
+else
+ AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>y) : (x)>>y))
+fi
+
+AC_MSG_CHECKING(count field in FILE structures)
AC_CACHE_VAL(rb_cv_fcnt,
[AC_TRY_COMPILE([#include <stdio.h>],
[FILE *f = stdin; f->_cnt = 0;], rb_cv_fcnt="_cnt", )
@@ -197,7 +400,13 @@ fi
if test "$rb_cv_fcnt" = ""; then
AC_TRY_COMPILE([#include <stdio.h>],
[FILE *f = stdin; f->readCount = 0;],
- rb_cv_fcnt="readCount", rb_cv_fcnt="not found")
+ rb_cv_fcnt="readCount", )
+fi
+dnl for emx0.9c
+if test "$rb_cv_fcnt" = ""; then
+ AC_TRY_COMPILE([#include <stdio.h>],
+ [FILE *f = stdin; f->_rcount = 0;],
+ rb_cv_fcnt="_rcount", rb_cv_fcnt="not found")
fi])
if test "$rb_cv_fcnt" = "not found"; then
AC_MSG_RESULT([not found(OK if using GNU libc)])
@@ -206,29 +415,32 @@ else
AC_DEFINE_UNQUOTED(FILE_COUNT, $rb_cv_fcnt)
fi
-if test "$ac_cv_func_getpwent" = yes; then
- AC_MSG_CHECKING(struct passwd)
- AC_EGREP_HEADER(pw_change, pwd.h, AC_DEFINE(PW_CHANGE))
- AC_EGREP_HEADER(pw_quota, pwd.h, AC_DEFINE(PW_QUOTA))
- AC_EGREP_HEADER(pw_age, pwd.h, AC_DEFINE(PW_AGE))
- AC_EGREP_HEADER(pw_class, pwd.h, AC_DEFINE(PW_CLASS))
- AC_EGREP_HEADER(pw_comment, pwd.h, AC_DEFINE(PW_COMMENT))
- AC_EGREP_HEADER(pw_expire, pwd.h, AC_DEFINE(PW_EXPIRE))
- AC_MSG_RESULT(done)
-fi
+dnl default value for $KANJI
+DEFAULT_KCODE="KCODE_NONE"
-dnl wheather use dln_a_out ot not
-AC_ARG_WITH(dln-a-out, [--with-dln-a-out use dln_a_out if possible], [
+AC_ARG_WITH(default-kcode,
+ [--with-default-kcode=CODE specify default value for \$KCODE (utf8|euc|sjis|none)],
+ [case $withval in
+ utf8) DEFAULT_KCODE="KCODE_UTF8";;
+ euc) DEFAULT_KCODE="KCODE_EUC";;
+ sjis) DEFAULT_KCODE="KCODE_SJIS";;
+ none) DEFAULT_KCODE="KCODE_NONE";;
+ *) AC_MSG_WARN($withval is not valid kcode; ignored);;
+ esac])
+AC_DEFINE_UNQUOTED(DEFAULT_KCODE, $DEFAULT_KCODE)
+
+dnl wheather use dln_a_out or not
+AC_ARG_WITH(dln-a-out,
+ [--with-dln-a-out use dln_a_out if possible], [
case $withval in
yes) with_dln_a_out=yes;;
*) with_dln_a_out=no;;
esac], [with_dln_a_out=no])
-case "$host_os" in
- linux*)
- AC_MSG_CHECKING(whether ELF binaries are produced)
- AC_CACHE_VAL(rb_cv_linux_elf,
- [AC_TRY_RUN([
+AC_SUBST(XLDFLAGS)dnl
+
+AC_CACHE_CHECK(whether ELF binaries are produced, rb_cv_binary_elf,
+[AC_TRY_RUN([
/* Test for whether ELF binaries are produced */
#include <fcntl.h>
#include <stdlib.h>
@@ -245,16 +457,30 @@ main() {
exit(0); /* succeed (yes, it's ELF) */
}
],
- rb_cv_linux_elf=yes,
- rb_cv_linux_elf=no,
- [:])])
- AC_MSG_RESULT($rb_cv_linux_elf)
- if test "$rb_cv_linux_elf" = no; then
+rb_cv_binary_elf=yes,
+rb_cv_binary_elf=no,
+rb_cv_binary_elf=yes)])
+
+if test "$rb_cv_binary_elf" = yes; then
+ AC_DEFINE(USE_ELF)
+fi
+
+case "$target_os" in
+ linux*)
+ if test "$rb_cv_binary_elf" = no; then
with_dln_a_out=yes
- host_os=linux-a.out
+ target_os=${target_os}-a_out
else
LDFLAGS="-rdynamic"
fi;;
+netbsd*)
+ if [[ "`$CC -dM -E - </dev/null | grep __ELF__`" != "" ]]
+ then
+ netbsd_elf=yes
+ else
+ netbsd_elf=no
+ fi
+ ;;
esac
AC_SUBST(DLDFLAGS)dnl
@@ -263,6 +489,7 @@ AC_SUBST(STATIC)dnl
AC_SUBST(CCDLFLAGS)dnl
AC_SUBST(LDSHARED)dnl
AC_SUBST(DLEXT)dnl
+AC_SUBST(DLEXT2)dnl
STATIC=
@@ -270,53 +497,121 @@ if test "$with_dln_a_out" != yes; then
rb_cv_dlopen=unknown
AC_MSG_CHECKING(whether OS depend dynamic link works)
if test "$GCC" = yes; then
- case "$host_os" in
+ case "$target_os" in
nextstep*) ;;
+ openstep*) ;;
+ rhapsody*) ;;
+ darwin*) CCDLFLAGS=-fno-common;;
human*) ;;
- *) CCDLFLAGS=-fpic;;
+ bsdi*) ;;
+ beos*) ;;
+ cygwin*) ;;
+ mingw*) ;;
+ netbsd*) CCDLFLAGS=-fpic
+ case "$target_cpu" in
+ mips*) CCDLFLAGS=-fPIC ;;
+ sparc) CCDLFLAGS=-fPIC ;;
+ *) ;;
+ esac ;;
+ *) CCDLFLAGS=-fPIC;;
esac
else
- case "$host_os" in
+ case "$target_os" in
hpux*) CCDLFLAGS='+z';;
- solaris*|irix*) CCDLFLAGS='-K pic' ;;
- sunos*) CCDLFLAGS='-pic' ;;
- esix*|uxpds*) CCDLFLAGS='-Kpic' ;;
+ solaris*|irix*) CCDLFLAGS='-KPIC' ;;
+ sunos*) CCDLFLAGS='-PIC' ;;
+ esix*|uxpds*) CCDLFLAGS='-KPIC' ;;
*) CCDLFLAGS='' ;;
esac
fi
- case "$host_os" in
+ case "$target_os" in
hpux*) DLDFLAGS="-E"
LDSHARED='ld -b'
LDFLAGS="-Wl,-E"
rb_cv_dlopen=yes;;
- solaris*) LDSHARED='ld -G'
+ solaris*) if test "$GCC" = yes; then
+ LDSHARED='$(CC) -Wl,-G'
+ `$CC --print-prog-name=ld` -v 2>&1 | grep "GNU ld" > /dev/null && LDFLAGS="-Wl,-E"
+ else
+ LDSHARED='ld -G'
+ fi
rb_cv_dlopen=yes;;
sunos*) LDSHARED='ld -assert nodefinitions'
rb_cv_dlopen=yes;;
- irix*) LDSHARED='ld -ignore_unresolved'
+ irix*) LDSHARED='ld -shared'
rb_cv_dlopen=yes;;
sysv4*) LDSHARED='ld -G'
rb_cv_dlopen=yes;;
+ nto-qnx*) LDSHARED="qcc -shared"
+ rb_cv_dlopen=yes ;;
esix*|uxpds*) LDSHARED="ld -G"
rb_cv_dlopen=yes ;;
- linux*) LDSHARED="gcc -shared"
+ osf*) LDSHARED="$CC -shared"
+ rb_cv_dlopen=yes ;;
+ linux*) LDSHARED="$CC -shared"
rb_cv_dlopen=yes ;;
- freebsd*) LDSHARED="ld -Bshareable"
+ freebsd*) LDSHARED="$CC -shared"
+ if test "$rb_cv_binary_elf" = yes; then
+ LDFLAGS="-rdynamic"
+ DLDFLAGS='-Wl,-soname,$(.TARGET)'
+ else
+ test "$GCC" = yes && `$CC --print-prog-name=ld` -v 2>&1 | grep "GNU ld" > /dev/null || LDSHARED="ld -Bshareable"
+ fi
rb_cv_dlopen=yes ;;
- netbsd*) LDSHARED="ld -Bshareable"
+ netbsd*) LDSHARED="ld -shared"
+ if test "$rb_cv_binary_elf" = yes; then
+ LDFLAGS="-export-dynamic"
+ fi
rb_cv_dlopen=yes ;;
- openbsd*) LDSHARED="ld -Bshareable"
+ openbsd*) LDSHARED="ld -Bforcearchive -Bshareable"
rb_cv_dlopen=yes ;;
- nextstep*) LDSHARED='cc -r'
+ bsdi3*) case "$CC" in
+ *shlicc*) LDSHARED="$CC -r"
+ rb_cv_dlopen=yes ;;
+ esac ;;
+ bsdi*) LDSHARED="ld -shared"
+ LDFLAGS='-rdynamic -Wl,-rpath,$(prefix)/lib/ruby/$(MAJOR).$(MINOR)/i386-bsdi4.0'
+ rb_cv_dlopen=yes ;;
+ nextstep*) LDSHARED='cc -r -nostdlib'
LDFLAGS="-u libsys_s"
DLDFLAGS="$ARCH_FLAG"
rb_cv_dlopen=yes ;;
- aix*) LDSHARED='../../miniruby ../aix_ld.rb $(TARGET)'
+ openstep*) LDSHARED='cc -dynamic -bundle -undefined suppress'
+ LDFLAGS=""
+ DLDFLAGS="$ARCH_FLAG"
+ rb_cv_dlopen=yes ;;
+ rhapsody*) LDSHARED='cc -dynamic -bundle -undefined suppress'
+ LDFLAGS=""
+ DLDFLAGS="$ARCH_FLAG"
+ rb_cv_dlopen=yes ;;
+ darwin*) LDSHARED='cc -dynamic -bundle -undefined suppress'
+ LDFLAGS=""
+ DLDFLAGS="$ARCH_FLAG"
+ rb_cv_dlopen=yes ;;
+ aix*) LDSHARED='/usr/ccs/bin/ld'
+ XLDFLAGS='-Wl,-bE:ruby.imp'
+ DLDFLAGS='-brtl -eInit_$(TARGET) -bI:$(topdir)/ruby.imp -bM:SRE -T512 -H512 -lc'
+ LDFLAGS="-brtl"
rb_cv_dlopen=yes ;;
+
human*) DLDFLAGS=''
LDSHARED=''
- LDFLAGS='' ;;
+ LDFLAGS=''
+ rb_cv_dlopen=yes ;;
+ beos*) case "$target_cpu" in
+ powerpc*)
+ LDSHARED="ld -xms"
+ DLDFLAGS='-export Init_$(TARGET) -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o'
+ ;;
+ i586*)
+ LDSHARED="ld -shared"
+ DLDFLAGS="-L/boot/develop/lib/x86 -lbe -lroot"
+ ;;
+ esac
+ rb_cv_dlopen=yes ;;
+ cygwin*|mingw*) : ${LDSHARED="${DLLWRAP} --target=${target_os} --as=${AS} --dlltool-name=${DLLTOOL} --driver-name=${CC} --export-all -s"}
+ rb_cv_dlopen=yes ;;
*) LDSHARED='ld' ;;
esac
AC_MSG_RESULT($rb_cv_dlopen)
@@ -325,9 +620,8 @@ fi
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
- AC_MSG_CHECKING(whether matz's dln works)
cat confdefs.h > config.h
- AC_CACHE_VAL(rb_cv_dln_a_out,
+ AC_CACHE_CHECK(whether matz's dln works, rb_cv_dln_a_out,
[AC_TRY_COMPILE([
#define USE_DLN_A_OUT
#include "dln.c"
@@ -335,7 +629,6 @@ if test "$ac_cv_header_a_out_h" = yes; then
[],
rb_cv_dln_a_out=yes,
rb_cv_dln_a_out=no)])
- AC_MSG_RESULT($rb_cv_dln_a_out)
if test "$rb_cv_dln_a_out" = yes; then
dln_a_out_works=yes
AC_DEFINE(USE_DLN_A_OUT)
@@ -349,15 +642,27 @@ if test "$dln_a_out_works" = yes; then
else
STATIC=-Bstatic
fi
- DLEXT=o
- AC_DEFINE(DLEXT, ".o")
+ DLEXT=so
+ AC_DEFINE(DLEXT, ".so")
CCDLFLAGS=
else
- case "$host_os" in
+ case "$target_os" in
hpux*) DLEXT=sl
AC_DEFINE(DLEXT, ".sl");;
- nextstep*) DLEXT=o
- AC_DEFINE(DLEXT, ".o");;
+ nextstep*) DLEXT=bundle
+ AC_DEFINE(DLEXT, ".bundle");;
+ openstep*) DLEXT=bundle
+ AC_DEFINE(DLEXT, ".bundle");;
+ rhapsody*) DLEXT=bundle
+ AC_DEFINE(DLEXT, ".bundle");;
+ darwin*) DLEXT=bundle
+ AC_DEFINE(DLEXT, ".bundle");;
+ os2_emx*) DLEXT=dll
+ AC_DEFINE(DLEXT, ".dll");;
+ cygwin*|mingw*) DLEXT=so
+ AC_DEFINE(DLEXT, ".so")
+ DLEXT2=dll
+ AC_DEFINE(DLEXT2, ".dll");;
*) DLEXT=so
AC_DEFINE(DLEXT, ".so");;
esac
@@ -370,11 +675,17 @@ else
STRIP=strip
fi
-case "$host_os" in
+case "$target_os" in
linux*)
STRIP='strip -S -x';;
nextstep*)
STRIP='strip -A -n';;
+ openstep*)
+ STRIP='strip -A -n';;
+ rhapsody*)
+ STRIP='strip -A -n';;
+ darwin*)
+ STRIP='strip -A -n';;
esac
EXTSTATIC=
@@ -387,13 +698,13 @@ AC_ARG_WITH(static-linked-ext,
*) ;;
esac])
-case "$host_os" in
+case "$target_os" in
human*)
AC_CHECK_LIB(signal, _harderr)
AC_CHECK_LIB(hmem, hmemset)
- AC_CHECK_FUNCS(select)
- AC_MSG_CHECKING(whether PD libc _dtos18 fail to convert big number)
- AC_CACHE_VAL(rb_cv_missing__dtos18,
+ AC_CHECK_FUNCS(select gettimeofday)
+ AC_CACHE_CHECK(whether PD libc _dtos18 fail to convert big number,
+ rb_cv_missing__dtos18,
[AC_TRY_RUN(
changequote(<<, >>)dnl
<<
@@ -406,13 +717,12 @@ main ()
}
>>,
changequote([, ])dnl
-rb_cv_missing__dtos18=yes, rb_cv_missing__dtos18=no)])
- AC_MSG_RESULT($rb_cv_missing__dtos18)
+rb_cv_missing__dtos18=yes, rb_cv_missing__dtos18=no, rb_cv_missing__dtos18=no)])
if test "$rb_cv_missing__dtos18" = yes; then
AC_DEFINE(MISSING__DTOS18)
fi
- AC_MSG_CHECKING(whether PD libc fconvert fail to round)
- AC_CACHE_VAL(rb_cv_missing_fconvert,
+ AC_CACHE_CHECK(whether PD libc fconvert fail to round,
+ rb_cv_missing_fconvert,
[AC_TRY_RUN(
changequote(<<, >>)dnl
<<
@@ -426,22 +736,29 @@ main ()
}
>>,
changequote([, ])dnl
-rb_cv_missing_fconvert=yes, rb_cv_missing_fconvert=no)])
- AC_MSG_RESULT($rb_cv_missing_fconvert)
+rb_cv_missing_fconvert=yes, rb_cv_missing_fconvert=no, rb_cv_missing_fconvert=no)])
if test "$rb_cv_missing_fconvert" = yes; then
AC_DEFINE(MISSING_FCONVERT)
fi
LIBOBJS="$LIBOBJS x68.o"
- CFLAGS="$CFLAGS -fansi-only -cc1-stack=196608 -cpp-stack=2694144"
- binsuffix=.x
+ CFLAGS="$CFLAGS -fansi-only -cc1-stack=262144 -cpp-stack=2694144"
+ EXEEXT=.x
+ OBJEXT=o
setup=Setup.x68
;;
+ dnl OS/2 environment w/ Autoconf 2.1x for EMX
+ os2_emx)
+ LIBOBJS="$LIBOBJS os2.$OBJEXT"
+ setup=Setup.emx
+ ;;
+ *djgpp*)
+ setup=Setup.dj
+ ;;
*)
- binsuffix=
setup=Setup
;;
esac
-AC_SUBST(binsuffix)
+
AC_SUBST(setup)
if test "$prefix" = NONE; then
@@ -449,33 +766,267 @@ if test "$prefix" = NONE; then
fi
if test "$fat_binary" = yes ; then
- CFLAGS="$CFLAGS -pipe $ARCH_FLAG"
+ CFLAGS="$CFLAGS $ARCH_FLAG"
fi
-AC_DEFINE_UNQUOTED(RUBY_LIB, "${prefix}/lib/ruby")
-AC_DEFINE_UNQUOTED(RUBY_SITE_LIB, "${prefix}/lib/site_ruby")
+if test x"$cross_compiling" = xyes; then
+ MINIRUBY="ruby -I`pwd` -rfake"
+ PREP=fake.rb
+else
+ MINIRUBY='./miniruby$(EXEEXT)'
+ PREP=''
+fi
+AC_SUBST(MINIRUBY)
+AC_SUBST(PREP)
+
+FIRSTMAKEFILE=""
+LIBRUBY_A='lib$(RUBY_INSTALL_NAME).a'
+LIBRUBY='$(LIBRUBY_A)'
+LIBRUBYARG='$(LIBRUBY_A)'
+SOLIBS=
+
+case "$target_os" in
+ cygwin*|mingw*|beos*|openstep*|nextstep*|rhapsody*|darwin*|os2_emx*)
+ DLDLIBS=""
+ ;;
+ *)
+ DLDLIBS="-lc"
+ ;;
+esac
+
+LIBRUBY_LDSHARED=$LDSHARED
+LIBRUBY_DLDFLAGS=$DLDFLAGS
+LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR).$(TEENY)'
+LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so'
+ENABLE_SHARED=no
+
+AC_ARG_ENABLE(enable-shared,
+ [--enable-shared build a shared library for Ruby. ],
+ [enable_shared=$enableval])
+if test "$enable_shared" = 'yes'; then
+ LIBRUBY='$(LIBRUBY_SO)'
+ LIBRUBYARG='-L. -l$(RUBY_INSTALL_NAME)'
+ CFLAGS="$CFLAGS $CCDLFLAGS"
+ ENABLE_SHARED=yes
+ if test "$rb_cv_binary_elf" = yes; then
+ SOLIBS='$(LIBS)'
+ fi
+ case "$target_os" in
+ sunos4*)
+ LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).so'
+ ;;
+ linux*)
+ LIBRUBY_DLDFLAGS='-Wl,-soname,lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR)'
+ LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).so'
+ ;;
+ freebsd*)
+ SOLIBS='$(LIBS)'
+ LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR)$(MINOR)'
+ if test "$rb_cv_binary_elf" != "yes" ; then
+ LIBRUBY_SO="$LIBRUBY_SO.\$(TEENY)"
+ LIBRUBY_ALIASES=''
+ fi
+ ;;
+ netbsd*)
+ SOLIBS='$(LIBS)'
+ LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR)'
+ if test "$rb_cv_binary_elf" = yes; then # ELF platforms
+ LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR) lib$(RUBY_INSTALL_NAME).so'
+ else
+ LIBRUBY_ALIASES= # a.out platforms
+ fi
+ ;;
+ openbsd*)
+ SOLIBS='$(LIBS)'
+ ;;
+ solaris*)
+ XLDFLAGS='-R${prefix}/lib'
+ ;;
+ hpux*)
+ XLDFLAGS='-Wl,+s,+b,$(prefix)/lib'
+ LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).sl.$(MAJOR).$(MINOR).$(TEENY)'
+ LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).sl.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).sl'
+ ;;
+ aix*)
+ if test "$GCC" = yes; then
+ LIBRUBY_LDSHARED='$(CC) -shared'
+ LIBRUBY_DLDFLAGS='-Wl,-bE:ruby.imp'
+ else
+ LIBRUBY_LDSHARED='/usr/ccs/bin/ld'
+ LIBRUBY_DLDFLAGS='-bE:ruby.imp -bM:SRE -bnoentry'
+ fi
+ LIBRUBYARG='-L${prefix}/lib -Wl,lib$(RUBY_INSTALL_NAME).so'
+ SOLIBS='-lm -lc'
+ ;;
+ beos*)
+ case "$target_cpu" in
+ powerpc*)
+ LIBRUBY_DLDFLAGS='-f ruby.exp -lnet -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o'
+ ;;
+ esac
+ ;;
+ darwin*)
+ LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).$(MAJOR).$(MINOR).$(TEENY).dylib'
+ LIBRUBY_LDSHARED='cc -dynamiclib -undefined suppress'
+ LIBRUBY_DLDFLAGS='-install_name lib$(RUBY_INSTALL_NAME).dylib -current_version $(MAJOR).$(MINOR).$(TEENY) -compatibility_version $(MAJOR).$(MINOR)'
+ LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).$(MAJOR).$(MINOR).dylib lib$(RUBY_INSTALL_NAME).dylib'
+ ;;
+ *)
+ ;;
+ esac
+fi
+
+case "$target_os" in
+ nextstep*)
+ CFLAGS="$CFLAGS -pipe"
+ ;;
+ openstep*)
+ CFLAGS="$CFLAGS -pipe"
+ ;;
+ rhapsody*)
+ CFLAGS="$CFLAGS -pipe -no-precomp"
+ ;;
+ darwin*)
+ CFLAGS="$CFLAGS -pipe -no-precomp"
+ ;;
+ os2_emx)
+ CFLAGS="$CFLAGS -DOS2"
+ ;;
+ osf*)
+ if test "$without_gcc" = "yes" ; then
+ # compile something small: taint.c is fine for this.
+ # the main point is the '-v' flag of 'cc'.
+ case "`cc -v -I. -c main.c -o /tmp/main.o 2>&1`" in
+ */gemc_cc*) # we have the new DEC GEM CC
+ CFLAGS="$CFLAGS -oldc"
+ ;;
+ *) # we have the old MIPS CC
+ ;;
+ esac
+ # cleanup
+ rm -f /tmp/main.o
+ CFLAGS="$CFLAGS -std"
+ fi
+ ;;
+ beos*)
+ case "$target_cpu" in
+ powerpc*)
+ CFLAGS="$CFLAGS -relax_pointers"
+ ;;
+ esac
+ ;;
+ cygwin*|mingw*)
+ RUBY_SO_NAME=$target_os-'$(RUBY_INSTALL_NAME)'${MAJOR}${MINOR}
+ if test x"$enable_shared" = xyes; then
+ LIBRUBY_SO='$(RUBY_SO_NAME)'.dll
+ LIBRUBY_DLDFLAGS='--dllname=$@ --output-lib=$(LIBRUBY) --add-stdcall-alias --def=$(RUBYDEF)'
+ else
+ LIBRUBY_SO=dummy
+ LIBRUBY_DLDFLAGS='--output-exp=$(RUBY_INSTALL_NAME).exp --dllname=$(RUBY_INSTALL_NAME)$(EXEEXT) --output-lib=$(LIBRUBY) --add-stdcall-alias --def=$(RUBYDEF)'
+ fi
+ LIBRUBY_ALIASES=''
+ LIBRUBY_A='lib$(RUBY_INSTALL_NAME)s.a'
+ LIBRUBY='lib$(RUBY_SO_NAME).a'
+ LIBRUBYARG='-L. -l$(RUBY_SO_NAME)'
+ FIRSTMAKEFILE=GNUmakefile:cygwin/GNUmakefile.in
+ SOLIBS='$(LIBS)'
+ case "$target_os" in
+ cygwin*)
+ LIBOBJS="$LIBOBJS strftime.o"
+ CCDLFLAGS=-DUSEIMPORTLIB ;;
+ mingw*)
+ LIBOBJS="$LIBOBJS win32.o"
+ CFLAGS="-DNT -D__MSVCRT__ $CFLAGS"
+ CCDLFLAGS=-DIMPORT ;;
+ esac
+ ;;
+ *)
+ ;;
+esac
+
+AC_SUBST(LIBRUBY_LDSHARED)
+AC_SUBST(LIBRUBY_DLDFLAGS)
+AC_SUBST(RUBY_INSTALL_NAME)
+AC_SUBST(RUBY_SO_NAME)
+AC_SUBST(LIBRUBY_A)
+AC_SUBST(LIBRUBY_SO)
+AC_SUBST(LIBRUBY_ALIASES)
+AC_SUBST(LIBRUBY)
+AC_SUBST(LIBRUBYARG)
+AC_SUBST(SOLIBS)
+AC_SUBST(DLDLIBS)
+AC_SUBST(ENABLE_SHARED)
+AC_SUBST(MAINLIBS)
+
+ri_prefix=
+test "$program_prefix" != NONE &&
+ ri_prefix=$program_prefix
+
+ri_suffix=
+test "$program_suffix" != NONE &&
+ ri_suffix=$program_suffix
+
+RUBY_INSTALL_NAME="${ri_prefix}ruby${ri_suffix}"
+case "$target_os" in
+ cygwin*|mingw*|*djgpp*|os2_emx*)
+ RUBY_LIB_PREFIX="/lib/ruby"
+ ;;
+ *)
+ RUBY_LIB_PREFIX="${prefix}/lib/ruby"
+ ;;
+esac
+RUBY_LIB_PATH="${RUBY_LIB_PREFIX}/${MAJOR}.${MINOR}"
+
+AC_ARG_WITH(sitedir,
+ [--with-sitedir=DIR site libraries in DIR [PREFIX/lib/ruby/site_ruby]],
+ [sitedir=$withval],
+ [sitedir='${prefix}/lib/ruby/site_ruby'])
+SITE_DIR="`eval \"echo ${sitedir}\"`"
+case "$target_os" in
+ cygwin*|mingw*|*djgpp*|os2_emx*)
+ RUBY_SITE_LIB_PATH="`expr "$SITE_DIR" : "$prefix\(/.*\)"`" ||
+ RUBY_SITE_LIB_PATH="$SITE_DIR";;
+ *)
+ RUBY_SITE_LIB_PATH="$SITE_DIR";;
+esac
+RUBY_SITE_LIB_PATH2="${RUBY_SITE_LIB_PATH}/${MAJOR}.${MINOR}"
+
+AC_DEFINE_UNQUOTED(RUBY_LIB, "${RUBY_LIB_PATH}")
+AC_DEFINE_UNQUOTED(RUBY_SITE_LIB, "${RUBY_SITE_LIB_PATH}")
+AC_DEFINE_UNQUOTED(RUBY_SITE_LIB2, "${RUBY_SITE_LIB_PATH2}")
+
AC_SUBST(arch)dnl
+AC_SUBST(sitedir)dnl
+
+configure_args=$ac_configure_args
+AC_SUBST(configure_args)dnl
if test "$fat_binary" = yes ; then
- arch="fat-${host_os}"
+ arch="fat-${target_os}"
AC_DEFINE_UNQUOTED(RUBY_THIN_ARCHLIB,
- "${prefix}/lib/ruby/" __ARCHITECTURE__ "-${host_os}" )
+ "${RUBY_LIB_PATH}/" __ARCHITECTURE__ "-${target_os}")
AC_DEFINE_UNQUOTED(RUBY_SITE_THIN_ARCHLIB,
- "${prefix}/lib/ruby/" __ARCHITECTURE__ "-${host_os}" )
-
- AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${prefix}/lib/ruby/${arch}")
- AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${prefix}/lib/site_ruby/${arch}")
- AC_DEFINE_UNQUOTED(RUBY_PLATFORM, __ARCHITECTURE__ "-${host_os}" )
+ "${RUBY_SITE_LIB_PATH}/" __ARCHITECTURE__ "-${target_os}")
+ AC_DEFINE_UNQUOTED(RUBY_PLATFORM, __ARCHITECTURE__ "-${target_os}")
else
- arch="${host_cpu}-${host_os}"
- AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${prefix}/lib/ruby/${arch}")
- AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${prefix}/lib/site_ruby/${arch}")
+ arch="${target_cpu}-${target_os}"
AC_DEFINE_UNQUOTED(RUBY_PLATFORM, "${arch}")
fi
+AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${RUBY_LIB_PATH}/${arch}")
+AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${RUBY_SITE_LIB_PATH2}/${arch}")
+
+AC_ARG_WITH(search-path,
+ [--with-search-path=DIR specify the additional search path],
+ [search_path=$withval])
+if test "$search_path" != ""; then
+ AC_DEFINE_UNQUOTED(RUBY_SEARCH_PATH,"$search_path")
+fi
+
echo "creating config.h"
-cat confdefs.h > config.h
+tr -d '\015' < confdefs.h > config.h
+: > confdefs.h
-AC_OUTPUT(Makefile ext/extmk.rb)
+AC_OUTPUT($FIRSTMAKEFILE Makefile ext/extmk.rb)
diff --git a/cygwin/GNUmakefile.in b/cygwin/GNUmakefile.in
new file mode 100644
index 0000000000..0e89d15dec
--- /dev/null
+++ b/cygwin/GNUmakefile.in
@@ -0,0 +1,41 @@
+include Makefile
+
+ENABLE_SHARED=@ENABLE_SHARED@
+
+ifneq (,$(findstring no, $(ENABLE_SHARED)))
+ EXTOBJS = $(RUBY_INSTALL_NAME).exp
+ LIBRUBYARG = $(LIBRUBY_A)
+endif
+
+ifneq (,$(findstring ruby, $(RUBY_INSTALL_NAME)))
+ RUBYW_INSTALL_NAME = $(subst ruby,rubyw,$(RUBY_INSTALL_NAME))
+else
+ RUBYW_INSTALL_NAME = $(RUBY_INSTALL_NAME)w
+endif
+WPROGRAM = $(RUBYW_INSTALL_NAME)$(EXEEXT)
+RUBYDEF = $(RUBY_INSTALL_NAME).def
+SOLIBS := $(LIBRUBY_SO).res.@OBJEXT@ $(SOLIBS)
+EXTOBJS += $(@:$(EXEEXT)=.res.@OBJEXT@)
+
+$(LIBRUBY_SO): $(RUBYDEF) $(LIBRUBY_SO).res.@OBJEXT@
+$(LIBRUBY): $(LIBRUBY_SO)
+
+%.res.@OBJEXT@: %.rc
+ @WINDRES@ --preprocessor '$(CC) -E -xc-header -DRC_INVOKE @MWIN32@' --include-dir . --include-dir $(<D) --include-dir $(srcdir)/win32 $< $@
+
+$(RUBY_INSTALL_NAME).rc $(RUBYW_INSTALL_NAME).rc $(LIBRUBY_SO).rc: rbconfig.rb
+ @@MINIRUBY@ $(srcdir)/win32/resource.rb \
+ -ruby_name=$(RUBY_INSTALL_NAME) -rubyw_name=$(RUBYW_INSTALL_NAME) \
+ -so_name=$(LIBRUBY_SO) \
+ . $(icondirs) $(srcdir)/win32
+
+$(PROGRAM): $(RUBY_INSTALL_NAME).res.@OBJEXT@
+$(WPROGRAM): $(RUBYW_INSTALL_NAME).res.@OBJEXT@
+ @rm -f $@
+ $(PURIFY) $(CC) -mwindows -e _mainCRTStartup $(LDFLAGS) $(XLDFLAGS) \
+ $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) -o $@
+
+$(RUBYDEF): $(LIBRUBY_A)
+ echo EXPORTS > $(RUBYDEF)
+ @NM@ --extern-only --defined-only $(LIBRUBY_A) | \
+ @MINIRUBY@ -ne 'puts $$1 if / [CDT] _(.*)$$/' >> $(RUBYDEF)
diff --git a/defines.h b/defines.h
index a24f9ebff7..fefddee23b 100644
--- a/defines.h
+++ b/defines.h
@@ -12,24 +12,41 @@
#define RUBY
-/* define EUC/SJIS for default kanji-code */
-#if defined(MSDOS) || defined(__CYGWIN32__) || defined(__human68k__)
-#undef EUC
-#define SJIS
+/* define RUBY_USE_EUC/SJIS for default kanji-code */
+#ifndef DEFAULT_KCODE
+#if defined(MSDOS) || defined(__CYGWIN__) || defined(__human68k__) || defined(__MACOS__) || defined(__EMX__) || defined(OS2) || defined(NT)
+#define DEFAULT_KCODE KCODE_SJIS
#else
-#define EUC
-#undef SJIS
+#define DEFAULT_KCODE KCODE_EUC
+#endif
#endif
#ifdef NeXT
#define DYNAMIC_ENDIAN /* determine endian at runtime */
+#ifndef __APPLE__
#define S_IXUSR _S_IXUSR /* execute/search permission, owner */
+#endif
#define S_IXGRP 0000010 /* execute/search permission, group */
#define S_IXOTH 0000001 /* execute/search permission, other */
+
+#define HAVE_SYS_WAIT_H /* configure fails to find this */
#endif /* NeXT */
#ifdef NT
-#include "missing/nt.h"
+#include "win32/win32.h"
+#endif
+
+#if defined __CYGWIN__
+# undef EXTERN
+# if defined USEIMPORTLIB
+# define EXTERN extern __declspec(dllimport)
+# else
+# define EXTERN extern __declspec(dllexport)
+# endif
+#endif
+
+#ifndef EXTERN
+#define EXTERN extern
#endif
#ifdef sparc
@@ -38,11 +55,28 @@
#define FLUSH_REGISTER_WINDOWS /* empty */
#endif
-#if defined(__human68k__) || defined(__CYGWIN32__)
+#if defined(MSDOS) || defined(_WIN32) || defined(__human68k__) || defined(__EMX__)
+#define DOSISH 1
+#endif
+
+#if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(OS2)
+#define PATH_SEP ";"
+#elif defined(riscos)
+#define PATH_SEP ","
+#else
+#define PATH_SEP ":"
+#endif
+#define PATH_SEP_CHAR PATH_SEP[0]
+
+#if defined(__human68k__)
#undef HAVE_RANDOM
#undef HAVE_SETITIMER
#endif
+#if defined(DJGPP) || defined(__BOW__) || defined __CYGWIN__
+#undef HAVE_SETITIMER
+#endif
+
#ifndef RUBY_PLATFORM
#define RUBY_PLATFORM "unknown-unknown"
#endif
diff --git a/dir.c b/dir.c
index 4c380e6b98..f2f4faa8aa 100644
--- a/dir.c
+++ b/dir.c
@@ -1,4 +1,4 @@
-/************************************************
+/**********************************************************************
dir.c -
@@ -6,9 +6,11 @@
$Date$
created at: Wed Jan 5 09:51:01 JST 1994
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-2000 Yukihiro Matsumoto
+ Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ Copyright (C) 2000 Information-technology Promotion Agency, Japan
-************************************************/
+**********************************************************************/
#include "ruby.h"
@@ -24,9 +26,12 @@
#include <unistd.h>
#endif
-#if HAVE_DIRENT_H
+#if defined HAVE_DIRENT_H && !defined NT
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
+#elif defined HAVE_DIRECT_H && !defined NT
+# include <direct.h>
+# define NAMLEN(dirent) strlen((dirent)->d_name)
#else
# define dirent direct
# define NAMLEN(dirent) (dirent)->d_namlen
@@ -39,18 +44,187 @@
# if HAVE_NDIR_H
# include <ndir.h>
# endif
-# ifdef NT
+# if defined(NT)
# include "missing/dir.h"
# endif
#endif
#include <errno.h>
-#ifndef NT
+#ifndef HAVE_STDLIB_H
char *getenv();
#endif
-static VALUE cDir;
+#ifndef HAVE_STRING_H
+char *strchr _((char*,char));
+#endif
+
+#include <ctype.h>
+
+#ifndef HAVE_LSTAT
+#define lstat rb_sys_stat
+#endif
+
+#define FNM_NOESCAPE 0x01
+#define FNM_PATHNAME 0x02
+#define FNM_PERIOD 0x04
+#define FNM_NOCASE 0x08
+
+#define FNM_NOMATCH 1
+#define FNM_ERROR 2
+
+#define downcase(c) (nocase && ISUPPER(c) ? tolower(c) : (c))
+
+#if defined DOSISH
+#define isdirsep(c) ((c) == '/' || (c) == '\\')
+static char *
+find_dirsep(s)
+ char *s;
+{
+ while (*s) {
+ if (isdirsep(*s))
+ return s;
+ s++;
+ }
+ return 0;
+}
+#else
+#define isdirsep(c) ((c) == '/')
+#define find_dirsep(s) strchr(s, '/')
+#endif
+
+static char *
+range(pat, test, flags)
+ char *pat;
+ char test;
+ int flags;
+{
+ int not, ok = 0;
+ int nocase = flags & FNM_NOCASE;
+ int escape = !(flags & FNM_NOESCAPE);
+
+ not = *pat == '!' || *pat == '^';
+ if (not)
+ pat++;
+
+ test = downcase(test);
+
+ while (*pat) {
+ int cstart, cend;
+ cstart = cend = *pat++;
+ if (cstart == ']')
+ return ok == not ? 0 : pat;
+ else if (escape && cstart == '\\')
+ cstart = cend = *pat++;
+ if (*pat == '-' && pat[1] != ']') {
+ if (escape && pat[1] == '\\')
+ pat++;
+ cend = pat[1];
+ if (!cend)
+ return 0;
+ pat += 2;
+ }
+ if (downcase(cstart) <= test && test <= downcase(cend))
+ ok = 1;
+ }
+ return 0;
+}
+
+#define PERIOD(s) (period && *(s) == '.' && \
+ ((s) == string || pathname && isdirsep(*(s))))
+static int
+fnmatch(pat, string, flags)
+ const char *pat;
+ const char *string;
+ int flags;
+{
+ int c;
+ int test;
+ const char *s = string;
+ int escape = !(flags & FNM_NOESCAPE);
+ int pathname = flags & FNM_PATHNAME;
+ int period = flags & FNM_PERIOD;
+ int nocase = flags & FNM_NOCASE;
+
+ while (c = *pat++) {
+ switch (c) {
+ case '?':
+ if (!*s || pathname && isdirsep(*s) || PERIOD(s))
+ return FNM_NOMATCH;
+ s++;
+ break;
+ case '*':
+ while ((c = *pat++) == '*')
+ ;
+
+ if (PERIOD(s))
+ return FNM_NOMATCH;
+
+ if (!c) {
+ if (pathname && find_dirsep(s))
+ return FNM_NOMATCH;
+ else
+ return 0;
+ }
+ else if (pathname && isdirsep(c)) {
+ s = find_dirsep(s);
+ if (s)
+ break;
+ return FNM_NOMATCH;
+ }
+
+ test = escape && c == '\\' ? *pat : c;
+ test = downcase(test);
+ pat--;
+ while (*s) {
+ if ((c == '[' || downcase(*s) == test) &&
+ !fnmatch(pat, s, flags & ~FNM_PERIOD))
+ return 0;
+ else if (pathname && isdirsep(*s))
+ break;
+ s++;
+ }
+ return FNM_NOMATCH;
+
+ case '[':
+ if (!*s || pathname && isdirsep(*s) || PERIOD(s))
+ return FNM_NOMATCH;
+ pat = range(pat, *s, flags);
+ if (!pat)
+ return FNM_NOMATCH;
+ s++;
+ break;
+
+ case '\\':
+ if (escape
+#if defined DOSISH
+ && *pat && strchr("*?[\\", *pat)
+#endif
+ ) {
+ c = *pat;
+ if (!c)
+ c = '\\';
+ else
+ pat++;
+ }
+ /* FALLTHROUGH */
+
+ default:
+#if defined DOSISH
+ if (pathname && isdirsep(c) && isdirsep(*s))
+ ;
+ else
+#endif
+ if(downcase(c) != downcase(*s))
+ return FNM_NOMATCH;
+ s++;
+ break;
+ }
+ }
+ return !*s ? 0 : FNM_NOMATCH;
+}
+
+VALUE rb_cDir;
static void
free_dir(dir)
@@ -62,37 +236,61 @@ free_dir(dir)
static VALUE dir_close _((VALUE));
static VALUE
-dir_s_open(dir_class, dirname)
- VALUE dir_class, dirname;
+dir_s_new(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_dir, 0);
+
+ rb_obj_call_init(obj, argc, argv);
+
+ return obj;
+}
+
+static VALUE
+dir_initialize(dir, dirname)
+ VALUE dir, dirname;
{
- VALUE obj;
DIR *dirp;
Check_SafeStr(dirname);
-
+ if (DATA_PTR(dir)) closedir(DATA_PTR(dir));
+ DATA_PTR(dir) = NULL;
dirp = opendir(RSTRING(dirname)->ptr);
if (dirp == NULL) {
if (errno == EMFILE || errno == ENFILE) {
- gc_gc();
+ rb_gc();
dirp = opendir(RSTRING(dirname)->ptr);
}
if (dirp == NULL) {
rb_sys_fail(RSTRING(dirname)->ptr);
}
}
+ DATA_PTR(dir) = dirp;
- obj = Data_Wrap_Struct(dir_class, 0, free_dir, dirp);
+ return dir;
+}
+
+static VALUE
+dir_s_open(klass, dirname)
+ VALUE klass, dirname;
+{
+ VALUE dir = Data_Wrap_Struct(klass, 0, free_dir, 0);
- if (iterator_p())
- rb_ensure(rb_yield, obj, dir_close, obj);
+ dir_initialize(dir, dirname);
+ if (rb_block_given_p()) {
+ rb_ensure(rb_yield, dir, dir_close, dir);
+ return Qnil;
+ }
- return obj;
+ return dir;
}
static void
dir_closed()
{
- Fail("closed directory");
+ rb_raise(rb_eIOError, "closed directory");
}
#define GetDIR(obj, dirp) {\
@@ -111,12 +309,14 @@ dir_read(dir)
errno = 0;
dp = readdir(dirp);
if (dp)
- return str_taint(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;
+ }
else {
- if (errno == 0) /* end of stream */
- return Qnil;
rb_sys_fail(0);
}
+ return Qnil; /* not reached */
}
static VALUE
@@ -125,12 +325,11 @@ dir_each(dir)
{
DIR *dirp;
struct dirent *dp;
- VALUE file;
GetDIR(dir, dirp);
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
- file = str_taint(str_new(dp->d_name, NAMLEN(dp)));
- rb_yield(file);
+ rb_yield(rb_tainted_str_new(dp->d_name, NAMLEN(dp)));
+ if (DATA_PTR(dir) == NULL) dir_closed();
}
return dir;
}
@@ -139,13 +338,13 @@ static VALUE
dir_tell(dir)
VALUE dir;
{
+#ifdef HAVE_TELLDIR
DIR *dirp;
- int pos;
+ long pos;
-#if !defined(__CYGWIN32__)
GetDIR(dir, dirp);
pos = telldir(dirp);
- return int2inum(pos);
+ return rb_int2inum(pos);
#else
rb_notimplement();
#endif
@@ -157,7 +356,7 @@ dir_seek(dir, pos)
{
DIR *dirp;
-#if !defined(__CYGWIN32__)
+#ifdef HAVE_SEEKDIR
GetDIR(dir, dirp);
seekdir(dirp, NUM2INT(pos));
return dir;
@@ -201,8 +400,7 @@ dir_s_chdir(argc, argv, obj)
char *dist = "";
rb_secure(2);
- rb_scan_args(argc, argv, "01", &path);
- if (!NIL_P(path)) {
+ if (rb_scan_args(argc, argv, "01", &path) == 1) {
Check_SafeStr(path);
dist = RSTRING(path)->ptr;
}
@@ -232,14 +430,14 @@ dir_s_getwd(dir)
if (getwd(path) == 0) rb_sys_fail(path);
#endif
- return str_taint(str_new2(path));
+ return rb_tainted_str_new2(path);
}
static VALUE
dir_s_chroot(dir, path)
VALUE dir, path;
{
-#if !defined(DJGPP) && !defined(NT) && !defined(__human68k__)
+#if defined(HAVE_CHROOT) && !defined(__CHECKER__)
rb_secure(2);
Check_SafeStr(path);
@@ -249,6 +447,7 @@ dir_s_chroot(dir, path)
return INT2FIX(0);
#else
rb_notimplement();
+ return Qnil; /* not reached */
#endif
}
@@ -261,7 +460,6 @@ dir_s_mkdir(argc, argv, obj)
VALUE path, vmode;
int mode;
- rb_secure(2);
if (rb_scan_args(argc, argv, "11", &path, &vmode) == 2) {
mode = NUM2INT(vmode);
}
@@ -270,7 +468,8 @@ dir_s_mkdir(argc, argv, obj)
}
Check_SafeStr(path);
-#ifndef NT
+ rb_secure(2);
+#if !defined(NT)
if (mkdir(RSTRING(path)->ptr, mode) == -1)
rb_sys_fail(RSTRING(path)->ptr);
#else
@@ -285,47 +484,259 @@ static VALUE
dir_s_rmdir(obj, dir)
VALUE obj, dir;
{
- rb_secure(2);
Check_SafeStr(dir);
+ rb_secure(2);
if (rmdir(RSTRING(dir)->ptr) < 0)
rb_sys_fail(RSTRING(dir)->ptr);
- return TRUE;
+ return INT2FIX(0);
}
-#define isdelim(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\0')
+/* Return nonzero if S has any special globbing chars in it. */
+static int
+has_magic(s, send)
+ char *s, *send;
+{
+ register char *p = s;
+ register char c;
+ int open = 0;
+
+ while ((c = *p++) != '\0') {
+ switch (c) {
+ case '?':
+ case '*':
+ return Qtrue;
+
+ case '[': /* Only accept an open brace if there is a close */
+ open++; /* brace to match it. Bracket expressions must be */
+ continue; /* complete, according to Posix.2 */
+ case ']':
+ if (open)
+ return Qtrue;
+ continue;
+
+ case '\\':
+ if (*p++ == '\0')
+ return Qfalse;
+ }
-char **glob_filename();
-extern char *glob_error_return;
+ if (send && p >= send) break;
+ }
+ return Qfalse;
+}
+
+static char*
+extract_path(p, pend)
+ char *p, *pend;
+{
+ char *alloc;
+ int len;
+
+ len = pend - p;
+ alloc = ALLOC_N(char, len+1);
+ memcpy(alloc, p, len);
+ if (len > 1 && pend[-1] == '/'
+#if defined DOSISH
+ && pend[-2] != ':'
+#endif
+ ) {
+ alloc[len-1] = 0;
+ }
+ else {
+ alloc[len] = 0;
+ }
+
+ return alloc;
+}
+
+static char*
+extract_elem(path)
+ char *path;
+{
+ char *pend;
+
+ pend = strchr(path, '/');
+ if (!pend) pend = path + strlen(path);
+
+ return extract_path(path, pend);
+}
+
+#ifndef S_ISDIR
+# define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
+#endif
+
+void
+rb_glob_helper(path, flag, func, arg)
+ char *path;
+ int flag;
+ void (*func)();
+ VALUE arg;
+{
+ struct stat st;
+ char *p, *m;
+
+ if (!has_magic(path, 0)) {
+ if (rb_sys_stat(path, &st) == 0) {
+ (*func)(path, arg);
+ }
+ return;
+ }
+
+ p = path;
+ while (p) {
+ if (*p == '/') p++;
+ m = strchr(p, '/');
+ if (has_magic(p, m)) {
+ char *dir, *base, *magic, *buf;
+ DIR *dirp;
+ struct dirent *dp;
+ int recursive = 0;
+
+ struct d_link {
+ char *path;
+ struct d_link *next;
+ } *tmp, *link = 0;
+
+ base = extract_path(path, p);
+ if (path == p) dir = ".";
+ else dir = base;
+
+ magic = extract_elem(p);
+ if (m && strcmp(magic, "**") == 0) {
+ recursive = 1;
+ buf = ALLOC_N(char, strlen(base)+strlen(m)+3);
+ sprintf(buf, "%s%s%s", base, (*base)?"":".", m);
+ rb_glob_helper(buf, flag, func, arg);
+ free(buf);
+ }
+ if (rb_sys_stat(dir, &st) < 0) {
+ free(base);
+ break;
+ }
+ if (S_ISDIR(st.st_mode)) {
+ dirp = opendir(dir);
+ if (dirp == NULL) {
+ free(base);
+ break;
+ }
+ }
+ else {
+ free(base);
+ break;
+ }
+
+#if defined DOSISH
+#define BASE (*base && !((isdirsep(*base) && !base[1]) || (base[1] == ':' && isdirsep(base[2]) && !base[3])))
+#else
+#define BASE (*base && !(*base == '/' && !base[1]))
+#endif
+
+ for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
+ if (recursive) {
+ if (strcmp(".", dp->d_name) == 0 || strcmp("..", dp->d_name) == 0)
+ continue;
+ buf = ALLOC_N(char, strlen(base)+NAMLEN(dp)+strlen(m)+6);
+ sprintf(buf, "%s%s%s/**%s", base, (BASE)?"/":"", dp->d_name, m);
+ sprintf(buf, "%s%s%s", base, (BASE)?"/":"", dp->d_name);
+ if (lstat(buf, &st) < 0) {
+ continue;
+ }
+ if (S_ISDIR(st.st_mode)) {
+ strcat(buf, "/**");
+ strcat(buf, m);
+ rb_glob_helper(buf, flag, func, arg);
+ }
+ free(buf);
+ continue;
+ }
+ if (fnmatch(magic, dp->d_name, flag) == 0) {
+ buf = ALLOC_N(char, strlen(base)+NAMLEN(dp)+2);
+ sprintf(buf, "%s%s%s", base, (BASE)?"/":"", dp->d_name);
+ if (!m) {
+ (*func)(buf, arg);
+ free(buf);
+ continue;
+ }
+ tmp = ALLOC(struct d_link);
+ tmp->path = buf;
+ tmp->next = link;
+ link = tmp;
+ }
+ }
+ closedir(dirp);
+ free(base);
+ free(magic);
+ while (link) {
+ stat(link->path, &st); /* should success */
+ if (S_ISDIR(st.st_mode)) {
+ int len = strlen(link->path);
+ int mlen = strlen(m);
+ char *t = ALLOC_N(char, len+mlen+1);
+
+ sprintf(t, "%s%s", link->path, m);
+ rb_glob_helper(t, flag, func, arg);
+ free(t);
+ }
+ tmp = link;
+ link = link->next;
+ free(tmp->path);
+ free(tmp);
+ }
+ }
+ p = m;
+ }
+}
+
+void
+rb_glob(path, func, arg)
+ char *path;
+ void (*func)();
+ VALUE arg;
+{
+ rb_glob_helper(path, FNM_PERIOD, func, arg);
+}
+
+void
+rb_iglob(path, func, arg)
+ char *path;
+ void (*func)();
+ VALUE arg;
+{
+ rb_glob_helper(path, FNM_PERIOD|FNM_NOCASE, func, arg);
+}
static void
-push_globs(ary, s)
+push_pattern(path, ary)
+ char *path;
VALUE ary;
- char *s;
{
- char **fnames, **ff;
+ VALUE str = rb_tainted_str_new2(path);
- fnames = glob_filename(s);
- if (fnames == (char**)-1) rb_sys_fail(s);
- ff = fnames;
- while (*ff) {
- ary_push(ary, str_taint(str_new2(*ff)));
- free(*ff);
- ff++;
+ if (ary) {
+ rb_ary_push(ary, str);
}
- if (fnames != &glob_error_return) {
- free(fnames);
+ else {
+ rb_yield(str);
}
}
static void
+push_globs(ary, s)
+ VALUE ary;
+ char *s;
+{
+ rb_glob(s, push_pattern, ary);
+}
+
+static void
push_braces(ary, s)
VALUE ary;
char *s;
{
- char buf[MAXPATHLEN];
+ char buffer[MAXPATHLEN], *buf = buffer;
char *p, *t, *b;
char *lbrace, *rbrace;
+ int nest = 0;
p = s;
lbrace = rbrace = 0;
@@ -337,7 +748,8 @@ push_braces(ary, s)
p++;
}
while (*p) {
- if (*p == '}' && lbrace) {
+ if (*p == '{') nest++;
+ if (*p == '}' && --nest == 0) {
rbrace = p;
break;
}
@@ -345,6 +757,9 @@ push_braces(ary, s)
}
if (lbrace) {
+ int len = strlen(s);
+ if (len >= MAXPATHLEN)
+ buf = xmalloc(len + 1);
memcpy(buf, s, lbrace-s);
b = buf + (lbrace-s);
p = lbrace;
@@ -358,44 +773,46 @@ push_braces(ary, s)
strcpy(b+(p-t), rbrace+1);
push_braces(ary, buf);
}
+ if (buf != buffer)
+ free(buf);
}
else {
push_globs(ary, s);
}
}
+#define isdelim(c) ((c)==' '||(c)=='\t'||(c)=='\n'||(c)=='\0')
+
static VALUE
-dir_s_glob(dir, vstr)
- VALUE dir, vstr;
+dir_s_glob(dir, str)
+ VALUE dir, str;
{
char *p, *pend;
- char buf[MAXPATHLEN];
- char *t, *t0;
+ char buffer[MAXPATHLEN], *buf = buffer;
+ char *t;
int nest;
- VALUE ary;
- struct RString *str;
+ VALUE ary = 0;
- Check_SafeStr(vstr);
- str = RSTRING(vstr);
- ary = ary_new();
+ Check_SafeStr(str);
+ if (!rb_block_given_p()) {
+ ary = rb_ary_new();
+ }
+ if (RSTRING(str)->len >= MAXPATHLEN)
+ buf = xmalloc(RSTRING(str)->len + 1);
- p = str->ptr;
- pend = p + str->len;
+ p = RSTRING(str)->ptr;
+ pend = p + RSTRING(str)->len;
while (p < pend) {
t = buf;
+ nest = 0;
while (p < pend && isdelim(*p)) p++;
while (p < pend && !isdelim(*p)) {
+ if (*p == '{') nest+=2;
+ if (*p == '}') nest+=3;
*t++ = *p++;
}
*t = '\0';
- t0 = buf;
- nest = 0;
- while (t0 < t) {
- if (*t0 == '{') nest+=2;
- if (*t0 == '}') nest+=3;
- t0++;
- }
if (nest == 0) {
push_globs(ary, buf);
}
@@ -404,6 +821,8 @@ dir_s_glob(dir, vstr)
}
/* else unmatched braces */
}
+ if (buf != buffer)
+ free(buf);
return ary;
}
@@ -413,39 +832,52 @@ dir_foreach(io, dirname)
{
VALUE dir;
- dir = rb_funcall(cDir, rb_intern("open"), 1, dirname);
- return rb_ensure(dir_each, dir, dir_close, dir);
+ dir = rb_funcall(rb_cDir, rb_intern("open"), 1, dirname);
+ rb_ensure(dir_each, dir, dir_close, dir);
+ return Qnil;
}
-void
-Init_Dir()
+static VALUE
+dir_entries(io, dirname)
+ VALUE io, dirname;
{
- extern VALUE mEnumerable;
-
- cDir = rb_define_class("Dir", cObject);
-
- rb_include_module(cDir, mEnumerable);
-
- rb_define_singleton_method(cDir, "new", dir_s_open, 1);
- rb_define_singleton_method(cDir, "open", dir_s_open, 1);
- rb_define_singleton_method(cDir, "foreach", dir_foreach, 1);
-
- rb_define_method(cDir,"read", dir_read, 0);
- rb_define_method(cDir,"each", dir_each, 0);
- rb_define_method(cDir,"rewind", dir_rewind, 0);
- rb_define_method(cDir,"tell", dir_tell, 0);
- rb_define_method(cDir,"seek", dir_seek, 1);
- rb_define_method(cDir,"close", dir_close, 0);
+ VALUE dir;
- rb_define_singleton_method(cDir,"chdir", dir_s_chdir, -1);
- rb_define_singleton_method(cDir,"getwd", dir_s_getwd, 0);
- rb_define_singleton_method(cDir,"pwd", dir_s_getwd, 0);
- rb_define_singleton_method(cDir,"chroot", dir_s_chroot, 1);
- rb_define_singleton_method(cDir,"mkdir", dir_s_mkdir, -1);
- rb_define_singleton_method(cDir,"rmdir", dir_s_rmdir, 1);
- rb_define_singleton_method(cDir,"delete", dir_s_rmdir, 1);
- rb_define_singleton_method(cDir,"unlink", dir_s_rmdir, 1);
+ dir = rb_funcall(rb_cDir, rb_intern("open"), 1, dirname);
+ return rb_ensure(rb_Array, dir, dir_close, dir);
+}
- rb_define_singleton_method(cDir,"glob", dir_s_glob, 1);
- rb_define_singleton_method(cDir,"[]", dir_s_glob, 1);
+void
+Init_Dir()
+{
+ rb_cDir = rb_define_class("Dir", rb_cObject);
+
+ rb_include_module(rb_cDir, rb_mEnumerable);
+
+ rb_define_singleton_method(rb_cDir, "new", dir_s_new, -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,"initialize", dir_initialize, 1);
+ rb_define_method(rb_cDir,"read", dir_read, 0);
+ rb_define_method(rb_cDir,"each", dir_each, 0);
+ rb_define_method(rb_cDir,"rewind", dir_rewind, 0);
+ rb_define_method(rb_cDir,"tell", dir_tell, 0);
+ rb_define_method(rb_cDir,"seek", dir_seek, 1);
+ rb_define_method(rb_cDir,"pos", dir_tell, 0);
+ rb_define_method(rb_cDir,"pos=", dir_seek, 1);
+ rb_define_method(rb_cDir,"close", dir_close, 0);
+
+ rb_define_singleton_method(rb_cDir,"chdir", dir_s_chdir, -1);
+ rb_define_singleton_method(rb_cDir,"getwd", dir_s_getwd, 0);
+ rb_define_singleton_method(rb_cDir,"pwd", dir_s_getwd, 0);
+ rb_define_singleton_method(rb_cDir,"chroot", dir_s_chroot, 1);
+ rb_define_singleton_method(rb_cDir,"mkdir", dir_s_mkdir, -1);
+ rb_define_singleton_method(rb_cDir,"rmdir", dir_s_rmdir, 1);
+ rb_define_singleton_method(rb_cDir,"delete", dir_s_rmdir, 1);
+ rb_define_singleton_method(rb_cDir,"unlink", dir_s_rmdir, 1);
+
+ rb_define_singleton_method(rb_cDir,"glob", dir_s_glob, 1);
+ rb_define_singleton_method(rb_cDir,"[]", dir_s_glob, 1);
}
diff --git a/djgpp/README.djgpp b/djgpp/README.djgpp
new file mode 100644
index 0000000000..d81259ccac
--- /dev/null
+++ b/djgpp/README.djgpp
@@ -0,0 +1,21 @@
+* How to compile and install on djgpp
+
+This is what you need to do to compile and install Ruby:
+
+ 1. Run configure.bat, which will generate config.h and Makefile
+ and ext/extmk.rb(GNU sed required).
+ Message like this is normal:
+ sed.exe: can't read 123456789: No such file or directory (ENOENT)
+
+ 2. Edit defines.h if you need. Probably this step will not need.
+
+ 3. Remove comment mark(#) before the module names from ext/Setup.dj (or
+ add module names if not present).
+
+ 4. Run make.
+
+ 5. Optionally, run 'make test' to check whether the compiled Ruby
+ interpreter works well. If you see the message "test succeeded",
+ your ruby works as it should (hopefully).
+
+ 6. Run 'make install'
diff --git a/djgpp/config.hin b/djgpp/config.hin
new file mode 100644
index 0000000000..973a0db93d
--- /dev/null
+++ b/djgpp/config.hin
@@ -0,0 +1,72 @@
+#define USE_THREAD 1
+#define SIZEOF_INT 4
+#define SIZEOF_SHORT 2
+#define SIZEOF_LONG 4
+#define SIZEOF_VOIDP 4
+#define SIZEOF_FLOAT 4
+#define SIZEOF_DOUBLE 8
+#define HAVE_PROTOTYPES 1
+#define TOKEN_PASTE(x,y) x##y
+#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_ISINF 1
+#define HAVE_ISNAN 1
+#define HAVE_FINITE 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_H 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 "/lib/ruby/@MAJOR@.@MINOR@"
+#define RUBY_SITE_LIB "/lib/ruby/site_ruby"
+#define RUBY_SITE_LIB2 "/lib/ruby/site_ruby/@MAJOR@.@MINOR@"
+#define RUBY_PLATFORM "i386-msdosdjgpp"
+#define RUBY_ARCHLIB "/lib/ruby/@MAJOR@.@MINOR@/i386-msdosdjgpp"
+#define RUBY_SITE_ARCHLIB "/lib/ruby/site_ruby/@MAJOR@.@MINOR@/i386-msdosdjgpp"
diff --git a/djgpp/config.sed b/djgpp/config.sed
new file mode 100644
index 0000000000..0713759f16
--- /dev/null
+++ b/djgpp/config.sed
@@ -0,0 +1,80 @@
+/^SHELL/s,/bin/sh,$(COMSPEC),
+s%@srcdir@%.%g
+s%@top_srcdir@%..%
+s%@CFLAGS@%-O2%g
+s%@CPPFLAGS@%%g
+s%@CXXFLAGS@%%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-msdosdjgpp%g
+s%@host_alias@%i386-msdosdjgpp%g
+s%@host_cpu@%i386%g
+s%@host_vendor@%pc%g
+s%@host_os@%msdosdjgpp%g
+s%@CC@%gcc%g
+s%@CPP@%gcc -E%g
+s%@YACC@%bison -y%g
+s%@RANLIB@%ranlib%g
+s%@AR@%ar%g
+s%@INSTALL_PROGRAM@%${INSTALL}%g
+s%@INSTALL_DATA@%${INSTALL} -m 644%g
+s%@SET_MAKE@%%g
+s%@LIBOBJS@% crypt.o flock.o vsnprintf.o%g
+s%@ALLOCA@%%g
+s%@DEFAULT_KCODE@%%g
+s%@EXEEXT@%.exe%g
+s%@OBJEXT@%o%g
+s%@XLDFLAGS@%%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%@LIBRUBY_A@%libruby.a%g
+s%@LIBRUBYARG@%libruby.a%g
+s%@LIBRUBY_SO@%%g
+s%@SOLIBS@%%g
+s%@arch@%i386-msdosdjgpp%g
+;s%/bin/rm%rm%
+s%@DLDLIBS@%-lc%g
+s%@PREP@%%
+s%@RUBY_INSTALL_NAME@%ruby%g
+s%@RUBY_SO_NAME@%%g
+s%@arch@%i386-msdosdjgpp%g
+s%@sitedir@%${prefix}/lib/ruby/site_ruby%g
+s%@configure_args@%%g
+s%@MINIRUBY@%./miniruby%
+s%@archlib@%/lib/ruby/i386-msdosdjgpp%
+;s%|| true%%
+;/\/dev\/null/ {
+;s,/dev/null 2>&1, nul,
+;s,2> /dev/null,,
+;}
+;/^config.status/ {
+; N;N;N;N;N;d
+;}
+;s%mv -f y\.tab\.c%if exist parse.c del parse.c\
+ ren y_tab.c%
+;s%y\.tab\.c%y_tab.c%
+/^,THIS_IS_DUMMY_PATTERN_/i\
+ac_given_srcdir=.
diff --git a/djgpp/configure.bat b/djgpp/configure.bat
new file mode 100644
index 0000000000..dbb4a08528
--- /dev/null
+++ b/djgpp/configure.bat
@@ -0,0 +1,21 @@
+@echo off
+if exist configure.bat cd ..
+if exist djgpp\version.sed goto exist
+ sed -n -f djgpp\mkver.sed < version.h > djgpp\version.sed
+:exist
+set _conv_=-f djgpp\config.sed -f djgpp\version.sed
+sed %_conv_% < Makefile.in > Makefile
+sed %_conv_% < ext\extmk.rb.in > ext\extmk.rb
+sed %_conv_% < djgpp\config.hin > config.h
+echo LFN check > 12345678
+sed -n /LFN/d 123456789 > nul
+if errorlevel 2 goto LFN
+ copy missing\vsnprintf.c missing\vsnprint.c > nul
+ copy djgpp\config.sed config.sta > nul
+goto end
+:LFN
+ copy djgpp\config.sed config.status > nul
+:end
+set _conv_=
+del 12345678
+echo Now you must run a make.
diff --git a/djgpp/mkver.sed b/djgpp/mkver.sed
new file mode 100644
index 0000000000..f29b9ddd3e
--- /dev/null
+++ b/djgpp/mkver.sed
@@ -0,0 +1 @@
+/RUBY_VERSION /s/^.*\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\).*$/s,@MAJOR@,\1,;s,@MINOR@,\2,;s,@TEENY@,\3,/p
diff --git a/dln.c b/dln.c
index ed20087b6a..40a326df63 100644
--- a/dln.c
+++ b/dln.c
@@ -1,4 +1,4 @@
-/************************************************
+/**********************************************************************
dln.c -
@@ -6,15 +6,22 @@
$Date$
created at: Tue Jan 18 17:05:06 JST 1994
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-2000 Yukihiro Matsumoto
-************************************************/
+**********************************************************************/
#include "config.h"
#include "defines.h"
#include "dln.h"
+#ifdef __CHECKER__
+#undef HAVE_DLOPEN
+#undef USE_DLN_A_OUT
+#undef USE_DLN_DLOPEN
+#endif
+
char *dln_argv0;
+void rb_loaderror();
#ifdef _AIX
#pragma alloca
@@ -30,14 +37,14 @@ char *dln_argv0;
# include <strings.h>
#endif
+#ifndef xmalloc
void *xmalloc();
void *xcalloc();
void *xrealloc();
+#endif
#include <stdio.h>
-#ifndef NT
-#include <sys/file.h>
-#else
+#ifdef NT
#include "missing/file.h"
#endif
#include <sys/types.h>
@@ -54,19 +61,29 @@ void *xrealloc();
#endif
#ifndef NT
-char *strdup();
char *getenv();
#endif
+#ifdef __MACOS__
+# include <TextUtils.h>
+# include <CodeFragments.h>
+# include <Aliases.h>
+# include "macruby_private.h"
+#endif
+
+#ifdef __BEOS__
+# include <image.h>
+#endif
+
int eaccess();
-#if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT)
+#if defined(HAVE_DLOPEN) && !defined(USE_DLN_A_OUT) && !defined(_AIX)
/* dynamic load with dlopen() */
# define USE_DLN_DLOPEN
#endif
#ifndef FUNCNAME_PATTERN
-# if defined(__hp9000s300) || defined(__NetBSD__) || defined(__BORLANDC__) || defined(__FreeBSD__) || defined(NeXT)
+# if defined(__hp9000s300) || (defined(__NetBSD__) && !defined(__ELF__)) || defined(__BORLANDC__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) || defined(__OpenBSD__) || defined(NeXT) || defined(__WATCOMC__) || defined(__APPLE__)
# define FUNCNAME_PATTERN "_Init_%.200s"
# else
# define FUNCNAME_PATTERN "Init_%.200s"
@@ -75,16 +92,21 @@ int eaccess();
static void
init_funcname(buf, file)
- char *buf, *file;
+ char *buf;
+ char *file;
{
char *p, *slash;
/* Load the file as an object one */
for (p = file, slash = p-1; *p; p++) /* Find position of last '/' */
+#ifdef __MACOS__
+ if (*p == ':') slash = p;
+#else
if (*p == '/') slash = p;
+#endif
- sprintf(buf, FUNCNAME_PATTERN, slash + 1);
- for (p = buf; *p; p++) { /* Delete suffix it it exists */
+ snprintf(buf, MAXPATHLEN, FUNCNAME_PATTERN, slash + 1);
+ for (p = buf; *p; p++) { /* Delete suffix if it exists */
if (*p == '.') {
*p = '\0'; break;
}
@@ -106,16 +128,15 @@ init_funcname(buf, file)
static int dln_errno;
#define DLN_ENOEXEC ENOEXEC /* Exec format error */
-#define DLN_ECONFL 201 /* Symbol name conflict */
-#define DLN_ENOINIT 202 /* No inititalizer given */
-#define DLN_EUNDEF 203 /* Undefine symbol remains */
-#define DLN_ENOTLIB 204 /* Not a library file */
-#define DLN_EBADLIB 205 /* Malformed library file */
-#define DLN_EINIT 206 /* Not initialized */
+#define DLN_ECONFL 1201 /* Symbol name conflict */
+#define DLN_ENOINIT 1202 /* No inititalizer given */
+#define DLN_EUNDEF 1203 /* Undefine symbol remains */
+#define DLN_ENOTLIB 1204 /* Not a library file */
+#define DLN_EBADLIB 1205 /* Malformed library file */
+#define DLN_EINIT 1206 /* Not initialized */
static int dln_init_p = 0;
-#include "st.h"
#include <ar.h>
#include <a.out.h>
#ifndef N_COMM
@@ -127,6 +148,9 @@ static int dln_init_p = 0;
#define INVALID_OBJECT(h) (N_MAGIC(h) != OMAGIC)
+#include "util.h"
+#include "st.h"
+
static st_table *sym_tbl;
static st_table *undef_tbl;
@@ -299,7 +323,7 @@ sym_hash(hdrp, syms)
static int
dln_init(prog)
- char *prog;
+ const char *prog;
{
char *file;
int fd;
@@ -352,6 +376,10 @@ dln_init(prog)
while (read(fd, p, 1) == 1) {
if (*p == '\n' || *p == '\t' || *p == ' ') break;
p++;
+ if (p-buf >= MAXPATHLEN) {
+ dln_errno = ENAMETOOLONG;
+ return -1;
+ }
}
*p = '\0';
@@ -446,7 +474,7 @@ struct undef {
static st_table *reloc_tbl = NULL;
static void
link_undef(name, base, reloc)
- char *name;
+ const char *name;
long base;
struct relocation_info *reloc;
{
@@ -476,7 +504,7 @@ link_undef(name, base, reloc)
}
struct reloc_arg {
- char *name;
+ const char *name;
long value;
};
@@ -546,7 +574,7 @@ reloc_undef(no, undef, arg)
static void
unlink_undef(name, value)
- char *name;
+ const char *name;
long value;
{
struct reloc_arg arg;
@@ -579,7 +607,7 @@ static int
load_1(fd, disp, need_init)
int fd;
long disp;
- char *need_init;
+ const char *need_init;
{
static char *libc = LIBC_NAME;
struct exec hdr;
@@ -590,7 +618,7 @@ load_1(fd, disp, need_init)
struct nlist *sym;
struct nlist *end;
int init_p = 0;
- char buf[256];
+ char buf[MAXPATHLEN];
if (load_header(fd, &hdr, disp) == -1) return -1;
if (INVALID_OBJECT(hdr)) {
@@ -814,7 +842,7 @@ load_1(fd, disp, need_init)
for (sym = syms; sym<end; sym++) {
char *name = sym->n_un.n_name;
if (name[0] == '_' && sym->n_value >= block) {
- if (strcmp(name+1, "libs_to_be_linked") == 0) {
+ if (strcmp(name+1, "dln_libs_to_be_linked") == 0) {
libs_to_be_linked = (char**)sym->n_value;
}
else if (strcmp(name+1, buf) == 0) {
@@ -857,11 +885,11 @@ load_1(fd, disp, need_init)
static int target_offset;
static int
search_undef(key, value, lib_tbl)
- char *key;
+ const char *key;
int value;
st_table *lib_tbl;
{
- int offset;
+ long offset;
if (st_lookup(lib_tbl, key, &offset) == 0) return ST_CONTINUE;
target_offset = offset;
@@ -869,15 +897,15 @@ search_undef(key, value, lib_tbl)
}
struct symdef {
- int str_index;
+ int rb_str_index;
int lib_offset;
};
-char *dln_library_path = DLN_DEFAULT_LIB_PATH;
+char *dln_librrb_ary_path = DLN_DEFAULT_LIB_PATH;
static int
load_lib(lib)
- char *lib;
+ const char *lib;
{
char *path, *file;
char armagic[SARMAG];
@@ -904,10 +932,10 @@ load_lib(lib)
/* library search path: */
/* look for environment variable DLN_LIBRARY_PATH first. */
- /* then variable dln_library_path. */
+ /* then variable dln_librrb_ary_path. */
/* if path is still NULL, use "." for path. */
path = getenv("DLN_LIBRARY_PATH");
- if (path == NULL) path = dln_library_path;
+ if (path == NULL) path = dln_librrb_ary_path;
file = dln_find_file(lib, path);
fd = open(file, O_RDONLY);
@@ -936,7 +964,7 @@ load_lib(lib)
base = (struct symdef*)(data + 1);
name_base = (char*)(base + nsym) + sizeof(int);
while (nsym > 0) {
- char *name = name_base + base->str_index;
+ char *name = name_base + base->rb_str_index;
st_insert(lib_tbl, name, base->lib_offset + sizeof(ahdr));
nsym--;
@@ -1014,7 +1042,7 @@ load_lib(lib)
static int
load(file)
- char *file;
+ const char *file;
{
int fd;
int result;
@@ -1040,7 +1068,7 @@ load(file)
void*
dln_sym(name)
- char *name;
+ const char *name;
{
struct nlist *sym;
@@ -1060,26 +1088,34 @@ dln_sym(name)
# endif
#endif
-#ifdef hpux
+#ifdef __hpux
#include <errno.h>
#include "dl.h"
#endif
-#ifdef _AIX
+#if defined(_AIX)
#include <ctype.h> /* for isdigit() */
#include <errno.h> /* for global errno */
#include <sys/ldr.h>
#endif
#ifdef NeXT
-/*#include <mach-o/rld.h>*/
+#if NS_TARGET_MAJOR < 4
+#include <mach-o/rld.h>
+#else
+#include <mach-o/dyld.h>
+#endif
+#endif
+#ifdef __APPLE__
+#include <mach-o/dyld.h>
#endif
-#ifdef _WIN32
+
+#if defined _WIN32 && !defined __CYGWIN__
#include <windows.h>
#endif
-static char *
+static const char *
dln_strerror()
{
#ifdef USE_DLN_A_OUT
@@ -1107,25 +1143,32 @@ dln_strerror()
return (char*)dlerror();
#endif
-#ifdef _WIN32
+#if defined _WIN32 && !defined __CYGWIN__
static char message[1024];
+ int error = GetLastError();
+ char *p = message;
+ p += sprintf(message, "%d: ", error);
FormatMessage(
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
- GetLastError(),
- MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
- message,
- sizeof message,
+ error,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ p,
+ sizeof message - strlen(message),
NULL);
+ for (p = message; *p; p++) {
+ if (*p == '\n' || *p == '\r')
+ *p = ' ';
+ }
return message;
#endif
}
-#ifdef _AIX
+#if defined(_AIX) && ! defined(_IA64)
static void
-aix_loaderror(char *pathname)
+aix_loaderror(const char *pathname)
{
char *message[8], errbuf[1024];
int i,j;
@@ -1151,72 +1194,61 @@ aix_loaderror(char *pathname)
#define LOAD_ERRTAB_LEN (sizeof(load_errtab)/sizeof(load_errtab[0]))
#define ERRBUF_APPEND(s) strncat(errbuf, s, sizeof(errbuf)-strlen(errbuf)-1)
- sprintf(errbuf, "load failed - %.200s ", pathname);
+ snprintf(errbuf, 1024, "load failed - %.200s ", pathname);
if (!loadquery(1, &message[0], sizeof(message)))
ERRBUF_APPEND(strerror(errno));
for(i = 0; message[i] && *message[i]; i++) {
int nerr = atoi(message[i]);
- for (j=0; j<LOAD_ERRTAB_LEN ; j++) {
+ for (j=0; j<LOAD_ERRTAB_LEN; j++) {
if (nerr == load_errtab[i].errno && load_errtab[i].errstr)
ERRBUF_APPEND(load_errtab[i].errstr);
}
- while (isdigit(*message[i])) message[i]++ ;
+ while (isdigit(*message[i])) message[i]++;
ERRBUF_APPEND(message[i]);
ERRBUF_APPEND("\n");
}
errbuf[strlen(errbuf)-1] = '\0'; /* trim off last newline */
- LoadError(errbuf);
+ rb_loaderror(errbuf);
return;
}
#endif
-void
+void*
dln_load(file)
- char *file;
+ const char *file;
{
-#ifdef _WIN32
+#if defined _WIN32 && !defined __CYGWIN__
HINSTANCE handle;
- char winfile[255];
+ char winfile[MAXPATHLEN];
void (*init_fct)();
char buf[MAXPATHLEN];
+ if (strlen(file) >= MAXPATHLEN) rb_loaderror("filename too long");
+
/* Load the file as an object one */
init_funcname(buf, file);
-#ifdef __CYGWIN32__
- cygwin32_conv_to_win32_path(file, winfile);
-#else
strcpy(winfile, file);
-#endif
/* Load file */
if ((handle =
LoadLibraryExA(winfile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)) == NULL) {
- printf("LoadLibraryExA\n");
goto failed;
}
-#ifdef __CYGWIN32__
- init_fct = (void(*)())GetProcAddress(handle, "impure_setup");
-
- if (init_fct)
- init_fct(_impure_ptr);
-#endif
-
if ((init_fct = (void(*)())GetProcAddress(handle, buf)) == NULL) {
- printf("GetProcAddress %s\n", buf);
- goto failed;
+ rb_loaderror("%s - %s\n%s", dln_strerror(), buf, file);
}
/* Call the init code */
(*init_fct)();
- return;
+ return handle;
#else
#ifdef USE_DLN_A_OUT
if (load(file) == -1) {
goto failed;
}
- return;
+ return 0;
#else
char buf[MAXPATHLEN];
@@ -1229,28 +1261,29 @@ dln_load(file)
void *handle;
void (*init_fct)();
-# ifndef RTLD_LAZY
-# define RTLD_LAZY 1
-# endif
-# ifndef RTLD_GLOBAL
-# define RTLD_GLOBAL 0
-# endif
+#ifndef RTLD_LAZY
+# define RTLD_LAZY 1
+#endif
+#ifndef RTLD_GLOBAL
+# define RTLD_GLOBAL 0
+#endif
/* Load file */
- if ((handle = dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == NULL) {
+ if ((handle = (void*)dlopen(file, RTLD_LAZY|RTLD_GLOBAL)) == NULL) {
goto failed;
}
if ((init_fct = (void(*)())dlsym(handle, buf)) == NULL) {
+ dlclose(handle);
goto failed;
}
/* Call the init code */
(*init_fct)();
- return;
+ return handle;
}
#endif /* USE_DLN_DLOPEN */
-#ifdef hpux
+#ifdef __hpux
#define DLN_DEFINED
{
shl_t lib = NULL;
@@ -1260,37 +1293,40 @@ dln_load(file)
flags = BIND_DEFERRED;
lib = shl_load(file, flags, 0);
if (lib == NULL) {
- rb_sys_fail(file);
+ extern int errno;
+ rb_loaderror("%s - %s", strerror(errno), file);
}
shl_findsym(&lib, buf, TYPE_PROCEDURE, (void*)&init_fct);
if (init_fct == NULL) {
shl_findsym(&lib, buf, TYPE_UNDEFINED, (void*)&init_fct);
if (init_fct == NULL) {
- extern int errno;
errno = ENOSYM;
- rb_sys_fail(file);
+ rb_loaderror("%s - %s", strerror(ENOSYM), file);
}
}
(*init_fct)();
- return;
+ return (void*)lib;
}
#endif /* hpux */
-#ifdef _AIX
+#if defined(_AIX) && ! defined(_IA64)
#define DLN_DEFINED
{
void (*init_fct)();
- init_fct = (void(*)())load(file, 1, 0);
+ init_fct = (void(*)())load((char*)file, 1, 0);
if (init_fct == NULL) {
aix_loaderror(file);
}
+ if (loadbind(0, (void*)dln_load, (void*)init_fct) == -1) {
+ aix_loaderror(file);
+ }
(*init_fct)();
- return;
+ return (void*)init_fct;
}
#endif /* _AIX */
-#ifdef NeXT
+#if defined(NeXT) || defined(__APPLE__)
#define DLN_DEFINED
/*----------------------------------------------------
By SHIROYAMA Takayuki Psi@fortune.nest.or.jp
@@ -1300,6 +1336,8 @@ dln_load(file)
Mi hisho@tasihara.nest.or.jp,
and... Miss ARAI Akino(^^;)
----------------------------------------------------*/
+#if defined(NeXT) && (NS_TARGET_MAJOR < 4)/* NeXTSTEP rld functions */
+
{
unsigned long init_address;
char *object_files[2] = {NULL, NULL};
@@ -1310,12 +1348,12 @@ dln_load(file)
/* Load object file, if return value ==0 , load failed*/
if(rld_load(NULL, NULL, object_files, NULL) == 0) {
- LoadError("Failed to load %.200s", file);
+ rb_loaderror("Failed to load %.200s", file);
}
/* lookup the initial function */
if(rld_lookup(NULL, buf, &init_address) == 0) {
- LoadError("Failed to lookup Init function %.200s",file);
+ rb_loaderror("Failed to lookup Init function %.200s", file);
}
/* Cannot call *init_address directory, so copy this value to
@@ -1323,10 +1361,136 @@ dln_load(file)
init_fct = (void(*)())init_address;
(*init_fct)();
- return ;
+ return (void*)init_address;
}
+#else/* OPENSTEP dyld functions */
+ {
+ int dyld_result;
+ NSObjectFileImage obj_file; /* handle, but not use it */
+ /* "file" is module file name .
+ "buf" is initial function name with "_" . */
+
+ void (*init_fct)();
+
+
+ dyld_result = NSCreateObjectFileImageFromFile(file, &obj_file);
+
+ if (dyld_result != NSObjectFileImageSuccess) {
+ rb_loaderror("Failed to load %.200s", file);
+ }
+
+ NSLinkModule(obj_file, file, TRUE);
+
+ /* lookup the initial function */
+ /*NSIsSymbolNameDefined require function name without "_" */
+ if(NSIsSymbolNameDefined(buf + 1)) {
+ rb_loaderror("Failed to lookup Init function %.200s",file);
+ }
+
+ /* NSLookupAndBindSymbol require function name with "_" !! */
+ init_fct = NSAddressOfSymbol(NSLookupAndBindSymbol(buf));
+ (*init_fct)();
+
+ return (void*)init_fct;
+ }
+#endif /* rld or dyld */
#endif
+#ifdef __BEOS__
+# define DLN_DEFINED
+ {
+ status_t err_stat; /* BeOS error status code */
+ image_id img_id; /* extention module unique id */
+ void (*init_fct)(); /* initialize function for extention module */
+
+ /* load extention module */
+ img_id = load_add_on(file);
+ if (img_id <= 0) {
+ rb_loaderror("Failed to load %.200s", file);
+ }
+
+ /* find symbol for module initialize function. */
+ /* The Be Book KernelKit Images section described to use
+ B_SYMBOL_TYPE_TEXT for symbol of function, not
+ B_SYMBOL_TYPE_CODE. Why ? */
+ /* strcat(init_fct_symname, "__Fv"); */ /* parameter nothing. */
+ /* "__Fv" dont need! The Be Book Bug ? */
+ err_stat = get_image_symbol(img_id, buf,
+ B_SYMBOL_TYPE_TEXT, (void **)&init_fct);
+
+ if (err_stat != B_NO_ERROR) {
+ char real_name[MAXPATHLEN];
+
+ strcpy(real_name, buf);
+ strcat(real_name, "__Fv");
+ err_stat = get_image_symbol(img_id, real_name,
+ B_SYMBOL_TYPE_TEXT, (void **)&init_fct);
+ }
+
+ if ((B_BAD_IMAGE_ID == err_stat) || (B_BAD_INDEX == err_stat)) {
+ unload_add_on(img_id);
+ rb_loaderror("Failed to lookup Init function %.200s", file);
+ }
+ else if (B_NO_ERROR != err_stat) {
+ char errmsg[] = "Internal of BeOS version. %.200s (symbol_name = %s)";
+ unload_add_on(img_id);
+ rb_loaderror(errmsg, strerror(err_stat), buf);
+ }
+
+ /* call module initialize function. */
+ (*init_fct)();
+ return (void*)img_id;
+ }
+#endif /* __BEOS__*/
+
+#ifdef __MACOS__
+# define DLN_DEFINED
+ {
+ OSErr err;
+ FSSpec libspec;
+ CFragConnectionID connID;
+ Ptr mainAddr;
+ char errMessage[1024];
+ Boolean isfolder, didsomething;
+ Str63 fragname;
+ Ptr symAddr;
+ CFragSymbolClass class;
+ void (*init_fct)();
+ char fullpath[MAXPATHLEN];
+
+ strcpy(fullpath, file);
+
+ /* resolve any aliases to find the real file */
+ c2pstr(fullpath);
+ (void)FSMakeFSSpec(0, 0, fullpath, &libspec);
+ err = ResolveAliasFile(&libspec, 1, &isfolder, &didsomething);
+ if (err) {
+ rb_loaderror("Unresolved Alias - %s", file);
+ }
+
+ /* Load the fragment (or return the connID if it is already loaded */
+ fragname[0] = 0;
+ err = GetDiskFragment(&libspec, 0, 0, fragname,
+ kLoadCFrag, &connID, &mainAddr,
+ errMessage);
+ if (err) {
+ p2cstr(errMessage);
+ rb_loaderror("%s - %s",errMessage , file);
+ }
+
+ /* Locate the address of the correct init function */
+ c2pstr(buf);
+ err = FindSymbol(connID, buf, &symAddr, &class);
+ if (err) {
+ rb_loaderror("Unresolved symbols - %s" , file);
+ }
+
+ init_fct = (void (*)())symAddr;
+ (*init_fct)();
+ return (void*)init_fct;
+ }
+#endif /* __MACOS__ */
+
#ifndef DLN_DEFINED
rb_notimplement("dynamic link not supported");
#endif
@@ -1335,7 +1499,7 @@ dln_load(file)
#endif
#if !defined(_AIX) && !defined(NeXT)
failed:
- LoadError("%s - %s", dln_strerror(), file);
+ rb_loaderror("%s - %s", dln_strerror(), file);
#endif
}
@@ -1343,35 +1507,47 @@ static char *dln_find_1();
char *
dln_find_exe(fname, path)
- char *fname;
- char *path;
+ const char *fname;
+ const char *path;
{
+ if (!path) {
#if defined(__human68k__)
- if (!path)
path = getenv("path");
- if (!path)
+#else
+ path = getenv("PATH");
+#endif
+ }
+
+ if (!path) {
+#if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__MACOS__)
path = "/usr/local/bin;/usr/ucb;/usr/bin;/bin;.";
#else
- if (!path) path = getenv("PATH");
- if (!path) path = "/usr/local/bin:/usr/ucb:/usr/bin:/bin:.";
+ path = "/usr/local/bin:/usr/ucb:/usr/bin:/bin:.";
#endif
+ }
return dln_find_1(fname, path, 1);
}
char *
dln_find_file(fname, path)
- char *fname;
- char *path;
+ const char *fname;
+ const char *path;
{
+#ifndef __MACOS__
if (!path) path = ".";
return dln_find_1(fname, path, 0);
+#else
+ if (!path) path = ".";
+ return _macruby_path_conv_posix_to_macos(dln_find_1(fname, path, 0));
+#endif
}
#if defined(__CYGWIN32__)
-char *
-conv_to_posix_path(win32, posix)
+const char *
+conv_to_posix_path(win32, posix, len)
char *win32;
char *posix;
+ int len;
{
char *first = win32;
char *p = win32;
@@ -1386,7 +1562,10 @@ conv_to_posix_path(win32, posix)
first = p + 1;
*p = ';';
}
- cygwin32_conv_to_posix_path(first, posix);
+ if (len < strlen(first))
+ fprintf(stderr, "PATH length too long: %s\n", first);
+ else
+ cygwin32_conv_to_posix_path(first, posix);
return dst;
}
#endif
@@ -1402,21 +1581,22 @@ dln_find_1(fname, path, exe_flag)
register char *dp;
register char *ep;
register char *bp;
+#ifndef __MACOS__
struct stat st;
-
-#if defined(__CYGWIN32__)
- char rubypath[MAXPATHLEN];
- conv_to_posix_path(path, rubypath);
- path = rubypath;
+#else
+ const char* mac_fullpath;
#endif
+
if (fname[0] == '/') return fname;
if (strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0)
return fname;
-#if defined(MSDOS) || defined(NT) || defined(__human68k__)
+ if (exe_flag && strchr(fname, '/')) return fname;
+#if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__EMX__)
if (fname[0] == '\\') return fname;
- if (fname[1] == ':') return fname;
+ if (strlen(fname) > 2 && fname[1] == ':') return fname;
if (strncmp(".\\", fname, 2) == 0 || strncmp("..\\", fname, 3) == 0)
return fname;
+ if (exe_flag && strchr(fname, '\\')) return fname;
#endif
for (dp = path;; dp = ++ep) {
@@ -1425,11 +1605,7 @@ dln_find_1(fname, path, exe_flag)
int fspace;
/* extract a component */
-#if !defined(MSDOS) && !defined(NT) && !defined(__human68k__)
- ep = strchr(dp, ':');
-#else
- ep = strchr(dp, ';');
-#endif
+ ep = strchr(dp, PATH_SEP[0]);
if (ep == NULL)
ep = dp+strlen(dp);
@@ -1446,7 +1622,11 @@ dln_find_1(fname, path, exe_flag)
** take the path literally.
*/
- if (*dp == '~' && (l == 1 || dp[1] == '/')) {
+ if (*dp == '~' && (l == 1 ||
+#if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__EMX__)
+ dp[1] == '\\' ||
+#endif
+ dp[1] == '/')) {
char *home;
home = getenv("HOME");
@@ -1484,12 +1664,20 @@ dln_find_1(fname, path, exe_flag)
}
memcpy(bp, fname, i + 1);
+#ifndef __MACOS__
if (stat(fbuf, &st) == 0) {
if (exe_flag == 0) return fbuf;
/* looking for executable */
if (eaccess(fbuf, X_OK) == 0) return fbuf;
}
-#if defined(MSDOS) || defined(NT) || defined(__human68k__)
+#else
+ if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf)) {
+ if (exe_flag == 0) return mac_fullpath;
+ /* looking for executable */
+ if (eaccess(mac_fullpath, X_OK) == 0) return mac_fullpath;
+ }
+#endif
+#if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__EMX__)
if (exe_flag) {
static const char *extension[] = {
#if defined(MSDOS)
@@ -1497,8 +1685,12 @@ dln_find_1(fname, path, exe_flag)
#if defined(DJGPP)
".btm", ".sh", ".ksh", ".pl", ".sed",
#endif
+#elif defined(__EMX__) || defined(NT)
+ ".exe", ".com", ".cmd", ".bat",
+/* end of __EMX__ or NT*/
#else
".r", ".R", ".x", ".X", ".bat", ".BAT",
+/* __human68k__ */
#endif
(char *) NULL
};
@@ -1512,11 +1704,16 @@ dln_find_1(fname, path, exe_flag)
continue;
}
strcpy(bp + i, extension[j]);
+#ifndef __MACOS__
if (stat(fbuf, &st) == 0)
return fbuf;
+#else
+ if (mac_fullpath = _macruby_exist_file_in_libdir_as_posix_name(fbuf))
+ return mac_fullpath;
+#endif
}
}
-#endif /* MSDOS or NT or __human68k__ */
+#endif /* MSDOS or NT or __human68k__ or __EMX__ */
/* if not, and no other alternatives, life is bleak */
if (*ep == '\0') {
return NULL;
diff --git a/dln.h b/dln.h
index 7af1f63a9d..c29d3bd8e9 100644
--- a/dln.h
+++ b/dln.h
@@ -1,30 +1,33 @@
-/************************************************
+/**********************************************************************
dln.h -
$Author$
- $Revision$
$Date$
created at: Wed Jan 19 16:53:09 JST 1994
-************************************************/
+ Copyright (C) 1993-2000 Yukihiro Matsumoto
+
+**********************************************************************/
+
#ifndef DLN_H
#define DLN_H
#ifndef _
#ifndef __STDC__
# define _(args) ()
+# define const
#else
# define _(args) args
#endif
#endif
-char *dln_find_exe _((char*,char*));
-char *dln_find_file _((char*,char*));
+char *dln_find_exe _((const char*,const char*));
+char *dln_find_file _((const char*,const char*));
#ifdef USE_DLN_A_OUT
extern char *dln_argv0;
#endif
-void dln_load _((char*));
+void *dln_load _((const char*));
#endif
diff --git a/doc/forwardable.rd b/doc/forwardable.rd
new file mode 100644
index 0000000000..7272c374b6
--- /dev/null
+++ b/doc/forwardable.rd
@@ -0,0 +1,84 @@
+ -- forwardable.rb
+
+ $Release Version: 1.1 $
+ $Revision$
+ $Date$
+ Original version by Tosh
+
+=begin
+
+= Forwardable
+
+A Module to define delegations for selected methods to a class.
+
+== Usage
+
+Using through extending the class.
+
+ class Foo
+ extend Forwardable
+
+ def_delegators("@out", "printf", "print")
+ def_delegators(:@in, :gets)
+ def_delegator(:@contents, :[], "content_at")
+ end
+ f = Foo.new
+ f.printf ...
+ f.gets
+ f.content_at(1)
+
+== Methods
+
+--- Forwardable#def_instance_delegators(accessor, *methods)
+
+ adding the delegations for each method of ((|methods|)) to
+ ((|accessor|)).
+
+--- Forwardable#def_instance_delegator(accessor, method, ali = method)
+
+ adding the delegation for ((|method|)) to ((|accessor|)). When
+ you give optional argument ((|ali|)), ((|ali|)) is used as the
+ name of the delegation method, instead of ((|method|)).
+
+--- Forwardable#def_delegators(accessor, *methods)
+
+ the alias of ((|Forwardable#def_instance_delegators|)).
+
+--- Forwardable#def_delegator(accessor, method, ali = method)
+
+ the alias of ((|Forwardable#def_instance_delegator|)).
+
+= SingleForwardable
+
+a Module to define delegations for selected methods to an object.
+
+== Usage
+
+Using through extending the object.
+
+ g = Goo.new
+ g.extend SingleForwardable
+ g.def_delegator("@out", :puts)
+ g.puts ...
+
+== Methods
+
+--- SingleForwardable#def_singleton_delegators(accessor, *methods)
+
+ adding the delegations for each method of ((|methods|)) to
+ ((|accessor|)).
+
+--- SingleForwardable#def_singleton_delegator(accessor, method, ali = method)
+
+ adding the delegation for ((|method|)) to ((|accessor|)). When
+ you give optional argument ((|ali|)), ((|ali|)) is used as the
+ name of the delegation method, instead of ((|method|)).
+
+--- SingleForwardable#def_delegators(accessor, *methods)
+
+ the alias of ((|SingleForwardable#def_instance_delegators|)).
+
+--- SingleForwardable#def_delegator(accessor, method, ali = method)
+
+ the alias of ((|SingleForwardable#def_instance_delegator|)).
+=end
diff --git a/doc/forwardable.rd.jp b/doc/forwardable.rd.jp
new file mode 100644
index 0000000000..d928fddc5e
--- /dev/null
+++ b/doc/forwardable.rd.jp
@@ -0,0 +1,81 @@
+ -- forwatable.rb
+ $Release Version: 1.1 $
+ $Revision$
+ $Date$
+
+=begin
+= Forwardable
+
+¥¯¥é¥¹¤ËÂФ·¥á¥½¥Ã¥É¤Î°Ñ¾ùµ¡Ç½¤òÄêµÁ¤·¤Þ¤¹.
+
+== »È¤¤Êý
+
+¥¯¥é¥¹¤ËÂФ·¤Æextend¤·¤Æ»È¤¤¤Þ¤¹.
+
+ class Foo
+ extend Forwardable
+
+ def_delegators("@out", "printf", "print")
+ def_delegators(:@in, :gets)
+ def_delegator(:@contents, :[], "content_at")
+ end
+ f = Foo.new
+ f.printf ...
+ f.gets
+ f.content_at(1)
+
+== ¥á¥½¥Ã¥É
+
+--- Forwardable#def_instance_delegators(accessor, *methods)
+
+ ((|methods|))¤ÇÅϤµ¤ì¤¿¥á¥½¥Ã¥É¤Î¥ê¥¹¥È¤ò((|accessor¤Ë|))°Ñ¾ù¤¹¤ë
+ ¤è¤¦¤Ë¤·¤Þ¤¹.
+
+--- Forwardable#def_instance_delegator(accessor, method, ali = method)
+
+ ((||method|))¤ÇÅϤµ¤ì¤¿¥á¥½¥Ã¥É¤ò((|accessor|))¤Ë°Ñ¾ù¤¹¤ë¤è¤¦¤Ë¤·
+ ¤Þ¤¹. ((|ali|))¤¬°ú¿ô¤È¤·¤ÆÅϤµ¤ì¤¿¤È¤­¤Ï, ¥á¥½¥Ã¥É((|ali|))¤¬¸Æ¤Ð
+ ¤ì¤¿¤È¤­¤Ë¤Ï, ((|accessor|))¤ËÂФ·((|method|))¤ò¸Æ¤Ó½Ð¤·¤Þ¤¹.
+
+--- Forwardable#def_delegators(accessor, *methods)
+
+ ((|Forwardable#def_instance_delegators|))¤ÎÊÌ̾¤Ç¤¹.
+
+--- Forwardable#def_delegator(accessor, method, ali = method)
+
+ ((|Forwardable#def_instance_delegator|))¤ÎÊÌ̾¤Ç¤¹.
+
+= SingleForwardable
+
+¥ª¥Ö¥¸¥§¥¯¥È¤ËÂФ·, ¥á¥½¥Ã¥É¤Î°Ñ¾ùµ¡Ç½¤òÄêµÁ¤·¤Þ¤¹.
+
+== »È¤¤Êý
+
+¥ª¥Ö¥¸¥§¥¯¥È¤ËÂФ·¤Æ((|extend|))¤·¤Æ»È¤¤¤Þ¤¹.
+
+ g = Goo.new
+ g.extend SingleForwardable
+ g.def_delegator("@out", :puts)
+ g.puts ...
+
+== ¥á¥½¥Ã¥É
+
+--- SingleForwardable#def_singleton_delegators(accessor, *methods)
+
+ ((|methods|))¤ÇÅϤµ¤ì¤¿¥á¥½¥Ã¥É¤Î¥ê¥¹¥È¤ò((|accessor|))¤Ë°Ñ¾ù¤¹¤ë
+ ¤è¤¦¤Ë¤·¤Þ¤¹.
+
+--- SingleForwardable#def_singleton_delegator(accessor, method, ali = method)
+
+ ((|method|))¤ÇÅϤµ¤ì¤¿¥á¥½¥Ã¥É¤ò((|accessor|))¤Ë°Ñ¾ù¤¹¤ë¤è¤¦¤Ë¤·¤Þ
+ ¤¹. ((|ali|))¤¬°ú¿ô¤È¤·¤ÆÅϤµ¤ì¤¿¤È¤­¤Ï, ¥á¥½¥Ã¥É((|ali|))¤¬¸Æ¤Ð¤ì
+ ¤¿¤È¤­¤Ë¤Ï, ((|accessor|))¤ËÂФ·((|method|))¤ò¸Æ¤Ó½Ð¤·¤Þ¤¹.
+
+--- SingleForwardable#def_delegators(accessor, *methods)
+
+ ((|SingleForwardable#def_singleton_delegators|))¤ÎÊÌ̾¤Ç¤¹.
+
+--- SingleForwardable#def_delegator(accessor, method, ali = method)
+
+ ((|SingleForwardable#def_singleton_delegator|))¤ÎÊÌ̾¤Ç¤¹.
+=end
diff --git a/doc/irb/irb-tools.rd.jp b/doc/irb/irb-tools.rd.jp
new file mode 100644
index 0000000000..64d9ab29c8
--- /dev/null
+++ b/doc/irb/irb-tools.rd.jp
@@ -0,0 +1,185 @@
+irb´ØÏ¢¤ª¤Þ¤±¥³¥Þ¥ó¥É¤È¥é¥¤¥Ö¥é¥ê
+ $Release Version: 0.7.1 $
+ $Revision$
+ $Date$
+ by Keiju ISHITSUKA(Nihon Rational Co.,Ltd.)
+
+=begin
+
+:¥³¥Þ¥ó¥É:
+* rtags -- ruby tags command
+
+:´Ø¿ô¥é¥¤¥Ö¥é¥ê:
+* xmp -- irb version of gotoken xmp-function
+
+:¥¯¥é¥¹¥é¥¤¥Ö¥é¥ê:
+* frame.rb -- frame tracer
+* completion.rb -- irb completor
+
+= rtags
+
+rtags¤ÏemacsµÚ¤ÓviÍѤÎ, TAG¥Õ¥¡¥¤¥ë¤ò¤Ä¤¯¤ë¥³¥Þ¥ó¥É¤Ç¤¹.
+
+== »È¤¤Êý
+
+ rtags [-vi] file....
+
+¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯¥È¥ê¤ËemacsÍѤÎTAGS¥Õ¥¡¥¤¥ë¤¬¤Ç¤­¤Þ¤¹. -vi¥ª¥×¥·¥ç¥ó¤ò
+¤Ä¤±¤¿»þ¤Ë¤ÏviÍѤÎtags¥Õ¥¡¥¤¥ë¤òºîÀ®¤·¤Þ¤¹.
+
+emacs¤Î¾ì¹ç, Ä̾ï¤Îetags.el¤¬¤½¤Î¤Þ¤Þ»È¤¨¤Þ¤¹. ¸¡º÷²Äǽ¤Ê¤Î¤Ï,
+
+* ¥¯¥é¥¹
+* ¥á¥½¥Ã¥É
+* ÆÃ°Û¥á¥½¥Ã¥É
+* alias
+* attr¤ÇÀë¸À¤µ¤ì¤¿¥¢¥¯¥»¥µ(¥Ñ¥é¥á¡¼¥¿¤¬¥·¥ó¥Ü¥ë¤«Ê¸»úÎó¥ê¥Æ¥é¥ë¤Ë¸Â¤ë)
+* attr_XXX¤ÇÀë¸À¤µ¤ì¤¿¥¢¥¯¥»¥µ(¥Ñ¥é¥á¡¼¥¿¤¬¥·¥ó¥Ü¥ë¤«Ê¸»úÎó¥ê¥Æ¥é¥ë¤Ë¸Â¤ë)
+
+¤Ç¤¹.
+
+C¤Ê¤É¤Ç»È¤Ã¤Æ¤¤¤ë¤Î¤È°ã¤¦¤Î¤Ï, ¥³¥ó¥×¥ê¡¼¥·¥ç¥ó¤Ë´Ø¤¹¤ëÉôʬ¤Ç,
+
+´Ø¿ô̾¤Ï,
+
+ ´Ø¿ô̾(
+
+¥¯¥é¥¹¤Ï,
+
+ ::¥¯¥é¥¹Ì¾::....::¥¯¥é¥¹Ì¾
+
+¥á¥½¥Ã¥É¤Ï,
+
+ ::¥¯¥é¥¹Ì¾::....::¥¯¥é¥¹Ì¾#¥á¥½¥Ã¥É̾
+
+ÆÃ°Û¥á¥½¥Ã¥É(¥¯¥é¥¹¥á¥½¥Ã¥É)¤Ï
+
+ ::¥¯¥é¥¹Ì¾::....::¥¯¥é¥¹Ì¾.¥á¥½¥Ã¥É̾
+
+¤Ç¥³¥ó¥×¥ê¡¼¥·¥ç¥ó¤ò¹Ô¤Ê¤¦¤È¤³¤í¤Ç¤¹.
+
+= xmp.rb
+
+¤´¤È¤±¤óxmp¤Î¾å°Ì¸ß´¹¥Ð¡¼¥¸¥ç¥ó¤Ç¤¹. ¤¿¤À, Èó¾ï¤Ë½Å¤¤¤Î¤Ç¤´¤È¤±¤óxmp¤Ç
+¤ÏÂбþ¤Ç¤­¤Ê¤¤»þ¤Ë, »ÈÍѤ¹¤ë¤ÈÎɤ¤¤Ç¤·¤ç¤¦.
+
+== »È¤¤Êý
+
+=== ´Ø¿ô¤È¤·¤Æ»È¤¦.
+
+ require "irb/xmp"
+ xmp <<END
+ foo = 1
+ foo
+ END
+ ---
+ foo = 1
+ ==>1
+ foo
+ ==>1
+
+=== XMP¥¤¥ó¥¹¥¿¥ó¥¹¤òÍѤ¤¤ë.
+
+¤³¤Î¾ì¹ç¤Ï, XMP¤¬¥³¥ó¥Æ¥­¥¹¥È¾ðÊó¤ò»ý¤Ä¤Î¤Ç, ÊÑ¿ô¤ÎÃͤʤɤòÊÝ»ý¤·¤Æ¤¤
+¤Þ¤¹.
+
+ require "irb/xmp"
+ xmp = XMP.new
+ xmp.puts <<END
+ foo = 1
+ foo
+ END
+ xmp.puts <<END
+ foo
+ END
+ ===
+ foo = 1
+ ==>1
+ foo
+ ==>1
+ foo
+ ==>1
+
+== ¥³¥ó¥Æ¥­¥¹¥È¤Ë´Ø¤·¤Æ
+
+XMP¥á¥½¥Ã¥É·²¤Î¥³¥ó¥Æ¥­¥¹¥È¤Ï, ¸Æ¤Ó½Ð¤¹Á°¤Î¥³¥ó¥Æ¥­¥¹¥È¤Çɾ²Á¤µ¤ì¤Þ¤¹.
+ÌÀ¼¨Åª¤Ë¥³¥ó¥Æ¥­¥¹¥È¤ò»ØÄꤹ¤ë¤È¤½¤Î¥³¥ó¥Æ¥­¥¹¥È¤Çɾ²Á¤·¤Þ¤¹.
+
+Îã:
+
+ xmp "foo", an_binding
+
+:Ãí:
+¥Þ¥ë¥Á¥¹¥ì¥Ã¥É¤Ë¤ÏÂбþ¤·¤Æ¤¤¤Þ¤»¤ó.
+
+= frame.rb
+¸½ºß¼Â¹ÔÃæ¤Î¥Õ¥ì¡¼¥à¾ðÊó¤ò¼è¤ê°·¤¦¤¿¤á¤Î¥¯¥é¥¹¤Ç¤¹.
+
+* IRB::Frame.top(n = 0)
+ ¾å¤«¤énÈÖÌܤΥ³¥ó¥Æ¥­¥¹¥È¤ò¼è¤ê½Ð¤·¤Þ¤¹. n¤Ï0¤¬ºÇ¾å°Ì¤Ë¤Ê¤ê¤Þ¤¹.
+* IRB::Frame.bottom(n = 0)
+ ²¼¤«¤énÈÖÌܤΥ³¥ó¥Æ¥­¥¹¥È¤ò¼è¤ê½Ð¤·¤Þ¤¹. n¤Ï0¤¬ºÇ²¼°Ì¤Ë¤Ê¤ê¤Þ¤¹.
+* IRB::Frame.sender
+ ¥»¥ó¥À¤Ë¤Ê¤Ã¤Æ¤¤¤ë¥ª¥Ö¥¸¥§¥¯¥È¤ò¼è¤ê½Ð¤·¤Þ¤¹. ¥»¥ó¥À¤È¤Ï, ¤½¤Î¥á¥½¥Ã
+ ¥É¤ò¸Æ¤Ó½Ð¤·¤¿Â¦¤Îself¤Î¤³¤È¤Ç¤¹.
+
+:Ãí:
+set_trace_func¤òÍѤ¤¤ÆRuby¤Î¼Â¹Ô¤ò¥È¥ì¡¼¥¹¤·¤Æ¤¤¤Þ¤¹. ¥Þ¥ë¥Á¥¹¥ì¥Ã¥É¤Ë
+¤ÏÂбþ¤·¤Æ¤¤¤Þ¤»¤ó.
+
+= completion.rb
+irb¤Îcompletionµ¡Ç½¤òÄ󶡤¹¤ë¤â¤Î¤Ç¤¹.
+
+== »È¤¤Êý
+
+ % irb -r irb/completion
+
+¤È¤¹¤ë¤«, ~/.irbrc Ãæ¤Ë
+
+ require "irb/completion"
+
+¤òÆþ¤ì¤Æ¤¯¤À¤µ¤¤. irb¼Â¹ÔÃæ¤Ë require "irb/completion" ¤·¤Æ¤â¤è¤¤¤Ç¤¹.
+
+irb¼Â¹ÔÃæ¤Ë (TAB) ¤ò²¡¤¹¤È¥³¥ó¥×¥ì¡¼¥·¥ç¥ó¤·¤Þ¤¹.
+
+¥È¥Ã¥×¥ì¥Ù¥ë¤Ç(TAB)¤ò²¡¤¹¤È¤¹¤Ù¤Æ¤Î¹½Ê¸Í×ÁÇ, ¥¯¥é¥¹, ¥á¥½¥Ã¥É¤Î¸õÊ䤬¤Ç
+¤Þ¤¹. ¸õÊ䤬ͣ°ì¤Ê¤é¤Ð´°Á´¤ËÊä´°¤·¤Þ¤¹.
+
+ irb(main):001:0> in
+ in inspect instance_eval
+ include install_alias_method instance_of?
+ initialize install_aliases instance_variables
+ irb(main):001:0> inspect
+ "main"
+ irb(main):002:0> foo = Object.new
+ #<Object:0x4027146c>
+
+ ((|ÊÑ¿ô̾.|))¤Î¸å¤Ë(TAB)¤ò²¡¤¹¤È, ¤½¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Î¥á¥½¥Ã¥É°ìÍ÷¤¬¤Ç¤Þ
+ ¤¹.
+
+ irb(main):003:0> foo.
+ foo.== foo.frozen? foo.protected_methods
+ foo.=== foo.hash foo.public_methods
+ foo.=~ foo.id foo.respond_to?
+ foo.__id__ foo.inspect foo.send
+ foo.__send__ foo.instance_eval foo.singleton_methods
+ foo.class foo.instance_of? foo.taint
+ foo.clone foo.instance_variables foo.tainted?
+ foo.display foo.is_a? foo.to_a
+ foo.dup foo.kind_of? foo.to_s
+ foo.eql? foo.method foo.type
+ foo.equal? foo.methods foo.untaint
+ foo.extend foo.nil?
+ foo.freeze foo.private_methods
+
+=end
+
+% Begin Emacs Environment
+% Local Variables:
+% mode: text
+% comment-column: 0
+% comment-start: "%"
+% comment-end: "\n"
+% End:
+%
+
diff --git a/doc/irb/irb.rd b/doc/irb/irb.rd
new file mode 100644
index 0000000000..528e5e17fb
--- /dev/null
+++ b/doc/irb/irb.rd
@@ -0,0 +1,377 @@
+irb -- interactive ruby
+ $Release Version: 0.5 $
+ $Revision$
+ $Date$
+ by Keiju ISHITSUKA(keiju@ishitsuka.com)
+ translate from japanese by gotoken-san
+
+=begin
+= What is irb?
+
+irb stands for `interactive ruby'. irb is a tool to execute interactively
+ruby expressions read from stdin.
+
+= Invoking
+
+ % ruby -r irb -e0
+ % irb
+
+Either of the aboves. In the former style, options can be specified
+as follows:
+
+ % ruby -r irb -e0 -- -v
+
+= Usage
+
+Use of irb is easy if you know ruby. Executing irb, prompts are
+displayed as follows. Then, enter expression of ruby. A input is
+executed when it is syntacticaly completed.
+
+ dim% irb
+ irb(main):001:0> 1+2
+ 3
+ irb(main):002:0> class Foo
+ irb(main):003:1> def foo
+ irb(main):004:2> print 1
+ irb(main):005:2> end
+ irb(main):006:1> end
+ nil
+ irb(main):007:0>
+
+And, Readline extesion module can be used with irb. Using Readline
+is the standard default action if Readline is installed.
+
+= Command line option
+
+ irb.rb [options] file_name opts
+ options:
+ -f suppress read ~/.irbrc
+ -m bc mode (fraction or matrix are available)
+ -d set $DEBUG to true (same as `ruby -d')
+ -r load-module same as `ruby -r'
+ --inspect uses `inspect' for output (the default except bc mode)
+ --noinspect doesn't uses inspect for output
+ --readline uses Readline extension module
+ --noreadline doesn't use Readline extension module
+ --prompt prompt-mode
+ --prompt-mode prompt-mode
+ switches prompt mode. Pre-defined prompt modes are
+ `defalut', `simple', `xmp' and `inf-ruby'
+
+ --inf-ruby-mode uses prompt appreciate for inf-ruby-mode on emacs.
+ Suppresses --readline.
+ --simple-prompt simple prompt mode
+ --noprompt no prompt
+ --tracer display trace for each execution of commands.
+ --back-trace-limit n
+ displayes backtrace top n and tail n. The default
+ value is 16.
+ --irb_debug n sets internal debug level to n (It shouldn't be used)
+ -v, --version prints the version of irb
+
+
+
+= Configurations
+
+irb reads `~/.irbrc' when it is invoked. If `~/.irbrb' doesn't exist
+irb try to read in the order `.irbrc', `irb.rc', `_irbrc' then `$irbrc'.
+
+The following is altanative to the command line option. To use them
+type as follows in an irb session.
+
+ IRB.conf[:IRB_NAME]="irb"
+ IRB.conf[:MATH_MODE]=false
+ IRB.conf[:USE_TRACER]=false
+ IRB.conf[:USE_LOADER]=false
+ IRB.conf[:IGNORE_SIGINT]=true
+ IRB.conf[:IGNORE_EOF]=false
+ IRB.conf[:INSPECT_MODE]=nil
+ IRB.conf[:IRB_RC] = nil
+ IRB.conf[:BACK_TRACE_LIMIT]=16
+ IRB.conf[:USE_LOADER] = false
+ IRB.conf[:USE_READLINE] = nil
+ IRB.conf[:USE_TRACER] = false
+ IRB.conf[:IGNORE_SIGINT] = true
+ IRB.conf[:IGNORE_EOF] = false
+ IRB.conf[:PROMPT_MODE] = :DEFALUT
+ IRB.conf[:PROMPT] = {...}
+ IRB.conf[:DEBUG_LEVEL]=0
+ IRB.conf[:VERBOSE]=true
+
+== Customizing prompt
+
+To costomize the prompt you set a variable
+
+ IRB.conf[:PROMPT]
+
+For example, describe as follows in `.irbrc'.
+
+ IRB.conf[:PROMPT][:MY_PROMPT] = { # name of prompt mode
+ :PROMPT_I => nil, # normal prompt
+ :PROMPT_S => nil, # prompt for continuated strings
+ :PROMPT_C => nil, # prompt for continuated statement
+ :RETURN => " ==>%s\n" # format to return value
+ }
+
+Then, invoke irb with the above prompt mode by
+
+ % irb --prompt my-prompt
+
+Or add the following in `.irbrc'.
+
+ IRB.conf[:PROMPT_MODE] = :MY_PROMPT
+
+Constants PROMPT_I, PROMPT_S and PROMPT_C specifies the format.
+In the prompt specification, some special strings are available.
+
+ %N command name which is running
+ %m to_s of main object (self)
+ %M inspect of main object (self)
+ %l type of string(", ', /, ]), `]' is inner %w[...]
+ %NNi indent level. NN is degits and means as same as printf("%NNd").
+ It can be ommited
+ %NNn line number.
+ %% %
+
+For instance, the default prompt mode is defined as follows:
+
+IRB.conf[:PROMPT_MODE][:DEFAULT] = {
+ :PROMPT_I => "%N(%m):%03n:%i> ",
+ :PROMPT_S => "%N(%m):%03n:%i%l ",
+ :PROMPT_C => "%N(%m):%03n:%i* ",
+ :RETURN => "%s\n"
+}
+
+RETURN is used to printf.
+
+== Configurating subirb
+
+The command line option or IRB.conf specify the default behavior of
+(sub)irb. On the other hand, each conf of in the next sction `6. Command'
+is used to individually configurate (sub)irb.
+
+If proc is set to IRB.conf[:IRB_RC], its subirb will be invoked after
+execution of that proc under giving the context of irb as its
+aregument. By this mechanism each subirb can be configurated.
+
+= Command
+
+For irb commands, both simple name and `irb_'-prefixed name are prepared.
+
+--- exit, quit, irb_exit
+ Quits (sub)irb.
+ if you've done cb (see below), exit from the binding mode.
+
+--- conf, irb_context
+ Displays current configuration. Modifing the configuration is
+ achieved by sending message to `conf'.
+
+--- conf.back_trace_limit
+ Sets display lines of backtrace as top n and tail n.
+ The default value is 16.
+
+--- conf.debug_level = N
+ Sets debug level of irb.
+
+--- conf.ignore_eof = true/false
+ Whether ^D (control-d) will be ignored or not.
+ If false is set, ^D means quit.
+
+--- conf.ignore_sigint= true/false
+ Whether ^C (control-c) will be ignored or not.
+ If false is set, ^D means quit. If true,
+ during input: cancel inputing then return to top level.
+ during execute: abondon current execution.
+
+--- conf.inf_ruby_mode = true/false
+ Whether inf-ruby-mode or not. The default value is false.
+
+--- conf.inspect_mode = true/false/nil
+ Specifies inspect mode.
+ true: display inspect
+ false: display to_s
+ nil: inspect mode in non math mode,
+ non inspect mode in math mode.
+
+--- conf.irb_level
+ The level of cb.
+
+--- conf.math_mode
+ Whether bc mode or not.
+
+--- conf.use_loader = true/false
+ Whether irb's own file reader method is used when load/require or not.
+ This mode is globaly affected (irb wide).
+
+--- conf.prompt_c
+ prompt for a continuating statement (e.g, immediately after of `if')
+
+--- conf.prompt_i
+ standard prompt
+
+--- conf.prompt_s
+ prompt for a continuating string
+
+--- conf.rc
+ Whether ~/.irbrc is read or not.
+
+--- conf.use_prompt = true/false
+ Prompting or not.
+
+--- conf.use_readline = true/false/nil
+ Whether readline is used or not.
+ true: uses
+ false: doen't use
+ nil: intends to use readline except for inf-reuby-mode (default)
+
+--- conf.verbose=T/F
+ Whether verbose messages are display or not.
+
+--- cb, irb_change_binding [obj]
+ Enter new binding which has a distinct scope of local variables.
+ If obj is given, obj will be self.
+
+--- irb [obj]
+ Invoke subirb. If obj is given, obj will be self.
+
+--- jobs, irb_jobs
+ List of subirb
+
+--- fg n, irb_fg n
+ Switch into specified subirb. The following is candidates of n:
+
+ irb number
+ thhread
+ irb object
+ self(obj which is specified of irb obj)
+
+--- kill n, irb_kill n
+ Kill subirb. The means of n is as same as the case of irb_fg.
+
+= System variable
+
+ _ The latest value of evaluation (it is local)
+
+
+= Session Example
+
+ dim% ruby irb.rb
+ irb(main):001:0> irb # invoke subirb
+ irb#1(main):001:0> jobs # list of subirbs
+ #0->irb on main (#<Thread:0x400fb7e4> : stop)
+ #1->irb#1 on main (#<Thread:0x40125d64> : running)
+ nil
+ irb#1(main):002:0> fg 0 # switch job
+ nil
+ irb(main):002:0> class Foo;end
+ nil
+ irb(main):003:0> irb Foo # invoke subirb which has the
+ # context of Foo
+ irb#2(Foo):001:0> def foo # define Foo#foo
+ irb#2(Foo):002:1> print 1
+ irb#2(Foo):003:1> end
+ nil
+ irb#2(Foo):004:0> fg 0 # switch job
+ nil
+ irb(main):004:0> jobs # list of job
+ #0->irb on main (#<Thread:0x400fb7e4> : running)
+ #1->irb#1 on main (#<Thread:0x40125d64> : stop)
+ #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop)
+ nil
+ irb(main):005:0> Foo.instance_methods # Foo#foo is defined asurely
+ ["foo"]
+ irb(main):006:0> fg 2 # switch job
+ nil
+ irb#2(Foo):005:0> def bar # define Foo#bar
+ irb#2(Foo):006:1> print "bar"
+ irb#2(Foo):007:1> end
+ nil
+ irb#2(Foo):010:0> Foo.instance_methods
+ ["bar", "foo"]
+ irb#2(Foo):011:0> fg 0
+ nil
+ irb(main):007:0> f = Foo.new
+ #<Foo:0x4010af3c>
+ irb(main):008:0> irb f # invoke subirb which has the
+ # context of f (instance of Foo)
+ irb#3(#<Foo:0x4010af3c>):001:0> jobs
+ #0->irb on main (#<Thread:0x400fb7e4> : stop)
+ #1->irb#1 on main (#<Thread:0x40125d64> : stop)
+ #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop)
+ #3->irb#3 on #<Foo:0x4010af3c> (#<Thread:0x4010a1e0> : running)
+ nil
+ irb#3(#<Foo:0x4010af3c>):002:0> foo # evaluate f.foo
+ 1nil
+ irb#3(#<Foo:0x4010af3c>):003:0> bar # evaluate f.bar
+ barnil
+ irb#3(#<Foo:0x4010af3c>):004:0> kill 1, 2, 3# kill job
+ nil
+ irb(main):009:0> jobs
+ #0->irb on main (#<Thread:0x400fb7e4> : running)
+ nil
+ irb(main):010:0> exit # exit
+ dim%
+
+= Restrictions
+
+Because irb evaluates the inputs immediately after the imput is
+syntactically completed, irb gives slight different result than
+directly use ruby. Known difference is pointed out here.
+
+
+== Declaration of the local variable
+
+The following causes an error in ruby:
+
+ eval "foo = 0"
+ foo
+ --
+ -:2: undefined local variable or method `foo' for #<Object:0x40283118> (NameError)
+ ---
+ NameError
+
+Though, the above will successfully done by irb.
+
+ >> eval "foo = 0"
+ => 0
+ >> foo
+ => 0
+
+Ruby evaluates a code after reading entire of code and determination
+of the scope of local variables. On the other hand, irb do
+immediately. More precisely, irb evaluate at first
+
+ evel "foo = 0"
+
+then foo is defined on this timing. It is because of this
+incompatibility.
+
+If you'd like to detect those differences, begin...end can be used:
+
+ >> begin
+ ?> eval "foo = 0"
+ >> foo
+ >> end
+ NameError: undefined local variable or method `foo' for #<Object:0x4013d0f0>
+ (irb):3
+ (irb_local_binding):1:in `eval'
+
+== Here-document
+
+Implementation of Here-document is incomplete.
+
+== Symbol
+
+Irb can not always recognize a symbol as to be Symbol. Concretely, an
+expression have completed, however Irb regard it as continuation line.
+
+=end
+
+% Begin Emacs Environment
+% Local Variables:
+% mode: text
+% comment-column: 0
+% comment-start: "%"
+% comment-end: "\n"
+% End:
+%
diff --git a/doc/irb/irb.rd.jp b/doc/irb/irb.rd.jp
new file mode 100644
index 0000000000..8b0de3cc62
--- /dev/null
+++ b/doc/irb/irb.rd.jp
@@ -0,0 +1,391 @@
+irb -- interactive ruby
+ $Release Version: 0.6 $
+ $Revision$
+ $Date$
+ by Keiju ISHITSUKA(keiju@ishitsuka.com)
+=begin
+= irb¤È¤Ï?
+
+irb¤Ïinteractive ruby¤Îά¤Ç¤¹. ruby¤Î¼°¤òɸ½àÆþÎϤ«¤é´Êñ¤ËÆþÎÏ/¼Â¹Ô¤¹
+¤ë¤¿¤á¤Î¥Ä¡¼¥ë¤Ç¤¹.
+
+= µ¯Æ°
+
+ % ruby -r irb -e0
+ % irb
+
+¤Î¤¤¤º¤ì¤«¤Ç¹Ô¤Ê¤¤¤Þ¤¹. Á°¼Ô¤Î¾ì¹çirb¤Ø¤Î¥ª¥×¥·¥ç¥ó»ØÄê¤Ï, °Ê²¼¤Î¤è¤¦¤Ë
+¤Ê¤ê¤Þ¤¹.
+
+ % ruby -r irb -e0 -- -v
+
+= »È¤¤Êý
+
+irb¤Î»È¤¤Êý¤Ï, Ruby¤µ¤¨ÃΤäƤ¤¤ì¤Ð¤¤¤¿¤Ã¤Æ´Êñ¤Ç¤¹. ´ðËÜŪ¤Ë¤Ï irb ¤È
+¤¤¤¦¥³¥Þ¥ó¥É¤ò¼Â¹Ô¤¹¤ë¤À¤±¤Ç¤¹. irb¤ò¼Â¹Ô¤¹¤ë¤È, °Ê²¼¤Î¤è¤¦¤Ê¥×¥í¥ó¥×
+¥È¤¬É½¤ì¤Æ¤­¤Þ¤¹. ¸å¤Ï, ruby¤Î¼°¤òÆþ¤ì¤Æ²¼¤µ¤¤. ¼°¤¬´°·ë¤·¤¿»þÅÀ¤Ç¼Â¹Ô
+¤µ¤ì¤Þ¤¹.
+
+ dim% irb
+ irb(main):001:0> 1+2
+ 3
+ irb(main):002:0> class Foo
+ irb(main):003:1> def foo
+ irb(main):004:2> print 1
+ irb(main):005:2> end
+ irb(main):006:1> end
+ nil
+ irb(main):007:0>
+
+¤Þ¤¿, irb¤ÏReadline¥â¥¸¥å¡¼¥ë¤Ë¤âÂбþ¤·¤Æ¤¤¤Þ¤¹. Readline¥â¥¸¥å¡¼¥ë¤¬
+¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Æ¤¤¤ë»þ¤Ë¤Ï, ¤½¤ì¤ò»È¤¦¤Î¤¬É¸½à¤Îưºî¤Ë¤Ê¤ê¤Þ¤¹.
+
+= ¥³¥Þ¥ó¥É¥ª¥×¥·¥ç¥ó
+
+ irb.rb [options] file_name opts
+ options:
+ -f ~/.irbrc ¤òÆÉ¤ß¹þ¤Þ¤Ê¤¤.
+ -m bc¥â¡¼¥É(ʬ¿ô, ¹ÔÎó¤Î·×»»¤¬¤Ç¤­¤ë)
+ -d $DEBUG ¤òtrue¤Ë¤¹¤ë(ruby -d ¤ÈƱ¤¸)
+ -r load-module ruby -r ¤ÈƱ¤¸.
+ --inspect ·ë²Ì½ÐÎϤËinspect¤òÍѤ¤¤ë(bc¥â¡¼¥É°Ê³°¤Ï¥Ç¥Õ¥©¥ë¥È).
+ --noinspect ·ë²Ì½ÐÎϤËinspect¤òÍѤ¤¤Ê¤¤.
+ --readline readline¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ¹¤ë.
+ --noreadline readline¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ·¤Ê¤¤. ¥Ç¥Õ¥©¥ë¥È¤Îưºî¤Ï,
+ inf-reuby-mode°Ê³°¤Çreadline¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ·¤è¤¦
+ ¤È¤¹¤ë.
+ --prompt prompt-mode
+ --prompt-mode prompt-mode
+ ¥×¥í¥ó¥×¥È¥â¡¼¥É¤òÀÚÂØ¤¨¤Þ¤¹. ¸½ºßÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥×
+ ¥í¥ó¥×¥È¥â¡¼¥É¤Ï, defalut, simple, xmp, inf-ruby¤¬
+ ÍѰդµ¤ì¤Æ¤¤¤Þ¤¹. ¥Ç¥Õ¥©¥ë¥È¤Ïdefault¥×¥í¥ó¥×¥È¥â¡¼
+ ¥É¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹.
+
+ --inf-ruby-mode emacs¤Îinf-ruby-modeÍѤΥץí¥ó¥×¥Èɽ¼¨¤ò¹Ô¤Ê¤¦. ÆÃ
+ ¤Ë»ØÄ꤬¤Ê¤¤¸Â¤ê, readline¥é¥¤¥Ö¥é¥ê¤Ï»È¤ï¤Ê¤¯¤Ê¤ë.
+ --simple-prompt
+ Èó¾ï¤Ë¥·¥ó¥×¥ë¤Ê¥×¥í¥ó¥×¥È¤òÍѤ¤¤ë¥â¡¼¥É¤Ç¤¹.
+ --noprompt ¥×¥í¥ó¥×¥Èɽ¼¨¤ò¹Ô¤Ê¤ï¤Ê¤¤.
+ --tracer ¥³¥Þ¥ó¥É¼Â¹Ô»þ¤Ë¥È¥ì¡¼¥¹¤ò¹Ô¤Ê¤¦.
+ --back-trace-limit n
+ ¥Ð¥Ã¥¯¥È¥ì¡¼¥¹É½¼¨¤ò¥Ð¥Ã¥¯¥È¥ì¡¼¥¹¤ÎƬ¤«¤é n, ¸å¤í
+ ¤«¤én¤À¤±¹Ô¤Ê¤¦. ¥Ç¥Õ¥©¥ë¥È¤Ï16
+ --irb_debug n irb¤Î¥Ç¥Ð¥Ã¥°¥Ç¥Ð¥Ã¥°¥ì¥Ù¥ë¤òn¤ËÀßÄꤹ¤ë(ÍøÍѤ·¤Ê
+ ¤¤Êý¤¬ÌµÆñ¤Ç¤·¤ç¤¦).
+ -v, --version irb¤Î¥Ð¡¼¥¸¥ç¥ó¤òɽ¼¨¤¹¤ë
+
+= ¥³¥ó¥Õ¥£¥®¥å¥ì¡¼¥·¥ç¥ó
+
+irbµ¯Æ°»þ¤Ë``~/.irbrc''¤òÆÉ¤ß¹þ¤ß¤Þ¤¹. ¤â¤·Â¸ºß¤·¤Ê¤¤¾ì¹ç¤Ï,
+``.irbrc'', ``irb.rc'', ``_irbrc'', ``$irbrc''¤Î½ç¤Ëload¤ò»î¤ß¤Þ¤¹.
+
+¥ª¥×¥·¥ç¥ó¤òÀßÄꤹ¤ëÂå¤ï¤ê¤Ë, °Ê²¼¤Î¥³¥Þ¥ó¥É¤Ç¤â¥Ç¥Õ¥©¥ë¥È¤Îưºî¤òÀßÄê
+¤Ç¤­¤Þ¤¹.
+
+ IRB.conf[:IRB_NAME]="irb"
+ IRB.conf[:MATH_MODE]=false
+ IRB.conf[:USE_TRACER]=false
+ IRB.conf[:USE_LOADER]=false
+ IRB.conf[:IGNORE_SIGINT]=true
+ IRB.conf[:IGNORE_EOF]=false
+ IRB.conf[:INSPECT_MODE]=nil
+ IRB.conf[:IRB_RC] = nil
+ IRB.conf[:BACK_TRACE_LIMIT]=16
+ IRB.conf[:USE_LOADER] = false
+ IRB.conf[:USE_READLINE] = nil
+ IRB.conf[:USE_TRACER] = false
+ IRB.conf[:IGNORE_SIGINT] = true
+ IRB.conf[:IGNORE_EOF] = false
+ IRB.conf[:PROMPT_MODE] = :DEFALUT
+ IRB.conf[:PROMPT] = {...}
+ IRB.conf[:DEBUG_LEVEL]=0
+ IRB.conf[:VERBOSE]=true
+
+== ¥×¥í¥ó¥×¥È¤ÎÀßÄê
+
+¥×¥í¥ó¥×¥È¤ò¥«¥¹¥¿¥Þ¥¤¥º¤·¤¿¤¤»þ¤Ë¤Ï,
+
+ IRB.conf[:PROMPT]
+
+¤òÍѤ¤¤Þ¤¹. Î㤨¤Ð, .irbrc¤ÎÃæ¤Ç²¼¤Î¤è¤¦¤Ê¼°¤òµ­½Ò¤·¤Þ¤¹:
+
+ IRB.conf[:PROMPT][:MY_PROMPT] = { # ¥×¥í¥ó¥×¥È¥â¡¼¥É¤Î̾Á°
+ :PROMPT_I => nil, # Ä̾ï¤Î¥×¥í¥ó¥×¥È
+ :PROMPT_S => nil, # ʸ»úÎó¤Ê¤É¤Î·Ñ³¹Ô¤Î¥×¥í¥ó¥×¥È
+ :PROMPT_C => nil, # ¼°¤¬·Ñ³¤·¤Æ¤¤¤ë»þ¤Î¥×¥í¥ó¥×¥È
+ :RETURN => " ==>%s\n" # ¥ê¥¿¡¼¥ó»þ¤Î¥×¥í¥ó¥×¥È
+ }
+
+¥×¥í¥ó¥×¥È¥â¡¼¥É¤ò»ØÄꤷ¤¿¤¤»þ¤Ë¤Ï,
+
+ irb --prompt my-prompt
+
+¤Ç¤½¤Î¥×¥í¥ó¥×¥È¥â¡¼¥É¤Çµ¯Æ°¤µ¤ì¤Þ¤¹. ¤Þ¤¿¤Ï, .irbrc¤Ë²¼¼°¤òµ­½Ò¤·¤Æ¤â
+OK¤Ç¤¹.
+
+ IRB.conf[:PROMPT_MODE] = :MY_PROMPT
+
+PROMPT_I, PROMPT_S, PROMPT_C¤Ï, ¥Õ¥©¡¼¥Þ¥Ã¥È¤ò»ØÄꤷ¤Þ¤¹.
+
+ %N µ¯Æ°¤·¤Æ¤¤¤ë¥³¥Þ¥ó¥É̾¤¬½ÐÎϤµ¤ì¤ë.
+ %m main¥ª¥Ö¥¸¥§¥¯¥È(self)¤¬to_s¤Ç½ÐÎϤµ¤ì¤ë.
+ %M main¥ª¥Ö¥¸¥§¥¯¥È(self)¤¬inspect¤µ¤ì¤Æ½ÐÎϤµ¤ì¤ë.
+ %l ʸ»úÎóÃæ¤Î¥¿¥¤¥×¤òɽ¤¹(", ', /, ], `]'¤Ï%w¤ÎÃæ¤Î»þ)
+ %NNi ¥¤¥ó¥Ç¥ó¥È¤Î¥ì¥Ù¥ë¤òɽ¤¹. NN¤Ï¿ô»ú¤¬Æþ¤êprintf¤Î%NNd¤ÈƱ¤¸. ¾Ê
+ ά²Äǽ
+ %NNn ¹ÔÈÖ¹æ¤òɽ¤·¤Þ¤¹.
+ %% %
+
+Î㤨¤Ð, ¥Ç¥Õ¥©¥ë¥È¤Î¥×¥í¥ó¥×¥È¥â¡¼¥É¤Ï:
+
+ IRB.conf[:PROMPT_MODE][:DEFAULT] = {
+ :PROMPT_I => "%N(%m):%03n:%i> ",
+ :PROMPT_S => "%N(%m):%03n:%i%l ",
+ :PROMPT_C => "%N(%m):%03n:%i* ",
+ :RETURN => "%s\n"
+ }
+
+¤È¤Ê¤Ã¤Æ¤¤¤Þ¤¹.
+
+RETURN¤Ï, ¸½ºß¤Î¤È¤³¤íprintf·Á¼°¤Ç¤¹. ¾­Íè»ÅÍͤ¬ÊѤï¤ë¤«¤âÃΤì¤Þ¤»¤ó.
+
+== ¥µ¥Öirb¤ÎÀßÄê
+
+¥³¥Þ¥ó¥É¥é¥¤¥ó¥ª¥×¥·¥ç¥ó¤ª¤è¤ÓIRB.conf¤Ï(¥µ¥Ö)irbµ¯Æ°»þ¤Î¥Ç¥Õ¥©¥ë¥È¤Î
+ÀßÄê¤ò·è¤á¤ë¤â¤Î¤Ç, `5. ¥³¥Þ¥ó¥É'¤Ë¤¢¤ëconf¤Ç¸ÄÊ̤Î(¥µ¥Ö)irb¤ÎÀßÄ꤬¤Ç
+¤­¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹.
+
+IRB.conf[:IRB_RC]¤Ëproc¤¬ÀßÄꤵ¤ì¤Æ¤¤¤ë¤È, ¥µ¥Öirb¤òµ¯Æ°¤¹¤ë»þ¤Ë¤½¤Î
+proc¤òirb¤Î¥³¥ó¥Æ¥­¥¹¥È¤ò°ú¿ô¤È¤·¤Æ¸Æ¤Ó½Ð¤·¤Þ¤¹. ¤³¤ì¤Ë¤è¤Ã¤Æ¸ÄÊ̤Υµ
+¥Öirb¤´¤È¤ËÀßÄê¤òÊѤ¨¤ë¤³¤È¤¬¤Ç¤­¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹.
+
+
+= ¥³¥Þ¥ó¥É
+
+irb³ÈÄ¥¥³¥Þ¥ó¥É¤Ï, ´Êñ¤Ê̾Á°¤ÈƬ¤Ë`irb_'¤ò¤Ä¤±¤¿Ì¾Á°¤ÈξÊýÄêµÁ¤µ¤ì¤Æ
+¤¤¤Þ¤¹. ¤³¤ì¤Ï, ´Êñ¤Ê̾Á°¤¬override¤µ¤ì¤¿»þ¤Î¤¿¤á¤Ç¤¹.
+
+--- exit, quit, irb_exit
+ ½ªÎ»¤¹¤ë.
+ ¥µ¥Öirb¤Î¾ì¹ç, ¤½¤Î¥µ¥Öirb¤ò½ªÎ»¤¹¤ë.
+ cb¤·¤Æ¤¤¤ë¾ì¹ç, ¤½¤Î¥Ð¥¤¥ó¥Ç¥£¥ó¥°¤Î¥â¡¼¥É¤ò½ªÎ»¤¹¤ë.
+
+--- conf, irb_context
+ irb¤Î¸½ºß¤ÎÀßÄê¤òɽ¼¨¤¹¤ë. ÀßÄê¤ÎÊѹ¹¤Ï, conf¤Ë¥á¥Ã¥»¡¼¥¸¤òÁ÷¤ë¤³
+ ¤È¤Ë¤è¤Ã¤Æ¹Ô¤Ê¤¨¤ë.
+
+--- conf.back_trace_limit
+ ¥Ð¥Ã¥¯¥È¥ì¡¼¥¹É½¼¨¤ò¥Ð¥Ã¥¯¥È¥ì¡¼¥¹¤ÎƬ¤«¤én, ¸å¤í¤«¤én¤À¤±¹Ô¤Ê¤¦.
+ ¥Ç¥Õ¥©¥ë¥È¤Ï16
+
+--- conf.debug_level = N
+ irbÍѤΥǥХå°¥ì¥Ù¥ë¤ÎÀßÄê
+
+--- conf.ignore_eof = true/false
+ ^D¤¬ÆþÎϤµ¤ì¤¿»þ¤Îưºî¤òÀßÄꤹ¤ë. true¤Î»þ¤Ï^D¤ò̵»ë¤¹¤ë, false¤Î
+ »þ¤Ïirb¤ò½ªÎ»¤¹¤ë.
+
+--- conf.ignore_sigint= true/false
+ ^C¤¬ÆþÎϤµ¤ì¤¿»þ¤Îưºî¤òÀßÄꤹ¤ë. false»þ¤Ï, irb¤ò½ªÎ»¤¹¤ë. true¤Î
+ »þ¤Îưºî¤Ï°Ê²¼¤Î¤è¤¦¤Ë¤Ê¤ë:
+ ÆþÎÏÃæ: ¤³¤ì¤Þ¤ÇÆþÎϤ·¤¿¤â¤Î¤ò¥­¥ã¥ó¥»¥ë¤·¥È¥Ã¥×¥ì¥Ù¥ë¤ËÌá¤ë.
+ ¼Â¹ÔÃæ: ¼Â¹Ô¤òÃæ»ß¤¹¤ë.
+
+--- conf.inf_ruby_mode = true/false
+ inf-ruby-modeÍѤΥץí¥ó¥×¥Èɽ¼¨¤ò¹Ô¤Ê¤¦. ¥Ç¥Õ¥©¥ë¥È¤Ïfalse.
+
+--- conf.inspect_mode = true/false/nil
+ ¥¤¥ó¥¹¥Ú¥¯¥È¥â¡¼¥É¤òÀßÄꤹ¤ë.
+ true: ¥¤¥ó¥¹¥Ú¥¯¥È¤·¤ÆÉ½¼¨¤¹¤ë.
+ false: Ä̾ï¤Îprint¤Çɽ¼¨¤¹¤ë.
+ nil: Ä̾ï¥â¡¼¥É¤Ç¤¢¤ì¤Ð, inspect mode¤È¤Ê¤ê, math¥â¡¼¥É¤Î»þ¤Ï, non
+ inspect mode¤È¤Ê¤ë.
+
+--- conf.irb_level
+ »²¾È¤Î¤ß. irb¤¬²¿ÃÊcb¤·¤Æ¤¤¤ë¤«?
+
+--- conf.math_mode
+ »²¾È¤Î¤ß. bc¥â¡¼¥É(ʬ¿ô, ¹ÔÎó¤Î·×»»¤¬¤Ç¤­¤Þ¤¹)¤«¤É¤¦¤«?
+
+--- conf.use_loader = true/false
+ load/require»þ¤Ëirb¤ÎfileÆÉ¤ß¹þ¤ßµ¡Ç½¤òÍѤ¤¤ë¥â¡¼¥É¤Î¥¹¥¤¥Ã¥Á(¥Ç¥Õ¥©
+ ¥ë¥È¤ÏÍѤ¤¤Ê¤¤). ¤³¤Î¥â¡¼¥É¤ÏIRBÁ´ÂΤËÈ¿±Ç¤µ¤ì¤ë.
+
+--- conf.prompt_c
+ if¤Îľ¸å¤Ê¤É, ¹Ô¤¬·Ñ³¤·¤Æ¤¤¤ë»þ¤Î¥×¥í¥ó¥×¥È.
+
+--- conf.prompt_i
+ Ä̾ï¤Î¥×¥í¥ó¥×¥È.
+
+--- conf.prompt_s
+ ʸ»úÎóÃæ¤Ê¤É¤òɽ¤¹¥×¥í¥ó¥×¥È.
+
+--- conf.rc
+ ~/.irbrc¤òÆÉ¤ß¹þ¤ó¤À¤«¤É¤¦¤«?
+
+--- conf.use_prompt = true/false
+ ¥×¥í¥ó¥×¥Èɽ¼¨¤¹¤ë¤«¤É¤¦¤«? ¥Ç¥Õ¥©¥ë¥È¤Ç¤Ï¥×¥í¥ó¥×¥È¤òɽ¼¨¤¹¤ë.
+
+--- conf.use_readline = true/false/nil
+ readline¤ò»È¤¦¤«¤É¤¦¤«?
+ true: readline¤ò»È¤¦.
+ false: readline¤ò»È¤ï¤Ê¤¤.
+ nil: (¥Ç¥Õ¥©¥ë¥È)inf-reuby-mode°Ê³°¤Çreadline¥é¥¤¥Ö¥é¥ê¤òÍøÍѤ·¤è
+ ¤¦¤È¤¹¤ë.
+
+--- conf.verbose=T/F
+ irb¤«¤é¤¤¤í¤¤¤í¤Ê¥á¥Ã¥»¡¼¥¸¤ò½ÐÎϤ¹¤ë¤«?
+
+--- cb, irb_change_binding [obj]
+ ¥í¡¼¥«¥ëÊÑ¿ô¤Î¥¹¥³¡¼¥×¤¬°ã¤¦¿·¤¿¤Êbinding¤Ë°Ü¤ë. obj¤¬»ØÄꤵ¤ì¤¿
+ »þ¤Ï, ¤½¤Îobj¤òself¤È¤¹¤ë.
+
+--- irb [obj]
+ ¥µ¥Öirb¤òΩ¤Á¤¢¤²¤ë. obj¤¬»ØÄꤵ¤ì¤¿»þ¤Ï, ¤½¤Îobj¤òself¤È¤¹¤ë.
+
+--- jobs, irb_jobs
+ ¥µ¥Öirb¤Î¥ê¥¹¥È
+
+--- fg n, irb_fg n
+ »ØÄꤷ¤¿¥µ¥Öirb¤Ë¥¹¥¤¥Ã¥Á¤¹¤ë. n¤Ï, ¼¡¤Î¤â¤Î¤ò»ØÄꤹ¤ë.
+
+ irbÈÖ¹æ
+ ¥¹¥ì¥Ã¥É
+ irb¥ª¥Ö¥¸¥§¥¯¥È
+ self(irb obj¤Çµ¯Æ°¤·¤¿»þ¤Îobj)
+
+--- kill n, irb_kill n
+ ¥µ¥Öirb¤òkill¤¹¤ë. n¤Ïfg¤ÈƱ¤¸.
+
+
+= ¥·¥¹¥Æ¥àÊÑ¿ô
+
+ _ Á°¤Î·×»»¤Î¼Â¹Ô·ë²Ì¤ò³Ð¤¨¤Æ¤¤¤ë(¥í¡¼¥«¥ëÊÑ¿ô).
+
+= »ÈÍÑÎã
+
+°Ê²¼¤Î¤è¤¦¤Ê´¶¤¸¤Ç¤¹.
+
+ dim% ruby irb.rb
+ irb(main):001:0> irb # ¥µ¥Öirb¤ÎΩ¤Á¤¢¤²
+ irb#1(main):001:0> jobs # ¥µ¥Öirb¤Î¥ê¥¹¥È
+ #0->irb on main (#<Thread:0x400fb7e4> : stop)
+ #1->irb#1 on main (#<Thread:0x40125d64> : running)
+ nil
+ irb#1(main):002:0> fg 0 # job¤Î¥¹¥¤¥Ã¥Á
+ nil
+ irb(main):002:0> class Foo;end
+ nil
+ irb(main):003:0> irb Foo # Foo¤ò¥³¥ó¥Æ¥­¥¹¥È¤·¤Æirb
+ # Ω¤Á¤¢¤²
+ irb#2(Foo):001:0> def foo # Foo#foo¤ÎÄêµÁ
+ irb#2(Foo):002:1> print 1
+ irb#2(Foo):003:1> end
+ nil
+ irb#2(Foo):004:0> fg 0 # job¤ò¥¹¥¤¥Ã¥Á
+ nil
+ irb(main):004:0> jobs # job¤Î¥ê¥¹¥È
+ #0->irb on main (#<Thread:0x400fb7e4> : running)
+ #1->irb#1 on main (#<Thread:0x40125d64> : stop)
+ #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop)
+ nil
+ irb(main):005:0> Foo.instance_methods # Foo#foo¤¬¤Á¤ã¤ó¤ÈÄêµÁ¤µ
+ # ¤ì¤Æ¤¤¤ë
+ ["foo"]
+ irb(main):006:0> fg 2 # job¤ò¥¹¥¤¥Ã¥Á
+ nil
+ irb#2(Foo):005:0> def bar # Foo#bar¤òÄêµÁ
+ irb#2(Foo):006:1> print "bar"
+ irb#2(Foo):007:1> end
+ nil
+ irb#2(Foo):010:0> Foo.instance_methods
+ ["bar", "foo"]
+ irb#2(Foo):011:0> fg 0
+ nil
+ irb(main):007:0> f = Foo.new
+ #<Foo:0x4010af3c>
+ irb(main):008:0> irb f # Foo¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤Çirb¤ò
+ # Ω¤Á¤¢¤²¤ë.
+ irb#3(#<Foo:0x4010af3c>):001:0> jobs
+ #0->irb on main (#<Thread:0x400fb7e4> : stop)
+ #1->irb#1 on main (#<Thread:0x40125d64> : stop)
+ #2->irb#2 on Foo (#<Thread:0x4011d54c> : stop)
+ #3->irb#3 on #<Foo:0x4010af3c> (#<Thread:0x4010a1e0> : running)
+ nil
+ irb#3(#<Foo:0x4010af3c>):002:0> foo # f.foo¤Î¼Â¹Ô
+ nil
+ irb#3(#<Foo:0x4010af3c>):003:0> bar # f.bar¤Î¼Â¹Ô
+ barnil
+ irb#3(#<Foo:0x4010af3c>):004:0> kill 1, 2, 3# job¤Îkill
+ nil
+ irb(main):009:0> jobs
+ #0->irb on main (#<Thread:0x400fb7e4> : running)
+ nil
+ irb(main):010:0> exit # ½ªÎ»
+ dim%
+
+= »ÈÍѾå¤ÎÀ©¸Â
+
+irb¤Ï, ɾ²Á¤Ç¤­¤ë»þÅÀ(¼°¤¬ÊĤ¸¤¿»þÅÀ)¤Ç¤ÎÃ༡¼Â¹Ô¤ò¹Ô¤Ê¤¤¤Þ¤¹. ¤·¤¿¤¬¤Ã
+¤Æ, ruby¤òľÀܻȤä¿»þ¤È, ¼ã´³°Û¤Ê¤ëưºî¤ò¹Ô¤Ê¤¦¾ì¹ç¤¬¤¢¤ê¤Þ¤¹.
+
+¸½ºßÌÀ¤é¤«¤Ë¤Ê¤Ã¤Æ¤¤¤ëÌäÂêÅÀ¤òÀâÌÀ¤·¤Þ¤¹.
+
+== ¥í¡¼¥«¥ëÊÑ¿ô¤ÎÀë¸À
+
+ruby¤Ç¤Ï, °Ê²¼¤Î¥×¥í¥°¥é¥à¤Ï¥¨¥é¡¼¤Ë¤Ê¤ê¤Þ¤¹.
+
+ eval "foo = 0"
+ foo
+ --
+ -:2: undefined local variable or method `foo' for #<Object:0x40283118> (NameError)
+ ---
+ NameError
+
+¤È¤³¤í¤¬, irb¤òÍѤ¤¤ë¤È
+
+ >> eval "foo = 0"
+ => 0
+ >> foo
+ => 0
+
+¤È¤Ê¤ê, ¥¨¥é¡¼¤òµ¯¤³¤·¤Þ¤»¤ó. ¤³¤ì¤Ï, ruby¤¬ºÇ½é¤Ë¥¹¥¯¥ê¥×¥ÈÁ´ÂΤò¥³¥ó
+¥Ñ¥¤¥ë¤·¤Æ¥í¡¼¥«¥ëÊÑ¿ô¤ò·èÄꤹ¤ë¤«¤é¤Ç¤¹. ¤½¤ì¤ËÂФ·, irb¤Ï¼Â¹Ô²Äǽ¤Ë
+¤Ê¤ë(¼°¤¬ÊĤ¸¤ë)¤È¼«Æ°Åª¤Ëɾ²Á¤·¤Æ¤¤¤ë¤«¤é¤Ç¤¹. ¾åµ­¤ÎÎã¤Ç¤Ï,
+
+ evel "foo = 0"
+
+¤ò¹Ô¤Ê¤Ã¤¿»þÅÀ¤Çɾ²Á¤ò¹Ô¤Ê¤¤, ¤½¤Î»þÅÀ¤ÇÊÑ¿ô¤¬ÄêµÁ¤µ¤ì¤ë¤¿¤á, ¼¡¼°¤Ç
+ÊÑ¿ôfoo¤ÏÄêµÁ¤µ¤ì¤Æ¤¤¤ë¤«¤é¤Ç¤¹.
+
+¤³¤Î¤è¤¦¤Êruby¤Èirb¤Îưºî¤Î°ã¤¤¤ò²ò·è¤·¤¿¤¤¾ì¹ç¤Ï, begin...end¤Ç³ç¤Ã¤Æ
+¥Ð¥Ã¥ÁŪ¤Ë¼Â¹Ô¤·¤Æ²¼¤µ¤¤:
+
+ >> begin
+ ?> eval "foo = 0"
+ >> foo
+ >> end
+ NameError: undefined local variable or method `foo' for #<Object:0x4013d0f0>
+ (irb):3
+ (irb_local_binding):1:in `eval'
+
+== ¥Ò¥¢¥É¥­¥å¥á¥ó¥È
+
+¸½ºß¤Î¤È¤³¤í¥Ò¥¢¥É¥­¥å¥á¥ó¥È¤Î¼ÂÁõ¤ÏÉÔ´°Á´¤Ç¤¹.
+
+== ¥·¥ó¥Ü¥ë
+
+¥·¥ó¥Ü¥ë¤Ç¤¢¤ë¤«¤É¤¦¤«¤ÎȽÃǤò´Ö°ã¤¨¤ë¤³¤È¤¬¤¢¤ê¤Þ¤¹. ¶ñÂÎŪ¤Ë¤Ï¼°¤¬´°Î»
+¤·¤Æ¤¤¤ë¤Î¤Ë·Ñ³¹Ô¤È¸«¤Ê¤¹¤³¤È¤¬¤¢¤ê¤Þ¤¹.
+
+=end
+
+% Begin Emacs Environment
+% Local Variables:
+% mode: text
+% comment-column: 0
+% comment-start: "%"
+% comment-end: "\n"
+% End:
+%
+
diff --git a/doc/shell.rd b/doc/shell.rd
new file mode 100644
index 0000000000..02ee1b020a
--- /dev/null
+++ b/doc/shell.rd
@@ -0,0 +1,348 @@
+ -- shell.rb
+ $Release Version: 0.6.0 $
+ $Revision$
+ $Date$
+ by Keiju ISHITSUKA(keiju@ishitsuka.com)
+
+=begin
+
+= What's shell.rb?
+
+It realizes a wish to do execution of commands with filters and pipes
+like sh/csh by using just native facilities of ruby.
+
+= Main classes
+
+== Shell
+
+Every shell object has its own current working directory, and executes
+each command as if it stands in the directory.
+
+--- Shell#cwd
+--- Shell#dir
+--- Shell#getwd
+--- Shell#pwd
+
+ Returns the current directory
+
+--- Shell#system_path
+
+ Returns the command search path in an array
+
+--- Shell#umask
+
+ Returns the umask
+
+== Filter
+
+Any result of command exection is a Filter. Filter include
+Enumerable, therefore a Filter object can use all Enumerable
+facilities.
+
+= Main methods
+
+== Command definitions
+
+In order to execute a command on your OS, you need to define it as a
+Shell method.
+
+Alternatively, you can execute any command via Shell#system even if it
+is not defined.
+
+--- Shell.def_system_command(command, path = command)
+
+ Defines a command. Registers <path> as a Shell method
+ <command>.
+
+ ex)
+ Shell.def_system_command "ls"
+ Defines ls.
+
+ Shell.def_system_command "sys_sort", "sort"
+ Defines sys_sort as sort.
+
+--- Shell.undef_system_command(command)
+
+ Undefines a commmand
+
+--- Shell.alias_command(ali, command, *opts) {...}
+
+ Aliases a command.
+
+ ex)
+ Shell.alias_command "lsC", "ls", "-CBF", "--show-control-chars"
+ Shell.alias_command("lsC", "ls"){|*opts| ["-CBF", "--show-control-chars", *opts]}
+
+--- Shell.unalias_command(ali)
+
+ Unaliases a command.
+
+--- Shell.install_system_commands(pre = "sys_")
+
+ Defines all commands in the default_system_path as Shell method,
+ all with <pre> prefixed to their names.
+
+== Creation
+
+--- Shell.new
+
+ Creates a Shell object which current directory is set to the
+ process current directory.
+
+--- Shell.cd(path)
+
+ Creates a Shell object which current directory is set to
+ <path>.
+
+== Process management
+
+--- Shell#jobs
+
+ Returns a list of scheduled jobs.
+
+--- Shell#kill sig, job
+
+ Sends a signal <sig> to <job>.
+
+== Current directory operations
+
+--- Shell#cd(path, &block)
+--- Shell#chdir
+
+ Changes the current directory to <path>. If a block is given,
+ it restores the current directory when the block ends.
+
+--- Shell#pushd(path = nil, &block)
+--- Shell#pushdir
+
+ Pushes the current directory to the directory stack, changing
+ the current directory to <path>. If <path> is omitted, it
+ exchanges its current directory and the top of its directory
+ stack. If a block is given, it restores the current directory
+ when the block ends.
+
+--- Shell#popd
+--- Shell#popdir
+
+ Pops a directory from the directory stack, and sets the current
+ directory to it.
+
+== File and directory operations
+
+--- Shell#foreach(path = nil, &block)
+
+ Same as:
+ File#foreach (when path is a file)
+ Dir#foreach (when path is a directory)
+
+--- Shell#open(path, mode)
+
+ Same as:
+ File#open (when path is a file)
+ Dir#open (when path is a directory)
+
+--- Shell#unlink(path)
+
+ Same as:
+ Dir#open (when path is a file)
+ Dir#unlink (when path is a directory)
+
+--- Shell#test(command, file1, file2)
+--- Shell#[command, file1, file2]
+
+ Same as test().
+ ex)
+ sh[?e, "foo"]
+ sh[:e, "foo"]
+ sh["e", "foo"]
+ sh[:exists?, "foo"]
+ sh["exists?", "foo"]
+
+--- Shell#mkdir(*path)
+
+ Same as Dir.mkdir (with multiple directories allowed)
+
+--- Shell#rmdir(*path)
+
+ Same as Dir.rmdir (with multiple directories allowed)
+
+== Command execution
+
+--- System#system(command, *opts)
+
+ Executes <command> with <opts>.
+
+ ex)
+ print sh.system("ls", "-l")
+ sh.system("ls", "-l") | sh.head > STDOUT
+
+--- System#rehash
+
+ Does rehash.
+
+--- Shell#transact &block
+
+ Executes a block as self.
+ ex)
+ sh.transact{system("ls", "-l") | head > STDOUT}
+
+--- Shell#out(dev = STDOUT, &block)
+
+ Does transact, with redirecting the result output to <dev>.
+
+== Internal commands
+
+--- Shell#echo(*strings)
+--- Shell#cat(*files)
+--- Shell#glob(patten)
+--- Shell#tee(file)
+
+ Return Filter objects, which are results of their execution.
+
+--- Filter#each &block
+
+ Iterates a block for each line of it.
+
+--- Filter#<(src)
+
+ Inputs from <src>, which is either a string of a file name or an
+ IO.
+
+--- Filter#>(to)
+
+ Outputs to <to>, which is either a string of a file name or an
+ IO.
+
+--- Filter#>>(to)
+
+ Appends the ouput to <to>, which is either a string of a file
+ name or an IO.
+
+--- Filter#|(filter)
+
+ Processes a pipeline.
+
+--- Filter#+(filter)
+
+ (filter1 + filter2) outputs filter1, and then outputs filter2.
+
+--- Filter#to_a
+--- Filter#to_s
+
+== Built-in commands
+
+--- Shell#atime(file)
+--- Shell#basename(file, *opt)
+--- Shell#chmod(mode, *files)
+--- Shell#chown(owner, group, *file)
+--- Shell#ctime(file)
+--- Shell#delete(*file)
+--- Shell#dirname(file)
+--- Shell#ftype(file)
+--- Shell#join(*file)
+--- Shell#link(file_from, file_to)
+--- Shell#lstat(file)
+--- Shell#mtime(file)
+--- Shell#readlink(file)
+--- Shell#rename(file_from, file_to)
+--- Shell#split(file)
+--- Shell#stat(file)
+--- Shell#symlink(file_from, file_to)
+--- Shell#truncate(file, length)
+--- Shell#utime(atime, mtime, *file)
+
+ Equivalent to the class methods of File with the same names.
+
+--- Shell#blockdev?(file)
+--- Shell#chardev?(file)
+--- Shell#directory?(file)
+--- Shell#executable?(file)
+--- Shell#executable_real?(file)
+--- Shell#exist?(file)/Shell#exists?(file)
+--- Shell#file?(file)
+--- Shell#grpowned?(file)
+--- Shell#owned?(file)
+--- Shell#pipe?(file)
+--- Shell#readable?(file)
+--- Shell#readable_real?(file)
+--- Shell#setgid?(file)
+--- Shell#setuid?(file)
+--- Shell#size(file)/Shell#size?(file)
+--- Shell#socket?(file)
+--- Shell#sticky?(file)
+--- Shell#symlink?(file)
+--- Shell#writable?(file)
+--- Shell#writable_real?(file)
+--- Shell#zero?(file)
+
+ Equivalent to the class methods of FileTest with the same names.
+
+--- Shell#syscopy(filename_from, filename_to)
+--- Shell#copy(filename_from, filename_to)
+--- Shell#move(filename_from, filename_to)
+--- Shell#compare(filename_from, filename_to)
+--- Shell#safe_unlink(*filenames)
+--- Shell#makedirs(*filenames)
+--- Shell#install(filename_from, filename_to, mode)
+
+ Equivalent to the class methods of FileTools with the same
+ names.
+
+ And also, there are some aliases for convenience:
+
+--- Shell#cmp <- Shell#compare
+--- Shell#mv <- Shell#move
+--- Shell#cp <- Shell#copy
+--- Shell#rm_f <- Shell#safe_unlink
+--- Shell#mkpath <- Shell#makedirs
+
+= Samples
+
+== ex1
+
+ sh = Shell.cd("/tmp")
+ sh.mkdir "shell-test-1" unless sh.exists?("shell-test-1")
+ sh.cd("shell-test-1")
+ for dir in ["dir1", "dir3", "dir5"]
+ if !sh.exists?(dir)
+ sh.mkdir dir
+ sh.cd(dir) do
+ f = sh.open("tmpFile", "w")
+ f.print "TEST\n"
+ f.close
+ end
+ print sh.pwd
+ end
+ end
+
+== ex2
+
+ sh = Shell.cd("/tmp")
+ sh.transact do
+ mkdir "shell-test-1" unless exists?("shell-test-1")
+ cd("shell-test-1")
+ for dir in ["dir1", "dir3", "dir5"]
+ if !exists?(dir)
+ mkdir dir
+ cd(dir) do
+ f = open("tmpFile", "w")
+ f.print "TEST\n"
+ f.close
+ end
+ print pwd
+ end
+ end
+ end
+
+== ex3
+
+ sh.cat("/etc/printcap") | sh.tee("tee1") > "tee2"
+ (sh.cat < "/etc/printcap") | sh.tee("tee11") > "tee12"
+ sh.cat("/etc/printcap") | sh.tee("tee1") >> "tee2"
+ (sh.cat < "/etc/printcap") | sh.tee("tee11") >> "tee12"
+
+== ex4
+
+ print sh.cat("/etc/passwd").head.collect{|l| l =~ /keiju/}
+
+=end
diff --git a/doc/shell.rd.jp b/doc/shell.rd.jp
new file mode 100644
index 0000000000..073e71ea42
--- /dev/null
+++ b/doc/shell.rd.jp
@@ -0,0 +1,336 @@
+ -- shell.rb
+ $Release Version: 0.6.0 $
+ $Revision$
+ $Date$
+ by Keiju ISHITSUKA(keiju@ishitsuka.com)
+
+=begin
+
+= ÌÜŪ
+
+ruby¾å¤Çsh/csh¤Î¤è¤¦¤Ë¥³¥Þ¥ó¥É¤Î¼Â¹ÔµÚ¤Ó¥Õ¥£¥ë¥¿¥ê¥ó¥°¤ò¼ê·Ú¤Ë¹Ô¤¦.
+sh/csh¤ÎÀ©¸æÊ¸¤Ïruby¤Îµ¡Ç½¤òÍѤ¤¤Æ¼Â¸½¤¹¤ë.
+
+= ¼ç¤Ê¥¯¥é¥¹°ìÍ÷
+
+== Shell
+
+Shell¥ª¥Ö¥¸¥§¥¯¥È¤Ï¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯¥È¥ê¤ò»ý¤Á, ¥³¥Þ¥ó¥É¼Â¹Ô¤Ï¤½¤³¤«¤é¤Î
+ÁêÂХѥ¹¤Ë¤Ê¤ê¤Þ¤¹.
+
+--- Shell#cwd
+--- Shell#dir
+--- Shell#getwd
+--- Shell#pwd
+
+ ¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯¥È¥ê¤òÊÖ¤¹¡£
+
+--- Shell#system_path
+
+ ¥³¥Þ¥ó¥É¥µ¡¼¥Á¥Ñ¥¹¤ÎÇÛÎó¤òÊÖ¤¹¡£
+
+--- Shell#umask
+
+ umask¤òÊÖ¤¹¡£
+
+== Filter
+
+¥³¥Þ¥ó¥É¤Î¼Â¹Ô·ë²Ì¤Ï¤¹¤Ù¤ÆFilter¤È¤·¤Æ¤«¤¨¤ê¤Þ¤¹. Enumerable¤òinclude¤·
+¤Æ¤¤¤Þ¤¹.
+
+= ¼ç¤Ê¥á¥½¥Ã¥É°ìÍ÷
+
+== ¥³¥Þ¥ó¥ÉÄêµÁ
+
+OS¾å¤Î¥³¥Þ¥ó¥É¤ò¼Â¹Ô¤¹¤ë¤Ë¤Ï¤Þ¤º, Shell¤Î¥á¥½¥Ã¥É¤È¤·¤ÆÄêµÁ¤·¤Þ¤¹.
+
+Ãí) ¥³¥Þ¥ó¥É¤òÄêµÁ¤·¤Ê¤¯¤È¤âľÀܼ¹ԤǤ­¤ëShell#system¥³¥Þ¥ó¥É¤â¤¢¤ê¤Þ¤¹.
+
+--- Shell.def_system_command(command, path = command)
+
+ Shell¤Î¥á¥½¥Ã¥É¤È¤·¤Æcommand¤òÅÐÏ¿¤·¤Þ¤¹.
+
+ Îã)
+ Shell.def_system_command "ls"
+ ls ¤òÄêµÁ
+
+ Shell.def_system_command "sys_sort", "sort"
+ sort¥³¥Þ¥ó¥É¤òsys_sort¤È¤·¤ÆÄêµÁ
+
+--- Shell.undef_system_command(command)
+
+ command¤òºï½ü¤·¤Þ¤¹.
+
+--- Shell.alias_command(ali, command, *opts) {...}
+
+ command¤Îalias¤ò¤·¤Þ¤¹.
+
+ Îã)
+ Shell.alias_command "lsC", "ls", "-CBF", "--show-control-chars"
+ Shell.alias_command("lsC", "ls"){|*opts| ["-CBF", "--show-control-chars", *opts]}
+
+--- Shell.unalias_command(ali)
+
+ command¤Îalias¤òºï½ü¤·¤Þ¤¹.
+
+--- Shell.install_system_commands(pre = "sys_")
+
+ system_path¾å¤Ë¤¢¤ëÁ´¤Æ¤Î¼Â¹Ô²Äǽ¥Õ¥¡¥¤¥ë¤òShell¤ËÄêµÁ¤¹¤ë. ¥á¥½¥Ã
+ ¥É̾¤Ï¸µ¤Î¥Õ¥¡¥¤¥ë̾¤ÎƬ¤Ëpre¤ò¤Ä¤±¤¿¤â¤Î¤È¤Ê¤ë.
+
+== À¸À®
+
+--- Shell.new
+
+ ¥×¥í¥»¥¹¤Î¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯¥È¥ê¤ò¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯¥È¥ê¤È¤¹¤ëShell¥ª
+ ¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Þ¤¹.
+
+--- Shell.cd(path)
+
+ path¤ò¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯¥È¥ê¤È¤¹¤ëShell¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Þ¤¹.
+
+== ¥×¥í¥»¥¹´ÉÍý
+
+--- Shell#jobs
+
+ ¥¹¥±¥¸¥å¡¼¥ê¥ó¥°¤µ¤ì¤Æ¤¤¤ëjob¤Î°ìÍ÷¤òÊÖ¤¹.
+
+--- Shell#kill sig, job
+
+ job¤Ë¥·¥°¥Ê¥ësig¤òÁ÷¤ë
+
+== ¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯¥È¥êÁàºî
+
+--- Shell#cd(path, &block)
+--- Shell#chdir
+
+ ¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯¥È¥ê¤òpath¤Ë¤¹¤ë. ¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ð¤ì¤¿¤È¤­¤Ë¤Ï
+ ¥Ö¥í¥Ã¥¯¼Â¹ÔÃæ¤Î¤ß¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯¥È¥ê¤òÊѹ¹¤¹¤ë.
+
+--- Shell#pushd(path = nil, &block)
+--- Shell#pushdir
+
+ ¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯¥È¥ê¤ò¥Ç¥£¥ì¥¯¥È¥ê¥¹¥¿¥Ã¥¯¤Ë¤Ä¤ß, ¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯
+ ¥È¥ê¤òpath¤Ë¤¹¤ë. path¤¬¾Êά¤µ¤ì¤¿¤È¤­¤Ë¤Ï, ¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯¥È¥ê¤È
+ ¥Ç¥£¥ì¥¯¥È¥ê¥¹¥¿¥Ã¥¯¤Î¥È¥Ã¥×¤ò¸ò´¹¤¹¤ë. ¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ð¤ì¤¿¤È
+ ¤­¤Ë¤Ï, ¥Ö¥í¥Ã¥¯¼Â¹ÔÃæ¤Î¤ßpushd¤¹¤ë.
+
+--- Shell#popd
+--- Shell#popdir
+
+ ¥Ç¥£¥ì¥¯¥È¥ê¥¹¥¿¥Ã¥¯¤«¤é¥Ý¥Ã¥×¤·, ¤½¤ì¤ò¥«¥ì¥ó¥È¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤¹¤ë.
+
+== ¥Õ¥¡¥¤¥ë/¥Ç¥£¥ì¥¯¥È¥êÁàºî
+
+--- Shell#foreach(path = nil, &block)
+
+ path¤¬¥Õ¥¡¥¤¥ë¤Ê¤é, File#foreach
+ path¤¬¥Ç¥£¥ì¥¯¥È¥ê¤Ê¤é, Dir#foreach
+
+--- Shell#open(path, mode)
+
+ path¤¬¥Õ¥¡¥¤¥ë¤Ê¤é, File#open
+ path¤¬¥Ç¥£¥ì¥¯¥È¥ê¤Ê¤é, Dir#open
+
+--- Shell#unlink(path)
+
+ path¤¬¥Õ¥¡¥¤¥ë¤Ê¤é, File#unlink
+ path¤¬¥Ç¥£¥ì¥¯¥È¥ê¤Ê¤é, Dir#unlink
+
+--- Shell#test(command, file1, file2)
+--- Shell#[command, file1, file2]
+
+ ¥Õ¥¡¥¤¥ë¥Æ¥¹¥È´Ø¿ôtest¤ÈƱ¤¸.
+ Îã)
+ sh[?e, "foo"]
+ sh[:e, "foo"]
+ sh["e", "foo"]
+ sh[:exists?, "foo"]
+ sh["exists?", "foo"]
+
+--- Shell#mkdir(*path)
+
+ Dir.mkdir¤ÈƱ¤¸(Ê£¿ô²Ä)
+
+--- Shell#rmdir(*path)
+
+ Dir.rmdir¤ÈƱ¤¸(Ê£¿ô²Ä)
+
+== ¥³¥Þ¥ó¥É¼Â¹Ô
+
+--- System#system(command, *opts)
+
+ command¤ò¼Â¹Ô¤¹¤ë.
+ Îã)
+ print sh.system("ls", "-l")
+ sh.system("ls", "-l") | sh.head > STDOUT
+
+--- System#rehash
+
+ ¥ê¥Ï¥Ã¥·¥å¤¹¤ë
+
+--- Shell#transact &block
+
+ ¥Ö¥í¥Ã¥¯Ãæ¤Ç¤Ïshell¤òself¤È¤·¤Æ¼Â¹Ô¤¹¤ë.
+ Îã)
+ sh.transact{system("ls", "-l") | head > STDOUT}
+
+--- Shell#out(dev = STDOUT, &block)
+
+ transact¤ò¸Æ¤Ó½Ð¤·¤½¤Î·ë²Ì¤òdev¤Ë½ÐÎϤ¹¤ë.
+
+== ÆâÉô¥³¥Þ¥ó¥É
+
+--- Shell#echo(*strings)
+--- Shell#cat(*files)
+--- Shell#glob(patten)
+--- Shell#tee(file)
+
+ ¤³¤ì¤é¤Ï¼Â¹Ô¤¹¤ë¤È, ¤½¤ì¤é¤òÆâÍÆ¤È¤¹¤ëFilter¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤·¤Þ¤¹.
+
+--- Filter#each &block
+
+ ¥Õ¥£¥ë¥¿¤Î°ì¹Ô¤º¤Ä¤òblock¤ËÅϤ¹.
+
+--- Filter#<(src)
+
+ src¤ò¥Õ¥£¥ë¥¿¤ÎÆþÎϤȤ¹¤ë. src¤¬, ʸ»úÎó¤Ê¤é¤Ð¥Õ¥¡¥¤¥ë¤ò, IO¤Ç¤¢¤ì
+ ¤Ð¤½¤ì¤ò¤½¤Î¤Þ¤ÞÆþÎϤȤ¹¤ë.
+
+--- Filter#>(to)
+
+ src¤ò¥Õ¥£¥ë¥¿¤Î½ÐÎϤȤ¹¤ë. to¤¬, ʸ»úÎó¤Ê¤é¤Ð¥Õ¥¡¥¤¥ë¤Ë, IO¤Ç¤¢¤ì
+ ¤Ð¤½¤ì¤ò¤½¤Î¤Þ¤Þ½ÐÎϤȤ¹¤ë.
+
+--- Filter#>>(to)
+
+ src¤ò¥Õ¥£¥ë¥¿¤ËÄɲ乤ë. to¤¬, ʸ»úÎó¤Ê¤é¤Ð¥Õ¥¡¥¤¥ë¤Ë, IO¤Ç¤¢¤ì¤Ð
+ ¤½¤ì¤ò¤½¤Î¤Þ¤Þ½ÐÎϤȤ¹¤ë.
+
+--- Filter#|(filter)
+
+ ¥Ñ¥¤¥×·ë¹ç
+
+--- Filter#+(filter)
+
+ filter1 + filter2 ¤Ï filter1¤Î½ÐÎϤθå, filter2¤Î½ÐÎϤò¹Ô¤¦.
+
+--- Filter#to_a
+--- Filter#to_s
+
+== Áȹþ¤ß¥³¥Þ¥ó¥É
+
+--- Shell#atime(file)
+--- Shell#basename(file, *opt)
+--- Shell#chmod(mode, *files)
+--- Shell#chown(owner, group, *file)
+--- Shell#ctime(file)
+--- Shell#delete(*file)
+--- Shell#dirname(file)
+--- Shell#ftype(file)
+--- Shell#join(*file)
+--- Shell#link(file_from, file_to)
+--- Shell#lstat(file)
+--- Shell#mtime(file)
+--- Shell#readlink(file)
+--- Shell#rename(file_from, file_to)
+--- Shell#split(file)
+--- Shell#stat(file)
+--- Shell#symlink(file_from, file_to)
+--- Shell#truncate(file, length)
+--- Shell#utime(atime, mtime, *file)
+
+ ¤³¤ì¤é¤ÏFile¥¯¥é¥¹¤Ë¤¢¤ëƱ̾¤Î¥¯¥é¥¹¥á¥½¥Ã¥É¤ÈƱ¤¸¤Ç¤¹.
+
+--- Shell#blockdev?(file)
+--- Shell#chardev?(file)
+--- Shell#directory?(file)
+--- Shell#executable?(file)
+--- Shell#executable_real?(file)
+--- Shell#exist?(file)/Shell#exists?(file)
+--- Shell#file?(file)
+--- Shell#grpowned?(file)
+--- Shell#owned?(file)
+--- Shell#pipe?(file)
+--- Shell#readable?(file)
+--- Shell#readable_real?(file)
+--- Shell#setgid?(file)
+--- Shell#setuid?(file)
+--- Shell#size(file)/Shell#size?(file)
+--- Shell#socket?(file)
+--- Shell#sticky?(file)
+--- Shell#symlink?(file)
+--- Shell#writable?(file)
+--- Shell#writable_real?(file)
+--- Shell#zero?(file)
+
+ ¤³¤ì¤é¤ÏFileTest¥¯¥é¥¹¤Ë¤¢¤ëƱ̾¤Î¥¯¥é¥¹¥á¥½¥Ã¥É¤ÈƱ¤¸¤Ç¤¹.
+
+--- Shell#syscopy(filename_from, filename_to)
+--- Shell#copy(filename_from, filename_to)
+--- Shell#move(filename_from, filename_to)
+--- Shell#compare(filename_from, filename_to)
+--- Shell#safe_unlink(*filenames)
+--- Shell#makedirs(*filenames)
+--- Shell#install(filename_from, filename_to, mode)
+
+ ¤³¤ì¤é¤ÏFileTools¥¯¥é¥¹¤Ë¤¢¤ëƱ̾¤Î¥¯¥é¥¹¥á¥½¥Ã¥É¤ÈƱ¤¸¤Ç¤¹.
+
+ ¤½¤Î¾, °Ê²¼¤Î¤â¤Î¤¬¥¨¥¤¥ê¥¢¥¹¤µ¤ì¤Æ¤¤¤Þ¤¹.
+
+--- Shell#cmp <- Shell#compare
+--- Shell#mv <- Shell#move
+--- Shell#cp <- Shell#copy
+--- Shell#rm_f <- Shell#safe_unlink
+--- Shell#mkpath <- Shell#makedirs
+
+= ¥µ¥ó¥×¥ë
+
+== ex1
+
+ sh = Shell.cd("/tmp")
+ sh.mkdir "shell-test-1" unless sh.exists?("shell-test-1")
+ sh.cd("shell-test-1")
+ for dir in ["dir1", "dir3", "dir5"]
+ if !sh.exists?(dir)
+ sh.mkdir dir
+ sh.cd(dir) do
+ f = sh.open("tmpFile", "w")
+ f.print "TEST\n"
+ f.close
+ end
+ print sh.pwd
+ end
+ end
+
+== ex2
+
+ sh = Shell.cd("/tmp")
+ sh.transact do
+ mkdir "shell-test-1" unless exists?("shell-test-1")
+ cd("shell-test-1")
+ for dir in ["dir1", "dir3", "dir5"]
+ if !exists?(dir)
+ mkdir dir
+ cd(dir) do
+ f = open("tmpFile", "w")
+ f.print "TEST\n"
+ f.close
+ end
+ print pwd
+ end
+ end
+ end
+
+== ex3
+
+ sh.cat("/etc/printcap") | sh.tee("tee1") > "tee2"
+ (sh.cat < "/etc/printcap") | sh.tee("tee11") > "tee12"
+ sh.cat("/etc/printcap") | sh.tee("tee1") >> "tee2"
+ (sh.cat < "/etc/printcap") | sh.tee("tee11") >> "tee12"
+
+== ex4
+
+ print sh.cat("/etc/passwd").head.collect{|l| l =~ /keiju/}
+
+=end
diff --git a/enum.c b/enum.c
index 3b804fae48..4a97811384 100644
--- a/enum.c
+++ b/enum.c
@@ -1,4 +1,4 @@
-/************************************************
+/**********************************************************************
enum.c -
@@ -6,13 +6,14 @@
$Date$
created at: Fri Oct 1 15:15:19 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-2000 Yukihiro Matsumoto
-************************************************/
+**********************************************************************/
#include "ruby.h"
+#include "node.h"
-VALUE mEnumerable;
+VALUE rb_mEnumerable;
static ID id_each, id_eqq, id_cmp;
VALUE
@@ -27,17 +28,17 @@ grep_i(i, arg)
VALUE i, *arg;
{
if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
- ary_push(arg[1], i);
+ rb_ary_push(arg[1], i);
}
return Qnil;
}
static VALUE
-grep_iter_i(i, pat)
- VALUE i, pat;
+grep_iter_i(i, arg)
+ VALUE i, *arg;
{
- if (RTEST(rb_funcall(pat, id_eqq, 1, i))) {
- rb_yield(i);
+ if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) {
+ rb_ary_push(arg[1], rb_yield(i));
}
return Qnil;
}
@@ -46,33 +47,26 @@ static VALUE
enum_grep(obj, pat)
VALUE obj, pat;
{
- if (iterator_p()) {
- rb_iterate(rb_each, obj, grep_iter_i, pat);
- return obj;
+ VALUE tmp, arg[2];
+
+ arg[0] = pat; arg[1] = tmp = rb_ary_new();
+ if (rb_block_given_p()) {
+ rb_iterate(rb_each, obj, grep_iter_i, (VALUE)arg);
}
else {
- VALUE tmp, arg[2];
-
- arg[0] = pat; arg[1] = tmp = ary_new();
rb_iterate(rb_each, obj, grep_i, (VALUE)arg);
-
- return tmp;
}
+ return tmp;
}
-struct find_arg {
- int found;
- VALUE val;
-};
-
static VALUE
-find_i(i, arg)
+find_i(i, memo)
VALUE i;
- struct find_arg *arg;
+ NODE *memo;
{
if (RTEST(rb_yield(i))) {
- arg->found = TRUE;
- arg->val = i;
+ memo->u2.value = Qtrue;
+ memo->u1.value = i;
rb_iter_break();
}
return Qnil;
@@ -84,18 +78,19 @@ enum_find(argc, argv, obj)
VALUE* argv;
VALUE obj;
{
- struct find_arg arg;
+ NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, Qfalse, 0);
VALUE if_none;
rb_scan_args(argc, argv, "01", &if_none);
- arg.found = FALSE;
- rb_iterate(rb_each, obj, find_i, (VALUE)&arg);
- if (arg.found) {
- return arg.val;
+ rb_iterate(rb_each, obj, find_i, (VALUE)memo);
+ if (memo->u2.value) {
+ rb_gc_force_recycle((VALUE)memo);
+ return memo->u1.value;
}
if (!NIL_P(if_none)) {
- rb_eval_cmd(if_none, Qnil);
+ rb_eval_cmd(if_none, rb_ary_new2(0));
}
+ rb_gc_force_recycle((VALUE)memo);
return Qnil;
}
@@ -104,7 +99,7 @@ find_all_i(i, tmp)
VALUE i, tmp;
{
if (RTEST(rb_yield(i))) {
- ary_push(tmp, i);
+ rb_ary_push(tmp, i);
}
return Qnil;
}
@@ -115,62 +110,47 @@ enum_find_all(obj)
{
VALUE tmp;
- tmp = ary_new();
+ tmp = rb_ary_new();
rb_iterate(rb_each, obj, find_all_i, tmp);
return tmp;
}
static VALUE
-collect_i(i, tmp)
+reject_i(i, tmp)
VALUE i, tmp;
{
- VALUE retval;
-
- retval = rb_yield(i);
- if (RTEST(retval)) {
- ary_push(tmp, retval);
+ if (!RTEST(rb_yield(i))) {
+ rb_ary_push(tmp, i);
}
return Qnil;
}
static VALUE
-enum_collect(obj)
+enum_reject(obj)
VALUE obj;
{
VALUE tmp;
- tmp = ary_new();
- rb_iterate(rb_each, obj, collect_i, tmp);
+ tmp = rb_ary_new();
+ rb_iterate(rb_each, obj, reject_i, tmp);
return tmp;
}
static VALUE
-reverse_i(i, tmp)
+collect_i(i, tmp)
VALUE i, tmp;
{
- ary_unshift(tmp, i);
+ rb_ary_push(tmp, rb_yield(i));
return Qnil;
}
static VALUE
-enum_reverse(obj)
- VALUE obj;
-{
- VALUE tmp;
-
- tmp = ary_new();
- rb_iterate(rb_each, obj, reverse_i, tmp);
-
- return tmp;
-}
-
-static VALUE
enum_all(i, ary)
VALUE i, ary;
{
- ary_push(ary, i);
+ rb_ary_push(ary, i);
return Qnil;
}
@@ -180,47 +160,61 @@ enum_to_a(obj)
{
VALUE ary;
- ary = ary_new();
+ ary = rb_ary_new();
rb_iterate(rb_each, obj, enum_all, ary);
return ary;
}
static VALUE
+enum_collect(obj)
+ VALUE obj;
+{
+ VALUE tmp;
+
+ tmp = rb_ary_new();
+ rb_iterate(rb_each, obj, rb_block_given_p() ? collect_i : enum_all, tmp);
+
+ return tmp;
+}
+
+static VALUE
enum_sort(obj)
VALUE obj;
{
- return ary_sort(enum_to_a(obj));
+ return rb_ary_sort(enum_to_a(obj));
}
static VALUE
-min_i(i, min)
- VALUE i, *min;
+min_i(i, memo)
+ VALUE i;
+ NODE *memo;
{
VALUE cmp;
- if (NIL_P(*min))
- *min = i;
+ if (NIL_P(memo->u1.value))
+ memo->u1.value = i;
else {
- cmp = rb_funcall(i, id_cmp, 1, *min);
- if (FIX2INT(cmp) < 0)
- *min = i;
+ cmp = rb_funcall(i, id_cmp, 1, memo->u1.value);
+ if (NUM2LONG(cmp) < 0)
+ memo->u1.value = i;
}
return Qnil;
}
static VALUE
-min_ii(i, min)
- VALUE i, *min;
+min_ii(i, memo)
+ VALUE i;
+ NODE *memo;
{
VALUE cmp;
- if (NIL_P(*min))
- *min = i;
+ if (NIL_P(memo->u1.value))
+ memo->u1.value = i;
else {
- cmp = rb_yield(assoc_new(i, *min));
- if (FIX2INT(cmp) < 0)
- *min = i;
+ cmp = rb_yield(rb_assoc_new(i, memo->u1.value));
+ if (NUM2LONG(cmp) < 0)
+ memo->u1.value = i;
}
return Qnil;
}
@@ -229,40 +223,43 @@ static VALUE
enum_min(obj)
VALUE obj;
{
- VALUE min = Qnil;
+ NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
- rb_iterate(rb_each, obj, iterator_p()?min_ii:min_i, (VALUE)&min);
- return min;
+ rb_iterate(rb_each, obj, rb_block_given_p()?min_ii:min_i, (VALUE)memo);
+ rb_gc_force_recycle((VALUE)memo);
+ return memo->u1.value;
}
static VALUE
-max_i(i, max)
- VALUE i, *max;
+max_i(i, memo)
+ VALUE i;
+ NODE *memo;
{
VALUE cmp;
- if (NIL_P(*max))
- *max = i;
+ if (NIL_P(memo->u1.value))
+ memo->u1.value = i;
else {
- cmp = rb_funcall(i, id_cmp, 1, *max);
- if (FIX2INT(cmp) > 0)
- *max = i;
+ cmp = rb_funcall(i, id_cmp, 1, memo->u1.value);
+ if (NUM2LONG(cmp) > 0)
+ memo->u1.value = i;
}
return Qnil;
}
static VALUE
-max_ii(i, max)
- VALUE i, *max;
+max_ii(i, memo)
+ VALUE i;
+ NODE *memo;
{
VALUE cmp;
- if (NIL_P(*max))
- *max = i;
+ if (NIL_P(memo->u1.value))
+ memo->u1.value = i;
else {
- cmp = rb_yield(assoc_new(i, *max));
- if (FIX2INT(cmp) > 0)
- *max = i;
+ cmp = rb_yield(rb_assoc_new(i, memo->u1.value));
+ if (NUM2LONG(cmp) > 0)
+ memo->u1.value = i;
}
return Qnil;
}
@@ -271,54 +268,20 @@ static VALUE
enum_max(obj)
VALUE obj;
{
- VALUE max = Qnil;
-
- rb_iterate(rb_each, obj, iterator_p()?max_ii:max_i, (VALUE)&max);
- return max;
-}
-
-struct i_v_pair {
- int i;
- VALUE v;
- int found;
-};
-
-static VALUE
-index_i(item, iv)
- VALUE item;
- struct i_v_pair *iv;
-{
- if (rb_equal(item, iv->v)) {
- iv->found = 1;
- rb_iter_break();
- }
- else {
- iv->i++;
- }
- return Qnil;
-}
+ NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
-static VALUE
-enum_index(obj, val)
- VALUE obj, val;
-{
- struct i_v_pair iv;
-
- iv.i = 0;
- iv.v = val;
- iv.found = 0;
- rb_iterate(rb_each, obj, index_i, (VALUE)&iv);
- if (iv.found) return INT2FIX(iv.i);
- return Qnil; /* not found */
+ rb_iterate(rb_each, obj, rb_block_given_p()?max_ii:max_i, (VALUE)memo);
+ rb_gc_force_recycle((VALUE)memo);
+ return memo->u1.value;
}
static VALUE
-member_i(item, iv)
+member_i(item, memo)
VALUE item;
- struct i_v_pair *iv;
+ NODE *memo;
{
- if (rb_equal(item, iv->v)) {
- iv->i = 1;
+ if (rb_equal(item, memo->u1.value)) {
+ memo->u2.value = Qtrue;
rb_iter_break();
}
return Qnil;
@@ -328,74 +291,59 @@ static VALUE
enum_member(obj, val)
VALUE obj, val;
{
- struct i_v_pair iv;
-
- iv.i = 0;
- iv.v = val;
- rb_iterate(rb_each, obj, member_i, (VALUE)&iv);
- if (iv.i) return TRUE;
- return FALSE;
-}
-
-static VALUE
-length_i(i, length)
- VALUE i;
- int *length;
-{
- (*length)++;
- return Qnil;
-}
+ VALUE result;
-VALUE
-enum_length(obj)
- VALUE obj;
-{
- int length = 0;
+ NODE *memo = rb_node_newnode(NODE_MEMO, val, Qfalse, 0);
- rb_iterate(rb_each, obj, length_i, (VALUE)&length);
- return INT2FIX(length);
+ rb_iterate(rb_each, obj, member_i, (VALUE)memo);
+ result = memo->u2.value;
+ rb_gc_force_recycle((VALUE)memo);
+ return result;
}
-each_with_index_i(val, indexp)
+static VALUE
+each_with_index_i(val, memo)
VALUE val;
- int *indexp;
+ NODE *memo;
{
- rb_yield(assoc_new(val, INT2FIX(*indexp)));
- (*indexp)++;
+ rb_yield(rb_assoc_new(val, INT2FIX(memo->u3.cnt)));
+ memo->u3.cnt++;
return Qnil;
}
-VALUE
+static VALUE
enum_each_with_index(obj)
VALUE obj;
{
- int index = 0;
+ NODE *memo = rb_node_newnode(NODE_MEMO, 0, 0, 0);
- rb_iterate(rb_each, obj, each_with_index_i, (VALUE)&index);
+ rb_iterate(rb_each, obj, each_with_index_i, (VALUE)memo);
+ rb_gc_force_recycle((VALUE)memo);
return Qnil;
}
void
Init_Enumerable()
{
- mEnumerable = rb_define_module("Enumerable");
-
- rb_define_method(mEnumerable,"to_a", enum_to_a, 0);
-
- rb_define_method(mEnumerable,"sort", enum_sort, 0);
- rb_define_method(mEnumerable,"grep", enum_grep, 1);
- rb_define_method(mEnumerable,"find", enum_find, -1);
- rb_define_method(mEnumerable,"find_all", enum_find_all, 0);
- rb_define_method(mEnumerable,"collect", enum_collect, 0);
- rb_define_method(mEnumerable,"reverse", enum_reverse, 0);
- rb_define_method(mEnumerable,"min", enum_min, 0);
- rb_define_method(mEnumerable,"max", enum_max, 0);
- rb_define_method(mEnumerable,"index", enum_index, 1);
- rb_define_method(mEnumerable,"member?", enum_member, 1);
- rb_define_method(mEnumerable,"include?", enum_member, 1);
- rb_define_method(mEnumerable,"length", enum_length, 0);
- rb_define_method(mEnumerable,"size", enum_length, 0);
- rb_define_method(mEnumerable,"each_with_index", enum_each_with_index, 0);
+ rb_mEnumerable = rb_define_module("Enumerable");
+
+ rb_define_method(rb_mEnumerable,"to_a", enum_to_a, 0);
+ rb_define_method(rb_mEnumerable,"entries", enum_to_a, 0);
+
+ rb_define_method(rb_mEnumerable,"sort", enum_sort, 0);
+ rb_define_method(rb_mEnumerable,"grep", enum_grep, 1);
+ rb_define_method(rb_mEnumerable,"find", enum_find, -1);
+ rb_define_method(rb_mEnumerable,"detect", enum_find, -1);
+ rb_define_method(rb_mEnumerable,"find_all", enum_find_all, 0);
+ rb_define_method(rb_mEnumerable,"select", enum_find_all, 0);
+ rb_define_method(rb_mEnumerable,"reject", enum_reject, 0);
+ rb_define_method(rb_mEnumerable,"collect", enum_collect, 0);
+ rb_define_method(rb_mEnumerable,"map", enum_collect, 0);
+ rb_define_method(rb_mEnumerable,"min", enum_min, 0);
+ rb_define_method(rb_mEnumerable,"max", enum_max, 0);
+ rb_define_method(rb_mEnumerable,"member?", enum_member, 1);
+ rb_define_method(rb_mEnumerable,"include?", enum_member, 1);
+ rb_define_method(rb_mEnumerable,"each_with_index", enum_each_with_index, 0);
id_eqq = rb_intern("===");
id_each = rb_intern("each");
diff --git a/env.h b/env.h
index b254ddef1c..7060fbec8f 100644
--- a/env.h
+++ b/env.h
@@ -1,13 +1,15 @@
-/************************************************
+/**********************************************************************
env.h -
$Author$
- $Revision$
$Date$
created at: Mon Jul 11 11:53:03 JST 1994
-************************************************/
+ Copyright (C) 1993-2000 Yukihiro Matsumoto
+
+**********************************************************************/
+
#ifndef ENV_H
#define ENV_H
@@ -19,27 +21,33 @@ extern struct FRAME {
VALUE last_class;
VALUE cbase;
struct FRAME *prev;
+ struct FRAME *tmp;
char *file;
int line;
int iter;
-} *the_frame;
+ int flags;
+} *ruby_frame;
+
+void rb_gc_mark_frame _((struct FRAME *));
-void gc_mark_frame _((struct FRAME *));
+#define FRAME_ALLOCA 0
+#define FRAME_MALLOC 1
extern struct SCOPE {
struct RBasic super;
ID *local_tbl;
VALUE *local_vars;
int flag;
-} *the_scope;
+} *ruby_scope;
#define SCOPE_ALLOCA 0
#define SCOPE_MALLOC 1
#define SCOPE_NOSTACK 2
+#define SCOPE_DONT_RECYCLE 4
-extern int rb_in_eval;
+extern int ruby_in_eval;
-extern VALUE the_class;
+extern VALUE ruby_class;
struct RVarmap {
struct RBasic super;
@@ -47,6 +55,6 @@ struct RVarmap {
VALUE val;
struct RVarmap *next;
};
-extern struct RVarmap *the_dyna_vars;
+extern struct RVarmap *ruby_dyna_vars;
#endif /* ENV_H */
diff --git a/error.c b/error.c
index a4e433a869..6a008cdac5 100644
--- a/error.c
+++ b/error.c
@@ -1,4 +1,4 @@
-/************************************************
+/**********************************************************************
error.c -
@@ -6,147 +6,181 @@
$Date$
created at: Mon Aug 9 16:11:34 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-2000 Yukihiro Matsumoto
-************************************************/
+**********************************************************************/
#include "ruby.h"
#include "env.h"
+#include "version.h"
+
#include <stdio.h>
+#ifdef HAVE_STDARG_PROTOTYPES
+#include <stdarg.h>
+#define va_init_list(a,b) va_start(a,b)
+#else
#include <varargs.h>
+#define va_init_list(a,b) va_start(a)
+#endif
-extern char *sourcefile;
-extern int sourceline;
+#if defined __CYGWIN__
+# include <cygwin/version.h>
+# if (CYGWIN_VERSION_API_MAJOR > 0) || (CYGWIN_VERSION_API_MINOR >= 8)
+# define sys_nerr _sys_nerr
+# endif
+#endif
-int nerrs;
+int ruby_nerrs;
static void
-err_sprintf(buf, fmt, args)
+err_snprintf(buf, len, fmt, args)
char *buf, *fmt;
+ int len;
va_list args;
{
- if (!sourcefile) {
- vsprintf(buf, fmt, args);
- }
- else {
- sprintf(buf, "%s:%d: ", sourcefile, sourceline);
- vsprintf((char*)buf+strlen(buf), fmt, args);
- }
-}
+ int n;
-static void
-err_append(s)
- char *s;
-{
- extern VALUE errinfo;
-
- if (rb_in_eval) {
- if (NIL_P(errinfo)) {
- errinfo = str_new2(s);
- }
- else {
- str_cat(errinfo, "\n", 1);
- str_cat(errinfo, s, strlen(s));
- }
+ if (!ruby_sourcefile) {
+ vsnprintf(buf, len, fmt, args);
+ return;
+ }
+ else if (ruby_sourceline == 0) {
+ n = snprintf(buf, len, "%s: ", ruby_sourcefile);
}
else {
- fputs(s, stderr);
- fputs("\n", stderr);
- fflush(stderr);
+ n = snprintf(buf, len, "%s:%d: ", ruby_sourcefile, ruby_sourceline);
+ }
+ if (len > n) {
+ vsnprintf((char*)buf+n, len-n, fmt, args);
}
}
+static void err_append _((const char*));
static void
err_print(fmt, args)
- char *fmt;
+ const char *fmt;
va_list args;
{
char buf[BUFSIZ];
- err_sprintf(buf, fmt, args);
+ err_snprintf(buf, BUFSIZ, fmt, args);
err_append(buf);
}
void
-Error(fmt, va_alist)
- char *fmt;
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_compile_error(const char *fmt, ...)
+#else
+rb_compile_error(fmt, va_alist)
+ const char *fmt;
va_dcl
+#endif
{
va_list args;
- va_start(args);
+ va_init_list(args, fmt);
err_print(fmt, args);
va_end(args);
- nerrs++;
+ ruby_nerrs++;
}
void
-Error_Append(fmt, va_alist)
- char *fmt;
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_compile_error_append(const char *fmt, ...)
+#else
+rb_compile_error_append(fmt, va_alist)
+ const char *fmt;
va_dcl
+#endif
{
va_list args;
char buf[BUFSIZ];
- va_start(args);
- vsprintf(buf, fmt, args);
+ va_init_list(args, fmt);
+ vsnprintf(buf, BUFSIZ, fmt, args);
va_end(args);
err_append(buf);
}
+static void
+warn_print(fmt, args)
+ const char *fmt;
+ va_list args;
+{
+ char buf[BUFSIZ];
+
+ err_snprintf(buf, BUFSIZ, fmt, args);
+ fputs(buf, stderr);
+ fputs("\n", stderr);
+ fflush(stderr);
+}
+
void
-Warn(fmt, va_alist)
- char *fmt;
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_warn(const char *fmt, ...)
+#else
+rb_warn(fmt, va_alist)
+ const char *fmt;
va_dcl
+#endif
{
char buf[BUFSIZ];
va_list args;
- sprintf(buf, "warning: %s", fmt);
+ snprintf(buf, BUFSIZ, "warning: %s", fmt);
- va_start(args);
- err_print(buf, args);
+ va_init_list(args, fmt);
+ warn_print(buf, args);
va_end(args);
}
-/* Warning() reports only in verbose mode */
+/* rb_warning() reports only in verbose mode */
void
-Warning(fmt, va_alist)
- char *fmt;
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_warning(const char *fmt, ...)
+#else
+rb_warning(fmt, va_alist)
+ const char *fmt;
va_dcl
+#endif
{
char buf[BUFSIZ];
va_list args;
- if (!RTEST(verbose)) return;
+ if (!RTEST(ruby_verbose)) return;
- sprintf(buf, "warning: %s", fmt);
+ snprintf(buf, BUFSIZ, "warning: %s", fmt);
- va_start(args);
- err_print(buf, args);
+ va_init_list(args, fmt);
+ warn_print(buf, args);
va_end(args);
}
void
-Bug(fmt, va_alist)
- char *fmt;
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_bug(const char *fmt, ...)
+#else
+rb_bug(fmt, va_alist)
+ const char *fmt;
va_dcl
+#endif
{
char buf[BUFSIZ];
va_list args;
- sprintf(buf, "[BUG] %s", fmt);
- rb_in_eval = 0;
+ snprintf(buf, BUFSIZ, "[BUG] %s", fmt);
+ ruby_in_eval = 0;
- va_start(args);
- err_print(buf, args);
+ va_init_list(args, fmt);
+ warn_print(buf, args);
va_end(args);
+ fprintf(stderr, "ruby %s (%s) [%s]\n", RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM);
abort();
}
static struct types {
int type;
- char *name;
+ const char *name;
} builtin_types[] = {
T_NIL, "nil",
T_OBJECT, "Object",
@@ -162,27 +196,30 @@ static struct types {
T_STRUCT, "Struct",
T_BIGNUM, "Bignum",
T_FILE, "File",
- T_TRUE, "TRUE",
- T_FALSE, "FALSE",
+ T_TRUE, "true",
+ T_FALSE, "false",
+ T_SYMBOL, "Symbol", /* :symbol */
T_DATA, "Data", /* internal use: wrapped C pointers */
T_MATCH, "Match", /* data of $~ */
T_VARMAP, "Varmap", /* internal use: dynamic variables */
T_SCOPE, "Scope", /* internal use: variable scope */
T_NODE, "Node", /* internal use: syntax tree node */
+ T_UNDEF, "undef", /* internal use: #undef; should not happen */
-1, 0,
};
-extern void TypeError();
-
void
rb_check_type(x, t)
VALUE x;
int t;
{
struct types *type = builtin_types;
- int tt = TYPE(x);
- if (tt != t) {
+ if (x == Qundef) {
+ rb_bug("undef leaked to the Ruby space");
+ }
+
+ if (TYPE(x) != t) {
while (type->type >= 0) {
if (type->type == t) {
char *etype;
@@ -194,313 +231,505 @@ rb_check_type(x, t)
etype = "Fixnum";
}
else if (rb_special_const_p(x)) {
- etype = RSTRING(obj_as_string(x))->ptr;
+ etype = RSTRING(rb_obj_as_string(x))->ptr;
}
else {
etype = rb_class2name(CLASS_OF(x));
}
- TypeError("wrong argument type %s (expected %s)",
- etype, type->name);
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected %s)",
+ etype, type->name);
}
type++;
}
- Bug("unknown type 0x%x", t);
+ rb_bug("unknown type 0x%x", t);
}
}
/* exception classes */
-#include "errno.h"
-
-extern VALUE cString;
-VALUE eGlobalExit, eException;
-VALUE eSystemExit, eInterrupt, eFatal;
-VALUE eRuntimeError;
-VALUE eSyntaxError;
-VALUE eTypeError;
-VALUE eArgError;
-VALUE eNameError;
-VALUE eIndexError;
-VALUE eNotImpError;
-VALUE eLoadError;
-VALUE eSecurityError;
-
-VALUE eSystemCallError;
-VALUE mErrno;
+#include <errno.h>
+
+VALUE rb_eException;
+VALUE rb_eSystemExit;
+VALUE rb_eInterrupt;
+VALUE rb_eSignal;
+VALUE rb_eFatal;
+VALUE rb_eStandardError;
+VALUE rb_eRuntimeError;
+VALUE rb_eTypeError;
+VALUE rb_eArgError;
+VALUE rb_eIndexError;
+VALUE rb_eRangeError;
+VALUE rb_eSecurityError;
+VALUE rb_eNotImpError;
+VALUE rb_eNoMemError;
+
+VALUE rb_eScriptError;
+VALUE rb_eNameError;
+VALUE rb_eSyntaxError;
+VALUE rb_eLoadError;
+
+VALUE rb_eSystemCallError;
+VALUE rb_mErrno;
VALUE
-exc_new(etype, ptr, len)
+rb_exc_new(etype, ptr, len)
VALUE etype;
- char *ptr;
- UINT len;
+ const char *ptr;
+ long len;
{
- NEWOBJ(exc, struct RString);
- OBJSETUP(exc, etype, T_STRING);
+ VALUE exc = rb_obj_alloc(etype);
- exc->len = len;
- exc->orig = 0;
- exc->ptr = ALLOC_N(char,len+1);
- if (ptr) {
- memcpy(exc->ptr, ptr, len);
- }
- exc->ptr[len] = '\0';
- return (VALUE)exc;
+ rb_iv_set(exc, "mesg", rb_str_new(ptr, len));
+ return exc;
}
VALUE
-exc_new2(etype, s)
+rb_exc_new2(etype, s)
VALUE etype;
- char *s;
+ const char *s;
{
- return exc_new(etype, s, strlen(s));
+ return rb_exc_new(etype, s, strlen(s));
}
VALUE
-exc_new3(etype, str)
+rb_exc_new3(etype, str)
VALUE etype, str;
{
- Check_Type(str, T_STRING);
- return exc_new(etype, RSTRING(str)->ptr, RSTRING(str)->len);
+ char *s;
+ int len;
+
+ s = rb_str2cstr(str, &len);
+ return rb_exc_new(etype, s, len);
}
static VALUE
-exc_s_new(argc, argv, etype)
+exc_initialize(argc, argv, exc)
int argc;
VALUE *argv;
- VALUE etype;
+ VALUE exc;
{
- VALUE arg, exc;
+ VALUE mesg;
- if (rb_scan_args(argc, argv, "01", &arg) == 0) {
- exc = exc_new(etype, 0, 0);
+ if (rb_scan_args(argc, argv, "01", &mesg) == 1) {
+ STR2CSTR(mesg); /* ensure mesg can be converted to String */
}
- else {
- exc = exc_new3(etype, obj_as_string(arg));
+ rb_iv_set(exc, "mesg", mesg);
+
+ return exc;
+}
+
+static VALUE
+exc_exception(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
+{
+ VALUE etype, exc;
+
+ if (argc == 0) return self;
+ if (argc == 1 && self == argv[0]) return self;
+ etype = CLASS_OF(self);
+ while (FL_TEST(etype, FL_SINGLETON)) {
+ etype = RCLASS(etype)->super;
}
- obj_call_init(exc);
+ exc = rb_obj_alloc(etype);
+ rb_obj_call_init(exc, argc, argv);
+
return exc;
}
static VALUE
+exc_to_s(exc)
+ VALUE exc;
+{
+ VALUE mesg = rb_iv_get(exc, "mesg");
+
+ if (NIL_P(mesg)) return rb_class_path(CLASS_OF(exc));
+ if (OBJ_TAINTED(exc)) OBJ_TAINT(mesg);
+ return mesg;
+}
+
+static VALUE
exc_inspect(exc)
VALUE exc;
{
VALUE str, klass;
klass = CLASS_OF(exc);
+ exc = rb_obj_as_string(exc);
if (RSTRING(exc)->len == 0) {
- return str_dup(rb_class_path(klass));
+ return rb_str_dup(rb_class_path(klass));
}
- str = str_new2("#<");
+ str = rb_str_new2("#<");
klass = rb_class_path(klass);
- str_cat(str, RSTRING(klass)->ptr, RSTRING(klass)->len);
- str_cat(str, ":", 1);
- str_cat(str, RSTRING(exc)->ptr, RSTRING(exc)->len);
- str_cat(str, ">", 1);
+ rb_str_append(str, klass);
+ rb_str_cat(str, ": ", 2);
+ rb_str_append(str, exc);
+ rb_str_cat(str, ">", 1);
return str;
}
static VALUE
-exception(argc, argv)
- int argc;
- VALUE *argv;
+exc_backtrace(exc)
+ VALUE exc;
+{
+ ID bt = rb_intern("bt");
+
+ if (!rb_ivar_defined(exc, bt)) return Qnil;
+ return rb_ivar_get(exc, bt);
+}
+
+static VALUE
+check_backtrace(bt)
+ VALUE bt;
{
- void ArgError();
- VALUE v = Qnil;
int i;
- ID id;
+ static char *err = "backtrace must be Array of String";
- if (argc == 0) {
- ArgError("wrong # of arguments");
- }
- for (i=0; i<argc; i++) { /* argument check */
- id = rb_to_id(argv[i]);
- if (!rb_id2name(id)) {
- ArgError("argument needs to be symbol or string");
+ if (!NIL_P(bt)) {
+ int t = TYPE(bt);
+
+ if (t == T_STRING) return rb_ary_new3(1, bt);
+ if (t != T_ARRAY) {
+ rb_raise(rb_eTypeError, err);
}
- if (!rb_is_const_id(id)) {
- ArgError("identifier %s needs to be constant", rb_id2name(id));
+ for (i=0;i<RARRAY(bt)->len;i++) {
+ if (TYPE(RARRAY(bt)->ptr[i]) != T_STRING) {
+ rb_raise(rb_eTypeError, err);
+ }
}
}
- for (i=0; i<argc; i++) {
- v = rb_define_class_under(the_class, rb_id2name(rb_to_id(argv[i])), eException);
- }
- return v;
+ return bt;
+}
+
+static VALUE
+exc_set_backtrace(exc, bt)
+ VALUE exc;
+ VALUE bt;
+{
+ return rb_iv_set(exc, "bt", check_backtrace(bt));
}
+#ifdef __BEOS__
+typedef struct {
+ VALUE *list;
+ int n;
+} syserr_list_entry;
+
+typedef struct {
+ int ix;
+ int n;
+} syserr_index_entry;
+
+static VALUE syserr_error;
+static VALUE syserr_list_b_general[16+1];
+static VALUE syserr_list_b_os0[2+1];
+static VALUE syserr_list_b_os1[5+1];
+static VALUE syserr_list_b_os2[2+1];
+static VALUE syserr_list_b_os3[3+1];
+static VALUE syserr_list_b_os4[1+1];
+static VALUE syserr_list_b_app[15+1];
+static VALUE syserr_list_b_interface[0+1];
+static VALUE syserr_list_b_media[8+1];
+static VALUE syserr_list_b_midi[0+1];
+static VALUE syserr_list_b_storage[15+1];
+static VALUE syserr_list_b_posix[38+1];
+static VALUE syserr_list_b_mail[8+1];
+static VALUE syserr_list_b_print[1+1];
+static VALUE syserr_list_b_device[14+1];
+
+# define SYSERR_LIST_B(n) {(n), sizeof(n)/sizeof(VALUE)}
+static const syserr_list_entry syserr_list[] = {
+ SYSERR_LIST_B(syserr_list_b_general),
+ SYSERR_LIST_B(syserr_list_b_os0),
+ SYSERR_LIST_B(syserr_list_b_os1),
+ SYSERR_LIST_B(syserr_list_b_os2),
+ SYSERR_LIST_B(syserr_list_b_os3),
+ SYSERR_LIST_B(syserr_list_b_os4),
+ SYSERR_LIST_B(syserr_list_b_app),
+ SYSERR_LIST_B(syserr_list_b_interface),
+ SYSERR_LIST_B(syserr_list_b_media),
+ SYSERR_LIST_B(syserr_list_b_midi),
+ SYSERR_LIST_B(syserr_list_b_storage),
+ SYSERR_LIST_B(syserr_list_b_posix),
+ SYSERR_LIST_B(syserr_list_b_mail),
+ SYSERR_LIST_B(syserr_list_b_print),
+ SYSERR_LIST_B(syserr_list_b_device),
+};
+# undef SYSERR_LIST_B
+
+static const syserr_index_entry syserr_index[]= {
+ {0, 1}, {1, 5}, {6, 1}, {7, 1}, {8, 1}, {9, 1}, {10, 1}, {11, 1},
+ {12, 1}, {13, 1}, {14, 1}, {0, 0},
+};
+#else
static VALUE *syserr_list;
+#endif
-#ifndef NT
+#if !defined NT && !defined sys_nerr
extern int sys_nerr;
#endif
-static void
+static VALUE
set_syserr(i, name)
int i;
- char *name;
+ const char *name;
{
+#ifdef __BEOS__
+ VALUE *list;
+ int ix, offset;
+#endif
+ VALUE error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError);
+ rb_define_const(error, "Errno", INT2FIX(i));
+#ifdef __BEOS__
+ if (i == B_ERROR) {
+ syserr_error = error;
+ rb_global_variable(&syserr_error);
+ return error;
+ }
+ i -= B_GENERAL_ERROR_BASE;
+ ix = (i >> 12) & 0xf;
+ offset = (i >> 8) & 0xf;
+ if (offset < syserr_index[ix].n) {
+ ix = syserr_index[ix].ix;
+ if ((i & 0xff) < syserr_list[ix + offset].n) {
+ list = syserr_list[ix + offset].list;
+ list[i & 0xff] = error;
+ rb_global_variable(&list[i & 0xff]);
+ }
+ }
+#else
if (i <= sys_nerr) {
- syserr_list[i] = rb_define_class_under(mErrno, name, eSystemCallError);
- rb_global_variable(&syserr_list[i]);
+ syserr_list[i] = error;
}
+#endif
+ return error;
}
-static void init_syserr();
-
-void
-Init_Exception()
+static VALUE
+syserr_errno(self)
+ VALUE self;
{
- eGlobalExit = rb_define_class("GlobalExit", cString);
- rb_define_singleton_method(eGlobalExit, "new", exc_s_new, -1);
- rb_define_method(eGlobalExit, "inspect", exc_inspect, 0);
-
- eSystemExit = rb_define_class("SystemExit", eGlobalExit);
- eFatal = rb_define_class("fatal", eGlobalExit);
- eInterrupt = rb_define_class("Interrupt", eGlobalExit);
-
- eException = rb_define_class("Exception", eGlobalExit);
- eSyntaxError = rb_define_class("SyntaxError", eException);
- eTypeError = rb_define_class("TypeError", eException);
- eArgError = rb_define_class("ArgumentError", eException);
- eNameError = rb_define_class("NameError", eException);
- eIndexError = rb_define_class("IndexError", eException);
- eNotImpError = rb_define_class("NotImplementError", eException);
- eLoadError = rb_define_class("LoadError", eException);
-
- eRuntimeError = rb_define_class("RuntimeError", eException);
- eSecurityError = rb_define_class("SecurityError", eException);
-
- init_syserr();
-
- rb_define_global_function("Exception", exception, -1);
-}
-
-#define RAISE_ERROR(klass) {\
- va_list args;\
- char buf[BUFSIZ];\
-\
- va_start(args);\
- vsprintf(buf, fmt, args);\
- va_end(args);\
-\
- rb_raise(exc_new2(klass, buf));\
+ return rb_iv_get(self, "errno");
}
-void
-Raise(exc, fmt, va_alist)
- VALUE exc;
- char *fmt;
- va_dcl
+#ifdef __BEOS__
+static VALUE
+get_syserr(int i)
{
- RAISE_ERROR(exc);
+ VALUE *list;
+ int ix, offset;
+
+ if (i == B_ERROR) return syserr_error;
+ i -= B_GENERAL_ERROR_BASE;
+ ix = (i >> 12) & 0xf;
+ offset = (i >> 8) & 0xf;
+ if (offset < syserr_index[ix].n) {
+ ix = syserr_index[ix].ix;
+ if ((i & 0xff) < syserr_list[ix + offset].n) {
+ list = syserr_list[ix + offset].list;
+ return list[i & 0xff];
+ }
+ }
+ return 0;
}
+#endif /* __BEOS__ */
-void
-TypeError(fmt, va_alist)
- char *fmt;
- va_dcl
-{
- RAISE_ERROR(eTypeError);
-}
+static void init_syserr _((void));
void
-ArgError(fmt, va_alist)
- char *fmt;
- va_dcl
+Init_Exception()
{
- RAISE_ERROR(eArgError);
-}
+ rb_eException = rb_define_class("Exception", rb_cObject);
+ rb_define_singleton_method(rb_eException, "exception", rb_class_new_instance, -1);
+ rb_define_method(rb_eException, "exception", exc_exception, -1);
+ rb_define_method(rb_eException, "initialize", exc_initialize, -1);
+ rb_define_method(rb_eException, "to_s", exc_to_s, 0);
+ rb_define_method(rb_eException, "to_str", exc_to_s, 0);
+ rb_define_method(rb_eException, "message", exc_to_s, 0);
+ rb_define_method(rb_eException, "inspect", exc_inspect, 0);
+ rb_define_method(rb_eException, "backtrace", exc_backtrace, 0);
+ rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1);
+
+ rb_eSystemExit = rb_define_class("SystemExit", rb_eException);
+ rb_eFatal = rb_define_class("fatal", rb_eException);
+ rb_eInterrupt = rb_define_class("Interrupt", rb_eException);
+ rb_eSignal = rb_define_class("SignalException", rb_eException);
+
+ rb_eStandardError = rb_define_class("StandardError", rb_eException);
+ rb_eTypeError = rb_define_class("TypeError", rb_eStandardError);
+ rb_eArgError = rb_define_class("ArgumentError", rb_eStandardError);
+ rb_eIndexError = rb_define_class("IndexError", rb_eStandardError);
+ rb_eRangeError = rb_define_class("RangeError", rb_eStandardError);
+
+ rb_eScriptError = rb_define_class("ScriptError", rb_eException);
+ rb_eSyntaxError = rb_define_class("SyntaxError", rb_eScriptError);
+ rb_eNameError = rb_define_class("NameError", rb_eScriptError);
+ rb_eLoadError = rb_define_class("LoadError", rb_eScriptError);
+ rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError);
+ /* backward compatibility -- will be removed in the future */
+ rb_define_global_const("NotImplementError", rb_eNotImpError);
+
+ rb_eRuntimeError = rb_define_class("RuntimeError", rb_eStandardError);
+ rb_eSecurityError = rb_define_class("SecurityError", rb_eStandardError);
+ rb_eNoMemError = rb_define_class("NoMemoryError", rb_eException);
-void
-NameError(fmt, va_alist)
- char *fmt;
- va_dcl
-{
- RAISE_ERROR(eNameError);
+ init_syserr();
}
void
-IndexError(fmt, va_alist)
- char *fmt;
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_raise(VALUE exc, const char *fmt, ...)
+#else
+rb_raise(exc, fmt, va_alist)
+ VALUE exc;
+ const char *fmt;
va_dcl
+#endif
{
- RAISE_ERROR(eIndexError);
+ va_list args;
+ char buf[BUFSIZ];
+
+ va_init_list(args,fmt);
+ vsnprintf(buf, BUFSIZ, fmt, args);
+ va_end(args);
+ rb_exc_raise(rb_exc_new2(exc, buf));
}
void
-Fail(fmt, va_alist)
- char *fmt;
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_loaderror(const char *fmt, ...)
+#else
+rb_loaderror(fmt, va_alist)
+ const char *fmt;
va_dcl
+#endif
{
- RAISE_ERROR(eRuntimeError);
-}
+ va_list args;
+ char buf[BUFSIZ];
-void
-rb_notimplement()
-{
- Raise(eNotImpError,
- "The %s() function is unimplemented on this machine",
- rb_id2name(the_frame->last_func));
+ va_init_list(args, fmt);
+ vsnprintf(buf, BUFSIZ, fmt, args);
+ va_end(args);
+ rb_exc_raise(rb_exc_new2(rb_eLoadError, buf));
}
void
-LoadError(fmt, va_alist)
- char *fmt;
- va_dcl
+rb_notimplement()
{
- RAISE_ERROR(eLoadError);
+ rb_raise(rb_eNotImpError,
+ "The %s() function is unimplemented on this machine",
+ rb_id2name(ruby_frame->last_func));
}
void
-Fatal(fmt, va_alist)
- char *fmt;
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_fatal(const char *fmt, ...)
+#else
+rb_fatal(fmt, va_alist)
+ const char *fmt;
va_dcl
+#endif
{
va_list args;
char buf[BUFSIZ];
- va_start(args);
- vsprintf(buf, fmt, args);
+ va_init_list(args, fmt);
+ vsnprintf(buf, BUFSIZ, fmt, args);
va_end(args);
- rb_in_eval = 0;
- rb_fatal(exc_new2(eFatal, buf));
+ ruby_in_eval = 0;
+ rb_exc_fatal(rb_exc_new2(rb_eFatal, buf));
}
void
rb_sys_fail(mesg)
- char *mesg;
+ const char *mesg;
{
#ifndef NT
char *strerror();
#endif
- char buf[BUFSIZ];
+ char *err;
+ char *buf;
extern int errno;
int n = errno;
+ VALUE ee;
+
+ err = strerror(errno);
+ if (mesg) {
+ volatile VALUE tmp = rb_str_inspect(rb_str_new2(mesg));
- if (RTEST(mesg))
- sprintf(buf, "%s - %s", strerror(errno), mesg);
- else
- sprintf(buf, "%s", strerror(errno));
+ buf = ALLOCA_N(char, strlen(err)+RSTRING(tmp)->len+4);
+ sprintf(buf, "%s - %s", err, RSTRING(tmp)->ptr);
+ }
+ else {
+ buf = ALLOCA_N(char, strlen(err)+1);
+ strcpy(buf, err);
+ }
errno = 0;
+#ifdef __BEOS__
+ ee = get_syserr(n);
+ if (!ee) {
+ char name[6];
+
+ sprintf(name, "E%03d", n);
+ ee = set_syserr(n, name);
+ }
+#else
if (n > sys_nerr || !syserr_list[n]) {
char name[6];
sprintf(name, "E%03d", n);
- set_syserr(n, name);
+ ee = set_syserr(n, name);
}
- rb_raise(exc_new2(syserr_list[n], buf));
+ else {
+ ee = syserr_list[n];
+ }
+#endif
+ ee = rb_exc_new2(ee, buf);
+ rb_iv_set(ee, "errno", INT2FIX(n));
+ rb_exc_raise(ee);
+}
+
+void
+rb_load_fail(path)
+ char *path;
+{
+ rb_loaderror("%s -- %s", strerror(errno), path);
+}
+
+void
+rb_error_frozen(what)
+ char *what;
+{
+ rb_raise(rb_eTypeError, "can't modify frozen %s", what);
}
static void
init_syserr()
{
- eSystemCallError = rb_define_class("SystemCallError", eException);
- mErrno = rb_define_module("Errno");
+#ifdef __BEOS__
+ int i, ix, offset;
+#endif
+ rb_eSystemCallError = rb_define_class("SystemCallError", rb_eStandardError);
+ rb_define_method(rb_eSystemCallError, "errno", syserr_errno, 0);
+
+ rb_mErrno = rb_define_module("Errno");
+#ifdef __BEOS__
+ for (i = 0; syserr_index[i].n != 0; i++) {
+ ix = syserr_index[i].ix;
+ for (offset = 0; offset < syserr_index[i].n; offset++) {
+ MEMZERO(syserr_list[ix + offset].list, VALUE, syserr_list[ix + offset].n);
+ }
+ }
+ set_syserr(B_ERROR, "ERROR");
+#else
syserr_list = ALLOC_N(VALUE, sys_nerr+1);
MEMZERO(syserr_list, VALUE, sys_nerr+1);
+#endif
#ifdef EPERM
set_syserr(EPERM, "EPERM");
@@ -869,3 +1098,28 @@ init_syserr()
set_syserr(EDQUOT, "EDQUOT");
#endif
}
+
+static void
+err_append(s)
+ const char *s;
+{
+ extern VALUE ruby_errinfo;
+
+ if (ruby_in_eval) {
+ if (NIL_P(ruby_errinfo)) {
+ ruby_errinfo = rb_exc_new2(rb_eSyntaxError, s);
+ }
+ else {
+ VALUE str = rb_str_to_str(ruby_errinfo);
+
+ rb_str_cat2(str, "\n");
+ rb_str_cat2(str, s);
+ ruby_errinfo = rb_exc_new3(rb_eSyntaxError, str);
+ }
+ }
+ else {
+ fputs(s, stderr);
+ fputs("\n", stderr);
+ fflush(stderr);
+ }
+}
diff --git a/eval.c b/eval.c
index e2905deb01..12baccb2d7 100644
--- a/eval.c
+++ b/eval.c
@@ -1,4 +1,4 @@
-/************************************************
+/**********************************************************************
eval.c -
@@ -6,28 +6,65 @@
$Date$
created at: Thu Jun 10 14:22:17 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-2001 Yukihiro Matsumoto
+ Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
+ Copyright (C) 2000 Information-technology Promotion Agency, Japan
-************************************************/
+**********************************************************************/
#include "ruby.h"
#include "node.h"
#include "env.h"
-#include "sig.h"
+#include "rubysig.h"
#include <stdio.h>
#include <setjmp.h>
#include "st.h"
#include "dln.h"
+/* Make alloca work the best possible way. */
+#ifdef __GNUC__
+# ifndef atarist
+# ifndef alloca
+# define alloca __builtin_alloca
+# endif
+# endif /* atarist */
+#else
+# if defined(HAVE_ALLOCA_H)
+# include <alloca.h>
+# elif !defined(alloca)
+char *alloca();
+# endif
+#endif /* __GNUC__ */
+
+#ifdef _AIX
+#pragma alloca
+#endif
+
+#ifdef HAVE_STDARG_PROTOTYPES
+#include <stdarg.h>
+#define va_init_list(a,b) va_start(a,b)
+#else
+#include <varargs.h>
+#define va_init_list(a,b) va_start(a)
+#endif
+
#ifndef HAVE_STRING_H
-char *strrchr _((char*,char));
+char *strrchr _((const char*,const char));
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
+#ifdef __BEOS__
+#include <net/socket.h>
+#endif
+
+#ifdef __MACOS__
+#include "macruby_private.h"
+#endif
+
#ifndef setjmp
#ifdef HAVE__SETJMP
#define setjmp(env) _setjmp(env)
@@ -35,15 +72,43 @@ char *strrchr _((char*,char));
#endif
#endif
-VALUE cProc;
-static VALUE cBinding;
+#include <sys/types.h>
+#ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+#else
+#ifndef NT
+struct timeval {
+ long tv_sec; /* seconds */
+ long tv_usec; /* and microseconds */
+};
+#endif /* NT */
+#endif
+#include <signal.h>
+#include <errno.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
+
+#include <sys/stat.h>
+
+VALUE rb_cProc;
+static VALUE rb_cBinding;
static VALUE proc_call _((VALUE,VALUE));
-static VALUE f_binding _((VALUE));
-static void f_END _((void));
-static VALUE f_iterator_p _((void));
+static VALUE rb_f_binding _((VALUE));
+static void rb_f_END _((void));
+static VALUE rb_f_block_given_p _((void));
static VALUE block_pass _((VALUE,NODE*));
-static VALUE cMethod;
+static VALUE rb_cMethod;
static VALUE method_proc _((VALUE));
+static VALUE method_call _((int, VALUE*, VALUE));
+static VALUE rb_cUnboundMethod;
+static VALUE umethod_bind _((VALUE, VALUE));
+static VALUE rb_mod_define_method _((int, VALUE*, VALUE));
static int scope_vmode;
#define SCOPE_PUBLIC 0
@@ -54,9 +119,64 @@ static int scope_vmode;
#define SCOPE_SET(f) do {scope_vmode=(f);} while(0)
#define SCOPE_TEST(f) (scope_vmode&(f))
-#define CACHE_SIZE 0x200
-#define CACHE_MASK 0x1ff
-#define EXPR1(c,m) ((((int)(c)>>3)^(m))&CACHE_MASK)
+int ruby_safe_level = 0;
+/* safe-level:
+ 0 - strings from streams/environment/ARGV are tainted (default)
+ 1 - no dangerous operation by tainted value
+ 2 - process/file operations prohibited
+ 3 - all genetated objects are tainted
+ 4 - no global (non-tainted) variable modification/no direct output
+*/
+
+static VALUE safe_getter _((void));
+static void safe_setter _((VALUE val));
+
+void
+rb_secure(level)
+ int level;
+{
+ if (level <= ruby_safe_level) {
+ rb_raise(rb_eSecurityError, "Insecure operation `%s' at level %d",
+ rb_id2name(ruby_frame->last_func), ruby_safe_level);
+ }
+}
+
+void
+rb_check_safe_str(x)
+ VALUE x;
+{
+ if (ruby_safe_level > 0 && OBJ_TAINTED(x)){
+ if (ruby_frame->last_func) {
+ rb_raise(rb_eSecurityError, "Insecure operation - %s",
+ rb_id2name(ruby_frame->last_func));
+ }
+ else {
+ rb_raise(rb_eSecurityError, "Insecure operation: -r");
+ }
+ }
+ rb_secure(4);
+ if (TYPE(x)!= T_STRING) {
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected String)",
+ rb_class2name(CLASS_OF(x)));
+ }
+}
+
+static void print_undef _((VALUE, ID)) NORETURN;
+static void
+print_undef(klass, id)
+ VALUE klass;
+ ID id;
+{
+ rb_raise(rb_eNameError, "undefined method `%s' for %s `%s'",
+ rb_id2name(id),
+ (TYPE(klass) == T_MODULE)?"module":"class",
+ rb_class2name(klass));
+}
+
+
+#define CACHE_SIZE 0x800
+#define CACHE_MASK 0x7ff
+#define EXPR1(c,m) ((((c)>>3)^(m))&CACHE_MASK)
struct cache_entry { /* method hash table. */
ID mid; /* method's id */
@@ -105,7 +225,14 @@ rb_add_method(klass, mid, node, noex)
{
NODE *body;
- if (NIL_P(klass)) klass = cObject;
+ if (NIL_P(klass)) klass = rb_cObject;
+ if (klass == rb_cObject) {
+ rb_secure(4);
+ }
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't define method");
+ }
+ if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
body = NEW_METHOD(node, noex);
st_insert(RCLASS(klass)->m_tbl, mid, body);
}
@@ -117,6 +244,7 @@ search_method(klass, id, origin)
{
NODE *body;
+ if (!klass) return 0;
while (!st_lookup(RCLASS(klass)->m_tbl, id, &body)) {
klass = RCLASS(klass)->super;
if (!klass) return 0;
@@ -135,13 +263,20 @@ rb_get_method_body(klassp, idp, noexp)
ID id = *idp;
VALUE klass = *klassp;
VALUE origin;
- NODE *body;
+ NODE * volatile body;
struct cache_entry *ent;
- if ((body = search_method(klass, id, &origin)) == 0) {
+ if ((body = search_method(klass, id, &origin)) == 0 || !body->nd_body) {
+ /* store empty info in cache */
+ ent = cache + EXPR1(klass, id);
+ ent->klass = klass;
+ ent->origin = klass;
+ ent->mid = ent->mid0 = id;
+ ent->noex = 0;
+ ent->method = 0;
+
return 0;
}
- if (!body->nd_body) return 0;
/* store in cache */
ent = cache + EXPR1(klass, id);
@@ -166,36 +301,6 @@ rb_get_method_body(klassp, idp, noexp)
return body;
}
-void
-rb_alias(klass, name, def)
- VALUE klass;
- ID name, def;
-{
- VALUE origin;
- NODE *orig, *body;
-
- if (name == def) return;
- orig = search_method(klass, def, &origin);
- if (!orig || !orig->nd_body) {
- if (TYPE(klass) == T_MODULE) {
- orig = search_method(cObject, def, &origin);
- }
- }
- if (!orig || !orig->nd_body) {
- NameError("undefined method `%s' for `%s'",
- rb_id2name(def), rb_class2name(klass));
- }
- body = orig->nd_body;
- if (nd_type(body) == NODE_FBODY) { /* was alias */
- body = body->nd_head;
- def = body->nd_mid;
- origin = body->nd_orig;
- }
-
- st_insert(RCLASS(klass)->m_tbl, name,
- NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex));
-}
-
static void
remove_method(klass, mid)
VALUE klass;
@@ -203,9 +308,16 @@ remove_method(klass, mid)
{
NODE *body;
+ if (klass == rb_cObject) {
+ rb_secure(4);
+ }
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't remove method");
+ }
+ if (OBJ_FROZEN(klass)) rb_error_frozen("class/module");
if (!st_delete(RCLASS(klass)->m_tbl, &mid, &body)) {
- NameError("method `%s' not defined in %s",
- rb_id2name(mid), rb_class2name(klass));
+ rb_raise(rb_eNameError, "method `%s' not defined in %s",
+ rb_id2name(mid), rb_class2name(klass));
}
rb_clear_cache_by_id(mid);
}
@@ -213,15 +325,23 @@ remove_method(klass, mid)
void
rb_remove_method(klass, name)
VALUE klass;
- char *name;
+ const char *name;
{
remove_method(klass, rb_intern(name));
}
+static VALUE
+rb_mod_remove_method(mod, name)
+ VALUE mod, name;
+{
+ remove_method(mod, rb_to_id(name));
+ return mod;
+}
+
void
rb_disable_super(klass, name)
VALUE klass;
- char *name;
+ const char *name;
{
VALUE origin;
NODE *body;
@@ -229,89 +349,96 @@ rb_disable_super(klass, name)
body = search_method(klass, mid, &origin);
if (!body || !body->nd_body) {
- NameError("undefined method `%s' for `%s'",
- rb_id2name(mid), rb_class2name(klass));
+ print_undef(klass, mid);
}
if (origin == klass) {
body->nd_noex |= NOEX_UNDEF;
}
else {
+ rb_add_method(klass, mid, 0, NOEX_UNDEF);
rb_clear_cache_by_id(mid);
- rb_add_method(the_class, mid, 0, NOEX_UNDEF);
}
}
void
rb_enable_super(klass, name)
VALUE klass;
- char *name;
+ const char *name;
{
VALUE origin;
NODE *body;
ID mid = rb_intern(name);
body = search_method(klass, mid, &origin);
- if (!body || !body->nd_body || origin != klass) {
- NameError("undefined method `%s' for `%s'",
- rb_id2name(mid), rb_class2name(klass));
+ if (!body) {
+ print_undef(klass, mid);
+ }
+ if (!body->nd_body) {
+ remove_method(klass, mid);
+ }
+ else {
+ body->nd_noex &= ~NOEX_UNDEF;
}
- body->nd_noex &= ~NOEX_UNDEF;
}
static void
rb_export_method(klass, name, noex)
VALUE klass;
ID name;
- int noex;
+ ID noex;
{
NODE *body;
VALUE origin;
+ if (klass == rb_cObject) {
+ rb_secure(4);
+ }
body = search_method(klass, name, &origin);
if (!body && TYPE(klass) == T_MODULE) {
- body = search_method(cObject, name, &origin);
+ body = search_method(rb_cObject, name, &origin);
}
if (!body) {
- NameError("undefined method `%s' for `%s'",
- rb_id2name(name), rb_class2name(klass));
+ print_undef(klass, name);
}
if (body->nd_noex != noex) {
if (klass == origin) {
body->nd_noex = noex;
}
else {
- rb_clear_cache_by_id(name);
rb_add_method(klass, name, NEW_ZSUPER(), noex);
+ rb_clear_cache_by_id(name);
}
}
}
-static VALUE
-method_boundp(klass, id, ex)
+int
+rb_method_boundp(klass, id, ex)
VALUE klass;
ID id;
int ex;
{
+ struct cache_entry *ent;
int noex;
+ /* is it in the method cache? */
+ ent = cache + EXPR1(klass, id);
+ if (ent->mid == id && ent->klass == klass) {
+ if (ex && (ent->noex & NOEX_PRIVATE))
+ return Qfalse;
+ if (!ent->method) return Qfalse;
+ return Qtrue;
+ }
if (rb_get_method_body(&klass, &id, &noex)) {
- if (ex && noex & NOEX_PRIVATE)
- return FALSE;
- return TRUE;
+ if (ex && (noex & NOEX_PRIVATE))
+ return Qfalse;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
-int
-rb_method_boundp(klass, id, ex)
- VALUE klass;
- ID id;
- int ex;
-{
- if (method_boundp(klass, id, ex))
- return TRUE;
- return FALSE;
-}
+static ID init, eqq, each, aref, aset, match, to_ary;
+static ID missing, added, singleton_added;
+static ID __id__, __send__;
void
rb_attr(klass, id, read, write, ex)
@@ -319,16 +446,16 @@ rb_attr(klass, id, read, write, ex)
ID id;
int read, write, ex;
{
- char *name;
+ const char *name;
char *buf;
- ID attr, attreq, attriv;
+ ID attriv;
int noex;
if (!ex) noex = NOEX_PUBLIC;
else {
if (SCOPE_TEST(SCOPE_PRIVATE)) {
noex = NOEX_PRIVATE;
- Warning("private attribute?");
+ rb_warning("private attribute?");
}
else if (SCOPE_TEST(SCOPE_PROTECTED)) {
noex = NOEX_PROTECTED;
@@ -339,56 +466,66 @@ rb_attr(klass, id, read, write, ex)
}
name = rb_id2name(id);
- attr = rb_intern(name);
+ if (!name) {
+ rb_raise(rb_eArgError, "argument needs to be symbol or string");
+ }
buf = ALLOCA_N(char,strlen(name)+2);
- sprintf(buf, "%s=", name);
- attreq = rb_intern(buf);
sprintf(buf, "@%s", name);
attriv = rb_intern(buf);
if (read) {
- rb_add_method(klass, attr, NEW_IVAR(attriv), noex);
+ rb_add_method(klass, id, NEW_IVAR(attriv), noex);
+ rb_clear_cache_by_id(id);
+ rb_funcall(klass, added, 1, ID2SYM(id));
}
if (write) {
- rb_add_method(klass, attreq, NEW_ATTRSET(attriv), noex);
+ sprintf(buf, "%s=", name);
+ id = rb_intern(buf);
+ rb_add_method(klass, id, NEW_ATTRSET(attriv), noex);
+ rb_clear_cache_by_id(id);
+ rb_funcall(klass, added, 1, ID2SYM(id));
}
}
-static ID init, eqq, each, aref, aset, match;
-VALUE errinfo = Qnil, errat = Qnil;
-extern NODE *eval_tree0;
-extern NODE *eval_tree;
-extern int nerrs;
+extern int ruby_in_compile;
-extern VALUE mKernel;
-extern VALUE cModule;
-extern VALUE eFatal;
-extern VALUE eGlobalExit;
-extern VALUE eInterrupt;
-extern VALUE eSystemExit;
-extern VALUE eException;
-extern VALUE eRuntimeError;
-extern VALUE eSyntaxError;
-static VALUE eLocalJumpError;
-static VALUE eSysStackError;
-extern VALUE eSecurityError;
+VALUE ruby_errinfo = Qnil;
+extern NODE *ruby_eval_tree_begin;
+extern NODE *ruby_eval_tree;
+extern int ruby_nerrs;
-extern VALUE TopSelf;
+static VALUE rb_eLocalJumpError;
+static VALUE rb_eSysStackError;
-struct FRAME *the_frame;
-struct SCOPE *the_scope;
+extern VALUE ruby_top_self;
+
+struct FRAME *ruby_frame;
+struct SCOPE *ruby_scope;
static struct FRAME *top_frame;
static struct SCOPE *top_scope;
#define PUSH_FRAME() { \
struct FRAME _frame; \
- _frame.prev = the_frame; \
- _frame.file = sourcefile; \
- _frame.line = sourceline; \
- _frame.iter = the_iter->iter; \
- _frame.cbase = the_frame->cbase; \
- the_frame = &_frame; \
-
-#define POP_FRAME() the_frame = _frame.prev; }
+ _frame.prev = ruby_frame; \
+ _frame.tmp = 0; \
+ _frame.file = ruby_sourcefile; \
+ _frame.line = ruby_sourceline; \
+ _frame.iter = ruby_iter->iter; \
+ _frame.cbase = ruby_frame->cbase; \
+ _frame.argc = 0; \
+ _frame.argv = 0; \
+ _frame.flags = FRAME_ALLOCA; \
+ ruby_frame = &_frame; \
+
+#define POP_FRAME() \
+ ruby_sourcefile = _frame.file; \
+ ruby_sourceline = _frame.line; \
+ ruby_frame = _frame.prev; }
+
+struct BLOCKTAG {
+ struct RBasic super;
+ long dst;
+ long flags;
+};
struct BLOCK {
NODE *var;
@@ -396,97 +533,123 @@ struct BLOCK {
VALUE self;
struct FRAME frame;
struct SCOPE *scope;
+ struct BLOCKTAG *tag;
VALUE klass;
- struct tag *tag;
int iter;
int vmode;
- struct RVarmap *d_vars;
-#ifdef THREAD
+ int flags;
+ struct RVarmap *dyna_vars;
VALUE orig_thread;
-#endif
struct BLOCK *prev;
};
-static struct BLOCK *the_block;
+
+#define BLOCK_D_SCOPE 1
+#define BLOCK_DYNAMIC 2
+#define BLOCK_ORPHAN 4
+
+static struct BLOCK *ruby_block;
+
+static struct BLOCKTAG*
+new_blktag()
+{
+ NEWOBJ(blktag, struct BLOCKTAG);
+ OBJSETUP(blktag, 0, T_BLKTAG);
+ blktag->dst = 0;
+ blktag->flags = 0;
+ return blktag;
+}
#define PUSH_BLOCK(v,b) { \
struct BLOCK _block; \
- _block.tag = prot_tag; \
+ _block.tag = new_blktag(); \
_block.var = v; \
_block.body = b; \
_block.self = self; \
- _block.frame = *the_frame; \
- _block.klass = the_class; \
- _block.frame.file = sourcefile; \
- _block.frame.line = sourceline; \
- _block.scope = the_scope; \
- _block.d_vars = the_dyna_vars; \
- _block.prev = the_block; \
- _block.iter = the_iter->iter; \
+ _block.frame = *ruby_frame; \
+ _block.klass = ruby_class; \
+ _block.frame.file = ruby_sourcefile;\
+ _block.frame.line = ruby_sourceline;\
+ _block.scope = ruby_scope; \
+ _block.prev = ruby_block; \
+ _block.iter = ruby_iter->iter; \
_block.vmode = scope_vmode; \
- the_block = &_block;
+ _block.flags = BLOCK_D_SCOPE; \
+ _block.dyna_vars = ruby_dyna_vars; \
+ ruby_block = &_block;
-#define PUSH_BLOCK2(b) { \
- struct BLOCK _block; \
- _block = *b; \
- _block.prev = the_block; \
- the_block = &_block;
+#define POP_BLOCK_TAG(tag) do { \
+ if ((tag)->flags & BLOCK_DYNAMIC) \
+ (tag)->flags |= BLOCK_ORPHAN; \
+ else \
+ rb_gc_force_recycle((VALUE)tag); \
+} while (0)
#define POP_BLOCK() \
- the_block = _block.prev; \
+ POP_BLOCK_TAG(_block.tag); \
+ ruby_block = _block.prev; \
}
-struct RVarmap *the_dyna_vars;
+struct RVarmap *ruby_dyna_vars;
#define PUSH_VARS() { \
struct RVarmap * volatile _old; \
- _old = the_dyna_vars; \
- the_dyna_vars = 0;
+ _old = ruby_dyna_vars; \
+ ruby_dyna_vars = 0;
#define POP_VARS() \
- the_dyna_vars = _old; \
+ if (_old && (ruby_scope->flag & SCOPE_DONT_RECYCLE)) \
+ FL_SET(_old, DVAR_DONT_RECYCLE); \
+ ruby_dyna_vars = _old; \
}
+#define DVAR_DONT_RECYCLE FL_USER2
+
static struct RVarmap*
-new_dvar(id, value)
+new_dvar(id, value, prev)
ID id;
VALUE value;
+ struct RVarmap *prev;
{
NEWOBJ(vars, struct RVarmap);
OBJSETUP(vars, 0, T_VARMAP);
vars->id = id;
vars->val = value;
- if (id == 0) {
- vars->next = the_dyna_vars;
- }
- else if (the_dyna_vars) {
- vars->next = the_dyna_vars->next;
- the_dyna_vars->next = vars;
- }
- else { /* complie time dyna_var check */
- vars->next = the_dyna_vars;
- the_dyna_vars = vars;
- }
+ vars->next = prev;
return vars;
}
VALUE
-dyna_var_defined(id)
+rb_dvar_defined(id)
+ ID id;
+{
+ struct RVarmap *vars = ruby_dyna_vars;
+
+ while (vars) {
+ if (vars->id == id) return Qtrue;
+ vars = vars->next;
+ }
+ return Qfalse;
+}
+
+VALUE
+rb_dvar_curr(id)
ID id;
{
- struct RVarmap *vars = the_dyna_vars;
+ struct RVarmap *vars = ruby_dyna_vars;
while (vars) {
- if (vars->id == id) return TRUE;
+ if (vars->id == 0) break;
+ if (vars->id == id) return Qtrue;
vars = vars->next;
}
- return FALSE;
+ return Qfalse;
}
VALUE
-dyna_var_ref(id)
+rb_dvar_ref(id)
ID id;
{
- struct RVarmap *vars = the_dyna_vars;
+ struct RVarmap *vars = ruby_dyna_vars;
while (vars) {
if (vars->id == id) {
@@ -497,29 +660,64 @@ dyna_var_ref(id)
return Qnil;
}
-VALUE
-dyna_var_asgn(id, value)
+void
+rb_dvar_push(id, value)
ID id;
VALUE value;
{
- struct RVarmap *vars = the_dyna_vars;
+ ruby_dyna_vars = new_dvar(id, value, ruby_dyna_vars);
+}
+
+static void
+dvar_asgn_internal(id, value, curr)
+ ID id;
+ VALUE value;
+ int curr;
+{
+ int n = 0;
+ struct RVarmap *vars = ruby_dyna_vars;
while (vars) {
+ if (curr && vars->id == 0) {
+ n++;
+ if (n == 2) break;
+ }
if (vars->id == id) {
vars->val = value;
- return value;
+ return;
}
vars = vars->next;
}
- new_dvar(id, value);
- return value;
+ if (!ruby_dyna_vars) {
+ ruby_dyna_vars = new_dvar(id, value, 0);
+ }
+ else {
+ vars = new_dvar(id, value, ruby_dyna_vars->next);
+ ruby_dyna_vars->next = vars;
+ }
+}
+
+void
+dvar_asgn(id, value)
+ ID id;
+ VALUE value;
+{
+ dvar_asgn_internal(id, value, 0);
+}
+
+static void
+dvar_asgn_curr(id, value)
+ ID id;
+ VALUE value;
+{
+ dvar_asgn_internal(id, value, 1);
}
struct iter {
int iter;
struct iter *prev;
};
-static struct iter *the_iter;
+static struct iter *ruby_iter;
#define ITER_NOT 0
#define ITER_PRE 1
@@ -527,12 +725,12 @@ static struct iter *the_iter;
#define PUSH_ITER(i) { \
struct iter _iter; \
- _iter.prev = the_iter; \
+ _iter.prev = ruby_iter; \
_iter.iter = (i); \
- the_iter = &_iter; \
+ ruby_iter = &_iter; \
#define POP_ITER() \
- the_iter = _iter.prev; \
+ ruby_iter = _iter.prev; \
}
struct tag {
@@ -541,7 +739,8 @@ struct tag {
struct iter *iter;
ID tag;
VALUE retval;
- ID dst;
+ struct SCOPE *scope;
+ int dst;
struct tag *prev;
};
static struct tag *prot_tag;
@@ -549,10 +748,10 @@ static struct tag *prot_tag;
#define PUSH_TAG(ptag) { \
struct tag _tag; \
_tag.retval = Qnil; \
- _tag.frame = the_frame; \
- _tag.iter = the_iter; \
+ _tag.frame = ruby_frame; \
+ _tag.iter = ruby_iter; \
_tag.prev = prot_tag; \
- _tag.retval = Qnil; \
+ _tag.scope = ruby_scope; \
_tag.tag = ptag; \
_tag.dst = 0; \
prot_tag = &_tag;
@@ -564,8 +763,8 @@ static struct tag *prot_tag;
#define EXEC_TAG() setjmp(prot_tag->buf)
#define JUMP_TAG(st) { \
- the_frame = prot_tag->frame; \
- the_iter = prot_tag->iter; \
+ ruby_frame = prot_tag->frame; \
+ ruby_iter = prot_tag->iter; \
longjmp(prot_tag->buf,(st)); \
}
@@ -575,6 +774,10 @@ static struct tag *prot_tag;
prot_tag = _tag.prev; \
}
+#define POP_TMPTAG() \
+ prot_tag = _tag.prev; \
+}
+
#define TAG_RETURN 0x1
#define TAG_BREAK 0x2
#define TAG_NEXT 0x3
@@ -585,148 +788,125 @@ static struct tag *prot_tag;
#define TAG_FATAL 0x8
#define TAG_MASK 0xf
-VALUE the_class;
+VALUE ruby_class;
+static VALUE ruby_wrapper; /* security wrapper */
+
+#define PUSH_CLASS() { \
+ VALUE _class = ruby_class; \
-#define PUSH_CLASS() { \
- VALUE _class = the_class; \
+#define POP_CLASS() ruby_class = _class; }
-#define POP_CLASS() the_class = _class; }
+static NODE *ruby_cref = 0;
+static NODE *top_cref;
+#define PUSH_CREF(c) ruby_cref = rb_node_newnode(NODE_CREF,(c),0,ruby_cref)
+#define POP_CREF() ruby_cref = ruby_cref->nd_next
#define PUSH_SCOPE() { \
- int volatile _vmode = scope_vmode; \
+ volatile int _vmode = scope_vmode; \
struct SCOPE * volatile _old; \
NEWOBJ(_scope, struct SCOPE); \
OBJSETUP(_scope, 0, T_SCOPE); \
_scope->local_tbl = 0; \
_scope->local_vars = 0; \
_scope->flag = 0; \
- _old = the_scope; \
- the_scope = _scope; \
+ _old = ruby_scope; \
+ ruby_scope = _scope; \
scope_vmode = SCOPE_PUBLIC;
-#define POP_SCOPE() \
- if (the_scope->flag == SCOPE_ALLOCA) {\
- the_scope->local_vars = 0;\
- the_scope->local_tbl = 0;\
- if (the_scope != top_scope)\
- gc_force_recycle(the_scope);\
- }\
- else {\
- the_scope->flag |= SCOPE_NOSTACK;\
- }\
- the_scope = _old;\
+typedef struct thread * rb_thread_t;
+static rb_thread_t curr_thread = 0;
+static rb_thread_t main_thread;
+static void scope_dup _((struct SCOPE *));
+
+#define POP_SCOPE() \
+ if (ruby_scope->flag & SCOPE_DONT_RECYCLE) {\
+ if (_old) scope_dup(_old); \
+ } \
+ if (!(ruby_scope->flag & SCOPE_MALLOC)) {\
+ ruby_scope->local_vars = 0; \
+ ruby_scope->local_tbl = 0; \
+ if (!(ruby_scope->flag & SCOPE_DONT_RECYCLE) && \
+ ruby_scope != top_scope) { \
+ rb_gc_force_recycle((VALUE)ruby_scope);\
+ } \
+ } \
+ ruby_scope->flag |= SCOPE_NOSTACK; \
+ ruby_scope = _old; \
+ scope_vmode = _vmode; \
}
static VALUE rb_eval _((VALUE,NODE*));
static VALUE eval _((VALUE,VALUE,VALUE,char*,int));
-static NODE *compile _((VALUE,char*));
+static NODE *compile _((VALUE, char*, int));
+static VALUE rb_yield_0 _((VALUE, VALUE, VALUE, int));
static VALUE rb_call _((VALUE,VALUE,ID,int,VALUE*,int));
static VALUE module_setup _((VALUE,NODE*));
-static VALUE massign _((VALUE,NODE*,VALUE));
-static void assign _((VALUE,NODE*,VALUE));
-
-static int safe_level = 0;
-/* safe-level:
- 0 - strings from streams/environment/ARGV are tainted (default)
- 1 - no dangerous operation by tainted string
- 2 - some process operations prohibited
- 3 - all genetated strings are tainted
- 4 - no global variable value modification/no direct output
- 5 - no instance variable value modification
-*/
+static VALUE massign _((VALUE,NODE*,VALUE,int));
+static void assign _((VALUE,NODE*,VALUE,int));
-int
-rb_safe_level()
-{
- return safe_level;
-}
-
-void
-rb_set_safe_level(level)
- int level;
-{
- if (level > safe_level) {
- safe_level = level;
- }
-}
-
-static VALUE
-safe_getter()
-{
- return INT2FIX(safe_level);
-}
+static VALUE trace_func = 0;
+static int tracing = 0;
+static void call_trace_func _((char*,char*,int,VALUE,ID,VALUE));
static void
-safe_setter(val)
- VALUE val;
-{
- int level = NUM2INT(val);
-
- if (level < safe_level) {
- Raise(eSecurityError, "tried to downgrade safe level from %d to %d",
- safe_level, level);
- }
- safe_level = level;
-}
-
-void
-rb_check_safe_str(x)
- VALUE x;
+error_pos()
{
- if (TYPE(x)!= T_STRING) {
- TypeError("wrong argument type %s (expected String)",
- rb_class2name(CLASS_OF(x)));
- }
- if (str_tainted(x)) {
- if (safe_level > 0){
- Raise(eSecurityError, "Insecure operation - %s",
- rb_id2name(the_frame->last_func));
+ if (ruby_sourcefile) {
+ if (ruby_frame->last_func) {
+ fprintf(stderr, "%s:%d:in `%s'", ruby_sourcefile, ruby_sourceline,
+ rb_id2name(ruby_frame->last_func));
+ }
+ else if (ruby_sourceline == 0) {
+ fprintf(stderr, "%s", ruby_sourcefile);
+ }
+ else {
+ fprintf(stderr, "%s:%d", ruby_sourcefile, ruby_sourceline);
}
- Warning("Insecure operation - %s",
- rb_id2name(the_frame->last_func));
}
}
-void
-rb_secure(level)
- int level;
+static VALUE
+get_backtrace(info)
+ VALUE info;
{
- if (level <= safe_level) {
- Raise(eSecurityError, "Insecure operation `%s' for level %d",
- rb_id2name(the_frame->last_func), level);
- }
+ if (NIL_P(info)) return Qnil;
+ return rb_funcall(info, rb_intern("backtrace"), 0);
}
-extern int sourceline;
-extern char *sourcefile;
-
-static VALUE trace_func = 0;
-static void call_trace_func _((char*,char*,int,VALUE,ID));
-
static void
-error_pos()
+set_backtrace(info, bt)
+ VALUE info, bt;
{
- if (sourcefile) {
- if (the_frame->last_func) {
- fprintf(stderr, "%s:%d:in `%s'", sourcefile, sourceline,
- rb_id2name(the_frame->last_func));
- }
- else {
- fprintf(stderr, "%s:%d", sourcefile, sourceline);
- }
- }
+ rb_funcall(info, rb_intern("set_backtrace"), 1, bt);
}
static void
error_print()
{
- VALUE eclass;
+ VALUE errat = Qnil; /* OK */
+ volatile VALUE eclass;
+ char *einfo;
+ int elen;
- if (NIL_P(errinfo)) return;
+ if (NIL_P(ruby_errinfo)) return;
- if (!NIL_P(errat)) {
+ PUSH_TAG(PROT_NONE);
+ if (EXEC_TAG() == 0) {
+ errat = get_backtrace(ruby_errinfo);
+ }
+ else {
+ errat = Qnil;
+ }
+ POP_TAG();
+ if (NIL_P(errat)) {
+ if (ruby_sourcefile)
+ fprintf(stderr, "%s:%d", ruby_sourcefile, ruby_sourceline);
+ else
+ fprintf(stderr, "%d", ruby_sourceline);
+ }
+ else {
VALUE mesg = RARRAY(errat)->ptr[0];
if (NIL_P(mesg)) error_pos();
@@ -735,37 +915,46 @@ error_print()
}
}
- eclass = CLASS_OF(errinfo);
- if (eclass == eRuntimeError && RSTRING(errinfo)->len == 0) {
+ eclass = CLASS_OF(ruby_errinfo);
+ PUSH_TAG(PROT_NONE);
+ if (EXEC_TAG() == 0) {
+ einfo = str2cstr(rb_obj_as_string(ruby_errinfo), &elen);
+ }
+ else {
+ einfo = "";
+ elen = 0;
+ }
+ POP_TAG();
+ if (eclass == rb_eRuntimeError && elen == 0) {
fprintf(stderr, ": unhandled exception\n");
}
else {
VALUE epath;
epath = rb_class_path(eclass);
- if (RSTRING(errinfo)->len == 0) {
+ if (elen == 0) {
fprintf(stderr, ": ");
fwrite(RSTRING(epath)->ptr, 1, RSTRING(epath)->len, stderr);
putc('\n', stderr);
}
else {
- unsigned char *tail = 0;
- int len = RSTRING(errinfo)->len;
+ char *tail = 0;
+ int len = elen;
if (RSTRING(epath)->ptr[0] == '#') epath = 0;
- if (tail = strchr(RSTRING(errinfo)->ptr, '\n')) {
- len = tail - RSTRING(errinfo)->ptr;
+ if (tail = strchr(einfo, '\n')) {
+ len = tail - einfo;
tail++; /* skip newline */
}
fprintf(stderr, ": ");
- fwrite(RSTRING(errinfo)->ptr, 1, len, stderr);
+ fwrite(einfo, 1, len, stderr);
if (epath) {
fprintf(stderr, " (");
fwrite(RSTRING(epath)->ptr, 1, RSTRING(epath)->len, stderr);
fprintf(stderr, ")\n");
}
if (tail) {
- fwrite(tail, 1, RSTRING(errinfo)->len-len-1, stderr);
+ fwrite(tail, 1, elen-len-1, stderr);
putc('\n', stderr);
}
}
@@ -781,9 +970,11 @@ error_print()
ep = RARRAY(errat);
for (i=1; i<ep->len; i++) {
- fprintf(stderr, "\tfrom %s\n", RSTRING(ep->ptr[i])->ptr);
+ if (TYPE(ep->ptr[i]) == T_STRING) {
+ fprintf(stderr, "\tfrom %s\n", RSTRING(ep->ptr[i])->ptr);
+ }
if (i == TRACE_HEAD && ep->len > TRACE_MAX) {
- fprintf(stderr, "\t ... %d levels...\n",
+ fprintf(stderr, "\t ... %ld levels...\n",
ep->len - TRACE_HEAD - TRACE_TAIL);
i = ep->len - TRACE_TAIL;
}
@@ -791,53 +982,139 @@ error_print()
}
}
-#ifndef NT
+#if !defined(NT) && !defined(__MACOS__)
extern char **environ;
#endif
-char **origenviron;
+char **rb_origenviron;
void rb_call_inits _((void));
-void init_stack _((void));
-void init_heap _((void));
+void Init_stack _((void*));
+void Init_heap _((void));
void Init_ext _((void));
-void gc_call_finalizer_at_exit _((void));
void
ruby_init()
{
+ static int initialized = 0;
static struct FRAME frame;
static struct iter iter;
int state;
- the_frame = top_frame = &frame;
- the_iter = &iter;
+ if (initialized)
+ return;
+ initialized = 1;
+
+ ruby_frame = top_frame = &frame;
+ ruby_iter = &iter;
- origenviron = environ;
+#ifdef __MACOS__
+ rb_origenviron = 0;
+#else
+ rb_origenviron = environ;
+#endif
- init_heap();
+ Init_stack(0);
+ Init_heap();
PUSH_SCOPE();
- the_scope->local_vars = 0;
- the_scope->local_tbl = 0;
- top_scope = the_scope;
+ ruby_scope->local_vars = 0;
+ ruby_scope->local_tbl = 0;
+ top_scope = ruby_scope;
/* default visibility is private at toplevel */
SCOPE_SET(SCOPE_PRIVATE);
- PUSH_TAG(PROT_NONE)
+ PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
rb_call_inits();
- the_class = cObject;
- the_frame->self = TopSelf;
- the_frame->cbase = (VALUE)node_newnode(NODE_CREF,cObject,0,0);
- rb_define_global_const("TOPLEVEL_BINDING", f_binding(TopSelf));
+ ruby_class = rb_cObject;
+ ruby_frame->self = ruby_top_self;
+ top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0);
+ ruby_cref = top_cref;
+ ruby_frame->cbase = (VALUE)ruby_cref;
+ rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(ruby_top_self));
+#ifdef __MACOS__
+ _macruby_init();
+#endif
ruby_prog_init();
}
POP_TAG();
if (state) error_print();
POP_SCOPE();
- the_scope = top_scope;
+ ruby_scope = top_scope;
}
-static int ext_init = 0;
+static VALUE
+eval_node(self, node)
+ VALUE self;
+ NODE *node;
+{
+ NODE *beg_tree = ruby_eval_tree_begin;
+
+ ruby_eval_tree_begin = 0;
+ if (beg_tree) {
+ rb_eval(self, beg_tree);
+ }
+
+ if (!node) return Qnil;
+ return rb_eval(self, node);
+}
+
+int ruby_in_eval;
+
+static void rb_thread_cleanup _((void));
+static void rb_thread_wait_other_threads _((void));
+
+static int exit_status;
+
+static int
+error_handle(ex)
+ int ex;
+{
+ switch (ex & TAG_MASK) {
+ case 0:
+ ex = 0;
+ break;
+
+ case TAG_RETURN:
+ error_pos();
+ fprintf(stderr, ": unexpected return\n");
+ ex = 1;
+ break;
+ case TAG_NEXT:
+ error_pos();
+ fprintf(stderr, ": unexpected next\n");
+ ex = 1;
+ break;
+ case TAG_BREAK:
+ error_pos();
+ fprintf(stderr, ": unexpected break\n");
+ ex = 1;
+ break;
+ case TAG_REDO:
+ error_pos();
+ fprintf(stderr, ": unexpected redo\n");
+ ex = 1;
+ break;
+ case TAG_RETRY:
+ error_pos();
+ fprintf(stderr, ": retry outside of rescue clause\n");
+ ex = 1;
+ break;
+ case TAG_RAISE:
+ case TAG_FATAL:
+ if (rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) {
+ ex = exit_status;
+ }
+ else {
+ error_print();
+ ex = 1;
+ }
+ break;
+ default:
+ rb_bug("Unknown longjmp status %d", ex);
+ break;
+ }
+ return ex;
+}
void
ruby_options(argc, argv)
@@ -848,220 +1125,181 @@ ruby_options(argc, argv)
PUSH_TAG(PROT_NONE)
if ((state = EXEC_TAG()) == 0) {
- NODE *save;
-
ruby_process_options(argc, argv);
- ext_init = 1; /* Init_ext() called in ruby_process_options */
- save = eval_tree;
- eval_tree = 0;
- ruby_require_modules();
- eval_tree = save;
}
POP_TAG();
if (state) {
- error_print();
- exit(1);
+ trace_func = 0;
+ tracing = 0;
+ exit(error_handle(state));
}
}
-static VALUE
-eval_node(self)
- VALUE self;
-{
- VALUE result = Qnil;
- NODE *tree;
+void rb_exec_end_proc _((void));
- if (eval_tree0) {
- tree = eval_tree0;
- eval_tree0 = 0;
- rb_eval(self, tree);
+void
+ruby_finalize()
+{
+ PUSH_TAG(PROT_NONE);
+ if (EXEC_TAG() == 0) {
+ rb_trap_exit();
+ rb_exec_end_proc();
+ rb_gc_call_finalizer_at_exit();
}
-
- if (!eval_tree) return Qnil;
-
- tree = eval_tree;
- eval_tree = 0;
-
- result = rb_eval(self, tree);
- return result;
+ POP_TAG();
}
-int rb_in_eval;
-
-#ifdef THREAD
-static void thread_cleanup _((void));
-static void thread_wait_other_threads _((void));
-static VALUE thread_current _((void));
-#endif
-
-static int exit_status;
-
-static void exec_end_proc _((void));
-
void
-ruby_run()
+ruby_stop(ex)
+ int ex;
{
int state;
- static int ex;
-
- if (nerrs > 0) exit(nerrs);
-
- init_stack();
- errat = Qnil; /* clear for execution */
PUSH_TAG(PROT_NONE);
PUSH_ITER(ITER_NOT);
if ((state = EXEC_TAG()) == 0) {
- if (!ext_init) Init_ext();
- eval_node(TopSelf);
+ rb_thread_cleanup();
+ rb_thread_wait_other_threads();
}
+ else if (ex == 0) {
+ ex = state;
+ }
POP_ITER();
POP_TAG();
- if (state && !ex) ex = state;
+ ex = error_handle(ex);
+ ruby_finalize();
+ exit(ex);
+}
+
+void
+ruby_run()
+{
+ int state;
+ static int ex;
+ volatile NODE *tmp;
+
+ if (ruby_nerrs > 0) exit(ruby_nerrs);
+
+ Init_stack(&tmp);
PUSH_TAG(PROT_NONE);
PUSH_ITER(ITER_NOT);
if ((state = EXEC_TAG()) == 0) {
- rb_trap_exit();
-#ifdef THREAD
- thread_cleanup();
- thread_wait_other_threads();
-#endif
- exec_end_proc();
- gc_call_finalizer_at_exit();
- }
- else {
- ex = state;
+ eval_node(ruby_top_self, ruby_eval_tree);
}
POP_ITER();
POP_TAG();
- switch (ex & 0xf) {
- case 0:
- exit(0);
-
- case TAG_RETURN:
- error_pos();
- fprintf(stderr, "unexpected return\n");
- exit(1);
- break;
- case TAG_NEXT:
- error_pos();
- fprintf(stderr, "unexpected next\n");
- exit(1);
- break;
- case TAG_BREAK:
- error_pos();
- fprintf(stderr, "unexpected break\n");
- exit(1);
- break;
- case TAG_REDO:
- error_pos();
- fprintf(stderr, "unexpected redo\n");
- exit(1);
- break;
- case TAG_RETRY:
- error_pos();
- fprintf(stderr, "retry outside of rescue clause\n");
- exit(1);
- break;
- case TAG_RAISE:
- case TAG_FATAL:
- if (obj_is_kind_of(errinfo, eSystemExit)) {
- exit(exit_status);
- }
- error_print();
- exit(1);
- break;
- default:
- Bug("Unknown longjmp status %d", ex);
- break;
- }
+ if (state && !ex) ex = state;
+ ruby_stop(ex);
}
static void
compile_error(at)
- char *at;
+ const char *at;
{
- VALUE mesg;
+ VALUE str;
- mesg = errinfo;
- nerrs = 0;
- errinfo = exc_new2(eSyntaxError, "compile error");
+ ruby_nerrs = 0;
+ str = rb_str_new2("compile error");
if (at) {
- str_cat(errinfo, " in ", 4);
- str_cat(errinfo, at, strlen(at));
+ rb_str_cat2(str, " in ");
+ rb_str_cat2(str, at);
+ }
+ rb_str_cat(str, "\n", 1);
+ if (!NIL_P(ruby_errinfo)) {
+ rb_str_concat(str, ruby_errinfo);
}
- str_cat(errinfo, "\n", 1);
- str_cat(errinfo, RSTRING(mesg)->ptr, RSTRING(mesg)->len);
- rb_raise(errinfo);
+ rb_exc_raise(rb_exc_new3(rb_eSyntaxError, str));
}
VALUE
rb_eval_string(str)
- char *str;
+ const char *str;
{
VALUE v;
- char *oldsrc = sourcefile;
+ char *oldsrc = ruby_sourcefile;
- sourcefile = "(eval)";
- v = eval(TopSelf, str_new2(str), Qnil, 0, 0);
- sourcefile = oldsrc;
+ ruby_sourcefile = "(eval)";
+ v = eval(ruby_top_self, rb_str_new2(str), Qnil, 0, 0);
+ ruby_sourcefile = oldsrc;
return v;
}
-void
-rb_eval_cmd(cmd, arg)
- VALUE cmd, arg;
+VALUE
+rb_eval_string_protect(str, state)
+ const char *str;
+ int *state;
{
- int state;
- struct SCOPE *saved_scope;
- volatile int safe = rb_safe_level();
+ VALUE result; /* OK */
+ int status;
- if (TYPE(cmd) != T_STRING) {
- Check_Type(arg, T_ARRAY);
- rb_funcall2(cmd, rb_intern("call"),
- RARRAY(arg)->len, RARRAY(arg)->ptr);
- return;
+ PUSH_TAG(PROT_NONE);
+ if ((status = EXEC_TAG()) == 0) {
+ result = rb_eval_string(str);
+ }
+ POP_TAG();
+ if (state) {
+ *state = status;
+ }
+ if (status != 0) {
+ return Qnil;
}
- PUSH_CLASS();
- PUSH_TAG(PROT_NONE);
- saved_scope = the_scope;
- the_scope = top_scope;
+ return result;
+}
- the_class = cObject;
- if (str_tainted(cmd)) {
- safe_level = 5;
- }
+VALUE
+rb_eval_string_wrap(str, state)
+ const char *str;
+ int *state;
+{
+ int status;
+ VALUE self = ruby_top_self;
+ VALUE wrapper = ruby_wrapper;
+ VALUE val;
- if ((state = EXEC_TAG()) == 0) {
- eval(TopSelf, cmd, Qnil, 0, 0);
- }
+ PUSH_CLASS();
+ ruby_class = ruby_wrapper = rb_module_new();
+ ruby_top_self = rb_obj_clone(ruby_top_self);
+ rb_extend_object(self, ruby_class);
+
+ val = rb_eval_string_protect(str, &status);
+ ruby_top_self = self;
- the_scope = saved_scope;
- safe_level = safe;
- POP_TAG();
POP_CLASS();
+ ruby_wrapper = wrapper;
+ if (state) {
+ *state = status;
+ }
+ else if (status) {
+ JUMP_TAG(status);
+ }
+ return val;
+}
+static void
+jump_tag_but_local_jump(state)
+ int state;
+{
switch (state) {
case 0:
break;
case TAG_RETURN:
- Raise(eLocalJumpError, "unexpected return");
+ rb_raise(rb_eLocalJumpError, "unexpected return");
break;
case TAG_NEXT:
- Raise(eLocalJumpError, "unexpected next");
+ rb_raise(rb_eLocalJumpError, "unexpected next");
break;
case TAG_BREAK:
- Raise(eLocalJumpError, "unexpected break");
+ rb_raise(rb_eLocalJumpError, "unexpected break");
break;
case TAG_REDO:
- Raise(eLocalJumpError, "unexpected redo");
+ rb_raise(rb_eLocalJumpError, "unexpected redo");
break;
case TAG_RETRY:
- Raise(eLocalJumpError, "retry outside of rescue clause");
+ rb_raise(rb_eLocalJumpError, "retry outside of rescue clause");
break;
default:
JUMP_TAG(state);
@@ -1069,22 +1307,63 @@ rb_eval_cmd(cmd, arg)
}
}
-void
+VALUE
+rb_eval_cmd(cmd, arg)
+ VALUE cmd, arg;
+{
+ int state;
+ VALUE val; /* OK */
+ struct SCOPE *saved_scope;
+ volatile int safe = ruby_safe_level;
+
+ if (TYPE(cmd) != T_STRING) {
+ return rb_funcall2(cmd, rb_intern("call"),
+ RARRAY(arg)->len, RARRAY(arg)->ptr);
+ }
+
+ PUSH_CLASS();
+ PUSH_TAG(PROT_NONE);
+ saved_scope = ruby_scope;
+ ruby_scope = top_scope;
+
+ ruby_class = rb_cObject;
+ if (OBJ_TAINTED(cmd)) {
+ ruby_safe_level = 4;
+ }
+
+ if ((state = EXEC_TAG()) == 0) {
+ val = eval(ruby_top_self, cmd, Qnil, 0, 0);
+ }
+
+ if (ruby_scope->flag & SCOPE_DONT_RECYCLE)
+ scope_dup(saved_scope);
+ ruby_scope = saved_scope;
+ ruby_safe_level = safe;
+ POP_TAG();
+ POP_CLASS();
+
+ jump_tag_but_local_jump(state);
+ return val;
+}
+
+static VALUE
rb_trap_eval(cmd, sig)
VALUE cmd;
int sig;
{
int state;
+ VALUE val; /* OK */
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
- rb_eval_cmd(cmd, ary_new3(1, INT2FIX(sig)));
+ val = rb_eval_cmd(cmd, rb_ary_new3(1, INT2FIX(sig)));
}
POP_TAG();
if (state) {
- trap_immediate = 0;
+ rb_trap_immediate = 0;
JUMP_TAG(state);
}
+ return val;
}
static VALUE
@@ -1092,7 +1371,7 @@ superclass(self, node)
VALUE self;
NODE *node;
{
- VALUE val = 0; /* OK */
+ VALUE val; /* OK */
int state;
PUSH_TAG(PROT_NONE);
@@ -1100,39 +1379,44 @@ superclass(self, node)
val = rb_eval(self, node);
}
POP_TAG();
- if (state == TAG_RAISE) {
+ if (state) {
superclass_error:
switch (nd_type(node)) {
case NODE_COLON2:
- TypeError("undefined superclass `%s'", rb_id2name(node->nd_mid));
- case NODE_CVAR:
- TypeError("undefined superclass `%s'", rb_id2name(node->nd_vid));
+ rb_raise(rb_eTypeError, "undefined superclass `%s'",
+ rb_id2name(node->nd_mid));
+ case NODE_CONST:
+ rb_raise(rb_eTypeError, "undefined superclass `%s'",
+ rb_id2name(node->nd_vid));
default:
- TypeError("superclass undefined");
+ rb_raise(rb_eTypeError, "superclass undefined");
}
JUMP_TAG(state);
}
if (TYPE(val) != T_CLASS) goto superclass_error;
if (FL_TEST(val, FL_SINGLETON)) {
- TypeError("can't make subclass of virtual class");
+ rb_raise(rb_eTypeError, "can't make subclass of virtual class");
}
return val;
}
+#define ruby_cbase (RNODE(ruby_frame->cbase)->nd_clss)
+
static VALUE
-ev_const_defined(cref, id)
+ev_const_defined(cref, id, self)
NODE *cref;
ID id;
+ VALUE self;
{
NODE *cbase = cref;
- while (cbase && cbase->nd_clss != cObject) {
+ while (cbase && cbase->nd_next) {
struct RClass *klass = RCLASS(cbase->nd_clss);
- if (klass->iv_tbl &&
- st_lookup(klass->iv_tbl, id, 0)) {
- return TRUE;
+ if (NIL_P(klass)) return rb_const_defined(CLASS_OF(self), id);
+ if (klass->iv_tbl && st_lookup(klass->iv_tbl, id, 0)) {
+ return Qtrue;
}
cbase = cbase->nd_next;
}
@@ -1140,18 +1424,19 @@ ev_const_defined(cref, id)
}
static VALUE
-ev_const_get(cref, id)
+ev_const_get(cref, id, self)
NODE *cref;
ID id;
+ VALUE self;
{
NODE *cbase = cref;
VALUE result;
- while (cbase && cbase->nd_clss != cObject) {
+ while (cbase && cbase->nd_next) {
struct RClass *klass = RCLASS(cbase->nd_clss);
- if (klass->iv_tbl &&
- st_lookup(klass->iv_tbl, id, &result)) {
+ if (NIL_P(klass)) return rb_const_get(CLASS_OF(self), id);
+ if (klass->iv_tbl && st_lookup(klass->iv_tbl, id, &result)) {
return result;
}
cbase = cbase->nd_next;
@@ -1160,72 +1445,176 @@ ev_const_get(cref, id)
}
static VALUE
-mod_nesting()
+rb_mod_nesting()
{
- NODE *cbase = (NODE*)the_frame->cbase;
- VALUE ary = ary_new();
+ NODE *cbase = RNODE(ruby_frame->cbase);
+ VALUE ary = rb_ary_new();
- while (cbase && cbase->nd_clss != cObject) {
- ary_push(ary, cbase->nd_clss);
+ while (cbase && cbase->nd_next) {
+ if (!NIL_P(cbase->nd_clss)) rb_ary_push(ary, cbase->nd_clss);
cbase = cbase->nd_next;
}
return ary;
}
static VALUE
-mod_s_constants()
+rb_mod_s_constants()
{
- NODE *cbase = (NODE*)the_frame->cbase;
- VALUE ary = ary_new();
+ NODE *cbase = RNODE(ruby_frame->cbase);
+ VALUE ary = rb_ary_new();
- while (cbase && cbase->nd_clss != cObject) {
- mod_const_at(cbase->nd_clss, ary);
+ while (cbase) {
+ if (!NIL_P(cbase->nd_clss)) rb_mod_const_at(cbase->nd_clss, ary);
cbase = cbase->nd_next;
}
- mod_const_of(((NODE*)the_frame->cbase)->nd_clss, ary);
+ if (!NIL_P(ruby_cbase)) rb_mod_const_of(ruby_cbase, ary);
return ary;
}
+void
+rb_frozen_class_p(klass)
+ VALUE klass;
+{
+ char *desc = "something(?!)";
+
+ if (OBJ_FROZEN(klass)) {
+ if (FL_TEST(klass, FL_SINGLETON))
+ desc = "object";
+ else {
+ switch (TYPE(klass)) {
+ case T_MODULE:
+ case T_ICLASS:
+ desc = "module"; break;
+ case T_CLASS:
+ desc = "class"; break;
+ }
+ }
+ rb_error_frozen(desc);
+ }
+}
+
+void
+rb_undef(klass, id)
+ VALUE klass;
+ ID id;
+{
+ VALUE origin;
+ NODE *body;
+
+ if (ruby_class == rb_cObject) {
+ rb_secure(4);
+ }
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't undef");
+ }
+ rb_frozen_class_p(klass);
+ if (id == __id__ || id == __send__) {
+ rb_warn("undefining `%s' may cause serious problem",
+ rb_id2name(id));
+ }
+ body = search_method(ruby_class, id, &origin);
+ if (!body || !body->nd_body) {
+ char *s0 = " class";
+ VALUE c = klass;
+
+ if (FL_TEST(c, FL_SINGLETON)) {
+ VALUE obj = rb_iv_get(klass, "__attached__");
+
+ switch (TYPE(obj)) {
+ case T_MODULE:
+ case T_CLASS:
+ c = obj;
+ s0 = "";
+ }
+ }
+ else if (TYPE(c) == T_MODULE) {
+ s0 = " module";
+ }
+ rb_raise(rb_eNameError, "undefined method `%s' for%s `%s'",
+ rb_id2name(id),s0,rb_class2name(c));
+ }
+ rb_add_method(klass, id, 0, NOEX_PUBLIC);
+ rb_clear_cache_by_id(id);
+}
+
static VALUE
-mod_remove_method(mod, name)
+rb_mod_undef_method(mod, name)
VALUE mod, name;
{
- remove_method(mod, rb_to_id(name));
+ rb_undef(mod, rb_to_id(name));
return mod;
}
-static VALUE
-mod_undef_method(mod, name)
- VALUE mod, name;
+void
+rb_alias(klass, name, def)
+ VALUE klass;
+ ID name, def;
{
- ID id = rb_to_id(name);
+ VALUE origin;
+ NODE *orig, *body;
- rb_add_method(mod, id, 0, NOEX_PUBLIC);
- rb_clear_cache_by_id(id);
- return mod;
+ rb_frozen_class_p(klass);
+ if (name == def) return;
+ if (klass == rb_cObject) {
+ rb_secure(4);
+ }
+ orig = search_method(klass, def, &origin);
+ if (!orig || !orig->nd_body) {
+ if (TYPE(klass) == T_MODULE) {
+ orig = search_method(rb_cObject, def, &origin);
+ }
+ }
+ if (!orig || !orig->nd_body) {
+ print_undef(klass, def);
+ }
+ body = orig->nd_body;
+ orig->nd_cnt++;
+ if (nd_type(body) == NODE_FBODY) { /* was alias */
+ def = body->nd_mid;
+ origin = body->nd_orig;
+ body = body->nd_head;
+ }
+
+ st_insert(RCLASS(klass)->m_tbl, name,
+ NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex));
+ rb_clear_cache_by_id(name);
}
static VALUE
-mod_alias_method(mod, newname, oldname)
+rb_mod_alias_method(mod, newname, oldname)
VALUE mod, newname, oldname;
{
- ID id = rb_to_id(newname);
-
- rb_alias(mod, id, rb_to_id(oldname));
- rb_clear_cache_by_id(id);
+ rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
return mod;
}
-#if defined(C_ALLOCA) && defined(THREAD)
-# define TMP_PROTECT NODE *__protect_tmp=0
-# define TMP_ALLOC(type,n) \
- (__protect_tmp = node_newnode(NODE_ALLOCA, \
- str_new(0,sizeof(type)*(n)),0,__protect_tmp), \
- (void*)RSTRING(__protect_tmp->nd_head)->ptr)
+static NODE*
+copy_node_scope(node, rval)
+ NODE *node;
+ VALUE rval;
+{
+ NODE *copy = rb_node_newnode(NODE_SCOPE,0,rval,node->nd_next);
+
+ if (node->nd_tbl) {
+ copy->nd_tbl = ALLOC_N(ID, node->nd_tbl[0]+1);
+ MEMCPY(copy->nd_tbl, node->nd_tbl, ID, node->nd_tbl[0]+1);
+ }
+ else {
+ copy->nd_tbl = 0;
+ }
+ return copy;
+}
+
+#ifdef C_ALLOCA
+# define TMP_PROTECT NODE * volatile tmp__protect_tmp=0
+# define TMP_ALLOC(n) \
+ (tmp__protect_tmp = rb_node_newnode(NODE_ALLOCA, \
+ ALLOC_N(VALUE,n),tmp__protect_tmp,n), \
+ (void*)tmp__protect_tmp->nd_head)
#else
# define TMP_PROTECT typedef int foobazzz
-# define TMP_ALLOC(type,n) ALLOCA_N(type,n)
+# define TMP_ALLOC(n) ALLOCA_N(VALUE,n)
#endif
#define SETUP_ARGS(anode) {\
@@ -1237,17 +1626,17 @@ mod_alias_method(mod, newname, oldname)
else if (nd_type(n) == NODE_ARRAY) {\
argc=n->nd_alen;\
if (argc > 0) {\
- char *file = sourcefile;\
- int line = sourceline;\
+ char *file = ruby_sourcefile;\
+ int line = ruby_sourceline;\
int i;\
n = anode;\
- argv = TMP_ALLOC(VALUE,argc);\
+ argv = TMP_ALLOC(argc);\
for (i=0;i<argc;i++) {\
argv[i] = rb_eval(self,n->nd_head);\
n=n->nd_next;\
}\
- sourcefile = file;\
- sourceline = line;\
+ ruby_sourcefile = file;\
+ ruby_sourceline = line;\
}\
else {\
argc = 0;\
@@ -1256,19 +1645,31 @@ mod_alias_method(mod, newname, oldname)
}\
else {\
VALUE args = rb_eval(self,n);\
- char *file = sourcefile;\
- int line = sourceline;\
+ char *file = ruby_sourcefile;\
+ int line = ruby_sourceline;\
if (TYPE(args) != T_ARRAY)\
args = rb_Array(args);\
argc = RARRAY(args)->len;\
argv = ALLOCA_N(VALUE, argc);\
MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);\
- sourcefile = file;\
- sourceline = line;\
+ ruby_sourcefile = file;\
+ ruby_sourceline = line;\
}\
}
-#define MATCH_DATA the_scope->local_vars[node->nd_cnt]
+#define BEGIN_CALLARGS {\
+ struct BLOCK *tmp_block = ruby_block;\
+ if (ruby_iter->iter == ITER_PRE) {\
+ ruby_block = ruby_block->prev;\
+ }\
+ PUSH_ITER(ITER_NOT);
+
+#define END_CALLARGS \
+ ruby_block = tmp_block;\
+ POP_ITER();\
+}
+
+#define MATCH_DATA ruby_scope->local_vars[node->nd_cnt]
static char* is_defined _((VALUE, NODE*, char*));
@@ -1311,9 +1712,10 @@ is_defined(self, node, buf)
switch (nd_type(node)) {
case NODE_SUPER:
case NODE_ZSUPER:
- if (the_frame->last_func == 0) return 0;
- else if (method_boundp(RCLASS(the_frame->last_class)->super,
- the_frame->last_func, 1)) {
+ if (ruby_frame->last_func == 0) return 0;
+ else if (ruby_frame->last_class == 0) return 0;
+ else if (rb_method_boundp(RCLASS(ruby_frame->last_class)->super,
+ ruby_frame->last_func, 0)) {
if (nd_type(node) == NODE_SUPER) {
return arg_defined(self, node->nd_args, buf, "super");
}
@@ -1321,8 +1723,8 @@ is_defined(self, node, buf)
}
break;
- case NODE_FCALL:
case NODE_VCALL:
+ case NODE_FCALL:
val = CLASS_OF(self);
goto check_bound;
@@ -1335,10 +1737,11 @@ is_defined(self, node, buf)
}
POP_TAG();
if (state) {
+ ruby_errinfo = Qnil;
return 0;
}
check_bound:
- if (method_boundp(val, node->nd_mid, nd_type(node)== NODE_CALL)) {
+ if (rb_method_boundp(val, node->nd_mid, nd_type(node)== NODE_CALL)) {
return arg_defined(self, node->nd_args, buf, "method");
}
break;
@@ -1348,7 +1751,7 @@ is_defined(self, node, buf)
return "method";
case NODE_YIELD:
- if (iterator_p()) {
+ if (rb_block_given_p()) {
return "yield";
}
break;
@@ -1371,15 +1774,17 @@ is_defined(self, node, buf)
case NODE_MASGN:
case NODE_LASGN:
case NODE_DASGN:
+ case NODE_DASGN_CURR:
case NODE_GASGN:
- case NODE_IASGN:
- case NODE_CASGN:
+ case NODE_CDECL:
+ case NODE_CVDECL:
+ case NODE_CVASGN:
return "assignment";
case NODE_LVAR:
return "local-variable";
case NODE_DVAR:
- return "local-variable(nested)";
+ return "local-variable(in-block)";
case NODE_GVAR:
if (rb_gvar_defined(node->nd_entry)) {
@@ -1393,12 +1798,33 @@ is_defined(self, node, buf)
}
break;
- case NODE_CVAR:
- if (ev_const_defined(the_frame->cbase, node->nd_vid)) {
+ case NODE_CONST:
+ if (ev_const_defined(RNODE(ruby_frame->cbase), node->nd_vid, self)) {
return "constant";
}
break;
+ case NODE_CVAR:
+ if (NIL_P(ruby_cbase)) {
+ if (rb_cvar_defined(CLASS_OF(self), node->nd_vid)) {
+ return "class variable";
+ }
+ break;
+ }
+ if (!FL_TEST(ruby_cbase, FL_SINGLETON)) {
+ if (rb_cvar_defined(ruby_cbase, node->nd_vid)) {
+ return "class variable";
+ }
+ break;
+ }
+ self = rb_iv_get(ruby_cbase, "__attached__");
+ /* fall through */
+ case NODE_CVAR2:
+ if (rb_cvar_defined(rb_cvar_singleton(self), node->nd_vid)) {
+ return "class variable";
+ }
+ break;
+
case NODE_COLON2:
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
@@ -1406,6 +1832,7 @@ is_defined(self, node, buf)
}
POP_TAG();
if (state) {
+ ruby_errinfo = Qnil;
return 0;
}
else {
@@ -1414,19 +1841,23 @@ is_defined(self, node, buf)
case T_MODULE:
if (rb_const_defined_at(val, node->nd_mid))
return "constant";
+ default:
+ if (rb_method_boundp(val, node->nd_mid, 1)) {
+ return "method";
+ }
}
}
break;
case NODE_NTH_REF:
- if (reg_nth_defined(node->nd_nth, MATCH_DATA)) {
+ if (RTEST(rb_reg_nth_defined(node->nd_nth, MATCH_DATA))) {
sprintf(buf, "$%d", node->nd_nth);
return buf;
}
break;
case NODE_BACK_REF:
- if (reg_nth_defined(0, MATCH_DATA)) {
+ if (RTEST(rb_reg_nth_defined(0, MATCH_DATA))) {
sprintf(buf, "$%c", node->nd_nth);
return buf;
}
@@ -1441,6 +1872,7 @@ is_defined(self, node, buf)
if (!state) {
return "expression";
}
+ ruby_errinfo = Qnil;
break;
}
return 0;
@@ -1451,6 +1883,26 @@ static int handle_rescue _((VALUE,NODE*));
static void blk_free();
static VALUE
+rb_obj_is_block(block)
+ VALUE block;
+{
+ if (TYPE(block) == T_DATA && RDATA(block)->dfree == (RUBY_DATA_FUNC)blk_free) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE
+rb_obj_is_proc(proc)
+ VALUE proc;
+{
+ if (rb_obj_is_block(proc) && rb_obj_is_kind_of(proc, rb_cProc)) {
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE
set_trace_func(obj, trace)
VALUE obj, trace;
{
@@ -1458,54 +1910,65 @@ set_trace_func(obj, trace)
trace_func = 0;
return Qnil;
}
- if (TYPE(trace) != T_DATA || RDATA(trace)->dfree != blk_free) {
- TypeError("trace_func needs to be Proc");
+ if (!rb_obj_is_proc(trace)) {
+ rb_raise(rb_eTypeError, "trace_func needs to be Proc");
}
return trace_func = trace;
}
static void
-call_trace_func(event, file, line, self, id)
+call_trace_func(event, file, line, self, id, klass)
char *event;
char *file;
int line;
VALUE self;
ID id;
+ VALUE klass; /* OK */
{
int state;
- volatile VALUE trace;
struct FRAME *prev;
+ char *file_save = ruby_sourcefile;
+ int line_save = ruby_sourceline;
+ VALUE srcfile;
if (!trace_func) return;
+ if (tracing) return;
- trace = trace_func;
- trace_func = 0;
-#ifdef THREAD
- thread_critical++;
-#endif
-
- prev = the_frame;
+ tracing = 1;
+ prev = ruby_frame;
PUSH_FRAME();
- *the_frame = *_frame.prev;
- the_frame->prev = prev;
+ *ruby_frame = *prev;
+ ruby_frame->prev = prev;
+ ruby_frame->iter = 0; /* blocks not available anyway */
- the_frame->line = sourceline = line;
- the_frame->file = sourcefile = file;
+ if (file) {
+ ruby_frame->line = ruby_sourceline = line;
+ ruby_frame->file = ruby_sourcefile = file;
+ }
+ if (klass) {
+ if (TYPE(klass) == T_ICLASS) {
+ klass = RBASIC(klass)->klass;
+ }
+ else if (FL_TEST(klass, FL_SINGLETON)) {
+ klass = self;
+ }
+ }
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
- proc_call(trace, ary_new3(5, str_new2(event),
- str_new2(sourcefile),
- INT2FIX(sourceline),
- INT2FIX(id),
- self?f_binding(self):Qnil));
- }
- POP_TAG();
+ srcfile = rb_str_new2(ruby_sourcefile?ruby_sourcefile:"(ruby)");
+ proc_call(trace_func, rb_ary_new3(6, rb_str_new2(event),
+ srcfile,
+ INT2FIX(ruby_sourceline),
+ id?ID2SYM(id):Qnil,
+ self?rb_f_binding(self):Qnil,
+ klass));
+ }
+ POP_TMPTAG(); /* do not propagate retval */
POP_FRAME();
-#ifdef THREAD
- thread_critical--;
-#endif
- if (!trace_func) trace_func = trace;
+ tracing = 0;
+ ruby_sourceline = line_save;
+ ruby_sourcefile = file_save;
if (state) JUMP_TAG(state);
}
@@ -1513,10 +1976,11 @@ static void return_check _((void));
#define return_value(v) prot_tag->retval = (v)
static VALUE
-rb_eval(self, node)
+rb_eval(self, n)
VALUE self;
- NODE * volatile node;
+ NODE *n;
{
+ NODE * volatile node = n;
int state;
volatile VALUE result = Qnil;
@@ -1527,14 +1991,15 @@ rb_eval(self, node)
switch (nd_type(node)) {
case NODE_BLOCK:
- while (node) {
- result = rb_eval(self, node->nd_head);
+ while (node->nd_next) {
+ rb_eval(self, node->nd_head);
node = node->nd_next;
}
- break;
+ node = node->nd_head;
+ goto again;
case NODE_POSTEXE:
- f_END();
+ rb_f_END();
nd_set_type(node, NODE_NIL); /* exec just once */
result = Qnil;
break;
@@ -1546,13 +2011,13 @@ rb_eval(self, node)
/* nodes for speed-up(default match) */
case NODE_MATCH:
- result = reg_match2(node->nd_head->nd_lit);
+ result = rb_reg_match2(node->nd_head->nd_lit);
break;
/* nodes for speed-up(literal match) */
case NODE_MATCH2:
- result = reg_match(rb_eval(self,node->nd_recv),
- rb_eval(self,node->nd_value));
+ result = rb_reg_match(rb_eval(self,node->nd_recv),
+ rb_eval(self,node->nd_value));
break;
/* nodes for speed-up(literal match) */
@@ -1561,7 +2026,7 @@ rb_eval(self, node)
VALUE r = rb_eval(self,node->nd_recv);
VALUE l = rb_eval(self,node->nd_value);
if (TYPE(r) == T_STRING) {
- result = reg_match(l, r);
+ result = rb_reg_match(l, r);
}
else {
result = rb_funcall(r, match, 1, l);
@@ -1569,11 +2034,31 @@ rb_eval(self, node)
}
break;
- /* nodes for speed-up(top-level loop for -n/-p) */
+ /* node for speed-up(top-level loop for -n/-p) */
case NODE_OPT_N:
- while (!NIL_P(f_gets())) {
- rb_eval(self, node->nd_body);
+ PUSH_TAG(PROT_NONE);
+ switch (state = EXEC_TAG()) {
+ case 0:
+ opt_n_next:
+ while (!NIL_P(rb_gets())) {
+ opt_n_redo:
+ rb_eval(self, node->nd_body);
+ }
+ break;
+
+ case TAG_REDO:
+ state = 0;
+ goto opt_n_redo;
+ case TAG_NEXT:
+ state = 0;
+ goto opt_n_next;
+ case TAG_BREAK:
+ state = 0;
+ default:
+ break;
}
+ POP_TAG();
+ if (state) JUMP_TAG(state);
RETURN(Qnil);
case NODE_SELF:
@@ -1583,13 +2068,13 @@ rb_eval(self, node)
RETURN(Qnil);
case NODE_TRUE:
- RETURN(TRUE);
+ RETURN(Qtrue);
case NODE_FALSE:
- RETURN(FALSE);
+ RETURN(Qfalse);
case NODE_IF:
- sourceline = nd_line(node);
+ ruby_sourceline = nd_line(node);
if (RTEST(rb_eval(self, node->nd_cond))) {
node = node->nd_body;
}
@@ -1598,6 +2083,44 @@ rb_eval(self, node)
}
goto again;
+ case NODE_WHEN:
+ while (node) {
+ NODE *tag;
+
+ if (nd_type(node) != NODE_WHEN) goto again;
+ tag = node->nd_head;
+ while (tag) {
+ if (trace_func) {
+ call_trace_func("line", tag->nd_file, nd_line(tag), self,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
+ }
+ ruby_sourcefile = tag->nd_file;
+ ruby_sourceline = nd_line(tag);
+ if (nd_type(tag->nd_head) == NODE_WHEN) {
+ VALUE v = rb_eval(self, tag->nd_head->nd_head);
+ int i;
+
+ if (TYPE(v) != T_ARRAY) v = rb_Array(v);
+ for (i=0; i<RARRAY(v)->len; i++) {
+ if (RTEST(RARRAY(v)->ptr[i])) {
+ node = node->nd_body;
+ goto again;
+ }
+ }
+ tag = tag->nd_next;
+ continue;
+ }
+ if (RTEST(rb_eval(self, tag->nd_head))) {
+ node = node->nd_body;
+ goto again;
+ }
+ tag = tag->nd_next;
+ }
+ node = node->nd_next;
+ }
+ RETURN(Qnil);
+
case NODE_CASE:
{
VALUE val;
@@ -1613,11 +2136,27 @@ rb_eval(self, node)
tag = node->nd_head;
while (tag) {
if (trace_func) {
- call_trace_func("line", tag->nd_file, nd_line(tag),
- self, the_frame->last_func);
+ call_trace_func("line", tag->nd_file, nd_line(tag), self,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
+ }
+ ruby_sourcefile = tag->nd_file;
+ ruby_sourceline = nd_line(tag);
+ if (nd_type(tag->nd_head) == NODE_WHEN) {
+ VALUE v = rb_eval(self, tag->nd_head->nd_head);
+ int i;
+
+ if (TYPE(v) != T_ARRAY) v = rb_Array(v);
+ for (i=0; i<RARRAY(v)->len; i++) {
+ if (RTEST(rb_funcall2(RARRAY(v)->ptr[i], eqq, 1, &val))){
+ node = node->nd_body;
+ goto again;
+ }
+ }
+ tag = tag->nd_next;
+ continue;
}
- sourceline = nd_line(tag);
- if (RTEST(rb_funcall2(rb_eval(self, tag->nd_head),eqq,1,&val))){
+ if (RTEST(rb_funcall2(rb_eval(self, tag->nd_head), eqq, 1, &val))) {
node = node->nd_body;
goto again;
}
@@ -1632,7 +2171,7 @@ rb_eval(self, node)
PUSH_TAG(PROT_NONE);
switch (state = EXEC_TAG()) {
case 0:
- sourceline = nd_line(node);
+ ruby_sourceline = nd_line(node);
if (node->nd_state && !RTEST(rb_eval(self, node->nd_cond)))
goto while_out;
do {
@@ -1656,9 +2195,7 @@ rb_eval(self, node)
}
while_out:
POP_TAG();
- if (state) {
- JUMP_TAG(state);
- }
+ if (state) JUMP_TAG(state);
RETURN(Qnil);
case NODE_UNTIL:
@@ -1688,9 +2225,7 @@ rb_eval(self, node)
}
until_out:
POP_TAG();
- if (state) {
- JUMP_TAG(state);
- }
+ if (state) JUMP_TAG(state);
RETURN(Qnil);
case NODE_BLOCK_PASS:
@@ -1701,38 +2236,38 @@ rb_eval(self, node)
case NODE_FOR:
{
iter_retry:
- PUSH_BLOCK(node->nd_var, node->nd_body);
- _block.d_vars = new_dvar(0,0);
PUSH_TAG(PROT_FUNC);
+ PUSH_BLOCK(node->nd_var, node->nd_body);
state = EXEC_TAG();
if (state == 0) {
+ PUSH_ITER(ITER_PRE);
if (nd_type(node) == NODE_ITER) {
- PUSH_ITER(ITER_PRE);
result = rb_eval(self, node->nd_iter);
- POP_ITER();
}
else {
VALUE recv;
- char *file = sourcefile;
- int line = sourceline;
+ char *file = ruby_sourcefile;
+ int line = ruby_sourceline;
+ _block.flags &= ~BLOCK_D_SCOPE;
+ BEGIN_CALLARGS;
recv = rb_eval(self, node->nd_iter);
- PUSH_ITER(ITER_PRE);
- sourcefile = file;
- sourceline = line;
+ END_CALLARGS;
+ ruby_sourcefile = file;
+ ruby_sourceline = line;
result = rb_call(CLASS_OF(recv),recv,each,0,0,0);
- POP_ITER();
}
+ POP_ITER();
}
- else if (the_block->tag->dst == state) {
+ else if (_block.tag->dst == state) {
state &= TAG_MASK;
if (state == TAG_RETURN) {
result = prot_tag->retval;
}
}
- POP_TAG();
POP_BLOCK();
+ POP_TAG();
switch (state) {
case 0:
break;
@@ -1768,14 +2303,32 @@ rb_eval(self, node)
JUMP_TAG(TAG_RETRY);
break;
+ case NODE_RESTARGS:
+ result = rb_eval(self, node->nd_head);
+ if (TYPE(result) != T_ARRAY) {
+ result = rb_Array(result);
+ }
+ break;
+
case NODE_YIELD:
- result = rb_yield_0(rb_eval(self, node->nd_stts), 0);
+ if (node->nd_stts) {
+ result = rb_eval(self, node->nd_stts);
+ if (nd_type(node->nd_stts) == NODE_RESTARGS &&
+ RARRAY(result)->len == 1)
+ {
+ result = RARRAY(result)->ptr[0];
+ }
+ }
+ else {
+ result = Qnil;
+ }
+ result = rb_yield_0(result, 0, 0, 0);
break;
case NODE_RESCUE:
retry_entry:
{
- volatile VALUE e_info = errinfo, e_at = errat;
+ volatile VALUE e_info = ruby_errinfo;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
@@ -1784,6 +2337,8 @@ rb_eval(self, node)
POP_TAG();
if (state == TAG_RAISE) {
NODE * volatile resq = node->nd_resq;
+
+ ruby_sourceline = nd_line(node);
while (resq) {
if (handle_rescue(self, resq)) {
state = 0;
@@ -1792,22 +2347,25 @@ rb_eval(self, node)
result = rb_eval(self, resq->nd_body);
}
POP_TAG();
- if (state == 0) {
- errinfo = e_info;
- errat = e_at;
- }
- else if (state == TAG_RETRY) {
+ if (state == TAG_RETRY) {
state = 0;
+ ruby_errinfo = Qnil;
goto retry_entry;
}
+ if (state != TAG_RAISE) {
+ ruby_errinfo = e_info;
+ }
break;
}
resq = resq->nd_head; /* next rescue */
}
}
- if (state) {
- JUMP_TAG(state);
+ else if (node->nd_else) { /* else clause given */
+ if (!state) { /* no exception raised */
+ result = rb_eval(self, node->nd_else);
+ }
}
+ if (state) JUMP_TAG(state);
}
break;
@@ -1819,13 +2377,13 @@ rb_eval(self, node)
POP_TAG();
if (node->nd_ensr) {
VALUE retval = prot_tag->retval; /* save retval */
+ VALUE errinfo = ruby_errinfo;
rb_eval(self, node->nd_ensr);
return_value(retval);
+ ruby_errinfo = errinfo;
}
- if (state) {
- JUMP_TAG(state);
- }
+ if (state) JUMP_TAG(state);
break;
case NODE_AND:
@@ -1841,66 +2399,97 @@ rb_eval(self, node)
goto again;
case NODE_NOT:
- if (RTEST(rb_eval(self, node->nd_body))) result = FALSE;
- else result = TRUE;
+ if (RTEST(rb_eval(self, node->nd_body))) result = Qfalse;
+ else result = Qtrue;
break;
case NODE_DOT2:
case NODE_DOT3:
- RETURN(range_new(rb_eval(self, node->nd_beg), rb_eval(self, node->nd_end)));
+ result = rb_range_new(rb_eval(self, node->nd_beg),
+ rb_eval(self, node->nd_end),
+ nd_type(node) == NODE_DOT3);
+ 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;
+ }
+ break;
case NODE_FLIP2: /* like AWK */
- if (node->nd_state == 0) {
+ if (ruby_scope->local_vars == 0) {
+ rb_bug("unexpected local variable");
+ }
+ if (!RTEST(ruby_scope->local_vars[node->nd_cnt])) {
if (RTEST(rb_eval(self, node->nd_beg))) {
- node->nd_state = rb_eval(self, node->nd_end)?0:1;
- result = TRUE;
+ ruby_scope->local_vars[node->nd_cnt] =
+ RTEST(rb_eval(self, node->nd_end))?Qfalse:Qtrue;
+ result = Qtrue;
}
else {
- result = FALSE;
+ result = Qfalse;
}
}
else {
if (RTEST(rb_eval(self, node->nd_end))) {
- node->nd_state = 0;
+ ruby_scope->local_vars[node->nd_cnt] = Qfalse;
}
- result = TRUE;
+ result = Qtrue;
}
break;
case NODE_FLIP3: /* like SED */
- if (node->nd_state == 0) {
- if (RTEST(rb_eval(self, node->nd_beg))) {
- node->nd_state = 1;
- result = TRUE;
- }
- result = FALSE;
+ if (ruby_scope->local_vars == 0) {
+ rb_bug("unexpected local variable");
+ }
+ if (!RTEST(ruby_scope->local_vars[node->nd_cnt])) {
+ result = RTEST(rb_eval(self, node->nd_beg)) ? Qtrue : Qfalse;
+ ruby_scope->local_vars[node->nd_cnt] = result;
}
else {
if (RTEST(rb_eval(self, node->nd_end))) {
- node->nd_state = 0;
+ ruby_scope->local_vars[node->nd_cnt] = Qfalse;
}
- result = TRUE;
+ result = Qtrue;
}
break;
case NODE_RETURN:
if (node->nd_stts) {
- return_value(rb_eval(self, node->nd_stts));
+ return_value(rb_eval(self, node->nd_stts));
+ }
+ else {
+ return_value(Qnil);
}
return_check();
JUMP_TAG(TAG_RETURN);
break;
+ case NODE_ARGSCAT:
+ result = rb_ary_concat(rb_eval(self, node->nd_head),
+ rb_eval(self, node->nd_body));
+ break;
+
+ case NODE_ARGSPUSH:
+ result = rb_ary_push(rb_obj_dup(rb_eval(self, node->nd_head)),
+ rb_eval(self, node->nd_body));
+ break;
+
case NODE_CALL:
{
VALUE recv;
int argc; VALUE *argv; /* used in SETUP_ARGS */
TMP_PROTECT;
- PUSH_ITER(ITER_NOT);
+ BEGIN_CALLARGS;
recv = rb_eval(self, node->nd_recv);
SETUP_ARGS(node->nd_args);
- POP_ITER();
+ END_CALLARGS;
+
result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0);
}
break;
@@ -1910,9 +2499,10 @@ rb_eval(self, node)
int argc; VALUE *argv; /* used in SETUP_ARGS */
TMP_PROTECT;
- PUSH_ITER(ITER_NOT);
+ BEGIN_CALLARGS;
SETUP_ARGS(node->nd_args);
- POP_ITER();
+ END_CALLARGS;
+
result = rb_call(CLASS_OF(self),self,node->nd_mid,argc,argv,1);
}
break;
@@ -1927,23 +2517,23 @@ rb_eval(self, node)
int argc; VALUE *argv; /* used in SETUP_ARGS */
TMP_PROTECT;
- if (the_frame->last_class == 0) {
- NameError("superclass method `%s' disabled",
- rb_id2name(the_frame->last_func));
+ if (ruby_frame->last_class == 0) {
+ rb_raise(rb_eNameError, "superclass method `%s' disabled",
+ rb_id2name(ruby_frame->last_func));
}
if (nd_type(node) == NODE_ZSUPER) {
- argc = the_frame->argc;
- argv = the_frame->argv;
+ argc = ruby_frame->argc;
+ argv = ruby_frame->argv;
}
else {
- PUSH_ITER(ITER_NOT);
+ BEGIN_CALLARGS;
SETUP_ARGS(node->nd_args);
- POP_ITER();
+ END_CALLARGS;
}
- PUSH_ITER(the_iter->iter?ITER_PRE:ITER_NOT);
- result = rb_call(RCLASS(the_frame->last_class)->super,
- the_frame->self, the_frame->last_func,
+ PUSH_ITER(ruby_iter->iter?ITER_PRE:ITER_NOT);
+ result = rb_call(RCLASS(ruby_frame->last_class)->super,
+ ruby_frame->self, ruby_frame->last_func,
argc, argv, 3);
POP_ITER();
}
@@ -1951,28 +2541,39 @@ rb_eval(self, node)
case NODE_SCOPE:
{
- VALUE save = the_frame->cbase;
+ struct FRAME frame;
+ NODE *saved_cref = 0;
+
+ frame = *ruby_frame;
+ frame.tmp = ruby_frame;
+ ruby_frame = &frame;
PUSH_SCOPE();
PUSH_TAG(PROT_NONE);
- if (node->nd_rval) the_frame->cbase = node->nd_rval;
+ if (node->nd_rval) {
+ saved_cref = ruby_cref;
+ ruby_cref = (NODE*)node->nd_rval;
+ ruby_frame->cbase = node->nd_rval;
+ }
if (node->nd_tbl) {
VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1);
*vars++ = (VALUE)node;
- the_scope->local_vars = vars;
- memclear(the_scope->local_vars, node->nd_tbl[0]);
- the_scope->local_tbl = node->nd_tbl;
+ ruby_scope->local_vars = vars;
+ rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
+ ruby_scope->local_tbl = node->nd_tbl;
}
else {
- the_scope->local_vars = 0;
- the_scope->local_tbl = 0;
+ ruby_scope->local_vars = 0;
+ ruby_scope->local_tbl = 0;
}
if ((state = EXEC_TAG()) == 0) {
- result = rb_eval(self, node->nd_body);
+ result = rb_eval(self, node->nd_next);
}
POP_TAG();
POP_SCOPE();
- the_frame->cbase = save;
+ ruby_frame = frame.tmp;
+ if (saved_cref)
+ ruby_cref = saved_cref;
if (state) JUMP_TAG(state);
}
break;
@@ -1988,7 +2589,18 @@ rb_eval(self, node)
rval = node->nd_args->nd_head;
SETUP_ARGS(node->nd_args->nd_next);
val = rb_funcall2(recv, aref, argc-1, argv);
- val = rb_funcall(val, node->nd_mid, 1, rb_eval(self, rval));
+ switch (node->nd_mid) {
+ case 0: /* OR */
+ if (RTEST(val)) RETURN(val);
+ val = rb_eval(self, rval);
+ break;
+ case 1: /* AND */
+ if (!RTEST(val)) RETURN(val);
+ val = rb_eval(self, rval);
+ break;
+ default:
+ val = rb_funcall(val, node->nd_mid, 1, rb_eval(self, rval));
+ }
argv[argc-1] = val;
val = rb_funcall2(recv, aset, argc, argv);
result = val;
@@ -2002,75 +2614,105 @@ rb_eval(self, node)
recv = rb_eval(self, node->nd_recv);
val = rb_funcall(recv, id, 0);
+ switch (node->nd_next->nd_mid) {
+ case 0: /* OR */
+ if (RTEST(val)) RETURN(val);
+ val = rb_eval(self, node->nd_value);
+ break;
+ case 1: /* AND */
+ if (!RTEST(val)) RETURN(val);
+ val = rb_eval(self, node->nd_value);
+ break;
+ default:
+ val = rb_funcall(val, node->nd_next->nd_mid, 1,
+ rb_eval(self, node->nd_value));
+ }
- val = rb_funcall(val, node->nd_next->nd_mid, 1,
- rb_eval(self, node->nd_value));
-
- rb_funcall2(recv, id_attrset(id), 1, &val);
+ rb_funcall2(recv, node->nd_next->nd_aid, 1, &val);
result = val;
}
break;
+ case NODE_OP_ASGN_AND:
+ result = rb_eval(self, node->nd_head);
+ if (!RTEST(result)) break;
+ node = node->nd_value;
+ goto again;
+
+ case NODE_OP_ASGN_OR:
+ if ((node->nd_aid && !rb_ivar_defined(self, node->nd_aid)) ||
+ !RTEST(result = rb_eval(self, node->nd_head))) {
+ node = node->nd_value;
+ goto again;
+ }
+ break;
+
case NODE_MASGN:
- result = massign(self, node, rb_eval(self, node->nd_value));
+ result = massign(self, node, rb_eval(self, node->nd_value),0);
break;
case NODE_LASGN:
- if (the_scope->local_vars == 0)
- Bug("unexpected local variable assignment");
+ if (ruby_scope->local_vars == 0)
+ rb_bug("unexpected local variable assignment");
result = rb_eval(self, node->nd_value);
- the_scope->local_vars[node->nd_cnt] = result;
+ ruby_scope->local_vars[node->nd_cnt] = result;
break;
case NODE_DASGN:
- result = dyna_var_asgn(node->nd_vid, rb_eval(self, node->nd_value));
+ result = rb_eval(self, node->nd_value);
+ dvar_asgn(node->nd_vid, result);
break;
- case NODE_GASGN:
- {
- VALUE val;
+ case NODE_DASGN_CURR:
+ result = rb_eval(self, node->nd_value);
+ dvar_asgn_curr(node->nd_vid, result);
+ break;
- val = rb_eval(self, node->nd_value);
- rb_gvar_set(node->nd_entry, val);
- result = val;
- }
+ case NODE_GASGN:
+ result = rb_eval(self, node->nd_value);
+ rb_gvar_set(node->nd_entry, result);
break;
case NODE_IASGN:
- {
- VALUE val;
+ result = rb_eval(self, node->nd_value);
+ rb_ivar_set(self, node->nd_vid, result);
+ break;
- val = rb_eval(self, node->nd_value);
- rb_ivar_set(self, node->nd_vid, val);
- result = val;
+ case NODE_CDECL:
+ if (NIL_P(ruby_class)) {
+ rb_raise(rb_eTypeError, "no class/module to define constant");
}
+ result = rb_eval(self, node->nd_value);
+ rb_const_set(ruby_class, node->nd_vid, result);
break;
- case NODE_CASGN:
- {
- VALUE val;
-
- val = rb_eval(self, node->nd_value);
- /* check for static scope constants */
- if (RTEST(verbose) &&
- ev_const_defined(the_frame->cbase, node->nd_vid)) {
- Warning("already initialized constant %s",
- rb_id2name(node->nd_vid));
- }
- rb_const_set(the_class, node->nd_vid, val);
- result = val;
+ case NODE_CVDECL:
+ if (NIL_P(ruby_cbase)) {
+ rb_raise(rb_eTypeError, "no class/module to define class variable");
+ }
+ result = rb_eval(self, node->nd_value);
+ if (FL_TEST(ruby_cbase, FL_SINGLETON)) {
+ rb_cvar_declare(rb_cvar_singleton(rb_iv_get(ruby_cbase, "__attached__")),
+ node->nd_vid, result);
+ break;
}
+ rb_cvar_declare(ruby_cbase, node->nd_vid, result);
+ break;
+
+ case NODE_CVASGN:
+ result = rb_eval(self, node->nd_value);
+ rb_cvar_set(rb_cvar_singleton(self), node->nd_vid, result);
break;
case NODE_LVAR:
- if (the_scope->local_vars == 0) {
- Bug("unexpected local variable");
+ if (ruby_scope->local_vars == 0) {
+ rb_bug("unexpected local variable");
}
- result = the_scope->local_vars[node->nd_cnt];
+ result = ruby_scope->local_vars[node->nd_cnt];
break;
case NODE_DVAR:
- result = dyna_var_ref(node->nd_vid);
+ result = rb_dvar_ref(node->nd_vid);
break;
case NODE_GVAR:
@@ -2081,16 +2723,31 @@ rb_eval(self, node)
result = rb_ivar_get(self, node->nd_vid);
break;
- case NODE_CVAR:
- result = ev_const_get(the_frame->cbase, node->nd_vid);
+ case NODE_CONST:
+ result = ev_const_get(RNODE(ruby_frame->cbase), node->nd_vid, self);
+ break;
+
+ case NODE_CVAR: /* normal method */
+ if (NIL_P(ruby_cbase)) {
+ result = rb_cvar_get(CLASS_OF(self), node->nd_vid);
+ break;
+ }
+ if (!FL_TEST(ruby_cbase, FL_SINGLETON)) {
+ result = rb_cvar_get(ruby_cbase, node->nd_vid);
+ break;
+ }
+ self = rb_iv_get(ruby_cbase, "__attached__");
+ /* fall through */
+ case NODE_CVAR2: /* singleton method */
+ result = rb_cvar_get(rb_cvar_singleton(self), node->nd_vid);
break;
case NODE_BLOCK_ARG:
- if (the_scope->local_vars == 0)
- Bug("unexpected block argument");
- if (iterator_p()) {
- result = f_lambda();
- the_scope->local_vars[node->nd_cnt] = result;
+ if (ruby_scope->local_vars == 0)
+ rb_bug("unexpected block argument");
+ if (rb_block_given_p()) {
+ result = rb_f_lambda();
+ ruby_scope->local_vars[node->nd_cnt] = result;
}
else {
result = Qnil;
@@ -2107,44 +2764,43 @@ rb_eval(self, node)
case T_MODULE:
break;
default:
- Check_Type(klass, T_CLASS);
- break;
+ return rb_funcall(klass, node->nd_mid, 0, 0);
}
- result = rb_const_get_at(klass, node->nd_mid);
+ result = rb_const_get(klass, node->nd_mid);
}
break;
case NODE_COLON3:
- result = rb_const_get_at(cObject, node->nd_mid);
+ result = rb_const_get_at(rb_cObject, node->nd_mid);
break;
case NODE_NTH_REF:
- result = reg_nth_match(node->nd_nth, MATCH_DATA);
+ result = rb_reg_nth_match(node->nd_nth, MATCH_DATA);
break;
case NODE_BACK_REF:
switch (node->nd_nth) {
case '&':
- result = reg_last_match(MATCH_DATA);
+ result = rb_reg_last_match(MATCH_DATA);
break;
case '`':
- result = reg_match_pre(MATCH_DATA);
+ result = rb_reg_match_pre(MATCH_DATA);
break;
case '\'':
- result = reg_match_post(MATCH_DATA);
+ result = rb_reg_match_post(MATCH_DATA);
break;
case '+':
- result = reg_match_last(MATCH_DATA);
+ result = rb_reg_match_last(MATCH_DATA);
break;
default:
- Bug("unexpected back-ref");
+ rb_bug("unexpected back-ref");
}
break;
case NODE_HASH:
{
NODE *list;
- VALUE hash = hash_new();
+ VALUE hash = rb_hash_new();
VALUE key, val;
list = node->nd_head;
@@ -2152,17 +2808,17 @@ rb_eval(self, node)
key = rb_eval(self, list->nd_head);
list = list->nd_next;
if (list == 0)
- Bug("odd number list for Hash");
+ rb_bug("odd number list for Hash");
val = rb_eval(self, list->nd_head);
list = list->nd_next;
- hash_aset(hash, key, val);
+ rb_hash_aset(hash, key, val);
}
result = hash;
}
break;
case NODE_ZARRAY: /* zero length list */
- result = ary_new();
+ result = rb_ary_new();
break;
case NODE_ARRAY:
@@ -2171,7 +2827,7 @@ rb_eval(self, node)
int i;
i = node->nd_alen;
- ary = ary_new2(i);
+ ary = rb_ary_new2(i);
for (i=0;node;node=node->nd_next) {
RARRAY(ary)->ptr[i++] = rb_eval(self, node->nd_head);
RARRAY(ary)->len = i;
@@ -2182,7 +2838,7 @@ rb_eval(self, node)
break;
case NODE_STR:
- result = str_new3(node->nd_lit);
+ result = rb_str_new3(node->nd_lit);
break;
case NODE_DSTR:
@@ -2193,36 +2849,44 @@ rb_eval(self, node)
VALUE str, str2;
NODE *list = node->nd_next;
- str = str_new3(node->nd_lit);
+ str = rb_str_new3(node->nd_lit);
while (list) {
- if (nd_type(list->nd_head) == NODE_STR) {
- str2 = list->nd_head->nd_lit;
- }
- else {
- if (nd_type(list->nd_head) == NODE_EVSTR) {
- rb_in_eval++;
- eval_tree = 0;
- list->nd_head = compile(list->nd_head->nd_lit,0);
- rb_in_eval--;
- if (nerrs > 0) {
- compile_error("string expand");
+ if (list->nd_head) {
+ switch (nd_type(list->nd_head)) {
+ case NODE_STR:
+ str2 = list->nd_head->nd_lit;
+ break;
+ case NODE_EVSTR:
+ result = ruby_errinfo;
+ ruby_errinfo = Qnil;
+ ruby_sourceline = nd_line(node);
+ ruby_in_eval++;
+ list->nd_head = compile(list->nd_head->nd_lit,
+ ruby_sourcefile,
+ ruby_sourceline);
+ ruby_eval_tree = 0;
+ ruby_in_eval--;
+ if (ruby_nerrs > 0) {
+ compile_error("string expansion");
}
+ if (!NIL_P(result)) ruby_errinfo = result;
+ /* fall through */
+ default:
+ str2 = rb_obj_as_string(rb_eval(self, list->nd_head));
+ break;
}
- str2 = rb_eval(self, list->nd_head);
- str2 = obj_as_string(str2);
- }
- if (str2) {
- str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
+ rb_str_append(str, str2);
+ OBJ_INFECT(str, str2);
}
list = list->nd_next;
}
switch (nd_type(node)) {
case NODE_DREGX:
- result = reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
+ result = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
node->nd_cflag);
break;
case NODE_DREGX_ONCE: /* regexp expand once */
- result = reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
+ result = rb_reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
node->nd_cflag);
nd_set_type(node, NODE_LIT);
node->nd_lit = result;
@@ -2246,23 +2910,39 @@ rb_eval(self, node)
break;
case NODE_ATTRSET:
- if (the_frame->argc != 1)
- ArgError("Wrong # of arguments(%d for 1)", the_frame->argc);
- result = rb_ivar_set(self, node->nd_vid, the_frame->argv[0]);
+ if (ruby_frame->argc != 1)
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)",
+ ruby_frame->argc);
+ result = rb_ivar_set(self, node->nd_vid, ruby_frame->argv[0]);
break;
case NODE_DEFN:
if (node->nd_defn) {
- NODE *body;
+ NODE *body, *defn;
VALUE origin;
int noex;
- body = search_method(the_class, node->nd_mid, &origin);
- if (body) {
- if (origin == the_class) {
- Warning("discarding old %s", rb_id2name(node->nd_mid));
+ if (NIL_P(ruby_class)) {
+ rb_raise(rb_eTypeError, "no class to add method");
+ }
+ if (ruby_class == rb_cObject && node->nd_mid == init) {
+ rb_warn("redefining Object#initialize may cause infinite loop");
+ }
+ if (node->nd_mid == __id__ || node->nd_mid == __send__) {
+ rb_warn("redefining `%s' may cause serious problem",
+ rb_id2name(node->nd_mid));
+ }
+ rb_frozen_class_p(ruby_class);
+ body = search_method(ruby_class, node->nd_mid, &origin);
+ if (body){
+ if (RTEST(ruby_verbose) && ruby_class == origin && body->nd_cnt == 0) {
+ rb_warning("discarding old %s", rb_id2name(node->nd_mid));
+ }
+ if (node->nd_noex) { /* toplevel */
+ /* should upgrade to rb_warn() if no super was called inside? */
+ rb_warning("overriding global function `%s'",
+ rb_id2name(node->nd_mid));
}
- rb_clear_cache_by_id(node->nd_mid);
}
if (SCOPE_TEST(SCOPE_PRIVATE) || node->nd_mid == init) {
@@ -2271,27 +2951,30 @@ rb_eval(self, node)
else if (SCOPE_TEST(SCOPE_PROTECTED)) {
noex = NOEX_PROTECTED;
}
+ else if (ruby_class == rb_cObject) {
+ noex = node->nd_noex;
+ }
else {
noex = NOEX_PUBLIC;
}
- if (body && origin == the_class && body->nd_noex & NOEX_UNDEF) {
+ if (body && origin == ruby_class && body->nd_noex & NOEX_UNDEF) {
noex |= NOEX_UNDEF;
}
- rb_add_method(the_class, node->nd_mid, node->nd_defn, noex);
+
+ defn = copy_node_scope(node->nd_defn, ruby_cref);
+ rb_add_method(ruby_class, node->nd_mid, defn, noex);
+ rb_clear_cache_by_id(node->nd_mid);
if (scope_vmode == SCOPE_MODFUNC) {
- rb_add_method(rb_singleton_class(the_class),
- node->nd_mid, node->nd_defn, NOEX_PUBLIC);
- rb_funcall(the_class, rb_intern("singleton_method_added"),
- 1, INT2FIX(node->nd_mid));
+ rb_add_method(rb_singleton_class(ruby_class),
+ node->nd_mid, defn, NOEX_PUBLIC);
+ rb_funcall(ruby_class, singleton_added, 1, ID2SYM(node->nd_mid));
}
- if (FL_TEST(the_class, FL_SINGLETON)) {
- rb_funcall(rb_iv_get(the_class, "__attached__"),
- rb_intern("singleton_method_added"),
- 1, INT2FIX(node->nd_mid));
+ if (FL_TEST(ruby_class, FL_SINGLETON)) {
+ rb_funcall(rb_iv_get(ruby_class, "__attached__"),
+ singleton_added, 1, ID2SYM(node->nd_mid));
}
else {
- rb_funcall(the_class, rb_intern("method_added"),
- 1, INT2FIX(node->nd_mid));
+ rb_funcall(ruby_class, added, 1, ID2SYM(node->nd_mid));
}
result = Qnil;
}
@@ -2301,66 +2984,52 @@ rb_eval(self, node)
if (node->nd_defn) {
VALUE recv = rb_eval(self, node->nd_recv);
VALUE klass;
- NODE *body = 0;
+ NODE *body = 0, *defn;
- if (FIXNUM_P(recv)) {
- TypeError("Can't define method \"%s\" for Fixnum",
- rb_id2name(node->nd_mid));
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(recv)) {
+ rb_raise(rb_eSecurityError, "Insecure; can't define singleton method");
}
- if (NIL_P(recv)) {
- TypeError("Can't define method \"%s\" for nil",
- rb_id2name(node->nd_mid));
- }
- if (rb_special_const_p(recv)) {
- TypeError("Can't define method \"%s\" for special constants",
- rb_id2name(node->nd_mid));
+ if (FIXNUM_P(recv) || SYMBOL_P(recv)) {
+ rb_raise(rb_eTypeError,
+ "can't define singleton method \"%s\" for %s",
+ rb_id2name(node->nd_mid),
+ rb_class2name(CLASS_OF(recv)));
}
+ if (OBJ_FROZEN(recv)) rb_error_frozen("object");
klass = rb_singleton_class(recv);
if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, &body)) {
- Warning("redefine %s", rb_id2name(node->nd_mid));
+ if (rb_safe_level() >= 4) {
+ rb_raise(rb_eSecurityError, "redefining method prohibited");
+ }
+ if (RTEST(ruby_verbose)) {
+ rb_warning("redefine %s", rb_id2name(node->nd_mid));
+ }
}
- rb_clear_cache_by_id(node->nd_mid);
- rb_add_method(klass, node->nd_mid, node->nd_defn,
+ defn = copy_node_scope(node->nd_defn, ruby_cref);
+ defn->nd_rval = (VALUE)ruby_cref;
+ rb_add_method(klass, node->nd_mid, defn,
NOEX_PUBLIC|(body?body->nd_noex&NOEX_UNDEF:0));
- rb_funcall(recv, rb_intern("singleton_method_added"),
- 1, INT2FIX(node->nd_mid));
+ rb_clear_cache_by_id(node->nd_mid);
+ rb_funcall(recv, singleton_added, 1, ID2SYM(node->nd_mid));
result = Qnil;
}
break;
case NODE_UNDEF:
- {
- VALUE origin;
- NODE *body;
-
- body = search_method(the_class, node->nd_mid, &origin);
- if (!body || !body->nd_body) {
- char *s0 = " class";
- VALUE klass = the_class;
-
- if (FL_TEST(the_class, FL_SINGLETON)) {
- VALUE obj = rb_iv_get(the_class, "__attached__");
- switch (TYPE(obj)) {
- case T_MODULE:
- case T_CLASS:
- klass = obj;
- s0 = "";
- }
- }
- NameError("undefined method `%s' for%s `%s'",
- rb_id2name(node->nd_mid),s0,rb_class2name(klass));
- }
- rb_clear_cache_by_id(node->nd_mid);
- rb_add_method(the_class, node->nd_mid, 0, NOEX_PUBLIC);
- result = Qnil;
+ if (NIL_P(ruby_class)) {
+ rb_raise(rb_eTypeError, "no class to undef method");
}
+ rb_undef(ruby_class, node->nd_mid);
+ result = Qnil;
break;
case NODE_ALIAS:
- rb_alias(the_class, node->nd_new, node->nd_old);
- rb_funcall(the_class, rb_intern("method_added"),
- 1, INT2FIX(node->nd_mid));
+ if (NIL_P(ruby_class)) {
+ rb_raise(rb_eTypeError, "no class to make alias");
+ }
+ rb_alias(ruby_class, node->nd_new, node->nd_old);
+ rb_funcall(ruby_class, added, 1, ID2SYM(node->nd_mid));
result = Qnil;
break;
@@ -2373,6 +3042,9 @@ rb_eval(self, node)
{
VALUE super, klass, tmp;
+ if (NIL_P(ruby_class)) {
+ rb_raise(rb_eTypeError, "no outer class/module");
+ }
if (node->nd_super) {
super = superclass(self, node->nd_super);
}
@@ -2380,13 +3052,17 @@ rb_eval(self, node)
super = 0;
}
- if (rb_const_defined_at(the_class, node->nd_cname) &&
- (the_class != cObject ||
- !rb_autoload_defined(node->nd_cname))) {
-
- klass = rb_const_get_at(the_class, node->nd_cname);
+ klass = 0;
+ if ((ruby_class == rb_cObject) && rb_autoload_defined(node->nd_cname)) {
+ rb_autoload_load(node->nd_cname);
+ }
+ if (rb_const_defined_at(ruby_class, node->nd_cname)) {
+ klass = rb_const_get(ruby_class, node->nd_cname);
+ }
+ if (klass) {
if (TYPE(klass) != T_CLASS) {
- TypeError("%s is not a class", rb_id2name(node->nd_cname));
+ rb_raise(rb_eTypeError, "%s is not a class",
+ rb_id2name(node->nd_cname));
}
if (super) {
tmp = RCLASS(klass)->super;
@@ -2397,24 +3073,28 @@ rb_eval(self, node)
tmp = RCLASS(tmp)->super;
}
if (tmp != super) {
- TypeError("superclass mismatch for %s",
- rb_id2name(node->nd_cname));
+ super = tmp;
+ goto override_class;
}
}
- if (safe_level >= 3) {
- Raise(eSecurityError, "extending class prohibited");
+ if (rb_safe_level() >= 4) {
+ rb_raise(rb_eSecurityError, "extending class prohibited");
}
rb_clear_cache();
}
else {
- if (!super) super = cObject;
+ override_class:
+ if (!super) super = rb_cObject;
klass = rb_define_class_id(node->nd_cname, super);
- rb_const_set(the_class, node->nd_cname, klass);
- rb_set_class_path(klass,the_class,rb_id2name(node->nd_cname));
- obj_call_init(klass);
+ rb_const_set(ruby_class, node->nd_cname, klass);
+ rb_set_class_path(klass,ruby_class,rb_id2name(node->nd_cname));
+ }
+ if (ruby_wrapper) {
+ rb_extend_object(klass, ruby_wrapper);
+ rb_include_module(klass, ruby_wrapper);
}
- return module_setup(klass, node->nd_body);
+ result = module_setup(klass, node->nd_body);
}
break;
@@ -2422,23 +3102,33 @@ rb_eval(self, node)
{
VALUE module;
- if (rb_const_defined_at(the_class, node->nd_cname) &&
- (the_class != cObject ||
- !rb_autoload_defined(node->nd_cname))) {
-
- module = rb_const_get_at(the_class, node->nd_cname);
+ if (NIL_P(ruby_class)) {
+ rb_raise(rb_eTypeError, "no outer class/module");
+ }
+ module = 0;
+ if ((ruby_class == rb_cObject) && rb_autoload_defined(node->nd_cname)) {
+ rb_autoload_load(node->nd_cname);
+ }
+ if (rb_const_defined_at(ruby_class, node->nd_cname)) {
+ module = rb_const_get(ruby_class, node->nd_cname);
+ }
+ if (module) {
if (TYPE(module) != T_MODULE) {
- TypeError("%s is not a module", rb_id2name(node->nd_cname));
+ rb_raise(rb_eTypeError, "%s is not a module",
+ rb_id2name(node->nd_cname));
}
- if (safe_level >= 3) {
- Raise(eSecurityError, "extending module prohibited");
+ if (rb_safe_level() >= 4) {
+ rb_raise(rb_eSecurityError, "extending module prohibited");
}
}
else {
module = rb_define_module_id(node->nd_cname);
- rb_const_set(the_class, node->nd_cname, module);
- rb_set_class_path(module,the_class,rb_id2name(node->nd_cname));
- obj_call_init(module);
+ rb_const_set(ruby_class, node->nd_cname, module);
+ rb_set_class_path(module,ruby_class,rb_id2name(node->nd_cname));
+ }
+ if (ruby_wrapper) {
+ rb_extend_object(module, ruby_wrapper);
+ rb_include_module(module, ruby_wrapper);
}
result = module_setup(module, node->nd_body);
@@ -2450,20 +3140,22 @@ rb_eval(self, node)
VALUE klass;
klass = rb_eval(self, node->nd_recv);
- if (FIXNUM_P(klass)) {
- TypeError("No virtual class for Fixnums");
- }
- if (NIL_P(klass)) {
- TypeError("No virtual class for nil");
- }
if (rb_special_const_p(klass)) {
- TypeError("No virtual class for special constants");
+ rb_raise(rb_eTypeError, "no virtual class for %s",
+ rb_class2name(CLASS_OF(klass)));
}
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass))
+ rb_raise(rb_eSecurityError, "Insecure: can't extend object");
if (FL_TEST(CLASS_OF(klass), FL_SINGLETON)) {
rb_clear_cache();
}
klass = rb_singleton_class(klass);
+ if (ruby_wrapper) {
+ rb_extend_object(klass, ruby_wrapper);
+ rb_include_module(klass, ruby_wrapper);
+ }
+
result = module_setup(klass, node->nd_body);
}
break;
@@ -2473,23 +3165,24 @@ rb_eval(self, node)
char buf[20];
char *desc = is_defined(self, node->nd_head, buf);
- if (desc) result = str_new2(desc);
- else result = FALSE;
+ if (desc) result = rb_str_new2(desc);
+ else result = Qnil;
}
break;
case NODE_NEWLINE:
- sourcefile = node->nd_file;
- sourceline = node->nd_nth;
+ ruby_sourcefile = node->nd_file;
+ ruby_sourceline = node->nd_nth;
if (trace_func) {
- call_trace_func("line", sourcefile, sourceline,
- self, the_frame->last_func);
+ call_trace_func("line", ruby_sourcefile, ruby_sourceline, self,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
}
node = node->nd_next;
goto again;
default:
- Bug("unknown node type %d", nd_type(node));
+ rb_bug("unknown node type %d", nd_type(node));
}
finish:
CHECK_INTS;
@@ -2497,53 +3190,60 @@ rb_eval(self, node)
}
static VALUE
-module_setup(module, node)
+module_setup(module, n)
VALUE module;
- NODE * volatile node;
+ NODE *n;
{
+ NODE * volatile node = n;
int state;
- VALUE save = the_frame->cbase;
+ struct FRAME frame;
VALUE result; /* OK */
- char *file = sourcefile;
- int line = sourceline;
+ char *file = ruby_sourcefile;
+ int line = ruby_sourceline;
TMP_PROTECT;
- /* fill c-ref */
- node->nd_clss = module;
- node = node->nd_body;
+ frame = *ruby_frame;
+ frame.tmp = ruby_frame;
+ ruby_frame = &frame;
PUSH_CLASS();
- the_class = module;
+ ruby_class = module;
PUSH_SCOPE();
+ PUSH_VARS();
- if (node->nd_rval) the_frame->cbase = node->nd_rval;
if (node->nd_tbl) {
- VALUE *vars = TMP_ALLOC(VALUE, node->nd_tbl[0]+1);
+ VALUE *vars = TMP_ALLOC(node->nd_tbl[0]+1);
*vars++ = (VALUE)node;
- the_scope->local_vars = vars;
- memclear(the_scope->local_vars, node->nd_tbl[0]);
- the_scope->local_tbl = node->nd_tbl;
+ ruby_scope->local_vars = vars;
+ rb_mem_clear(ruby_scope->local_vars, node->nd_tbl[0]);
+ ruby_scope->local_tbl = node->nd_tbl;
}
else {
- the_scope->local_vars = 0;
- the_scope->local_tbl = 0;
+ ruby_scope->local_vars = 0;
+ ruby_scope->local_tbl = 0;
}
+ PUSH_CREF(module);
+ ruby_frame->cbase = (VALUE)ruby_cref;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
if (trace_func) {
- call_trace_func("class", file, line,
- the_class, the_frame->last_func);
+ call_trace_func("class", file, line, ruby_class,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
}
- result = rb_eval(the_class, node->nd_body);
+ result = rb_eval(ruby_class, node->nd_next);
}
POP_TAG();
+ POP_CREF();
+ POP_VARS();
POP_SCOPE();
POP_CLASS();
- the_frame->cbase = save;
+ ruby_frame = frame.tmp;
if (trace_func) {
- call_trace_func("end", file, line, 0, the_frame->last_func);
+ call_trace_func("end", file, line, 0,
+ ruby_frame->last_func, ruby_frame->last_class);
}
if (state) JUMP_TAG(state);
@@ -2556,13 +3256,13 @@ rb_respond_to(obj, id)
ID id;
{
if (rb_method_boundp(CLASS_OF(obj), id, 0)) {
- return TRUE;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
static VALUE
-obj_respond_to(argc, argv, obj)
+rb_obj_respond_to(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -2573,19 +3273,19 @@ obj_respond_to(argc, argv, obj)
rb_scan_args(argc, argv, "11", &mid, &priv);
id = rb_to_id(mid);
if (rb_method_boundp(CLASS_OF(obj), id, !RTEST(priv))) {
- return TRUE;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
static VALUE
-mod_method_defined(mod, mid)
+rb_mod_method_defined(mod, mid)
VALUE mod, mid;
{
if (rb_method_boundp(mod, rb_to_id(mid), 1)) {
- return TRUE;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
void
@@ -2593,40 +3293,52 @@ rb_exit(status)
int status;
{
if (prot_tag) {
+ VALUE exit;
+
exit_status = status;
- rb_raise(exc_new(eSystemExit, 0, 0));
+ exit = rb_exc_new(rb_eSystemExit, 0, 0);
+ rb_iv_set(exit, "status", INT2NUM(status));
+ rb_exc_raise(exit);
}
+ ruby_finalize();
exit(status);
}
static VALUE
-f_exit(argc, argv, obj)
+rb_f_exit(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
{
VALUE status;
+ int istatus;
- rb_secure(2);
+ rb_secure(4);
if (rb_scan_args(argc, argv, "01", &status) == 1) {
- status = NUM2INT(status);
+ istatus = NUM2INT(status);
}
else {
- status = 0;
+ istatus = 0;
}
- rb_exit(status);
- /* not reached */
+ rb_exit(istatus);
+ return Qnil; /* not reached */
}
-static VALUE
-f_abort()
+static void
+rb_abort()
{
- rb_secure(2);
- if (errinfo) {
+ if (!NIL_P(ruby_errinfo)) {
error_print();
}
rb_exit(1);
- /* not reached */
+}
+
+static VALUE
+rb_f_abort()
+{
+ rb_secure(4);
+ rb_abort();
+ return Qnil; /* not reached */
}
void
@@ -2635,153 +3347,158 @@ rb_iter_break()
JUMP_TAG(TAG_BREAK);
}
-#ifdef __GNUC__
-static volatile voidfn rb_longjmp;
-#endif
-
+static void rb_longjmp _((int, VALUE)) NORETURN;
static VALUE make_backtrace _((void));
-static VALUE
-check_errat(val)
- VALUE val;
-{
- int i;
- static char *err = "value of $@ must be Array of String";
-
- if (!NIL_P(val)) {
- int t = TYPE(val);
-
- if (t == T_STRING) return ary_new3(1, val);
- if (t != T_ARRAY) {
- TypeError(err);
- }
- for (i=0;i<RARRAY(val)->len;i++) {
- if (TYPE(RARRAY(val)->ptr[i]) != T_STRING) {
- TypeError(err);
- }
- }
- }
- return val;
-}
-
static void
-rb_longjmp(tag, mesg, at)
+rb_longjmp(tag, mesg)
int tag;
- VALUE mesg, at;
+ VALUE mesg;
{
- if (NIL_P(errinfo) && NIL_P(mesg)) {
- errinfo = exc_new(eRuntimeError, 0, 0);
- }
+ VALUE at;
- if (debug && !NIL_P(errinfo)) {
- fprintf(stderr, "Exception `%s' at %s:%d\n",
- rb_class2name(CLASS_OF(errinfo)),
- sourcefile, sourceline);
+ if (NIL_P(mesg)) mesg = ruby_errinfo;
+ if (NIL_P(mesg)) {
+ mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
}
- if (!NIL_P(at)) {
- errat = check_errat(at);
+
+ if (ruby_sourcefile && !NIL_P(mesg)) {
+ at = get_backtrace(mesg);
+ if (NIL_P(at)) {
+ at = make_backtrace();
+ set_backtrace(mesg, at);
+ }
}
- else if (sourcefile && (NIL_P(errat) || !NIL_P(mesg))) {
- errat = make_backtrace();
+ if (!NIL_P(mesg)) {
+ ruby_errinfo = mesg;
}
- if (!NIL_P(mesg)) {
- if (obj_is_kind_of(mesg, eGlobalExit)) {
- errinfo = mesg;
- }
- else {
- errinfo = exc_new3(eRuntimeError, mesg);
- }
- str_freeze(errinfo);
+ if (RTEST(ruby_debug) && !NIL_P(ruby_errinfo)
+ && !rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) {
+ fprintf(stderr, "Exception `%s' at %s:%d - %s\n",
+ rb_class2name(CLASS_OF(ruby_errinfo)),
+ ruby_sourcefile, ruby_sourceline,
+ STR2CSTR(ruby_errinfo));
}
- trap_restore_mask();
+ rb_trap_restore_mask();
if (trace_func && tag != TAG_FATAL) {
- call_trace_func("raise", sourcefile, sourceline,
- the_frame->self, the_frame->last_func);
+ call_trace_func("raise", ruby_sourcefile, ruby_sourceline,
+ ruby_frame->self,
+ ruby_frame->last_func,
+ ruby_frame->last_class);
+ }
+ if (!prot_tag) {
+ error_print();
}
JUMP_TAG(tag);
}
void
-rb_raise(mesg)
+rb_exc_raise(mesg)
VALUE mesg;
{
- rb_longjmp(TAG_RAISE, mesg, Qnil);
+ rb_longjmp(TAG_RAISE, mesg);
}
void
-rb_fatal(mesg)
+rb_exc_fatal(mesg)
VALUE mesg;
{
- rb_longjmp(TAG_FATAL, mesg, Qnil);
+ rb_longjmp(TAG_FATAL, mesg);
}
void
rb_interrupt()
{
- Raise(eInterrupt, "");
+ rb_raise(rb_eInterrupt, "");
}
static VALUE
-f_raise(argc, argv)
+rb_f_raise(argc, argv)
int argc;
VALUE *argv;
{
- VALUE arg1, arg2, arg3;
- VALUE etype, mesg;
+ VALUE mesg;
+ ID exception;
int n;
- etype = eRuntimeError;
mesg = Qnil;
- switch (n = rb_scan_args(argc, argv, "03", &arg1, &arg2, &arg3)) {
- case 1:
- mesg = arg1;
+ switch (argc) {
+ case 0:
+ mesg = Qnil;
break;
+ case 1:
+ if (NIL_P(argv[0])) break;
+ if (TYPE(argv[0]) == T_STRING) {
+ mesg = rb_exc_new3(rb_eRuntimeError, argv[0]);
+ break;
+ }
+ n = 0;
+ goto exception_call;
+
case 2:
case 3:
- etype = arg1;
- if (obj_is_kind_of(etype, eGlobalExit)) {
- etype = CLASS_OF(etype);
- }
- else {
- Check_Type(etype, T_CLASS);
+ n = 1;
+ exception_call:
+ exception = rb_intern("exception");
+ if (!rb_respond_to(argv[0], exception)) {
+ rb_raise(rb_eTypeError, "exception class/object expected");
}
- mesg = arg2;
+ mesg = rb_funcall(argv[0], exception, n, argv[1]);
+ break;
+ default:
+ rb_raise(rb_eArgError, "wrong # of arguments");
break;
}
+ if (argc > 0) {
+ if (!rb_obj_is_kind_of(mesg, rb_eException))
+ rb_raise(rb_eTypeError, "exception object expected");
+ set_backtrace(mesg, (argc>2)?argv[2]:Qnil);
+ }
- if (!NIL_P(mesg)) {
- Check_Type(mesg, T_STRING);
- if (n == 2 || !obj_is_kind_of(mesg, eException)) {
- mesg = exc_new3(etype, mesg);
- }
+ if (ruby_frame != top_frame) {
+ PUSH_FRAME(); /* fake frame */
+ *ruby_frame = *_frame.prev->prev;
+ rb_longjmp(TAG_RAISE, mesg);
+ POP_FRAME();
}
+ rb_longjmp(TAG_RAISE, mesg);
- PUSH_FRAME(); /* fake frame */
- *the_frame = *_frame.prev->prev;
- rb_longjmp(TAG_RAISE, mesg, arg3);
- POP_FRAME();
+ return Qnil; /* not reached */
+}
+
+void
+rb_jump_tag(tag)
+ int tag;
+{
+ JUMP_TAG(tag);
}
int
-iterator_p()
+rb_block_given_p()
{
- if (the_frame->iter) return TRUE;
- return FALSE;
+ if (ruby_frame->iter) return Qtrue;
+ return Qfalse;
+}
+
+int
+rb_iterator_p()
+{
+ return rb_block_given_p();
}
static VALUE
-f_iterator_p()
+rb_f_block_given_p()
{
- if (the_frame->prev && the_frame->prev->iter) return TRUE;
- return FALSE;
+ if (ruby_frame->prev && ruby_frame->prev->iter) return Qtrue;
+ return Qfalse;
}
-VALUE
-rb_yield_0(val, self)
- VALUE val;
- volatile VALUE self;
+static VALUE
+rb_yield_0(val, self, klass, acheck)
+ VALUE val, self, klass; /* OK */
+ int acheck;
{
NODE *node;
volatile VALUE result = Qnil;
@@ -2789,31 +3506,67 @@ rb_yield_0(val, self)
struct SCOPE *old_scope;
struct FRAME frame;
int state;
- static USHORT serial = 1;
+ static unsigned serial = 1;
- if (!iterator_p()) {
- Raise(eLocalJumpError, "yield called out of iterator");
+ if (!(rb_block_given_p() || rb_f_block_given_p()) || !ruby_block) {
+ rb_raise(rb_eLocalJumpError, "yield called out of block");
}
PUSH_VARS();
PUSH_CLASS();
- block = the_block;
+ block = ruby_block;
frame = block->frame;
- frame.prev = the_frame;
- the_frame = &(frame);
- old_scope = the_scope;
- the_scope = block->scope;
- the_block = block->prev;
- the_dyna_vars = block->d_vars;
- the_class = block->klass;
- if (!self) self = block->self;
+ frame.prev = ruby_frame;
+ ruby_frame = &(frame);
+ old_scope = ruby_scope;
+ ruby_scope = block->scope;
+ ruby_block = block->prev;
+ if (block->flags & BLOCK_D_SCOPE) {
+ /* put place holder for dynamic (in-block) local variables */
+ ruby_dyna_vars = new_dvar(0, 0, block->dyna_vars);
+ }
+ else {
+ /* FOR does not introduce new scope */
+ ruby_dyna_vars = block->dyna_vars;
+ }
+ ruby_class = klass?klass:block->klass;
+ if (!klass) self = block->self;
node = block->body;
+
if (block->var) {
- if (nd_type(block->var) == NODE_MASGN)
- massign(self, block->var, val);
- else
- assign(self, block->var, val);
+ PUSH_TAG(PROT_NONE);
+ if ((state = EXEC_TAG()) == 0) {
+ if (block->var == (NODE*)1) {
+ if (acheck && val != Qundef &&
+ TYPE(val) == T_ARRAY && RARRAY(val)->len != 0) {
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 0)",
+ RARRAY(val)->len);
+ }
+ }
+ else {
+ if (nd_type(block->var) == NODE_MASGN)
+ massign(self, block->var, val, acheck);
+ else {
+ /* argument adjust for proc_call etc. */
+ if (acheck && val != Qundef &&
+ TYPE(val) == T_ARRAY && RARRAY(val)->len == 1) {
+ val = RARRAY(val)->ptr[0];
+ }
+ assign(self, block->var, val, acheck);
+ }
+ }
+ }
+ POP_TAG();
+ if (state) goto pop_state;
}
+ else {
+ /* argument adjust for proc_call etc. */
+ if (acheck && val != Qundef &&
+ TYPE(val) == T_ARRAY && RARRAY(val)->len == 1) {
+ val = RARRAY(val)->ptr[0];
+ }
+ }
+
PUSH_ITER(block->iter);
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
@@ -2821,7 +3574,8 @@ rb_yield_0(val, self)
if (!node) {
result = Qnil;
}
- else if (nd_type(node) == NODE_CFUNC) {
+ else if (nd_type(node) == NODE_CFUNC || nd_type(node) == NODE_IFUNC) {
+ if (val == Qundef) val = rb_ary_new2(0);
result = (*node->nd_cfnc)(val, node->nd_tval, self);
}
else {
@@ -2832,6 +3586,7 @@ rb_yield_0(val, self)
switch (state) {
case TAG_REDO:
state = 0;
+ CHECK_INTS;
goto redo;
case TAG_NEXT:
state = 0;
@@ -2841,20 +3596,66 @@ rb_yield_0(val, self)
case TAG_RETURN:
state |= (serial++ << 8);
state |= 0x10;
- block->tag->dst = state;
+ block->tag->dst = state;
break;
default:
break;
}
}
POP_TAG();
+ pop_state:
POP_ITER();
POP_CLASS();
+#if 0
+ if (ruby_dyna_vars && (block->flags & BLOCK_D_SCOPE) &&
+ (!(ruby_scope->flags & SCOPE_DONT_RECYCLE) ||
+ !(block->tag->flags & BLOCK_DYNAMIC) ||
+ !FL_TEST(ruby_dyna_vars, DVAR_DONT_RECYCLE))) {
+ struct RVarmap *vars, *tmp;
+
+ if (ruby_dyna_vars->id == 0) {
+ vars = ruby_dyna_vars->next;
+ rb_gc_force_recycle((VALUE)ruby_dyna_vars);
+ while (vars && vars->id != 0) {
+ tmp = vars->next;
+ rb_gc_force_recycle((VALUE)vars);
+ vars = tmp;
+ }
+ }
+ }
+#else
+ if (ruby_dyna_vars && (block->flags & BLOCK_D_SCOPE) &&
+ !FL_TEST(ruby_dyna_vars, DVAR_DONT_RECYCLE)) {
+ struct RVarmap *vars = ruby_dyna_vars;
+
+ if (ruby_dyna_vars->id == 0) {
+ vars = ruby_dyna_vars->next;
+ rb_gc_force_recycle((VALUE)ruby_dyna_vars);
+ while (vars && vars->id != 0) {
+ struct RVarmap *tmp = vars->next;
+ rb_gc_force_recycle((VALUE)vars);
+ vars = tmp;
+ }
+ }
+ }
+#endif
POP_VARS();
- the_block = block;
- the_frame = the_frame->prev;
- the_scope = old_scope;
- if (state) JUMP_TAG(state);
+ ruby_block = block;
+ ruby_frame = ruby_frame->prev;
+ if (ruby_scope->flag & SCOPE_DONT_RECYCLE)
+ scope_dup(old_scope);
+ ruby_scope = old_scope;
+ if (state) {
+ if (!block->tag) {
+ switch (state & TAG_MASK) {
+ case TAG_BREAK:
+ case TAG_RETURN:
+ jump_tag_but_local_jump(state & TAG_MASK);
+ break;
+ }
+ }
+ JUMP_TAG(state);
+ }
return result;
}
@@ -2862,60 +3663,90 @@ VALUE
rb_yield(val)
VALUE val;
{
- return rb_yield_0(val, 0);
+ return rb_yield_0(val, 0, 0, 0);
}
static VALUE
-f_loop()
+rb_f_loop()
{
- for (;;) { rb_yield(Qnil); }
+ for (;;) {
+ rb_yield_0(Qnil, 0, 0, 0);
+ CHECK_INTS;
+ }
+ return Qnil; /* dummy */
}
static VALUE
-massign(self, node, val)
+massign(self, node, val, check)
VALUE self;
NODE *node;
VALUE val;
+ int check;
{
NODE *list;
- int i, len;
+ int i = 0, len;
+ if (val == Qundef) {
+ val = rb_ary_new2(0);
+ }
+ else if (TYPE(val) != T_ARRAY) {
+ if (rb_respond_to(val, to_ary)) {
+ VALUE ary = rb_funcall(val, to_ary, 0);
+ if (TYPE(ary) != T_ARRAY) {
+ rb_raise(rb_eTypeError, "%s#to_ary should return Array",
+ rb_class2name(CLASS_OF(val)));
+ }
+ val = ary;
+ }
+ else {
+ val = rb_ary_new3(1, val);
+ }
+ }
+ len = RARRAY(val)->len;
list = node->nd_head;
-
- if (val) {
- if (TYPE(val) != T_ARRAY) {
- val = rb_Array(val);
+ for (i=0; list && i<len; i++) {
+ assign(self, list->nd_head, RARRAY(val)->ptr[i], check);
+ list = list->nd_next;
+ }
+ if (check && list) goto arg_error;
+ if (node->nd_args) {
+ if (node->nd_args == (NODE*)-1) {
+ /* no check for mere `*' */
}
- len = RARRAY(val)->len;
- for (i=0; list && i<len; i++) {
- assign(self, list->nd_head, RARRAY(val)->ptr[i]);
- list = list->nd_next;
+ else if (!list && i<len) {
+ assign(self, node->nd_args, rb_ary_new4(len-i, RARRAY(val)->ptr+i), check);
}
- if (node->nd_args) {
- if (!list && i<len) {
- assign(self, node->nd_args, ary_new4(len-i, RARRAY(val)->ptr+i));
- }
- else {
- assign(self, node->nd_args, ary_new2(0));
- }
+ else {
+ assign(self, node->nd_args, rb_ary_new2(0), check);
}
}
- else if (node->nd_args) {
- assign(self, node->nd_args, Qnil);
+ else if (check && i < len) {
+ goto arg_error;
}
+
while (list) {
- assign(self, list->nd_head, Qnil);
+ i++;
+ assign(self, list->nd_head, Qnil, check);
list = list->nd_next;
}
return val;
+
+ arg_error:
+ while (list) {
+ i++;
+ list = list->nd_next;
+ }
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for %d)", len, i);
}
static void
-assign(self, lhs, val)
+assign(self, lhs, val, check)
VALUE self;
NODE *lhs;
VALUE val;
+ int check;
{
+ if (val == Qundef) val = Qnil;
switch (nd_type(lhs)) {
case NODE_GASGN:
rb_gvar_set(lhs->nd_entry, val);
@@ -2926,40 +3757,60 @@ assign(self, lhs, val)
break;
case NODE_LASGN:
- if (the_scope->local_vars == 0)
- Bug("unexpected iterator variable assignment");
- the_scope->local_vars[lhs->nd_cnt] = val;
+ if (ruby_scope->local_vars == 0)
+ rb_bug("unexpected local variable assignment");
+ ruby_scope->local_vars[lhs->nd_cnt] = val;
break;
case NODE_DASGN:
- dyna_var_asgn(lhs->nd_vid, val);
+ dvar_asgn(lhs->nd_vid, val);
break;
- case NODE_CASGN:
- rb_const_set(the_class, lhs->nd_vid, val);
+ case NODE_DASGN_CURR:
+ dvar_asgn_curr(lhs->nd_vid, val);
+ break;
+
+ case NODE_CDECL:
+ rb_const_set(ruby_class, lhs->nd_vid, val);
+ break;
+
+ case NODE_CVDECL:
+ if (!FL_TEST(ruby_cbase, FL_SINGLETON)) {
+ rb_cvar_declare(ruby_cbase, lhs->nd_vid, val);
+ break;
+ }
+ self = rb_iv_get(ruby_cbase, "__attached__");
+ /* fall through */
+ case NODE_CVASGN:
+ rb_cvar_set(rb_cvar_singleton(self), lhs->nd_vid, val);
+ break;
+
+ case NODE_MASGN:
+ massign(self, lhs, val, check);
break;
case NODE_CALL:
{
VALUE recv;
recv = rb_eval(self, lhs->nd_recv);
- if (!lhs->nd_args->nd_head) {
+ if (!lhs->nd_args) {
/* 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 */
VALUE args;
args = rb_eval(self, lhs->nd_args);
- RARRAY(args)->ptr[RARRAY(args)->len-1] = val;
- rb_apply(recv, lhs->nd_mid, args);
+ rb_ary_push(args, val);
+ rb_call(CLASS_OF(recv), recv, lhs->nd_mid,
+ RARRAY(args)->len, RARRAY(args)->ptr, 0);
}
}
break;
default:
- Bug("bug in variable assignment");
+ rb_bug("bug in variable assignment");
break;
}
}
@@ -2971,20 +3822,19 @@ rb_iterate(it_proc, data1, bl_proc, data2)
{
int state;
volatile VALUE retval = Qnil;
- NODE *node = NEW_CFUNC(bl_proc, data2);
- VALUE self = TopSelf;
+ NODE *node = NEW_IFUNC(bl_proc, data2);
+ VALUE self = ruby_top_self;
iter_retry:
PUSH_ITER(ITER_PRE);
PUSH_BLOCK(0, node);
- _block.d_vars = new_dvar(0,0);
PUSH_TAG(PROT_NONE);
state = EXEC_TAG();
if (state == 0) {
retval = (*it_proc)(data1);
}
- if (the_block->tag->dst == state) {
+ if (ruby_block->tag->dst == state) {
state &= TAG_MASK;
if (state == TAG_RETURN) {
retval = prot_tag->retval;
@@ -3023,53 +3873,76 @@ handle_rescue(self, node)
TMP_PROTECT;
if (!node->nd_args) {
- return obj_is_kind_of(errinfo, eException);
+ return rb_obj_is_kind_of(ruby_errinfo, rb_eStandardError);
}
- PUSH_ITER(ITER_NOT);
+ BEGIN_CALLARGS;
SETUP_ARGS(node->nd_args);
- POP_ITER();
+ END_CALLARGS;
+
while (argc--) {
- if (!obj_is_kind_of(argv[0], cModule)) {
- TypeError("class or module required for rescue clause");
+ if (!rb_obj_is_kind_of(argv[0], rb_cModule)) {
+ rb_raise(rb_eTypeError, "class or module required for rescue clause");
}
- if (obj_is_kind_of(errinfo, argv[0])) return 1;
+ if (rb_obj_is_kind_of(ruby_errinfo, argv[0])) return 1;
argv++;
}
return 0;
}
VALUE
-rb_rescue(b_proc, data1, r_proc, data2)
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_rescue2(VALUE (*b_proc)(), VALUE data1, VALUE (*r_proc)(), VALUE data2, ...)
+#else
+rb_rescue2(b_proc, data1, r_proc, data2, va_alist)
VALUE (*b_proc)(), (*r_proc)();
VALUE data1, data2;
+ va_dcl
+#endif
{
int state;
volatile VALUE result;
+ volatile VALUE e_info = ruby_errinfo;
+ va_list args;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
retry_entry:
result = (*b_proc)(data1);
}
- else if (state == TAG_RAISE && obj_is_kind_of(errinfo, eException)) {
- if (r_proc) {
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
- result = (*r_proc)(data2, errinfo);
+ else if (state == TAG_RAISE) {
+ int handle = Qfalse;
+ VALUE eclass;
+
+ va_init_list(args, data2);
+ while (eclass = va_arg(args, VALUE)) {
+ if (rb_obj_is_kind_of(ruby_errinfo, eclass)) {
+ handle = Qtrue;
+ break;
}
- POP_TAG();
- if (state == TAG_RETRY) {
+ }
+ va_end(args);
+
+ if (handle) {
+ if (r_proc) {
+ PUSH_TAG(PROT_NONE);
+ if ((state = EXEC_TAG()) == 0) {
+ result = (*r_proc)(data2, ruby_errinfo);
+ }
+ POP_TAG();
+ if (state == TAG_RETRY) {
+ state = 0;
+ ruby_errinfo = Qnil;
+ goto retry_entry;
+ }
+ }
+ else {
+ result = Qnil;
state = 0;
- goto retry_entry;
}
- }
- else {
- result = Qnil;
- state = 0;
- }
- if (state == 0) {
- errat = Qnil;
+ if (state == 0) {
+ ruby_errinfo = e_info;
+ }
}
}
POP_TAG();
@@ -3079,9 +3952,41 @@ rb_rescue(b_proc, data1, r_proc, data2)
}
VALUE
+rb_rescue(b_proc, data1, r_proc, data2)
+ VALUE (*b_proc)(), (*r_proc)();
+ VALUE data1, data2;
+{
+ return rb_rescue2(b_proc, data1, r_proc, data2, rb_eStandardError, 0);
+}
+
+VALUE
+rb_protect(proc, data, state)
+ VALUE (*proc)();
+ VALUE data;
+ int *state;
+{
+ VALUE result; /* OK */
+ int status;
+
+ PUSH_TAG(PROT_NONE);
+ if ((status = EXEC_TAG()) == 0) {
+ result = (*proc)(data);
+ }
+ POP_TAG();
+ if (state) {
+ *state = status;
+ }
+ if (status != 0) {
+ return Qnil;
+ }
+
+ return result;
+}
+
+VALUE
rb_ensure(b_proc, data1, e_proc, data2)
VALUE (*b_proc)();
- void (*e_proc)();
+ VALUE (*e_proc)();
VALUE data1, data2;
{
int state;
@@ -3093,13 +3998,31 @@ rb_ensure(b_proc, data1, e_proc, data2)
result = (*b_proc)(data1);
}
POP_TAG();
- retval = prot_tag->retval; /* save retval */
+ retval = prot_tag ? prot_tag->retval : Qnil; /* save retval */
(*e_proc)(data2);
- return_value(retval);
+ if (prot_tag) return_value(retval);
- if (state) {
- JUMP_TAG(state);
+ if (state) JUMP_TAG(state);
+ return result;
+}
+
+VALUE
+rb_with_disable_interrupt(proc, data)
+ VALUE (*proc)();
+ VALUE data;
+{
+ VALUE result; /* OK */
+ int status;
+
+ DEFER_INTS;
+ PUSH_TAG(PROT_NONE);
+ if ((status = EXEC_TAG()) == 0) {
+ result = (*proc)(data);
}
+ POP_TAG();
+ ALLOW_INTS;
+ if (status) JUMP_TAG(status);
+
return result;
}
@@ -3110,18 +4033,23 @@ static int last_call_status;
#define CSTAT_VCALL 4
static VALUE
-f_missing(argc, argv, obj)
+rb_f_missing(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
{
ID id;
- VALUE desc = 0;
+ volatile VALUE d = 0;
char *format = 0;
- char *file = sourcefile;
- int line = sourceline;
+ char *desc = "";
+ char *file = ruby_sourcefile;
+ int line = ruby_sourceline;
+
+ if (argc == 0 || !SYMBOL_P(argv[0])) {
+ rb_raise(rb_eArgError, "no id given");
+ }
- id = FIX2INT(argv[0]);
+ id = SYM2ID(argv[0]);
argc--; argv++;
switch (TYPE(obj)) {
@@ -3129,51 +4057,49 @@ f_missing(argc, argv, obj)
format = "undefined method `%s' for nil";
break;
case T_TRUE:
- format = "undefined method `%s' for TRUE";
+ format = "undefined method `%s' for true";
break;
case T_FALSE:
- format = "undefined method `%s' for FALSE";
+ format = "undefined method `%s' for false";
break;
case T_OBJECT:
- desc = any_to_s(obj);
+ d = rb_any_to_s(obj);
break;
default:
- desc = rb_inspect(obj);
+ d = rb_inspect(obj);
break;
}
- if (desc) {
+ if (d) {
if (last_call_status & CSTAT_PRIV) {
- format = "private method `%s' called for %s";
+ format = "private method `%s' called for %s%s%s";
}
if (last_call_status & CSTAT_PROT) {
- format = "protected method `%s' called for %s";
- }
- else if (iterator_p()) {
- format = "undefined iterator `%s' for %s";
+ format = "protected method `%s' called for %s%s%s";
}
else if (last_call_status & CSTAT_VCALL) {
- char *mname = rb_id2name(id);
+ const char *mname = rb_id2name(id);
if (('a' <= mname[0] && mname[0] <= 'z') || mname[0] == '_') {
- format = "undefined local variable or method `%s' for %s";
+ format = "undefined local variable or method `%s' for %s%s%s";
}
}
if (!format) {
- format = "undefined method `%s' for %s";
+ format = "undefined method `%s' for %s%s%s";
}
- if (RSTRING(desc)->len > 65) {
- desc = any_to_s(obj);
+ if (RSTRING(d)->len > 65) {
+ d = rb_any_to_s(obj);
}
+ desc = RSTRING(d)->ptr;
}
- sourcefile = file;
- sourceline = line;
+ ruby_sourcefile = file;
+ ruby_sourceline = line;
PUSH_FRAME(); /* fake frame */
- *the_frame = *_frame.prev->prev;
+ *ruby_frame = *_frame.prev->prev;
- NameError(format,
- rb_id2name(id),
- desc?(char*)RSTRING(desc)->ptr:"");
+ rb_raise(rb_eNameError, format, rb_id2name(id),
+ desc, desc[0]=='#'?"":":",
+ desc[0]=='#'?"":rb_class2name(CLASS_OF(obj)));
POP_FRAME();
return Qnil; /* not reached */
@@ -3190,45 +4116,152 @@ rb_undefined(obj, id, argc, argv, call_status)
VALUE *nargv;
nargv = ALLOCA_N(VALUE, argc+1);
- nargv[0] = INT2FIX(id);
+ nargv[0] = ID2SYM(id);
MEMCPY(nargv+1, argv, VALUE, argc);
last_call_status = call_status;
- return rb_funcall2(obj, rb_intern("method_missing"), argc+1, nargv);
+ return rb_funcall2(obj, missing, argc+1, nargv);
}
#ifdef DJGPP
-# define STACK_LEVEL_MAX 65535
+static int STACK_LEVEL_MAX = 65535;
#else
#ifdef __human68k__
extern int _stacksize;
# define STACK_LEVEL_MAX (_stacksize - 4096)
+#undef HAVE_GETRLIMIT
+#else
+#ifdef HAVE_GETRLIMIT
+static int STACK_LEVEL_MAX = 655300;
#else
-# define STACK_LEVEL_MAX 655350
+# define STACK_LEVEL_MAX 655300
#endif
#endif
-extern VALUE *gc_stack_start;
+#endif
+
+extern VALUE *rb_gc_stack_start;
static int
-stack_length()
+stack_length(p)
+ VALUE **p;
{
- VALUE pos;
+#ifdef C_ALLOCA
+ VALUE stack_end;
+ alloca(0);
+# define STACK_END (&stack_end)
+#else
+# if defined(__GNUC__) && (defined(__i386__) || defined(__m68k__))
+ VALUE *stack_end = __builtin_frame_address(0);
+# else
+ VALUE *stack_end = alloca(1);
+# endif
+# define STACK_END (stack_end)
+#endif
+ if (p) *p = STACK_END;
-#ifdef sparc
- return gc_stack_start - &pos + 0x80;
+#ifdef __sparc__
+ return rb_gc_stack_start - STACK_END + 0x80;
#else
- return (&pos < gc_stack_start) ? gc_stack_start - &pos
- : &pos - gc_stack_start;
+ return (STACK_END < rb_gc_stack_start) ? rb_gc_stack_start - STACK_END
+ : STACK_END - rb_gc_stack_start;
#endif
}
static VALUE
+call_cfunc(func, recv, len, argc, argv)
+ VALUE (*func)();
+ VALUE recv;
+ int len, argc;
+ VALUE *argv;
+{
+ if (len >= 0 && argc != len) {
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for %d)",
+ argc, len);
+ }
+
+ switch (len) {
+ case -2:
+ return (*func)(recv, rb_ary_new4(argc, argv));
+ break;
+ case -1:
+ return (*func)(argc, argv, recv);
+ break;
+ case 0:
+ return (*func)(recv);
+ break;
+ case 1:
+ return (*func)(recv, argv[0]);
+ break;
+ case 2:
+ return (*func)(recv, argv[0], argv[1]);
+ break;
+ case 3:
+ return (*func)(recv, argv[0], argv[1], argv[2]);
+ break;
+ case 4:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3]);
+ break;
+ case 5:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4]);
+ break;
+ case 6:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5]);
+ break;
+ case 7:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6]);
+ break;
+ case 8:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7]);
+ break;
+ case 9:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7], argv[8]);
+ break;
+ case 10:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7], argv[8], argv[9]);
+ break;
+ case 11:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]);
+ break;
+ case 12:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7], argv[8], argv[9],
+ argv[10], argv[11]);
+ break;
+ case 13:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
+ argv[11], argv[12]);
+ break;
+ case 14:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
+ argv[11], argv[12], argv[13]);
+ break;
+ case 15:
+ return (*func)(recv, argv[0], argv[1], argv[2], argv[3], argv[4],
+ argv[5], argv[6], argv[7], argv[8], argv[9], argv[10],
+ argv[11], argv[12], argv[13], argv[14]);
+ break;
+ default:
+ rb_raise(rb_eArgError, "too many arguments(%d)", len);
+ break;
+ }
+ return Qnil; /* not reached */
+}
+
+static VALUE
rb_call0(klass, recv, id, argc, argv, body, nosuper)
VALUE klass, recv;
ID id;
int argc; /* OK */
VALUE *argv; /* OK */
- NODE *body;
+ NODE *body; /* OK */
int nosuper;
{
NODE *b2; /* OK */
@@ -3237,7 +4270,7 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper)
static int tick;
TMP_PROTECT;
- switch (the_iter->iter) {
+ switch (ruby_iter->iter) {
case ITER_PRE:
itr = ITER_CUR;
break;
@@ -3247,126 +4280,50 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper)
break;
}
- if ((++tick & 0xfff) == 0 && stack_length() > STACK_LEVEL_MAX)
- Raise(eSysStackError, "stack level too deep");
-
+ if ((++tick & 0xff) == 0) {
+ CHECK_INTS; /* better than nothing */
+ if (stack_length(0) > STACK_LEVEL_MAX) {
+ rb_raise(rb_eSysStackError, "stack level too deep");
+ }
+ }
PUSH_ITER(itr);
PUSH_FRAME();
- the_frame->last_func = id;
- the_frame->last_class = nosuper?0:klass;
- the_frame->self = recv;
- the_frame->argc = argc;
- the_frame->argv = argv;
+
+ ruby_frame->last_func = id;
+ ruby_frame->last_class = nosuper?0:klass;
+ ruby_frame->self = recv;
+ ruby_frame->argc = argc;
+ ruby_frame->argv = argv;
switch (nd_type(body)) {
case NODE_CFUNC:
{
int len = body->nd_argc;
- if (len >= 0 && argc != len) {
- ArgError("Wrong # of arguments(%d for %d)", argc, len);
+ if (len < -2) {
+ rb_bug("bad argc(%d) specified for `%s(%s)'",
+ len, rb_class2name(klass), rb_id2name(id));
}
-
- switch (len) {
- case -2:
- result = (*body->nd_cfnc)(recv, ary_new4(argc, argv));
- break;
- case -1:
- result = (*body->nd_cfnc)(argc, argv, recv);
- break;
- case 0:
- result = (*body->nd_cfnc)(recv);
- break;
- case 1:
- result = (*body->nd_cfnc)(recv, argv[0]);
- break;
- case 2:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1]);
- break;
- case 3:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2]);
- break;
- case 4:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3]);
- break;
- case 5:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4]);
- break;
- case 6:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5]);
- break;
- case 7:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6]);
- break;
- case 8:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7]);
- break;
- case 9:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8]);
- break;
- case 10:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9]);
- break;
- case 11:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10]);
- break;
- case 12:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10], argv[11]);
- break;
- case 13:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10], argv[11],
- argv[12]);
- break;
- case 14:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10], argv[11],
- argv[12], argv[13]);
- break;
- case 15:
- result = (*body->nd_cfnc)(recv, argv[0], argv[1], argv[2],
- argv[3], argv[4], argv[5],
- argv[6], argv[7], argv[8],
- argv[6], argv[7], argv[8],
- argv[9], argv[10], argv[11],
- argv[12], argv[13], argv[14]);
- break;
- default:
- if (len < 0) {
- Bug("bad argc(%d) specified for `%s(%s)'",
- len, rb_class2name(klass), rb_id2name(id));
+ if (trace_func) {
+ int state;
+ char *file = ruby_frame->prev->file;
+ int line = ruby_frame->prev->line;
+ if (!file) {
+ file = ruby_sourcefile;
+ line = ruby_sourceline;
}
- else {
- ArgError("too many arguments(%d)", len);
+
+ call_trace_func("c-call", 0, 0, recv, id, klass);
+ PUSH_TAG(PROT_FUNC);
+ if ((state = EXEC_TAG()) == 0) {
+ result = call_cfunc(body->nd_cfnc, recv, len, argc, argv);
}
- break;
+ POP_TAG();
+ call_trace_func("c-return", 0, 0, recv, id, klass);
+ if (state) JUMP_TAG(state);
+ }
+ else {
+ result = call_cfunc(body->nd_cfnc, recv, len, argc, argv);
}
}
break;
@@ -3379,29 +4336,42 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper)
result = rb_eval(recv, body);
break;
- default:
+ case NODE_DMETHOD:
+ result = method_call(argc, argv, umethod_bind(body->nd_cval, recv));
+ break;
+
+ case NODE_BMETHOD:
+ result = proc_call(body->nd_cval, rb_ary_new4(argc, argv));
+ break;
+
+ case NODE_SCOPE:
{
int state;
VALUE *local_vars; /* OK */
+ NODE *saved_cref = 0;
PUSH_SCOPE();
- if (body->nd_rval) the_frame->cbase = body->nd_rval;
+ if (body->nd_rval) {
+ saved_cref = ruby_cref;
+ ruby_cref = (NODE*)body->nd_rval;
+ ruby_frame->cbase = body->nd_rval;
+ }
if (body->nd_tbl) {
- local_vars = TMP_ALLOC(VALUE, body->nd_tbl[0]+1);
+ local_vars = TMP_ALLOC(body->nd_tbl[0]+1);
*local_vars++ = (VALUE)body;
- memclear(local_vars, body->nd_tbl[0]);
- the_scope->local_tbl = body->nd_tbl;
- the_scope->local_vars = local_vars;
+ rb_mem_clear(local_vars, body->nd_tbl[0]);
+ ruby_scope->local_tbl = body->nd_tbl;
+ ruby_scope->local_vars = local_vars;
}
else {
- local_vars = the_scope->local_vars = 0;
- the_scope->local_tbl = 0;
+ local_vars = ruby_scope->local_vars = 0;
+ ruby_scope->local_tbl = 0;
}
- b2 = body = body->nd_body;
+ b2 = body = body->nd_next;
- PUSH_TAG(PROT_FUNC);
PUSH_VARS();
+ PUSH_TAG(PROT_FUNC);
if ((state = EXEC_TAG()) == 0) {
NODE *node = 0;
@@ -3417,25 +4387,28 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper)
}
if (node) {
if (nd_type(node) != NODE_ARGS) {
- Bug("no argument-node");
+ rb_bug("no argument-node");
}
i = node->nd_cnt;
if (i > argc) {
- ArgError("Wrong # of arguments(%d for %d)", argc, i);
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for %d)",
+ argc, i);
}
if (node->nd_rest == -1) {
- int opt = argc - i;
+ int opt = i;
NODE *optnode = node->nd_opt;
while (optnode) {
- opt--;
+ opt++;
optnode = optnode->nd_next;
}
- if (opt > 0) {
- ArgError("Wrong # of arguments(%d for %d)",
- argc, argc-opt);
+ if (opt < argc) {
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for %d)",
+ argc, opt);
}
+ ruby_frame->argc = opt;
+ ruby_frame->argv = local_vars+2;
}
if (local_vars) {
@@ -3448,24 +4421,27 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper)
NODE *opt = node->nd_opt;
while (opt && argc) {
- assign(recv, opt->nd_head, *argv);
+ assign(recv, opt->nd_head, *argv, 1);
argv++; argc--;
opt = opt->nd_next;
}
rb_eval(recv, opt);
}
if (node->nd_rest >= 0) {
+ VALUE v;
+
if (argc > 0)
- local_vars[node->nd_rest]=ary_new4(argc,argv);
+ v = rb_ary_new4(argc,argv);
else
- local_vars[node->nd_rest]=ary_new2(0);
+ v = rb_ary_new2(0);
+ local_vars[node->nd_rest] = v;
}
}
}
if (trace_func) {
call_trace_func("call", b2->nd_file, nd_line(b2),
- recv, the_frame->last_func);
+ recv, id, klass);
}
result = rb_eval(recv, body);
}
@@ -3473,39 +4449,38 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper)
result = prot_tag->retval;
state = 0;
}
- POP_VARS();
POP_TAG();
+ POP_VARS();
POP_SCOPE();
+ ruby_cref = saved_cref;
if (trace_func) {
- char *file = the_frame->prev->file;
- int line = the_frame->prev->line;
+ char *file = ruby_frame->prev->file;
+ int line = ruby_frame->prev->line;
if (!file) {
- file = sourcefile;
- line = sourceline;
+ file = ruby_sourcefile;
+ line = ruby_sourceline;
}
- call_trace_func("return", file, line, 0, the_frame->last_func);
+ call_trace_func("return", file, line, recv, id, klass);
}
switch (state) {
case 0:
break;
- case TAG_NEXT:
- Raise(eLocalJumpError, "unexpected next");
- break;
- case TAG_BREAK:
- Raise(eLocalJumpError, "unexpected break");
- break;
- case TAG_REDO:
- Raise(eLocalJumpError, "unexpected redo");
- break;
case TAG_RETRY:
- if (!iterator_p()) {
- Raise(eLocalJumpError, "retry outside of rescue clause");
+ if (rb_block_given_p()) {
+ JUMP_TAG(state);
}
+ /* fall through */
default:
- JUMP_TAG(state);
+ jump_tag_but_local_jump(state);
+ break;
}
}
+ break;
+
+ default:
+ rb_bug("unknown node type %d", nd_type(body));
+ break;
}
POP_FRAME();
POP_ITER();
@@ -3525,9 +4500,14 @@ rb_call(klass, recv, mid, argc, argv, scope)
ID id = mid;
struct cache_entry *ent;
+ if (!klass) {
+ rb_raise(rb_eNotImpError, "method call on terminated object");
+ }
/* is it in the method cache? */
ent = cache + EXPR1(klass, mid);
if (ent->mid == mid && ent->klass == klass) {
+ if (!ent->method)
+ return rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
klass = ent->origin;
id = ent->mid0;
noex = ent->noex;
@@ -3535,18 +4515,26 @@ rb_call(klass, recv, mid, argc, argv, scope)
}
else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
if (scope == 3) {
- NameError("super: no superclass method `%s'", rb_id2name(mid));
+ rb_raise(rb_eNameError, "super: no superclass method `%s'",
+ rb_id2name(mid));
}
return rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0);
}
- /* receiver specified form for private method */
- if ((noex & NOEX_PRIVATE) && scope == 0)
- return rb_undefined(recv, mid, argc, argv, CSTAT_PRIV);
+ if (mid != missing) {
+ /* receiver specified form for private method */
+ if ((noex & NOEX_PRIVATE) && scope == 0)
+ return rb_undefined(recv, mid, argc, argv, CSTAT_PRIV);
- /* self must be kind of a specified form for private method */
- if ((noex & NOEX_PROTECTED) && !obj_is_kind_of(the_frame->self, klass))
- return rb_undefined(recv, mid, argc, argv, CSTAT_PROT);
+ /* self must be kind of a specified form for private method */
+ if ((noex & NOEX_PROTECTED)) {
+ VALUE defined_class = klass;
+ while (TYPE(defined_class) == T_ICLASS)
+ defined_class = RBASIC(defined_class)->klass;
+ if (!rb_obj_is_kind_of(ruby_frame->self, defined_class))
+ return rb_undefined(recv, mid, argc, argv, CSTAT_PROT);
+ }
+ }
return rb_call0(klass, recv, id, argc, argv, body, noex & NOEX_UNDEF);
}
@@ -3567,17 +4555,17 @@ rb_apply(recv, mid, args)
}
static VALUE
-f_send(argc, argv, recv)
+rb_f_send(argc, argv, recv)
int argc;
VALUE *argv;
VALUE recv;
{
VALUE vid;
- if (argc == 0) ArgError("no method name given");
+ if (argc == 0) rb_raise(rb_eArgError, "no method name given");
vid = *argv++; argc--;
- PUSH_ITER(iterator_p()?ITER_PRE:ITER_NOT);
+ PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
vid = rb_call(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, 1);
POP_ITER();
@@ -3585,14 +4573,24 @@ f_send(argc, argv, recv)
}
+#ifdef HAVE_STDARG_PROTOTYPES
+#include <stdarg.h>
+#define va_init_list(a,b) va_start(a,b)
+#else
#include <varargs.h>
+#define va_init_list(a,b) va_start(a)
+#endif
VALUE
+#ifdef HAVE_STDARG_PROTOTYPES
+rb_funcall(VALUE recv, ID mid, int n, ...)
+#else
rb_funcall(recv, mid, n, va_alist)
VALUE recv;
ID mid;
int n;
va_dcl
+#endif
{
va_list ar;
VALUE *argv;
@@ -3602,7 +4600,7 @@ rb_funcall(recv, mid, n, va_alist)
argv = ALLOCA_N(VALUE, n);
- va_start(ar);
+ va_init_list(ar, n);
for (i=0;i<n;i++) {
argv[i] = va_arg(ar, VALUE);
}
@@ -3625,51 +4623,87 @@ rb_funcall2(recv, mid, argc, argv)
return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1);
}
+VALUE
+rb_funcall3(recv, mid, argc, argv)
+ VALUE recv;
+ ID mid;
+ int argc;
+ VALUE *argv;
+{
+ return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 0);
+}
+
+VALUE
+rb_call_super(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE result;
+
+ if (ruby_frame->last_class == 0) {
+ rb_raise(rb_eNameError, "superclass method `%s' must be enabled by rb_enable_super()",
+ rb_id2name(ruby_frame->last_func));
+ }
+
+ PUSH_ITER(ruby_iter->iter?ITER_PRE:ITER_NOT);
+ result = rb_call(RCLASS(ruby_frame->last_class)->super,
+ ruby_frame->self, ruby_frame->last_func,
+ argc, argv, 3);
+ POP_ITER();
+
+ return result;
+}
+
static VALUE
backtrace(lev)
int lev;
{
- struct FRAME *frame = the_frame;
+ struct FRAME *frame = ruby_frame;
char buf[BUFSIZ];
VALUE ary;
- int slev = safe_level;
- safe_level = 0;
- ary = ary_new();
+ ary = rb_ary_new();
if (lev < 0) {
if (frame->last_func) {
- sprintf(buf, "%s:%d:in `%s'", sourcefile, sourceline,
- rb_id2name(frame->last_func));
+ snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
+ ruby_sourcefile, ruby_sourceline,
+ rb_id2name(frame->last_func));
+ }
+ else if (ruby_sourceline == 0) {
+ snprintf(buf, BUFSIZ, "%s", ruby_sourcefile);
}
else {
- sprintf(buf, "%s:%d", sourcefile, sourceline);
+ snprintf(buf, BUFSIZ, "%s:%d", ruby_sourcefile, ruby_sourceline);
}
- ary_push(ary, str_new2(buf));
+ rb_ary_push(ary, rb_str_new2(buf));
}
else {
while (lev-- > 0) {
frame = frame->prev;
- if (!frame) return Qnil;
+ if (!frame) {
+ ary = Qnil;
+ break;
+ }
}
}
while (frame && frame->file) {
if (frame->prev && frame->prev->last_func) {
- sprintf(buf, "%s:%d:in `%s'",
- frame->file, frame->line,
- rb_id2name(frame->prev->last_func));
+ snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
+ frame->file, frame->line,
+ rb_id2name(frame->prev->last_func));
}
else {
- sprintf(buf, "%s:%d", frame->file, frame->line);
+ snprintf(buf, BUFSIZ, "%s:%d", frame->file, frame->line);
}
- ary_push(ary, str_new2(buf));
+ rb_ary_push(ary, rb_str_new2(buf));
frame = frame->prev;
}
- safe_level = slev;
+
return ary;
}
static VALUE
-f_caller(argc, argv)
+rb_f_caller(argc, argv)
int argc;
VALUE *argv;
{
@@ -3680,7 +4714,7 @@ f_caller(argc, argv)
if (NIL_P(level)) lev = 1;
else lev = NUM2INT(level);
- if (lev < 0) ArgError("negative level(%d)", lev);
+ if (lev < 0) rb_raise(rb_eArgError, "negative level(%d)", lev);
return backtrace(lev);
}
@@ -3688,10 +4722,9 @@ f_caller(argc, argv)
void
rb_backtrace()
{
- int i, lev;
+ int i;
VALUE ary;
- lev = INT2FIX(0);
ary = backtrace(-1);
for (i=0; i<RARRAY(ary)->len; i++) {
printf("\tfrom %s\n", RSTRING(RARRAY(ary)->ptr[i])->ptr);
@@ -3701,30 +4734,28 @@ rb_backtrace()
static VALUE
make_backtrace()
{
- VALUE lev;
-
- lev = INT2FIX(0);
return backtrace(-1);
}
ID
rb_frame_last_func()
{
- return the_frame->last_func;
+ return ruby_frame->last_func;
}
static NODE*
-compile(src, place)
+compile(src, file, line)
VALUE src;
- char *place;
+ char *file;
+ int line;
{
NODE *node;
+ ruby_nerrs = 0;
Check_Type(src, T_STRING);
- if (place == 0) place = sourcefile;
- node = compile_string(place, RSTRING(src)->ptr, RSTRING(src)->len);
+ node = rb_compile_string(file, src, line);
- if (nerrs == 0) return node;
+ if (ruby_nerrs == 0) return node;
return 0;
}
@@ -3738,96 +4769,126 @@ eval(self, src, scope, file, line)
volatile VALUE result = Qnil;
struct SCOPE * volatile old_scope;
struct BLOCK * volatile old_block;
- struct RVarmap * volatile old_d_vars;
+ struct RVarmap * volatile old_dyna_vars;
+ VALUE volatile old_cref;
int volatile old_vmode;
struct FRAME frame;
- char *filesave = sourcefile;
- int linesave = sourceline;
- volatile int iter = the_frame->iter;
+ char *filesave = ruby_sourcefile;
+ int linesave = ruby_sourceline;
+ volatile int iter = ruby_frame->iter;
int state;
if (file == 0) {
- file = sourcefile;
- line = sourceline;
+ file = ruby_sourcefile;
+ line = ruby_sourceline;
}
if (!NIL_P(scope)) {
- if (TYPE(scope) != T_DATA || RDATA(scope)->dfree != blk_free) {
- TypeError("wrong argument type %s (expected Proc/Binding)",
- rb_class2name(CLASS_OF(scope)));
+ if (!rb_obj_is_block(scope)) {
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc/Binding)",
+ rb_class2name(CLASS_OF(scope)));
}
Data_Get_Struct(scope, struct BLOCK, data);
-
/* PUSH BLOCK from data */
frame = data->frame;
- frame.prev = the_frame;
- the_frame = &(frame);
- old_scope = the_scope;
- the_scope = data->scope;
- old_block = the_block;
- the_block = data->prev;
- old_d_vars = the_dyna_vars;
- the_dyna_vars = data->d_vars;
+ frame.tmp = ruby_frame; /* gc protection */
+ ruby_frame = &(frame);
+ old_scope = ruby_scope;
+ ruby_scope = data->scope;
+ old_block = ruby_block;
+ ruby_block = data->prev;
+ old_dyna_vars = ruby_dyna_vars;
+ ruby_dyna_vars = data->dyna_vars;
old_vmode = scope_vmode;
scope_vmode = data->vmode;
+ old_cref = (VALUE)ruby_cref;
+ ruby_cref = (NODE*)ruby_frame->cbase;
self = data->self;
- the_frame->iter = data->iter;
+ ruby_frame->iter = data->iter;
}
else {
- if (the_frame->prev) {
- the_frame->iter = the_frame->prev->iter;
+ if (ruby_frame->prev) {
+ ruby_frame->iter = ruby_frame->prev->iter;
}
}
PUSH_CLASS();
- the_class = ((NODE*)the_frame->cbase)->nd_clss;
+ ruby_class = ruby_cbase;
- rb_in_eval++;
- if (TYPE(the_class) == T_ICLASS) {
- the_class = RBASIC(the_class)->klass;
+ ruby_in_eval++;
+ if (TYPE(ruby_class) == T_ICLASS) {
+ ruby_class = RBASIC(ruby_class)->klass;
}
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
- eval_tree = 0;
- compile(src, file);
- if (nerrs > 0) {
+ NODE *node;
+
+ result = ruby_errinfo;
+ ruby_errinfo = Qnil;
+ node = compile(src, file, line);
+ if (ruby_nerrs > 0) {
compile_error(0);
}
- result = eval_node(self);
+ if (!NIL_P(result)) ruby_errinfo = result;
+ result = eval_node(self, node);
}
POP_TAG();
POP_CLASS();
- rb_in_eval--;
+ ruby_in_eval--;
if (!NIL_P(scope)) {
- the_frame = the_frame->prev;
- the_scope = old_scope;
- the_block = old_block;
- the_dyna_vars = old_d_vars;
+ int dont_recycle = ruby_scope->flag & SCOPE_DONT_RECYCLE;
+
+ ruby_cref = (NODE*)old_cref;
+ ruby_frame = frame.tmp;
+ ruby_scope = old_scope;
+ ruby_block = old_block;
+ ruby_dyna_vars = old_dyna_vars;
data->vmode = scope_vmode; /* write back visibility mode */
scope_vmode = old_vmode;
+ if (dont_recycle) {
+ struct tag *tag;
+ struct RVarmap *vars;
+
+ scope_dup(ruby_scope);
+ for (tag=prot_tag; tag; tag=tag->prev) {
+ scope_dup(tag->scope);
+ }
+ if (ruby_block) {
+ struct BLOCK *block = ruby_block;
+ while (block) {
+ block->tag->flags |= BLOCK_DYNAMIC;
+ block = block->prev;
+ }
+ }
+ for (vars = ruby_dyna_vars; vars; vars = vars->next) {
+ FL_SET(vars, DVAR_DONT_RECYCLE);
+ }
+ }
}
else {
- the_frame->iter = iter;
+ ruby_frame->iter = iter;
}
- sourcefile = filesave;
- sourceline = linesave;
+ ruby_sourcefile = filesave;
+ ruby_sourceline = linesave;
if (state) {
- VALUE err;
-
if (state == TAG_RAISE) {
+ VALUE err;
+ VALUE errat;
+
if (strcmp(file, "(eval)") == 0) {
- if (sourceline > 1) {
+ if (ruby_sourceline > 1) {
+ errat = get_backtrace(ruby_errinfo);
err = RARRAY(errat)->ptr[0];
- str_cat(err, ": ", 2);
- str_cat(err, RSTRING(errinfo)->ptr, RSTRING(errinfo)->len);
+ rb_str_cat2(err, ": ");
+ rb_str_append(err, ruby_errinfo);
}
else {
- err = str_dup(errinfo);
+ err = rb_str_dup(ruby_errinfo);
}
errat = Qnil;
- rb_raise(exc_new3(CLASS_OF(errinfo), err));
+ rb_exc_raise(rb_exc_new3(CLASS_OF(ruby_errinfo), err));
}
- rb_raise(Qnil);
+ rb_exc_raise(ruby_errinfo);
}
JUMP_TAG(state);
}
@@ -3836,28 +4897,47 @@ eval(self, src, scope, file, line)
}
static VALUE
-f_eval(argc, argv, self)
+rb_f_eval(argc, argv, self)
int argc;
VALUE *argv;
VALUE self;
{
VALUE src, scope, vfile, vline;
char *file = "(eval)";
- int line = 0;
+ int line = 1;
rb_scan_args(argc, argv, "13", &src, &scope, &vfile, &vline);
- if (!NIL_P(vfile)) {
+ if (argc >= 3) {
Check_Type(vfile, T_STRING);
file = RSTRING(vfile)->ptr;
}
- if (!NIL_P(vline)) {
+ if (argc >= 4) {
line = NUM2INT(vline);
}
- Check_SafeStr(src);
+ if (ruby_safe_level >= 4) {
+ Check_Type(src, T_STRING);
+ }
+ else {
+ Check_SafeStr(src);
+ }
+ if (NIL_P(scope) && ruby_frame->prev) {
+ struct FRAME *prev;
+ VALUE val;
+
+ prev = ruby_frame;
+ PUSH_FRAME();
+ *ruby_frame = *prev->prev;
+ ruby_frame->prev = prev;
+ val = eval(self, src, scope, file, line);
+ POP_FRAME();
+
+ return val;
+ }
return eval(self, src, scope, file, line);
}
+/* function to call func under the specified class/module context */
static VALUE
exec_under(func, under, args)
VALUE (*func)();
@@ -3867,16 +4947,19 @@ exec_under(func, under, args)
VALUE val; /* OK */
int state;
int mode;
- VALUE cbase = the_frame->cbase;
PUSH_CLASS();
- the_class = under;
+ ruby_class = under;
PUSH_FRAME();
- the_frame->last_func = _frame.prev->last_func;
- the_frame->last_class = _frame.prev->last_class;
- the_frame->argc = _frame.prev->argc;
- the_frame->argv = _frame.prev->argv;
- the_frame->cbase = (VALUE)node_newnode(NODE_CREF,under,0,cbase);
+ ruby_frame->last_func = _frame.prev->last_func;
+ ruby_frame->last_class = _frame.prev->last_class;
+ ruby_frame->argc = _frame.prev->argc;
+ ruby_frame->argv = _frame.prev->argv;
+ if (ruby_cbase != under) {
+ ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,under,0,ruby_frame->cbase);
+ }
+ PUSH_CREF(under);
+
mode = scope_vmode;
SCOPE_SET(SCOPE_PUBLIC);
PUSH_TAG(PROT_NONE);
@@ -3884,6 +4967,7 @@ exec_under(func, under, args)
val = (*func)(args);
}
POP_TAG();
+ POP_CREF();
SCOPE_SET(mode);
POP_FRAME();
POP_CLASS();
@@ -3896,17 +4980,28 @@ static VALUE
eval_under_i(args)
VALUE *args;
{
- return eval(args[0], args[1], Qnil, 0, 0);
+ return eval(args[0], args[1], Qnil, (char*)args[2], (int)args[3]);
}
+/* string eval under the class/module context */
static VALUE
-eval_under(under, self, src)
+eval_under(under, self, src, file, line)
VALUE under, self, src;
+ const char *file;
+ int line;
{
- VALUE args[2];
+ VALUE args[4];
+ if (ruby_safe_level >= 4) {
+ Check_Type(src, T_STRING);
+ }
+ else {
+ Check_SafeStr(src);
+ }
args[0] = self;
args[1] = src;
+ args[2] = (VALUE)file;
+ args[3] = (VALUE)line;
return exec_under(eval_under_i, under, args);
}
@@ -3914,9 +5009,36 @@ static VALUE
yield_under_i(self)
VALUE self;
{
- return rb_yield_0(self, self);
+ if (ruby_block->flags & BLOCK_DYNAMIC) {
+ struct BLOCK * volatile old_block = ruby_block;
+ struct BLOCK block;
+
+ /* cbase should be pointed from volatile local variable */
+ /* to be protected from GC. */
+ VALUE result;
+ int state;
+
+ block = *ruby_block;
+ /* copy the block to avoid modifying global data. */
+ block.frame.cbase = ruby_frame->cbase;
+ ruby_block = &block;
+
+ PUSH_TAG(PROT_NONE);
+ if ((state = EXEC_TAG()) == 0) {
+ result = rb_yield_0(self, self, ruby_class, 0);
+ }
+ POP_TAG();
+ ruby_block = old_block;
+ if (state) JUMP_TAG(state);
+
+ return result;
+ }
+ /* static block, no need to restore */
+ ruby_block->frame.cbase = ruby_frame->cbase;
+ return rb_yield_0(self, self, ruby_class, 0);
}
+/* block eval under the class/module context */
static VALUE
yield_under(under, self)
VALUE under, self;
@@ -3925,299 +5047,414 @@ yield_under(under, self)
}
static VALUE
-obj_instance_eval(argc, argv, self)
+specific_eval(argc, argv, klass, self)
int argc;
VALUE *argv;
- VALUE self;
+ VALUE klass, self;
{
- if (argc == 0) {
- if (!iterator_p()) {
- ArgError("block not supplied");
+ if (rb_block_given_p()) {
+ if (argc > 0) {
+ rb_raise(rb_eArgError, "wrong # of arguments (%d for 0)", argc);
}
- }
- else if (argc == 1) {
- Check_SafeStr(argv[0]);
+ return yield_under(klass, self);
}
else {
- ArgError("Wrong # of arguments: %s(src) or %s{..}",
- rb_id2name(the_frame->last_func),
- rb_id2name(the_frame->last_func));
- }
+ char *file = "(eval)";
+ int line = 1;
- if (argc == 0) {
- return yield_under(rb_singleton_class(self), self);
- }
- else {
- return eval_under(rb_singleton_class(self), self, argv[0]);
+ if (argc == 0) {
+ rb_raise(rb_eArgError, "block not supplied");
+ }
+ else {
+ if (ruby_safe_level >= 4) {
+ Check_Type(argv[0], T_STRING);
+ }
+ else {
+ Check_SafeStr(argv[0]);
+ }
+ if (argc > 3) {
+ rb_raise(rb_eArgError, "wrong # of arguments: %s(src) or %s{..}",
+ rb_id2name(ruby_frame->last_func),
+ rb_id2name(ruby_frame->last_func));
+ }
+ if (argc > 1) file = STR2CSTR(argv[1]);
+ if (argc > 2) line = NUM2INT(argv[2]);
+ }
+ return eval_under(klass, self, argv[0], file, line);
}
}
-static VALUE
-mod_module_eval(argc, argv, mod)
+VALUE
+rb_obj_instance_eval(argc, argv, self)
int argc;
VALUE *argv;
- VALUE mod;
+ VALUE self;
{
- if (argc == 0) {
- if (!iterator_p()) {
- ArgError("block not supplied");
- }
- }
- else if (argc == 1) {
- Check_SafeStr(argv[0]);
- }
- else {
- ArgError("Wrong # of arguments: %s(src) or %s{..}",
- rb_id2name(the_frame->last_func),
- rb_id2name(the_frame->last_func));
- }
+ VALUE klass;
- if (argc == 0) {
- return yield_under(mod, mod);
+ if (rb_special_const_p(self)) {
+ klass = Qnil;
}
else {
- return eval_under(mod, mod, argv[0]);
+ klass = rb_singleton_class(self);
}
-}
-VALUE rb_load_path;
+ return specific_eval(argc, argv, klass, self);
+}
-static char*
-find_file(file)
- char *file;
+static VALUE
+rb_mod_module_eval(argc, argv, mod)
+ int argc;
+ VALUE *argv;
+ VALUE mod;
{
- extern VALUE rb_load_path;
- VALUE vpath;
- char *path;
-
- if (file[0] == '/') return file;
-#if defined(MSDOS) || defined(NT) || defined(__human68k__)
- if (file[0] == '\\') return file;
- if (file[1] == ':') return file;
-#endif
-
- if (rb_load_path) {
- int i;
-
- Check_Type(rb_load_path, T_ARRAY);
- for (i=0;i<RARRAY(rb_load_path)->len;i++) {
- Check_SafeStr(RARRAY(rb_load_path)->ptr[i]);
- }
-#if !defined(MSDOS) && !defined(NT) && !defined(__human68k__)
- vpath = ary_join(rb_load_path, str_new2(":"));
-#else
- vpath = ary_join(rb_load_path, str_new2(";"));
-#endif
- Check_SafeStr(vpath);
- path = RSTRING(vpath)->ptr;
- }
- else {
- path = 0;
- }
-
- return dln_find_file(file, path);
+ return specific_eval(argc, argv, mod, mod);
}
-VALUE
-f_load(obj, fname)
- VALUE obj, fname;
+VALUE rb_load_path;
+
+void
+rb_load(fname, wrap)
+ VALUE fname;
+ int wrap;
{
int state;
char *file;
volatile ID last_func;
+ volatile VALUE wrapper = 0;
+ volatile VALUE self = ruby_top_self;
+ NODE *saved_cref = ruby_cref;
TMP_PROTECT;
- Check_SafeStr(fname);
- if (RSTRING(fname)->ptr[0] == '~') {
- fname = file_s_expand_path(0, fname);
+ if (wrap) {
+ Check_Type(fname, T_STRING);
+ }
+ else {
+ Check_SafeStr(fname);
+ }
+ file = rb_find_file(RSTRING(fname)->ptr);
+ if (!file) {
+ rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr);
}
- file = find_file(RSTRING(fname)->ptr);
- if (!file) LoadError("No such file to load -- %s", RSTRING(fname)->ptr);
- PUSH_TAG(PROT_NONE);
+ ruby_errinfo = Qnil; /* ensure */
+ PUSH_VARS();
PUSH_CLASS();
- the_class = cObject;
+ wrapper = ruby_wrapper;
+ ruby_cref = top_cref;
+ if (!wrap) {
+ rb_secure(4); /* should alter global state */
+ ruby_class = rb_cObject;
+ ruby_wrapper = 0;
+ }
+ else {
+ /* load in anonymous module as toplevel */
+ ruby_class = ruby_wrapper = rb_module_new();
+ self = rb_obj_clone(ruby_top_self);
+ rb_extend_object(self, ruby_class);
+ PUSH_CREF(ruby_wrapper);
+ }
+ PUSH_FRAME();
+ ruby_frame->last_func = 0;
+ ruby_frame->last_class = 0;
+ ruby_frame->self = self;
+ ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,ruby_class,0,0);
PUSH_SCOPE();
- if (top_scope->local_tbl) {
+ if (ruby_class == rb_cObject && top_scope->local_tbl) {
int len = top_scope->local_tbl[0]+1;
ID *tbl = ALLOC_N(ID, len);
- VALUE *vars = TMP_ALLOC(VALUE, len);
+ VALUE *vars = TMP_ALLOC(len);
*vars++ = 0;
MEMCPY(tbl, top_scope->local_tbl, ID, len);
- MEMCPY(vars, top_scope->local_vars, ID, len-1);
- the_scope->local_tbl = tbl;
- the_scope->local_vars = vars;
+ MEMCPY(vars, top_scope->local_vars, VALUE, len-1);
+ ruby_scope->local_tbl = tbl; /* copy toplevel scope */
+ ruby_scope->local_vars = vars; /* will not alter toplevel variables */
}
/* default visibility is private at loading toplevel */
SCOPE_SET(SCOPE_PRIVATE);
+ PUSH_TAG(PROT_NONE);
state = EXEC_TAG();
- last_func = the_frame->last_func;
- the_frame->last_func = 0;
+ last_func = ruby_frame->last_func;
if (state == 0) {
- rb_in_eval++;
+ NODE *node;
+
+ DEFER_INTS;
+ ruby_in_eval++;
rb_load_file(file);
- rb_in_eval--;
- if (nerrs == 0) {
- eval_node(TopSelf);
+ ruby_in_eval--;
+ node = ruby_eval_tree;
+ ALLOW_INTS;
+ if (ruby_nerrs == 0) {
+ eval_node(self, node);
}
}
- the_frame->last_func = last_func;
- if (the_scope->flag == SCOPE_ALLOCA && the_scope->local_tbl) {
- free(the_scope->local_tbl);
+ ruby_frame->last_func = last_func;
+ if (ruby_scope->flag == SCOPE_ALLOCA && ruby_class == rb_cObject) {
+ if (ruby_scope->local_tbl) /* toplevel was empty */
+ free(ruby_scope->local_tbl);
}
+ POP_TAG();
+ ruby_cref = saved_cref;
POP_SCOPE();
+ POP_FRAME();
POP_CLASS();
- POP_TAG();
- if (nerrs > 0) {
- rb_raise(errinfo);
+ POP_VARS();
+ ruby_wrapper = wrapper;
+ if (ruby_nerrs > 0) {
+ ruby_nerrs = 0;
+ rb_exc_raise(ruby_errinfo);
}
- if (state) JUMP_TAG(state);
+ if (state) jump_tag_but_local_jump(state);
+ if (!NIL_P(ruby_errinfo)) /* exception during load */
+ rb_exc_raise(ruby_errinfo);
+}
+
+void
+rb_load_protect(fname, wrap, state)
+ VALUE fname;
+ int wrap;
+ int *state;
+{
+ int status;
- return TRUE;
+ PUSH_TAG(PROT_NONE);
+ if ((status = EXEC_TAG()) == 0) {
+ rb_load(fname, wrap);
+ }
+ POP_TAG();
+ if (state) *state = status;
}
+static VALUE
+rb_f_load(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE fname, wrap;
+
+ rb_scan_args(argc, argv, "11", &fname, &wrap);
+ rb_load(fname, RTEST(wrap));
+ return Qtrue;
+}
+
+VALUE ruby_dln_librefs;
static VALUE rb_features;
+static st_table *loading_tbl;
static int
-rb_provided(feature)
- char *feature;
+rb_feature_p(feature, wait)
+ const char *feature;
+ int wait;
{
- struct RArray *features = RARRAY(rb_features);
VALUE *p, *pend;
char *f;
int len;
- p = features->ptr;
- pend = p + features->len;
+ p = RARRAY(rb_features)->ptr;
+ pend = p + RARRAY(rb_features)->len;
while (p < pend) {
- Check_Type(*p, T_STRING);
- f = RSTRING(*p)->ptr;
- if (strcmp(f, feature) == 0) return TRUE;
+ f = STR2CSTR(*p);
+ if (strcmp(f, feature) == 0) {
+ goto load_wait;
+ }
len = strlen(feature);
- if (strncmp(f, feature, len) == 0
- && (strcmp(f+len, ".rb") == 0 ||strcmp(f+len, ".o") == 0)) {
- return TRUE;
+ if (strncmp(f, feature, len) == 0) {
+ if (strcmp(f+len, ".so") == 0) {
+ return Qtrue;
+ }
+ if (strcmp(f+len, ".rb") == 0) {
+ if (wait) goto load_wait;
+ return Qtrue;
+ }
}
p++;
}
- return FALSE;
+ return Qfalse;
+
+ load_wait:
+ if (loading_tbl) {
+ char *ext = strrchr(f, '.');
+ if (ext && strcmp(ext, ".rb") == 0) {
+ rb_thread_t th;
+
+ while (st_lookup(loading_tbl, f, &th)) {
+ if (th == curr_thread) {
+ return Qtrue;
+ }
+ CHECK_INTS;
+ rb_thread_schedule();
+ }
+ }
+ }
+ return Qtrue;
}
-#ifdef THREAD
-static int thread_loading();
-static void thread_loading_done();
-#endif
+int
+rb_provided(feature)
+ const char *feature;
+{
+ return rb_feature_p(feature, Qfalse);
+}
void
rb_provide(feature)
- char *feature;
+ const char *feature;
{
char *buf, *ext;
- if (!rb_provided(feature)) {
- ext = strrchr(feature, '.');
- if (strcmp(DLEXT, ext) == 0) {
- buf = ALLOCA_N(char, strlen(feature)+1);
- strcpy(buf, feature);
- ext = strrchr(buf, '.');
- strcpy(ext, ".o");
- feature = buf;
- }
- ary_push(rb_features, str_new2(feature));
+ ext = strrchr(feature, '.');
+ if (ext && (strcmp(DLEXT, ext) == 0
+#ifdef DLEXT2
+ || strcmp(DLEXT2, ext) == 0
+#endif
+ )) {
+ buf = ALLOCA_N(char, strlen(feature)+4);
+ strcpy(buf, feature);
+ ext = strrchr(buf, '.');
+ strcpy(ext, ".so");
+ feature = buf;
}
+ if (rb_feature_p(feature, Qtrue)) return;
+ rb_ary_push(rb_features, rb_str_new2(feature));
}
VALUE
-f_require(obj, fname)
+rb_f_require(obj, fname)
VALUE obj, fname;
{
char *ext, *file, *feature, *buf; /* OK */
- VALUE load;
+ volatile VALUE load;
+ int state;
+ volatile int safe = ruby_safe_level;
Check_SafeStr(fname);
- if (rb_provided(RSTRING(fname)->ptr))
- return FALSE;
-
+ if (rb_feature_p(RSTRING(fname)->ptr, Qtrue))
+ return Qfalse;
ext = strrchr(RSTRING(fname)->ptr, '.');
if (ext) {
+ feature = file = RSTRING(fname)->ptr;
if (strcmp(".rb", ext) == 0) {
- feature = file = RSTRING(fname)->ptr;
- file = find_file(file);
- if (file) goto rb_load;
+ file = rb_find_file(file);
+ if (file) goto load_rb;
}
- else if (strcmp(".o", ext) == 0) {
- file = feature = RSTRING(fname)->ptr;
- if (strcmp(".o", DLEXT) != 0) {
- buf = ALLOCA_N(char, strlen(file)+sizeof(DLEXT)+1);
+ else if (strcmp(".so", ext) == 0 || strcmp(".o", ext) == 0) {
+ if (strcmp(ext, DLEXT) != 0) {
+ buf = ALLOCA_N(char, strlen(file)+sizeof(DLEXT)+4);
strcpy(buf, feature);
ext = strrchr(buf, '.');
strcpy(ext, DLEXT);
- file = find_file(buf);
+ file = feature = buf;
}
- if (file) goto dyna_load;
+ file = rb_find_file(file);
+ if (file) goto load_dyna;
+#ifdef DLEXT2
+ file = feature = RSTRING(fname)->ptr;
+ if (strcmp(ext, DLEXT2) != 0) {
+ buf = ALLOCA_N(char, strlen(file)+sizeof(DLEXT2)+4);
+ strcpy(buf, feature);
+ ext = strrchr(buf, '.');
+ strcpy(ext, DLEXT2);
+ file = feature = buf;
+ }
+ file = rb_find_file(file);
+ if (file) goto load_dyna;
+#endif
}
else if (strcmp(DLEXT, ext) == 0) {
feature = RSTRING(fname)->ptr;
- file = find_file(feature);
- if (file) goto dyna_load;
+ file = rb_find_file(feature);
+ if (file) goto load_dyna;
+ }
+#ifdef DLEXT2
+ else if (strcmp(DLEXT2, ext) == 0) {
+ feature = RSTRING(fname)->ptr;
+ file = rb_find_file(feature);
+ if (file) goto load_dyna;
}
+#endif
}
buf = ALLOCA_N(char, strlen(RSTRING(fname)->ptr) + 5);
- sprintf(buf, "%s.rb", RSTRING(fname)->ptr);
- file = find_file(buf);
+ strcpy(buf, RSTRING(fname)->ptr);
+ strcat(buf, ".rb");
+ if (rb_find_file(buf)) {
+ fname = rb_str_new2(buf);
+ feature = buf;
+ goto load_rb;
+ }
+ strcpy(buf, RSTRING(fname)->ptr);
+ strcat(buf, DLEXT);
+ file = rb_find_file(buf);
if (file) {
- fname = str_new2(file);
feature = buf;
- goto rb_load;
+ goto load_dyna;
}
- sprintf(buf, "%s%s", RSTRING(fname)->ptr, DLEXT);
- file = find_file(buf);
+#ifdef DLEXT2
+ strcpy(buf, RSTRING(fname)->ptr);
+ strcat(buf, DLEXT2);
+ file = rb_find_file(buf);
if (file) {
feature = buf;
- goto dyna_load;
+ goto load_dyna;
}
- LoadError("No such file to load -- %s", RSTRING(fname)->ptr);
-
- dyna_load:
-#ifdef THREAD
- if (thread_loading(feature)) return FALSE;
- else {
- int state;
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
#endif
- load = str_new2(file);
- file = RSTRING(load)->ptr;
- dln_load(file);
- rb_provide(feature);
-#ifdef THREAD
- }
- POP_TAG();
- thread_loading_done();
- if (state) JUMP_TAG(state);
+ rb_raise(rb_eLoadError, "No such file to load -- %s",
+ RSTRING(fname)->ptr);
+
+ load_dyna:
+ rb_provide(feature);
+
+ PUSH_TAG(PROT_NONE);
+ if ((state = EXEC_TAG()) == 0) {
+ void *handle;
+
+ load = rb_str_new2(file);
+ file = RSTRING(load)->ptr;
+ handle = dln_load(file);
+ rb_ary_push(ruby_dln_librefs, INT2NUM((long)handle));
}
-#endif
- return TRUE;
+ POP_TAG();
+ if (state) JUMP_TAG(state);
- rb_load:
-#ifdef THREAD
- if (thread_loading(feature)) return FALSE;
- else {
- int state;
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
-#endif
- f_load(obj, fname);
- rb_provide(feature);
-#ifdef THREAD
- }
- POP_TAG();
- thread_loading_done();
- if (state) JUMP_TAG(state);
+ return Qtrue;
+
+ load_rb:
+ ruby_safe_level = 0;
+ rb_provide(feature);
+ /* loading ruby library should be serialized. */
+ if (!loading_tbl) {
+ loading_tbl = st_init_strtable();
+ }
+ /* partial state */
+ st_insert(loading_tbl, strdup(feature), curr_thread);
+
+ PUSH_TAG(PROT_NONE);
+ if ((state = EXEC_TAG()) == 0) {
+ rb_load(fname, 0);
+ }
+ POP_TAG();
+ st_delete(loading_tbl, &feature, 0); /* loading done */
+ free(feature);
+ ruby_safe_level = safe;
+ if (state) JUMP_TAG(state);
+
+ return Qtrue;
+}
+
+VALUE
+rb_require(fname)
+ const char *fname;
+{
+ return rb_f_require(Qnil, rb_str_new2(fname));
+}
+
+static void
+secure_visibility(self)
+ VALUE self;
+{
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(self)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't change method visibility");
}
-#endif
- return TRUE;
}
static void
@@ -4225,21 +5462,23 @@ set_method_visibility(self, argc, argv, ex)
VALUE self;
int argc;
VALUE *argv;
- int ex;
+ ID ex;
{
int i;
+ secure_visibility(self);
for (i=0; i<argc; i++) {
rb_export_method(self, rb_to_id(argv[i]), ex);
}
}
static VALUE
-mod_public(argc, argv, module)
+rb_mod_public(argc, argv, module)
int argc;
VALUE *argv;
VALUE module;
{
+ secure_visibility(module);
if (argc == 0) {
SCOPE_SET(SCOPE_PUBLIC);
}
@@ -4250,11 +5489,12 @@ mod_public(argc, argv, module)
}
static VALUE
-mod_protected(argc, argv, module)
+rb_mod_protected(argc, argv, module)
int argc;
VALUE *argv;
VALUE module;
{
+ secure_visibility(module);
if (argc == 0) {
SCOPE_SET(SCOPE_PROTECTED);
}
@@ -4265,11 +5505,12 @@ mod_protected(argc, argv, module)
}
static VALUE
-mod_private(argc, argv, module)
+rb_mod_private(argc, argv, module)
int argc;
VALUE *argv;
VALUE module;
{
+ secure_visibility(module);
if (argc == 0) {
SCOPE_SET(SCOPE_PRIVATE);
}
@@ -4280,7 +5521,7 @@ mod_private(argc, argv, module)
}
static VALUE
-mod_public_method(argc, argv, obj)
+rb_mod_public_method(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -4290,7 +5531,7 @@ mod_public_method(argc, argv, obj)
}
static VALUE
-mod_private_method(argc, argv, obj)
+rb_mod_private_method(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -4304,7 +5545,7 @@ top_public(argc, argv)
int argc;
VALUE *argv;
{
- return mod_public(argc, argv, cObject);
+ return rb_mod_public(argc, argv, rb_cObject);
}
static VALUE
@@ -4312,11 +5553,11 @@ top_private(argc, argv)
int argc;
VALUE *argv;
{
- return mod_private(argc, argv, cObject);
+ return rb_mod_private(argc, argv, rb_cObject);
}
static VALUE
-mod_modfunc(argc, argv, module)
+rb_mod_modfunc(argc, argv, module)
int argc;
VALUE *argv;
VALUE module;
@@ -4325,6 +5566,11 @@ mod_modfunc(argc, argv, module)
ID id;
NODE *body;
+ if (TYPE(module) != T_MODULE) {
+ rb_raise(rb_eTypeError, "module_function must be called for modules");
+ }
+
+ secure_visibility(module);
if (argc == 0) {
SCOPE_SET(SCOPE_MODFUNC);
return module;
@@ -4335,17 +5581,17 @@ mod_modfunc(argc, argv, module)
id = rb_to_id(argv[i]);
body = search_method(module, id, 0);
if (body == 0 || body->nd_body == 0) {
- NameError("undefined method `%s' for module `%s'",
- rb_id2name(id), rb_class2name(module));
+ rb_bug("undefined method `%s'; can't happen", rb_id2name(id));
}
- rb_clear_cache_by_id(id);
rb_add_method(rb_singleton_class(module), id, body->nd_body, NOEX_PUBLIC);
+ rb_clear_cache_by_id(id);
+ rb_funcall(module, singleton_added, 1, ID2SYM(id));
}
return module;
}
static VALUE
-mod_append_features(module, include)
+rb_mod_append_features(module, include)
VALUE module, include;
{
switch (TYPE(include)) {
@@ -4362,7 +5608,7 @@ mod_append_features(module, include)
}
static VALUE
-mod_include(argc, argv, module)
+rb_mod_include(argc, argv, module)
int argc;
VALUE *argv;
VALUE module;
@@ -4377,16 +5623,18 @@ mod_include(argc, argv, module)
}
void
-obj_call_init(obj)
+rb_obj_call_init(obj, argc, argv)
VALUE obj;
+ int argc;
+ VALUE *argv;
{
- PUSH_ITER(iterator_p()?ITER_PRE:ITER_NOT);
- rb_funcall2(obj, init, the_frame->argc, the_frame->argv);
+ PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
+ rb_funcall2(obj, init, argc, argv);
POP_ITER();
}
VALUE
-class_new_instance(argc, argv, klass)
+rb_class_new_instance(argc, argv, klass)
int argc;
VALUE *argv;
VALUE klass;
@@ -4394,10 +5642,10 @@ class_new_instance(argc, argv, klass)
VALUE obj;
if (FL_TEST(klass, FL_SINGLETON)) {
- TypeError("can't create instance of virtual class");
+ rb_raise(rb_eTypeError, "can't create instance of virtual class");
}
- obj = obj_alloc(klass);
- obj_call_init(obj);
+ obj = rb_obj_alloc(klass);
+ rb_obj_call_init(obj, argc, argv);
return obj;
}
@@ -4408,7 +5656,7 @@ top_include(argc, argv)
VALUE *argv;
{
rb_secure(4);
- return mod_include(argc, argv, cObject);
+ return rb_mod_include(argc, argv, rb_cObject);
}
void
@@ -4419,7 +5667,7 @@ rb_extend_object(obj, module)
}
static VALUE
-mod_extend_object(mod, obj)
+rb_mod_extend_object(mod, obj)
VALUE mod, obj;
{
rb_extend_object(obj, mod);
@@ -4427,13 +5675,16 @@ mod_extend_object(mod, obj)
}
static VALUE
-obj_extend(argc, argv, obj)
+rb_obj_extend(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
{
int i;
+ if (argc == 0) {
+ rb_raise(rb_eArgError, "wrong # of arguments(0 for 1)");
+ }
for (i=0; i<argc; i++) Check_Type(argv[i], T_MODULE);
for (i=0; i<argc; i++) {
rb_funcall(argv[i], rb_intern("extend_object"), 1, obj);
@@ -4441,10 +5692,27 @@ obj_extend(argc, argv, obj)
return obj;
}
-VALUE f_trace_var();
-VALUE f_untrace_var();
+VALUE rb_f_trace_var();
+VALUE rb_f_untrace_var();
+
+static void
+errinfo_setter(val, id, var)
+ VALUE val;
+ ID id;
+ VALUE *var;
+{
+ if (!NIL_P(val) && !rb_obj_is_kind_of(val, rb_eException)) {
+ rb_raise(rb_eTypeError, "assigning non-exception to $!");
+ }
+ *var = val;
+}
-extern void rb_str_setter();
+static VALUE
+errat_getter(id)
+ ID id;
+{
+ return get_backtrace(ruby_errinfo);
+}
static void
errat_setter(val, id, var)
@@ -4452,32 +5720,33 @@ errat_setter(val, id, var)
ID id;
VALUE *var;
{
- *var = check_errat(val);
+ if (NIL_P(ruby_errinfo)) {
+ rb_raise(rb_eArgError, "$! not set");
+ }
+ set_backtrace(ruby_errinfo, val);
}
-VALUE f_global_variables();
-VALUE f_instance_variables();
-
-VALUE
-f_local_variables()
+static VALUE
+rb_f_local_variables()
{
ID *tbl;
int n, i;
- VALUE ary = ary_new();
+ VALUE ary = rb_ary_new();
struct RVarmap *vars;
- tbl = the_scope->local_tbl;
+ tbl = ruby_scope->local_tbl;
if (tbl) {
n = *tbl++;
for (i=2; i<n; i++) { /* skip first 2 ($_ and $~) */
- ary_push(ary, str_new2(rb_id2name(tbl[i])));
+ if (tbl[i] == 0) continue; /* skip flip states */
+ rb_ary_push(ary, rb_str_new2(rb_id2name(tbl[i])));
}
}
- vars = the_dyna_vars;
+ vars = ruby_dyna_vars;
while (vars) {
if (vars->id) {
- ary_push(ary, str_new2(rb_id2name(vars->id)));
+ rb_ary_push(ary, rb_str_new2(rb_id2name(vars->id)));
}
vars = vars->next;
}
@@ -4485,14 +5754,16 @@ f_local_variables()
return ary;
}
-static VALUE f_catch();
-static VALUE f_throw();
+static VALUE rb_f_catch _((VALUE,VALUE));
+static VALUE rb_f_throw _((int,VALUE*)) NORETURN;
struct end_proc_data {
void (*func)();
VALUE data;
struct end_proc_data *next;
-} *end_proc_data;
+};
+
+static struct end_proc_data *end_procs, *ephemeral_end_procs;
void
rb_set_end_proc(func, data)
@@ -4500,49 +5771,90 @@ rb_set_end_proc(func, data)
VALUE data;
{
struct end_proc_data *link = ALLOC(struct end_proc_data);
+ struct end_proc_data **list;
- link->next = end_proc_data;
+ if (ruby_wrapper) list = &ephemeral_end_procs;
+ else list = &end_procs;
+ link->next = *list;
link->func = func;
link->data = data;
- rb_global_variable(&link->data);
- end_proc_data = link;
+ *list = link;
+}
+
+void
+rb_mark_end_proc()
+{
+ struct end_proc_data *link;
+
+ link = end_procs;
+ while (link) {
+ rb_gc_mark(link->data);
+ link = link->next;
+ }
+ link = ephemeral_end_procs;
+ while (link) {
+ rb_gc_mark(link->data);
+ link = link->next;
+ }
}
static void
call_end_proc(data)
VALUE data;
{
- proc_call(data, Qnil);
+ PUSH_ITER(ITER_NOT);
+ PUSH_FRAME();
+ ruby_frame->self = ruby_frame->prev->self;
+ ruby_frame->last_func = 0;
+ ruby_frame->last_class = 0;
+ proc_call(data, Qundef);
+ POP_FRAME();
+ POP_ITER();
}
static void
-f_END()
+rb_f_END()
{
PUSH_FRAME();
- rb_set_end_proc(call_end_proc, f_lambda());
+ ruby_frame->argc = 0;
+ rb_set_end_proc(call_end_proc, rb_f_lambda());
POP_FRAME();
}
static VALUE
-f_at_exit()
+rb_f_at_exit()
{
VALUE proc;
- proc = f_lambda();
+ proc = rb_f_lambda();
rb_set_end_proc(call_end_proc, proc);
return proc;
}
-static void
-exec_end_proc()
+void
+rb_exec_end_proc()
{
- struct end_proc_data *link = end_proc_data;
+ struct end_proc_data *link;
+ int status;
+ link = end_procs;
while (link) {
- (*link->func)(link->data);
+ rb_protect((VALUE(*)())link->func, link->data, &status);
+ if (status) {
+ error_handle(status);
+ }
link = link->next;
}
+ while (ephemeral_end_procs) {
+ link = ephemeral_end_procs;
+ ephemeral_end_procs = link->next;
+ rb_protect((VALUE(*)())link->func, link->data, &status);
+ if (status) {
+ error_handle(status);
+ }
+ free(link);
+ }
}
void
@@ -4555,91 +5867,121 @@ Init_eval()
aref = rb_intern("[]");
aset = rb_intern("[]=");
match = rb_intern("=~");
+ to_ary = rb_intern("to_ary");
+ missing = rb_intern("method_missing");
+ added = rb_intern("method_added");
+ singleton_added = rb_intern("singleton_method_added");
+
+ __id__ = rb_intern("__id__");
+ __send__ = rb_intern("__send__");
rb_global_variable((VALUE*)&top_scope);
- rb_global_variable((VALUE*)&eval_tree0);
- rb_global_variable((VALUE*)&eval_tree);
- rb_global_variable((VALUE*)&the_dyna_vars);
+ rb_global_variable((VALUE*)&ruby_eval_tree_begin);
- rb_define_hooked_variable("$@", &errat, 0, errat_setter);
- rb_define_hooked_variable("$!", &errinfo, 0, rb_str_setter);
+ rb_global_variable((VALUE*)&ruby_eval_tree);
+ rb_global_variable((VALUE*)&ruby_dyna_vars);
- rb_define_global_function("eval", f_eval, -1);
- rb_define_global_function("iterator?", f_iterator_p, 0);
- rb_define_global_function("method_missing", f_missing, -1);
- rb_define_global_function("loop", f_loop, 0);
+ rb_define_virtual_variable("$@", errat_getter, errat_setter);
+ rb_define_hooked_variable("$!", &ruby_errinfo, 0, errinfo_setter);
- rb_define_method(mKernel, "respond_to?", obj_respond_to, -1);
+ rb_define_global_function("eval", rb_f_eval, -1);
+ rb_define_global_function("iterator?", rb_f_block_given_p, 0);
+ rb_define_global_function("block_given?", rb_f_block_given_p, 0);
+ rb_define_global_function("method_missing", rb_f_missing, -1);
+ rb_define_global_function("loop", rb_f_loop, 0);
- rb_define_global_function("raise", f_raise, -1);
- rb_define_alias(mKernel, "fail", "raise");
+ rb_define_method(rb_mKernel, "respond_to?", rb_obj_respond_to, -1);
- rb_define_global_function("caller", f_caller, -1);
+ rb_define_global_function("raise", rb_f_raise, -1);
+ rb_define_global_function("fail", rb_f_raise, -1);
- rb_define_global_function("exit", f_exit, -1);
- rb_define_global_function("abort", f_abort, 0);
+ rb_define_global_function("caller", rb_f_caller, -1);
- rb_define_global_function("at_exit", f_at_exit, 0);
+ rb_define_global_function("exit", rb_f_exit, -1);
+ rb_define_global_function("abort", rb_f_abort, 0);
- rb_define_global_function("catch", f_catch, 1);
- rb_define_global_function("throw", f_throw, -1);
- rb_define_global_function("global_variables", f_global_variables, 0);
- rb_define_global_function("local_variables", f_local_variables, 0);
+ rb_define_global_function("at_exit", rb_f_at_exit, 0);
- rb_define_method(mKernel, "send", f_send, -1);
- rb_define_method(mKernel, "__send__", f_send, -1);
- rb_define_method(mKernel, "instance_eval", obj_instance_eval, -1);
+ rb_define_global_function("catch", rb_f_catch, 1);
+ rb_define_global_function("throw", rb_f_throw, -1);
+ rb_define_global_function("global_variables", rb_f_global_variables, 0);
+ rb_define_global_function("local_variables", rb_f_local_variables, 0);
- rb_define_private_method(cModule, "append_features", mod_append_features, 1);
- rb_define_private_method(cModule, "extend_object", mod_extend_object, 1);
- rb_define_private_method(cModule, "include", mod_include, -1);
- rb_define_private_method(cModule, "public", mod_public, -1);
- rb_define_private_method(cModule, "protected", mod_protected, -1);
- rb_define_private_method(cModule, "private", mod_private, -1);
- rb_define_private_method(cModule, "module_function", mod_modfunc, -1);
- rb_define_method(cModule, "method_defined?", mod_method_defined, 1);
- rb_define_method(cModule, "public_class_method", mod_public_method, -1);
- rb_define_method(cModule, "private_class_method", mod_private_method, -1);
- rb_define_method(cModule, "module_eval", mod_module_eval, -1);
- rb_define_method(cModule, "class_eval", mod_module_eval, -1);
+ rb_define_method(rb_mKernel, "send", rb_f_send, -1);
+ rb_define_method(rb_mKernel, "__send__", rb_f_send, -1);
+ rb_define_method(rb_mKernel, "instance_eval", rb_obj_instance_eval, -1);
- rb_define_method(cModule, "remove_method", mod_remove_method, 1);
- rb_define_method(cModule, "undef_method", mod_undef_method, 1);
- rb_define_method(cModule, "alias_method", mod_alias_method, 2);
+ rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);
+ rb_define_private_method(rb_cModule, "extend_object", rb_mod_extend_object, 1);
+ rb_define_private_method(rb_cModule, "include", rb_mod_include, -1);
+ rb_define_private_method(rb_cModule, "public", rb_mod_public, -1);
+ rb_define_private_method(rb_cModule, "protected", rb_mod_protected, -1);
+ rb_define_private_method(rb_cModule, "private", rb_mod_private, -1);
+ rb_define_private_method(rb_cModule, "module_function", rb_mod_modfunc, -1);
+ rb_define_method(rb_cModule, "method_defined?", rb_mod_method_defined, 1);
+ rb_define_method(rb_cModule, "public_class_method", rb_mod_public_method, -1);
+ rb_define_method(rb_cModule, "private_class_method", rb_mod_private_method, -1);
+ rb_define_method(rb_cModule, "module_eval", rb_mod_module_eval, -1);
+ rb_define_method(rb_cModule, "class_eval", rb_mod_module_eval, -1);
- rb_define_singleton_method(cModule, "nesting", mod_nesting, 0);
- rb_define_singleton_method(cModule, "constants", mod_s_constants, 0);
+ rb_undef_method(rb_cClass, "module_function");
- rb_define_singleton_method(TopSelf, "include", top_include, -1);
- rb_define_singleton_method(TopSelf, "public", top_public, -1);
- rb_define_singleton_method(TopSelf, "private", top_private, -1);
+ rb_define_private_method(rb_cModule, "remove_method", rb_mod_remove_method, 1);
+ rb_define_private_method(rb_cModule, "undef_method", rb_mod_undef_method, 1);
+ rb_define_private_method(rb_cModule, "alias_method", rb_mod_alias_method, 2);
+ rb_define_private_method(rb_cModule, "define_method", rb_mod_define_method, -1);
- rb_define_method(mKernel, "extend", obj_extend, -1);
+ rb_define_singleton_method(rb_cModule, "nesting", rb_mod_nesting, 0);
+ rb_define_singleton_method(rb_cModule, "constants", rb_mod_s_constants, 0);
- rb_define_global_function("trace_var", f_trace_var, -1);
- rb_define_global_function("untrace_var", f_untrace_var, -1);
+ rb_define_singleton_method(ruby_top_self, "include", top_include, -1);
+ rb_define_singleton_method(ruby_top_self, "public", top_public, -1);
+ rb_define_singleton_method(ruby_top_self, "private", top_private, -1);
+
+ rb_define_method(rb_mKernel, "extend", rb_obj_extend, -1);
+
+ rb_define_global_function("trace_var", rb_f_trace_var, -1);
+ rb_define_global_function("untrace_var", rb_f_untrace_var, -1);
rb_define_global_function("set_trace_func", set_trace_func, 1);
+ rb_global_variable(&trace_func);
rb_define_virtual_variable("$SAFE", safe_getter, safe_setter);
+
+#ifdef HAVE_GETRLIMIT
+ {
+ struct rlimit rlim;
+
+ if (getrlimit(RLIMIT_STACK, &rlim) == 0) {
+ double space = (double)rlim.rlim_cur*0.2;
+
+ if (space > 1024*1024) space = 1024*1024;
+ STACK_LEVEL_MAX = (rlim.rlim_cur - space) / sizeof(VALUE);
+ }
+ }
+#endif
}
-VALUE f_autoload();
+VALUE rb_f_autoload();
void
Init_load()
{
- rb_load_path = ary_new();
+ rb_load_path = rb_ary_new();
rb_define_readonly_variable("$:", &rb_load_path);
rb_define_readonly_variable("$-I", &rb_load_path);
rb_define_readonly_variable("$LOAD_PATH", &rb_load_path);
- rb_features = ary_new();
+ rb_features = rb_ary_new();
rb_define_readonly_variable("$\"", &rb_features);
- rb_define_global_function("load", f_load, 1);
- rb_define_global_function("require", f_require, 1);
- rb_define_global_function("autoload", f_autoload, 2);
+ rb_define_global_function("load", rb_f_load, -1);
+ rb_define_global_function("require", rb_f_require, 1);
+ rb_define_global_function("autoload", rb_f_autoload, 2);
+ rb_global_variable(&ruby_wrapper);
+
+ ruby_dln_librefs = rb_ary_new();
+ rb_global_variable(&ruby_dln_librefs);
}
static void
@@ -4649,6 +5991,7 @@ scope_dup(scope)
ID *tbl;
VALUE *vars;
+ scope->flag |= SCOPE_DONT_RECYCLE;
if (scope->flag & SCOPE_MALLOC) return;
if (scope->local_tbl) {
@@ -4657,10 +6000,7 @@ scope_dup(scope)
*vars++ = scope->local_vars[-1];
MEMCPY(vars, scope->local_vars, VALUE, tbl[0]);
scope->local_vars = vars;
- scope->flag = SCOPE_MALLOC;
- }
- else {
- scope->flag = SCOPE_NOSTACK;
+ scope->flag |= SCOPE_MALLOC;
}
}
@@ -4669,12 +6009,14 @@ blk_mark(data)
struct BLOCK *data;
{
while (data) {
- gc_mark_frame(&data->frame);
- gc_mark(data->scope);
- gc_mark(data->var);
- gc_mark(data->body);
- gc_mark(data->self);
- gc_mark(data->d_vars);
+ rb_gc_mark_frame(&data->frame);
+ rb_gc_mark(data->scope);
+ rb_gc_mark(data->var);
+ rb_gc_mark(data->body);
+ rb_gc_mark(data->self);
+ rb_gc_mark(data->dyna_vars);
+ rb_gc_mark(data->klass);
+ rb_gc_mark(data->tag);
data = data->prev;
}
}
@@ -4683,10 +6025,20 @@ static void
blk_free(data)
struct BLOCK *data;
{
- struct BLOCK *tmp;
+ struct FRAME *frame;
+ void *tmp;
+ frame = data->frame.prev;
+ while (frame) {
+ if (frame->argc > 0 && (frame->flags & FRAME_MALLOC))
+ free(frame->argv);
+ tmp = frame;
+ frame = frame->prev;
+ free(tmp);
+ }
while (data) {
- free(data->frame.argv);
+ if (data->frame.argc > 0)
+ free(data->frame.argv);
tmp = data;
data = data->prev;
free(tmp);
@@ -4698,17 +6050,50 @@ blk_copy_prev(block)
struct BLOCK *block;
{
struct BLOCK *tmp;
+ struct RVarmap* vars;
while (block->prev) {
tmp = ALLOC_N(struct BLOCK, 1);
MEMCPY(tmp, block->prev, struct BLOCK, 1);
- tmp->frame.argv = ALLOC_N(VALUE, tmp->frame.argc);
- MEMCPY(tmp->frame.argv, block->frame.argv, VALUE, tmp->frame.argc);
+ if (tmp->frame.argc > 0) {
+ tmp->frame.argv = ALLOC_N(VALUE, tmp->frame.argc);
+ MEMCPY(tmp->frame.argv, block->prev->frame.argv, VALUE, tmp->frame.argc);
+ }
+ scope_dup(tmp->scope);
+ tmp->tag->flags |= BLOCK_DYNAMIC;
+
+ for (vars = tmp->dyna_vars; vars; vars = vars->next) {
+ if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
+ FL_SET(vars, DVAR_DONT_RECYCLE);
+ }
+
block->prev = tmp;
block = tmp;
}
}
+static void
+frame_dup(frame)
+ struct FRAME *frame;
+{
+ VALUE *argv;
+ struct FRAME *tmp;
+
+ for (;;) {
+ if (frame->argc > 0) {
+ argv = ALLOC_N(VALUE, frame->argc);
+ MEMCPY(argv, frame->argv, VALUE, frame->argc);
+ frame->argv = argv;
+ frame->flags = FRAME_MALLOC;
+ }
+ frame->tmp = 0; /* should not preserve tmp */
+ if (!frame->prev) break;
+ tmp = ALLOC(struct FRAME);
+ *tmp = *frame->prev;
+ frame->prev = tmp;
+ frame = tmp;
+ }
+}
static VALUE
bind_clone(self)
@@ -4718,10 +6103,10 @@ bind_clone(self)
VALUE bind;
Data_Get_Struct(self, struct BLOCK, orig);
- bind = Data_Make_Struct(self, struct BLOCK, blk_mark,blk_free,data);
+ bind = Data_Make_Struct(rb_cBinding,struct BLOCK,blk_mark,blk_free,data);
+ CLONESETUP(bind, self);
MEMCPY(data, orig, struct BLOCK, 1);
- data->frame.argv = ALLOC_N(VALUE, orig->frame.argc);
- MEMCPY(data->frame.argv, orig->frame.argv, VALUE, orig->frame.argc);
+ frame_dup(&data->frame);
if (data->iter) {
blk_copy_prev(data);
@@ -4734,25 +6119,24 @@ bind_clone(self)
}
static VALUE
-f_binding(self)
+rb_f_binding(self)
VALUE self;
{
- struct BLOCK *data;
+ struct BLOCK *data, *p;
+ struct RVarmap *vars;
VALUE bind;
PUSH_BLOCK(0,0);
- bind = Data_Make_Struct(cBinding, struct BLOCK, blk_mark,blk_free,data);
- MEMCPY(data, the_block, struct BLOCK, 1);
+ bind = Data_Make_Struct(rb_cBinding,struct BLOCK,blk_mark,blk_free,data);
+ *data = *ruby_block;
-#ifdef THREAD
- data->orig_thread = thread_current();
-#endif
- data->iter = f_iterator_p();
- if (the_frame->prev) {
- data->frame.last_func = the_frame->prev->last_func;
+ data->orig_thread = rb_thread_current();
+ data->iter = rb_f_block_given_p();
+ frame_dup(&data->frame);
+ if (ruby_frame->prev) {
+ data->frame.last_func = ruby_frame->prev->last_func;
+ data->frame.last_class = ruby_frame->prev->last_class;
}
- data->frame.argv = ALLOC_N(VALUE, data->frame.argc);
- MEMCPY(data->frame.argv, the_block->frame.argv, VALUE, data->frame.argc);
if (data->iter) {
blk_copy_prev(data);
@@ -4760,70 +6144,121 @@ f_binding(self)
else {
data->prev = 0;
}
+ data->flags |= BLOCK_DYNAMIC;
+ data->tag->flags |= BLOCK_DYNAMIC;
+ for (p = data; p; p = p->prev) {
+ for (vars = p->dyna_vars; vars; vars = vars->next) {
+ if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
+ FL_SET(vars, DVAR_DONT_RECYCLE);
+ }
+ }
scope_dup(data->scope);
POP_BLOCK();
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_TMAX (FL_USER1|FL_USER2)
#define PROC_TMASK (FL_USER1|FL_USER2)
+static void
+proc_save_safe_level(data)
+ VALUE data;
+{
+ if (OBJ_TAINTED(data)) {
+ switch (rb_safe_level()) {
+ case 3:
+ FL_SET(data, PROC_T3);
+ break;
+ case 4:
+ FL_SET(data, PROC_T4);
+ break;
+ default:
+ if (rb_safe_level() > 4) {
+ FL_SET(data, PROC_TMAX);
+ }
+ break;
+ }
+ }
+}
+
+static void
+proc_set_safe_level(data)
+ VALUE data;
+{
+ if (OBJ_TAINTED(data)) {
+ switch (RBASIC(data)->flags & PROC_TMASK) {
+ case PROC_T3:
+ ruby_safe_level = 3;
+ break;
+ case PROC_T4:
+ ruby_safe_level = 4;
+ break;
+ case PROC_TMAX:
+ ruby_safe_level = 5;
+ break;
+ }
+ }
+}
+
static VALUE
-proc_s_new(klass)
+proc_new(klass)
VALUE klass;
{
volatile VALUE proc;
- struct BLOCK *data;
+ struct BLOCK *data, *p;
+ struct RVarmap *vars;
- if (!iterator_p() && !f_iterator_p()) {
- ArgError("tryed to create Procedure-Object out of iterator");
+ if (!rb_block_given_p() && !rb_f_block_given_p()) {
+ rb_raise(rb_eArgError, "tried to create Proc object without a block");
}
proc = Data_Make_Struct(klass, struct BLOCK, blk_mark, blk_free, data);
- *data = *the_block;
+ *data = *ruby_block;
-#ifdef THREAD
- data->orig_thread = thread_current();
-#endif
- data->iter = data->prev?TRUE:FALSE;
- data->frame.argv = ALLOC_N(VALUE, data->frame.argc);
- MEMCPY(data->frame.argv, the_block->frame.argv, VALUE, data->frame.argc);
+ data->orig_thread = rb_thread_current();
+ data->iter = data->prev?Qtrue:Qfalse;
+ frame_dup(&data->frame);
if (data->iter) {
blk_copy_prev(data);
}
else {
data->prev = 0;
}
+ data->flags |= BLOCK_DYNAMIC;
+ data->tag->flags |= BLOCK_DYNAMIC;
- 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;
+ for (p = data; p; p = p->prev) {
+ for (vars = p->dyna_vars; vars; vars = vars->next) {
+ if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
+ FL_SET(vars, DVAR_DONT_RECYCLE);
}
}
- obj_call_init(proc);
+ scope_dup(data->scope);
+ proc_save_safe_level(proc);
return proc;
}
+static VALUE
+proc_s_new(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE proc = proc_new(klass);
+
+ rb_obj_call_init(proc, argc, argv);
+ return proc;
+}
+
VALUE
-f_lambda()
+rb_f_lambda()
{
- return proc_s_new(cProc);
+ return proc_new(rb_cProc);
}
static int
@@ -4834,176 +6269,238 @@ blk_orphan(data)
(data->scope->flag & SCOPE_NOSTACK)) {
return 1;
}
-#ifdef THREAD
- if (data->orig_thread != thread_current()) {
+ if (data->orig_thread != rb_thread_current()) {
return 1;
}
-#endif
return 0;
}
static VALUE
+callargs(args)
+ VALUE args;
+{
+ switch (RARRAY(args)->len) {
+ case 0:
+ return Qundef;
+ break;
+ default:
+ return args;
+ }
+}
+
+static VALUE
proc_call(proc, args)
VALUE proc, args; /* OK */
{
+ struct BLOCK * volatile old_block;
+ struct BLOCK _block;
struct BLOCK *data;
volatile VALUE result = Qnil;
int state;
volatile int orphan;
- volatile int safe = safe_level;
+ volatile int safe = ruby_safe_level;
- if (TYPE(args) == T_ARRAY) {
- switch (RARRAY(args)->len) {
- case 0:
- args = Qnil;
- break;
- case 1:
- args = RARRAY(args)->ptr[0];
- break;
- }
+ if (rb_block_given_p() && ruby_frame->last_func) {
+ rb_warning("block for %s#%s is useless",
+ rb_class2name(CLASS_OF(proc)),
+ rb_id2name(ruby_frame->last_func));
}
Data_Get_Struct(proc, struct BLOCK, data);
orphan = blk_orphan(data);
/* PUSH BLOCK from data */
- PUSH_BLOCK2(data);
- PUSH_ITER(ITER_CUR);
- the_frame->iter = ITER_CUR;
+ old_block = ruby_block;
+ _block = *data;
+ ruby_block = &_block;
+ ruby_block->frame.iter = ITER_NOT;
- if (orphan) {/* orphan procedure */
- if (iterator_p()) {
- the_block->frame.iter = ITER_CUR;
- }
- else {
- the_block->frame.iter = ITER_NOT;
- }
- }
+ PUSH_ITER(ITER_CUR);
+ ruby_frame->iter = ITER_CUR;
- if (FL_TEST(proc, PROC_TAINT)) {
- switch (RBASIC(proc)->flags & PROC_TMASK) {
- case PROC_T3:
- safe_level = 3;
- break;
- case PROC_T4:
- safe_level = 4;
- break;
- case PROC_T5:
- safe_level = 5;
- break;
- }
+ if (args != Qundef && TYPE(args) == T_ARRAY) {
+ args = callargs(args);
}
PUSH_TAG(PROT_NONE);
state = EXEC_TAG();
if (state == 0) {
- result = rb_yield(args);
+ proc_set_safe_level(proc);
+ result = rb_yield_0(args, 0, 0, Qtrue);
}
POP_TAG();
POP_ITER();
- if (the_block->tag->dst == state) {
+ if (ruby_block->tag->dst == state) {
state &= TAG_MASK;
}
- POP_BLOCK();
- safe_level = safe;
+ ruby_block = old_block;
+ ruby_safe_level = safe;
if (state) {
- if (orphan) {/* orphan procedure */
- switch (state) {
- case TAG_BREAK:
- Raise(eLocalJumpError, "break from proc-closure");
- break;
- case TAG_RETRY:
- Raise(eLocalJumpError, "retry from proc-closure");
- break;
- case TAG_RETURN:
- Raise(eLocalJumpError, "return from proc-closure");
- break;
+ switch (state) {
+ case TAG_BREAK:
+ break;
+ case TAG_RETRY:
+ rb_raise(rb_eLocalJumpError, "retry from proc-closure");
+ break;
+ case TAG_RETURN:
+ if (orphan) { /* orphan procedure */
+ rb_raise(rb_eLocalJumpError, "return from proc-closure");
}
+ /* fall through */
+ default:
+ JUMP_TAG(state);
}
- JUMP_TAG(state);
}
return result;
}
static VALUE
+proc_arity(proc)
+ VALUE proc;
+{
+ struct BLOCK *data;
+ NODE *list;
+ int n;
+
+ Data_Get_Struct(proc, struct BLOCK, data);
+ if (data->var == 0) return INT2FIX(-1);
+ if (data->var == (NODE*)1) return INT2FIX(0);
+ switch (nd_type(data->var)) {
+ default:
+ return INT2FIX(-1);
+ case NODE_MASGN:
+ list = data->var->nd_head;
+ n = 0;
+ while (list) {
+ n++;
+ list = list->nd_next;
+ }
+ if (data->var->nd_args) return INT2FIX(-n-1);
+ return INT2FIX(n);
+ }
+}
+
+static VALUE
+proc_eq(self, other)
+ VALUE self, other;
+{
+ struct BLOCK *data, *data2;
+
+ if (self == other) return Qtrue;
+ if (TYPE(other) != T_DATA) return Qfalse;
+ if (RDATA(other)->dmark != (RUBY_DATA_FUNC)blk_mark) return Qfalse;
+ if (CLASS_OF(self) != CLASS_OF(other)) return Qfalse;
+ Data_Get_Struct(self, struct BLOCK, data);
+ Data_Get_Struct(other, struct BLOCK, data2);
+ if (data->tag == data2->tag) return Qtrue;
+ return Qfalse;
+}
+
+static VALUE
+proc_to_s(self, other)
+ VALUE self, other;
+{
+ struct BLOCK *data;
+ char *cname = rb_class2name(CLASS_OF(self));
+ VALUE str;
+
+ Data_Get_Struct(self, struct BLOCK, data);
+ str = rb_str_new(0, strlen(cname)+6+16+1); /* 6:tags 16:addr 1:eos */
+ sprintf(RSTRING(str)->ptr, "#<%s:0x%lx>", cname, data->tag);
+ RSTRING(str)->len = strlen(RSTRING(str)->ptr);
+ if (OBJ_TAINTED(self)) OBJ_TAINT(str);
+
+ return str;
+}
+
+static VALUE
block_pass(self, node)
VALUE self;
NODE *node;
{
- VALUE block = rb_eval(self, node->nd_body);
+ VALUE block = rb_eval(self, node->nd_body); /* OK */
+ struct BLOCK * volatile old_block;
+ struct BLOCK _block;
struct BLOCK *data;
volatile VALUE result = Qnil;
int state;
volatile int orphan;
- volatile int safe = safe_level;
+ volatile int safe = ruby_safe_level;
if (NIL_P(block)) {
return rb_eval(self, node->nd_iter);
}
- if (obj_is_kind_of(block, cMethod)) {
+ if (rb_obj_is_kind_of(block, rb_cMethod)) {
block = method_proc(block);
}
- else if (TYPE(block) != T_DATA
- || RDATA(block)->dfree != blk_free
- || !obj_is_kind_of(block, cProc)) {
- TypeError("wrong argument type %s (expected Proc)",
- rb_class2name(CLASS_OF(block)));
+ else if (!rb_obj_is_proc(block)) {
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc)",
+ rb_class2name(CLASS_OF(block)));
}
Data_Get_Struct(block, struct BLOCK, data);
orphan = blk_orphan(data);
/* PUSH BLOCK from data */
- PUSH_BLOCK2(data);
+ old_block = ruby_block;
+ _block = *data;
+ ruby_block = &_block;
PUSH_ITER(ITER_PRE);
- the_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;
- }
- }
+ ruby_frame->iter = ITER_PRE;
PUSH_TAG(PROT_NONE);
state = EXEC_TAG();
if (state == 0) {
+ proc_set_safe_level(block);
+ if (safe > ruby_safe_level)
+ ruby_safe_level = safe;
result = rb_eval(self, node->nd_iter);
}
POP_TAG();
-
POP_ITER();
- if (the_block->tag->dst == state) {
- state &= TAG_MASK;
- orphan = 2;
- }
- POP_BLOCK();
- safe_level = safe;
+ if (_block.tag->dst == state) {
+ if (orphan) {
+ state &= TAG_MASK;
+ }
+ else {
+ struct BLOCK *ptr = old_block;
- if (state) {
- if (orphan == 2) {/* escape from orphan procedure */
- switch (state) {
- case TAG_BREAK:
- Raise(eLocalJumpError, "break from proc-closure");
- break;
- case TAG_RETRY:
- Raise(eLocalJumpError, "retry from proc-closure");
- break;
- case TAG_RETURN:
- Raise(eLocalJumpError, "return from proc-closure");
- break;
+ while (ptr) {
+ if (ptr->scope == _block.scope) {
+ ptr->tag->dst = state;
+ break;
+ }
+ ptr = ptr->prev;
}
+ if (!ptr) {
+ state &= TAG_MASK;
+ }
+ }
+ }
+ ruby_block = old_block;
+ ruby_safe_level = safe;
+
+ switch (state) {/* escape from orphan procedure */
+ case 0:
+ break;
+ case TAG_BREAK:
+ if (orphan) {
+ rb_raise(rb_eLocalJumpError, "break from proc-closure");
}
+ break;
+ case TAG_RETRY:
+ rb_raise(rb_eLocalJumpError, "retry from proc-closure");
+ break;
+ case TAG_RETURN:
+ if (orphan) {
+ rb_raise(rb_eLocalJumpError, "return from proc-closure");
+ }
+ default:
JUMP_TAG(state);
}
+
return result;
}
@@ -5018,30 +6515,27 @@ static void
bm_mark(data)
struct METHOD *data;
{
- gc_mark(data->oklass);
- gc_mark(data->klass);
- gc_mark(data->recv);
- gc_mark(data->body);
+ rb_gc_mark(data->oklass);
+ rb_gc_mark(data->klass);
+ rb_gc_mark(data->recv);
+ rb_gc_mark(data->body);
}
static VALUE
-obj_method(obj, vid)
- VALUE obj;
- VALUE vid;
+mnew(klass, obj, id, mklass)
+ VALUE klass, obj, mklass;
+ ID id;
{
VALUE method;
- VALUE klass = CLASS_OF(obj);
- ID mid, id;
NODE *body;
int noex;
- enum node_type type;
struct METHOD *data;
-
- id = rb_to_id(vid);
+ VALUE oklass = klass;
+ ID oid = id;
again:
if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) {
- return rb_undefined(obj, rb_to_id(vid), 0, 0, 0);
+ print_undef(oklass, oid);
}
if (nd_type(body) == NODE_ZSUPER) {
@@ -5049,18 +6543,77 @@ obj_method(obj, vid)
goto again;
}
- method = Data_Make_Struct(cMethod, struct METHOD, bm_mark, free, data);
+ method = Data_Make_Struct(mklass, struct METHOD, bm_mark, free, data);
data->klass = klass;
data->recv = obj;
data->id = id;
data->body = body;
- data->oklass = CLASS_OF(obj);
- data->oid = rb_to_id(vid);
+ data->oklass = oklass;
+ data->oid = oid;
+ OBJ_INFECT(method, klass);
return method;
}
static VALUE
+method_unbind(obj)
+ VALUE obj;
+{
+ VALUE method;
+ struct METHOD *orig, *data;
+
+ Data_Get_Struct(obj, struct METHOD, orig);
+ method = Data_Make_Struct(rb_cUnboundMethod, struct METHOD, bm_mark, free, data);
+ data->klass = orig->klass;
+ data->recv = obj;
+ data->id = orig->id;
+ data->body = orig->body;
+ data->oklass = orig->oklass;
+ data->oid = orig->oid;
+ OBJ_INFECT(method, obj);
+
+ return method;
+}
+
+static VALUE
+umethod_unbind(obj)
+ VALUE obj;
+{
+ return obj;
+}
+
+static VALUE
+rb_obj_method(obj, vid)
+ VALUE obj;
+ VALUE vid;
+{
+ return mnew(CLASS_OF(obj), obj, rb_to_id(vid), rb_cMethod);
+}
+
+static VALUE
+rb_mod_method(mod, vid)
+ VALUE mod;
+ VALUE vid;
+{
+ return mnew(mod, 0, rb_to_id(vid), rb_cUnboundMethod);
+}
+
+static VALUE
+method_clone(self)
+ VALUE self;
+{
+ VALUE clone;
+ struct METHOD *orig, *data;
+
+ Data_Get_Struct(self, struct METHOD, orig);
+ clone = Data_Make_Struct(CLASS_OF(self),struct METHOD,bm_mark,free,data);
+ CLONESETUP(clone, self);
+ *data = *orig;
+
+ return clone;
+}
+
+static VALUE
method_call(argc, argv, method)
int argc;
VALUE *argv;
@@ -5068,34 +6621,118 @@ method_call(argc, argv, method)
{
VALUE result;
struct METHOD *data;
+ int state;
+ volatile int safe = ruby_safe_level;
Data_Get_Struct(method, struct METHOD, data);
- PUSH_ITER(iterator_p()?ITER_PRE:ITER_NOT);
- result = rb_call0(data->klass, data->recv, data->id,
- argc, argv, data->body, 0);
+ PUSH_ITER(rb_block_given_p()?ITER_PRE:ITER_NOT);
+ PUSH_TAG(PROT_NONE);
+ if (OBJ_TAINTED(method) && ruby_safe_level < 4) {
+ ruby_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();
+ ruby_safe_level = safe;
+ if (state) JUMP_TAG(state);
return result;
}
static VALUE
+umethod_call(argc, argv, method)
+ int argc;
+ VALUE *argv;
+ VALUE method;
+{
+ rb_raise(rb_eTypeError, "you cannot call unbound method; bind first");
+ return Qnil; /* not reached */
+}
+
+static VALUE
+umethod_bind(method, recv)
+ VALUE method, recv;
+{
+ struct METHOD *data, *bound;
+
+ Data_Get_Struct(method, struct METHOD, data);
+ if (data->oklass != CLASS_OF(recv)) {
+ if (FL_TEST(data->oklass, FL_SINGLETON)) {
+ rb_raise(rb_eTypeError, "singleton method called for a different object");
+ }
+ if (FL_TEST(CLASS_OF(recv), FL_SINGLETON) &&
+ st_lookup(RCLASS(CLASS_OF(recv))->m_tbl, data->oid, 0)) {
+ rb_raise(rb_eTypeError, "method `%s' overridden", rb_id2name(data->oid));
+ }
+ if (!rb_obj_is_instance_of(recv, data->oklass)) {
+ rb_raise(rb_eTypeError, "first argument must be an instance of %s",
+ rb_class2name(data->oklass));
+ }
+ }
+
+ method = Data_Make_Struct(rb_cMethod,struct METHOD,bm_mark,free,bound);
+ *bound = *data;
+ bound->recv = recv;
+
+ return method;
+}
+
+static VALUE
+method_arity(method)
+ VALUE method;
+{
+ struct METHOD *data;
+ NODE *body;
+ int n;
+
+ Data_Get_Struct(method, struct METHOD, data);
+
+ body = data->body;
+ switch (nd_type(body)) {
+ case NODE_CFUNC:
+ if (body->nd_argc < 0) return INT2FIX(-1);
+ return INT2FIX(body->nd_argc);
+ case NODE_ZSUPER:
+ return INT2FIX(-1);
+ case NODE_ATTRSET:
+ return INT2FIX(1);
+ case NODE_IVAR:
+ return INT2FIX(0);
+ default:
+ body = body->nd_next; /* skip NODE_SCOPE */
+ if (nd_type(body) == NODE_BLOCK)
+ body = body->nd_head;
+ if (!body) return INT2FIX(0);
+ n = body->nd_cnt;
+ if (body->nd_opt || body->nd_rest != -1)
+ n = -n-1;
+ return INT2FIX(n);
+ }
+}
+
+static VALUE
method_inspect(method)
VALUE method;
{
struct METHOD *data;
VALUE str;
- char *s;
+ const char *s;
Data_Get_Struct(method, struct METHOD, data);
- str = str_new2("#<");
+ str = rb_str_new2("#<");
s = rb_class2name(CLASS_OF(method));
- str_cat(str, s, strlen(s));
- str_cat(str, ": ", 2);
+ rb_str_cat2(str, s);
+ rb_str_cat2(str, ": ");
s = rb_class2name(data->oklass);
- str_cat(str, s, strlen(s));
- str_cat(str, "#", 1);
+ rb_str_cat2(str, s);
+ rb_str_cat2(str, "(");
+ s = rb_class2name(data->klass);
+ rb_str_cat2(str, s);
+ rb_str_cat2(str, ")#");
s = rb_id2name(data->oid);
- str_cat(str, s, strlen(s));
- str_cat(str, ">", 1);
+ rb_str_cat2(str, s);
+ rb_str_cat2(str, ">");
return str;
}
@@ -5108,7 +6745,7 @@ mproc()
/* emulate ruby's method call */
PUSH_ITER(ITER_CUR);
PUSH_FRAME();
- proc = f_lambda();
+ proc = rb_f_lambda();
POP_FRAME();
POP_ITER();
@@ -5116,7 +6753,7 @@ mproc()
}
static VALUE
-mcall(args, method)
+bmcall(args, method)
VALUE args, method;
{
if (TYPE(args) == T_ARRAY) {
@@ -5126,81 +6763,135 @@ mcall(args, method)
}
static VALUE
+umcall(args, method)
+ VALUE args, method;
+{
+ if (TYPE(args) == T_ARRAY) {
+ return umethod_call(RARRAY(args)->len, RARRAY(args)->ptr, method);
+ }
+ return umethod_call(1, &args, method);
+}
+
+static VALUE
method_proc(method)
VALUE method;
{
- return rb_iterate(mproc, 0, mcall, method);
+ return rb_iterate(mproc, 0, bmcall, method);
}
-void
-Init_Proc()
+static VALUE
+umethod_proc(method)
+ VALUE method;
{
- eLocalJumpError = rb_define_class("LocalJumpError", eException);
- eSysStackError = rb_define_class("SystemStackError", eException);
-
- cProc = rb_define_class("Proc", cObject);
- rb_define_singleton_method(cProc, "new", proc_s_new, 0);
-
- rb_define_method(cProc, "call", proc_call, -2);
- rb_define_global_function("proc", f_lambda, 0);
- rb_define_global_function("lambda", f_lambda, 0);
- rb_define_global_function("binding", f_binding, 0);
- cBinding = rb_define_class("Binding", cObject);
- rb_undef_method(CLASS_OF(cMethod), "new");
- rb_define_method(cBinding, "clone", bind_clone, 0);
-
- cMethod = rb_define_class("Method", cObject);
- rb_undef_method(CLASS_OF(cMethod), "new");
- rb_define_method(cMethod, "call", method_call, -1);
- rb_define_method(cMethod, "inspect", method_inspect, 0);
- rb_define_method(cMethod, "to_s", method_inspect, 0);
- rb_define_method(cMethod, "to_proc", method_proc, 0);
- rb_define_method(mKernel, "method", obj_method, 1);
+ return rb_iterate(mproc, 0, umcall, method);
}
-#ifdef THREAD
-
-static VALUE eThreadError;
-
-int thread_pending = 0;
-
-static VALUE cThread;
+static VALUE
+rb_mod_define_method(argc, argv, mod)
+ int argc;
+ VALUE *argv;
+ VALUE mod;
+{
+ ID id;
+ VALUE body;
-#include <sys/types.h>
-#ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
-#else
-#ifndef NT
-struct timeval {
- long tv_sec; /* seconds */
- long tv_usec; /* and microseconds */
-};
-#endif /* NT */
-#endif
-#include <signal.h>
-#include <errno.h>
+ if (argc == 1) {
+ id = rb_to_id(argv[0]);
+ body = rb_f_lambda();
+ }
+ else if (argc == 2) {
+ id = rb_to_id(argv[0]);
+ body = argv[1];
+ }
+ else {
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)", argc);
+ }
+ if (TYPE(body) != T_DATA) {
+ /* type error */
+ rb_raise(rb_eTypeError, "wrong argument type (expected Proc)");
+ }
+ if (RDATA(body)->dmark == (RUBY_DATA_FUNC)bm_mark) {
+ rb_add_method(mod, id, NEW_DMETHOD(method_unbind(body)), NOEX_PUBLIC);
+ }
+ else if (RDATA(body)->dmark == (RUBY_DATA_FUNC)blk_mark) {
+ rb_add_method(mod, id, NEW_BMETHOD(body), NOEX_PUBLIC);
+ }
+ else {
+ /* type error */
+ rb_raise(rb_eTypeError, "wrong argument type (expected Proc)");
+ }
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
+ rb_clear_cache_by_id(id);
+ return body;
+}
-extern VALUE last_status;
+void
+Init_Proc()
+{
+ rb_eLocalJumpError = rb_define_class("LocalJumpError", rb_eStandardError);
+ rb_eSysStackError = rb_define_class("SystemStackError", rb_eStandardError);
+
+ rb_cProc = rb_define_class("Proc", rb_cObject);
+ rb_define_singleton_method(rb_cProc, "new", proc_s_new, -1);
+
+ rb_define_method(rb_cProc, "call", proc_call, -2);
+ rb_define_method(rb_cProc, "arity", proc_arity, 0);
+ rb_define_method(rb_cProc, "[]", proc_call, -2);
+ rb_define_method(rb_cProc, "==", proc_eq, 1);
+ rb_define_method(rb_cProc, "to_s", proc_to_s, 0);
+ rb_define_global_function("proc", rb_f_lambda, 0);
+ rb_define_global_function("lambda", rb_f_lambda, 0);
+ rb_define_global_function("binding", rb_f_binding, 0);
+ rb_cBinding = rb_define_class("Binding", rb_cObject);
+ rb_undef_method(CLASS_OF(rb_cBinding), "new");
+ rb_define_method(rb_cBinding, "clone", bind_clone, 0);
+
+ rb_cMethod = rb_define_class("Method", rb_cObject);
+ rb_undef_method(CLASS_OF(rb_cMethod), "new");
+ rb_define_method(rb_cMethod, "clone", method_clone, 0);
+ rb_define_method(rb_cMethod, "call", method_call, -1);
+ rb_define_method(rb_cMethod, "[]", method_call, -1);
+ rb_define_method(rb_cMethod, "arity", method_arity, 0);
+ rb_define_method(rb_cMethod, "inspect", method_inspect, 0);
+ rb_define_method(rb_cMethod, "to_s", method_inspect, 0);
+ rb_define_method(rb_cMethod, "to_proc", method_proc, 0);
+ rb_define_method(rb_cMethod, "unbind", method_unbind, 0);
+ rb_define_method(rb_mKernel, "method", rb_obj_method, 1);
+
+ rb_cUnboundMethod = rb_define_class("UnboundMethod", rb_cMethod);
+ rb_define_method(rb_cUnboundMethod, "call", umethod_call, -1);
+ rb_define_method(rb_cUnboundMethod, "[]", umethod_call, -1);
+ rb_define_method(rb_cUnboundMethod, "to_proc", umethod_proc, 0);
+ rb_define_method(rb_cUnboundMethod, "bind", umethod_bind, 1);
+ rb_define_method(rb_cUnboundMethod, "unbind", umethod_unbind, 0);
+ rb_define_method(rb_cModule, "instance_method", rb_mod_method, 1);
+}
+
+static VALUE rb_eThreadError;
+
+int rb_thread_pending = 0;
+
+VALUE rb_cThread;
+
+extern VALUE rb_last_status;
enum thread_status {
+ THREAD_TO_KILL,
THREAD_RUNNABLE,
THREAD_STOPPED,
- THREAD_TO_KILL,
- THREAD_KILLED,
+ THREAD_KILLED
};
#define WAIT_FD (1<<0)
-#define WAIT_TIME (1<<1)
-#define WAIT_JOIN (1<<2)
+#define WAIT_SELECT (1<<1)
+#define WAIT_TIME (1<<2)
+#define WAIT_JOIN (1<<3)
+#define WAIT_PID (1<<4)
/* +infty, for this purpose */
#define DELAY_INFTY 1E30
-typedef struct thread * thread_t;
+/* typedef struct thread * rb_thread_t; */
struct thread {
struct thread *next, *prev;
@@ -5220,35 +6911,44 @@ struct thread {
struct iter *iter;
struct tag *tag;
VALUE klass;
+ VALUE wrapper;
+ NODE *cref;
- VALUE trace;
- int misc; /* misc. states (vmode/trap_immediate) */
+ int flags; /* misc. states (vmode/rb_trap_immediate/raised) */
char *file;
int line;
- VALUE errat, errinfo;
+ int tracing;
+ VALUE errinfo;
VALUE last_status;
VALUE last_line;
VALUE last_match;
int safe;
- enum thread_status status;
+ enum thread_status status;
int wait_for;
int fd;
+ fd_set readfds;
+ fd_set writefds;
+ fd_set exceptfds;
+ int select_value;
double delay;
- thread_t join;
+ rb_thread_t join;
int abort;
+ int priority;
+ int gid;
+
+ st_table *locals;
VALUE thread;
};
-static thread_t curr_thread;
-static int num_waiting_on_fd;
-static int num_waiting_on_timer;
-static int num_waiting_on_join;
+#define THREAD_RAISED 0x200 /* temporary flag */
+#define THREAD_TERMINATING 0x400 /* persistent flag */
+#define THREAD_FLAGS_MASK 0x400 /* mask for persistent flags */
#define FOREACH_THREAD_FROM(f,x) x = f; do { x = x->next;
#define END_FOREACH_FROM(f,x) } while (x != f)
@@ -5256,6 +6956,37 @@ static int num_waiting_on_join;
#define FOREACH_THREAD(x) FOREACH_THREAD_FROM(curr_thread,x)
#define END_FOREACH(x) END_FOREACH_FROM(curr_thread,x)
+/* $SAFE accessor */
+void
+rb_set_safe_level(level)
+ int level;
+{
+ if (level > ruby_safe_level) {
+ ruby_safe_level = level;
+ curr_thread->safe = level;
+ }
+}
+
+static VALUE
+safe_getter()
+{
+ return INT2NUM(ruby_safe_level);
+}
+
+static void
+safe_setter(val)
+ VALUE val;
+{
+ int level = NUM2INT(val);
+
+ if (level < ruby_safe_level) {
+ rb_raise(rb_eSecurityError, "tried to downgrade safe level from %d to %d",
+ ruby_safe_level, level);
+ }
+ ruby_safe_level = level;
+ curr_thread->safe = level;
+}
+
/* Return the current time as a floating-point number */
static double
timeofday()
@@ -5265,157 +6996,219 @@ timeofday()
return (double)tv.tv_sec + (double)tv.tv_usec * 1e-6;
}
-static thread_t main_thread;
-
-#define ADJ(addr) (void*)(((VALUE*)(addr)-th->stk_pos)+th->stk_ptr)
-#define STACK(addr) (th->stk_pos<(addr) && (addr)<th->stk_pos+th->stk_len)
+#define STACK(addr) (th->stk_pos<(VALUE*)(addr) && (VALUE*)(addr)<th->stk_pos+th->stk_len)
+#define ADJ(addr) (void*)(STACK(addr)?(((VALUE*)(addr)-th->stk_pos)+th->stk_ptr):(VALUE*)(addr))
static void
thread_mark(th)
- thread_t th;
+ rb_thread_t th;
{
struct FRAME *frame;
struct BLOCK *block;
- gc_mark(th->result);
+ rb_gc_mark(th->result);
+ rb_gc_mark(th->thread);
+ if (th->join) rb_gc_mark(th->join->thread);
+
+ rb_gc_mark(th->klass);
+ rb_gc_mark(th->wrapper);
+ rb_gc_mark(th->cref);
+
+ rb_gc_mark(th->scope);
+ rb_gc_mark(th->dyna_vars);
+ rb_gc_mark(th->errinfo);
+ rb_gc_mark(th->last_line);
+ rb_gc_mark(th->last_match);
+ rb_mark_tbl(th->locals);
+
+ /* mark data in copied stack */
+ if (th == curr_thread) return;
+ if (th->status == THREAD_KILLED) return;
+ if (th->stk_len == 0) return; /* stack not active, no need to mark. */
if (th->stk_ptr) {
- gc_mark_locations(th->stk_ptr, th->stk_ptr+th->stk_len);
+ rb_gc_mark_locations(th->stk_ptr, th->stk_ptr+th->stk_len);
#if defined(THINK_C) || defined(__human68k__)
- gc_mark_locations(th->stk_ptr+2, th->stk_ptr+th->stk_len+2);
+ rb_gc_mark_locations(th->stk_ptr+2, th->stk_ptr+th->stk_len+2);
#endif
}
- gc_mark(th->thread);
- if (th->join) gc_mark(th->join->thread);
-
- gc_mark(th->scope);
- gc_mark(th->dyna_vars);
- gc_mark(th->errat);
- gc_mark(th->errinfo);
- gc_mark(th->last_line);
- gc_mark(th->last_match);
-
- /* mark data in copied stack */
frame = th->frame;
while (frame && frame != top_frame) {
frame = ADJ(frame);
- if (frame->argv && !STACK(frame->argv)) {
- gc_mark_frame(frame);
+ rb_gc_mark_frame(frame);
+ if (frame->tmp) {
+ struct FRAME *tmp = frame->tmp;
+
+ while (tmp && tmp != top_frame) {
+ tmp = ADJ(tmp);
+ rb_gc_mark_frame(tmp);
+ tmp = tmp->prev;
+ }
}
frame = frame->prev;
}
block = th->block;
while (block) {
block = ADJ(block);
- if (block->frame.argv && !STACK(block->frame.argv)) {
- gc_mark_frame(&block->frame);
- }
+ rb_gc_mark_frame(&block->frame);
block = block->prev;
}
}
void
-gc_mark_threads()
+rb_gc_mark_threads()
{
- thread_t th;
+ rb_thread_t th;
+ if (!curr_thread) return;
FOREACH_THREAD(th) {
- thread_mark(th);
+ rb_gc_mark(th->thread);
} END_FOREACH(th);
}
static void
thread_free(th)
- thread_t th;
+ rb_thread_t th;
{
if (th->stk_ptr) free(th->stk_ptr);
th->stk_ptr = 0;
+ if (th->locals) st_free_table(th->locals);
+ if (th->status != THREAD_KILLED) {
+ if (th->prev) th->prev->next = th->next;
+ if (th->next) th->next->prev = th->prev;
+ }
if (th != main_thread) free(th);
}
-static thread_t
-thread_check(data)
+static rb_thread_t
+rb_thread_check(data)
VALUE data;
{
- if (TYPE(data) != T_DATA || RDATA(data)->dfree != thread_free) {
- TypeError("wrong argument type %s (expected Thread)",
- rb_class2name(CLASS_OF(data)));
+ if (TYPE(data) != T_DATA || RDATA(data)->dfree != (RUBY_DATA_FUNC)thread_free) {
+ rb_raise(rb_eTypeError, "wrong argument type %s (expected Thread)",
+ rb_class2name(CLASS_OF(data)));
}
- return (thread_t)RDATA(data)->data;
+ return (rb_thread_t)RDATA(data)->data;
}
-VALUE lastline_get();
-void lastline_set();
-VALUE backref_get();
-void backref_set();
+static VALUE rb_thread_raise _((int, VALUE*, rb_thread_t));
+
+static int th_raise_argc;
+static VALUE th_raise_argv[2];
+static char *th_raise_file;
+static int th_raise_line;
+static VALUE th_cmd;
+static int th_sig;
+static char *th_signm;
+
+#define RESTORE_NORMAL 1
+#define RESTORE_FATAL 2
+#define RESTORE_INTERRUPT 3
+#define RESTORE_TRAP 4
+#define RESTORE_RAISE 5
+#define RESTORE_SIGNAL 6
static void
-thread_save_context(th)
- thread_t th;
+rb_thread_save_context(th)
+ rb_thread_t th;
{
- VALUE v;
+ VALUE *pos;
+ int len;
- th->stk_len = stack_length();
- th->stk_pos = (gc_stack_start<(VALUE*)&v)?gc_stack_start
- :gc_stack_start - th->stk_len;
- if (th->stk_len > th->stk_max) {
- th->stk_max = th->stk_len;
- REALLOC_N(th->stk_ptr, VALUE, th->stk_max);
- }
- FLUSH_REGISTER_WINDOWS;
+ len = stack_length(&pos);
+ th->stk_len = 0;
+ th->stk_pos = (rb_gc_stack_start<pos)?rb_gc_stack_start
+ :rb_gc_stack_start - len;
+ if (len > th->stk_max) {
+ REALLOC_N(th->stk_ptr, VALUE, len);
+ th->stk_max = len;
+ }
+ th->stk_len = len;
+ FLUSH_REGISTER_WINDOWS;
MEMCPY(th->stk_ptr, th->stk_pos, VALUE, th->stk_len);
- th->frame = the_frame;
- th->scope = the_scope;
- th->klass = the_class;
- th->dyna_vars = the_dyna_vars;
- th->block = the_block;
- th->misc = scope_vmode | (trap_immediate<<8);
- th->iter = the_iter;
+ th->frame = ruby_frame;
+ th->scope = ruby_scope;
+ th->klass = ruby_class;
+ th->wrapper = ruby_wrapper;
+ th->cref = ruby_cref;
+ th->dyna_vars = ruby_dyna_vars;
+ th->block = ruby_block;
+ th->flags &= THREAD_FLAGS_MASK;
+ th->flags |= (rb_trap_immediate<<8) | scope_vmode;
+ th->iter = ruby_iter;
th->tag = prot_tag;
- th->errat = errat;
- th->errinfo = errinfo;
- th->last_status = last_status;
- th->last_line = lastline_get();
- th->last_match = backref_get();
- th->safe = safe_level;
+ th->tracing = tracing;
+ th->errinfo = ruby_errinfo;
+ th->last_status = rb_last_status;
+ th->last_line = rb_lastline_get();
+ th->last_match = rb_backref_get();
+ th->safe = ruby_safe_level;
- th->trace = trace_func;
- th->file = sourcefile;
- th->line = sourceline;
+ th->file = ruby_sourcefile;
+ th->line = ruby_sourceline;
+}
+
+static int
+thread_switch(n)
+ int n;
+{
+ switch (n) {
+ case 0:
+ return 0;
+ case RESTORE_FATAL:
+ JUMP_TAG(TAG_FATAL);
+ break;
+ case RESTORE_INTERRUPT:
+ rb_interrupt();
+ break;
+ case RESTORE_TRAP:
+ rb_trap_eval(th_cmd, th_sig);
+ errno = EINTR;
+ break;
+ case RESTORE_RAISE:
+ ruby_frame->last_func = 0;
+ ruby_sourcefile = th_raise_file;
+ ruby_sourceline = th_raise_line;
+ rb_f_raise(th_raise_argc, th_raise_argv);
+ break;
+ case RESTORE_SIGNAL:
+ rb_raise(rb_eSignal, "SIG%s", th_signm);
+ break;
+ case RESTORE_NORMAL:
+ default:
+ break;
+ }
+ return 1;
}
-static void thread_restore_context();
+#define THREAD_SAVE_CONTEXT(th) \
+ (rb_thread_save_context(th),thread_switch(setjmp((th)->context)))
+
+static void rb_thread_restore_context _((rb_thread_t,int));
static void
stack_extend(th, exit)
- thread_t th;
+ rb_thread_t th;
int exit;
{
VALUE space[1024];
memset(space, 0, 1); /* prevent array from optimization */
- thread_restore_context(th, exit);
+ rb_thread_restore_context(th, exit);
}
-static int th_raise_argc;
-static VALUE th_raise_argv[2];
-static char *th_raise_file;
-static int th_raise_line;
-static VALUE th_cmd;
-static int th_sig;
-
static void
-thread_restore_context(th, exit)
- thread_t th;
+rb_thread_restore_context(th, exit)
+ rb_thread_t th;
int exit;
{
VALUE v;
- static thread_t tmp;
+ static rb_thread_t tmp;
static int ex;
- if (!th->stk_ptr) Bug("unsaved context");
+ if (!th->stk_ptr) rb_bug("unsaved context");
- if (&v < gc_stack_start) {
+ if (&v < rb_gc_stack_start) {
/* Stack grows downward */
if (&v > th->stk_pos) stack_extend(th, exit);
}
@@ -5424,114 +7217,179 @@ thread_restore_context(th, exit)
if (&v < th->stk_pos + th->stk_len) stack_extend(th, exit);
}
- the_frame = th->frame;
- the_scope = th->scope;
- the_class = th->klass;
- the_dyna_vars = th->dyna_vars;
- the_block = th->block;
- scope_vmode = th->misc&SCOPE_MASK;
- trap_immediate = th->misc>>8;
- the_iter = th->iter;
+ ruby_frame = th->frame;
+ ruby_scope = th->scope;
+ ruby_class = th->klass;
+ ruby_wrapper = th->wrapper;
+ ruby_cref = th->cref;
+ ruby_dyna_vars = th->dyna_vars;
+ ruby_block = th->block;
+ scope_vmode = th->flags&SCOPE_MASK;
+ rb_trap_immediate = (th->flags&0x100)?1:0;
+ ruby_iter = th->iter;
prot_tag = th->tag;
- errat = th->errat;
- errinfo = th->errinfo;
- last_status = th->last_status;
- safe_level = th->safe;
+ tracing = th->tracing;
+ ruby_errinfo = th->errinfo;
+ rb_last_status = th->last_status;
+ ruby_safe_level = th->safe;
- trace_func = th->trace;
- sourcefile = th->file;
- sourceline = th->line;
+ ruby_sourcefile = th->file;
+ ruby_sourceline = th->line;
tmp = th;
ex = exit;
FLUSH_REGISTER_WINDOWS;
MEMCPY(tmp->stk_pos, tmp->stk_ptr, VALUE, tmp->stk_len);
- lastline_set(tmp->last_line);
- backref_set(tmp->last_match);
+ rb_lastline_set(tmp->last_line);
+ rb_backref_set(tmp->last_match);
- switch (ex) {
- case 1:
- JUMP_TAG(TAG_FATAL);
- break;
+ longjmp(tmp->context, ex);
+}
- case 2:
- rb_interrupt();
- break;
+static void
+rb_thread_ready(th)
+ rb_thread_t th;
+{
+ th->wait_for = 0;
+ th->status = THREAD_RUNNABLE;
+}
- case 3:
- rb_trap_eval(th_cmd, th_sig);
- errno = EINTR;
- break;
+static void
+rb_thread_remove(th)
+ rb_thread_t th;
+{
+ if (th->status == THREAD_KILLED) return;
- case 4:
- the_frame->last_func = 0;
- sourcefile = th_raise_file;
- sourceline = th_raise_line;
- f_raise(th_raise_argc, th_raise_argv);
- break;
+ rb_thread_ready(th);
+ th->status = THREAD_KILLED;
+ th->prev->next = th->next;
+ th->next->prev = th->prev;
+}
- default:
- longjmp(tmp->context, 1);
+static int
+rb_thread_dead(th)
+ rb_thread_t th;
+{
+ return th->status == THREAD_KILLED;
+}
+
+void
+rb_thread_fd_close(fd)
+ int fd;
+{
+ rb_thread_t th;
+
+ FOREACH_THREAD(th) {
+ if ((th->wait_for & WAIT_FD) && fd == th->fd) {
+ VALUE exc = rb_exc_new2(rb_eIOError, "stream closed");
+ rb_thread_raise(1, &exc, th);
+ }
}
+ END_FOREACH(th);
}
static void
-thread_ready(th)
- thread_t th;
+rb_thread_deadlock()
{
- /* The thread is no longer waiting on anything */
- if (th->wait_for & WAIT_FD) {
- num_waiting_on_fd--;
- }
- if (th->wait_for & WAIT_TIME) {
- num_waiting_on_timer--;
- }
- if (th->wait_for & WAIT_JOIN) {
- num_waiting_on_join--;
+ if (curr_thread == main_thread) {
+ rb_raise(rb_eFatal, "Thread: deadlock");
}
- th->wait_for = 0;
- th->status = THREAD_RUNNABLE;
+ curr_thread = main_thread;
+ th_raise_argc = 1;
+ th_raise_argv[0] = rb_exc_new2(rb_eFatal, "Thread: deadlock");
+ th_raise_file = ruby_sourcefile;
+ th_raise_line = ruby_sourceline;
+ rb_thread_restore_context(main_thread, RESTORE_RAISE);
}
static void
-thread_remove()
+copy_fds(dst, src, max)
+ fd_set *dst, *src;
+ int max;
{
- thread_ready(curr_thread);
- curr_thread->status = THREAD_KILLED;
- curr_thread->prev->next = curr_thread->next;
- curr_thread->next->prev = curr_thread->prev;
- thread_schedule();
+ int n = 0;
+ int i;
+
+ for (i=0; i<=max; i++) {
+ if (FD_ISSET(i, src)) {
+ n = i;
+ FD_SET(i, dst);
+ }
+ }
}
static int
-thread_dead(th)
- thread_t th;
+match_fds(dst, src, max)
+ fd_set *dst, *src;
+ int max;
{
- return th->status == THREAD_KILLED;
+ int i;
+
+ for (i=0; i<=max; i++) {
+ if (FD_ISSET(i, src) && FD_ISSET(i, dst)) {
+ return Qtrue;
+ }
+ }
+ return Qfalse;
}
static void
-thread_deadlock()
+intersect_fds(src, dst, max)
+ fd_set *src, *dst;
+ int max;
{
- curr_thread = main_thread;
- th_raise_argc = 1;
- th_raise_argv[0] = exc_new2(eFatal, "Thread: deadlock");
- th_raise_file = sourcefile;
- th_raise_line = sourceline;
- f_abort();
+ int i;
+
+ for (i=0; i<=max; i++) {
+ if (FD_ISSET(i, dst)) {
+ if (FD_ISSET(i, src)) {
+ /* Wake up only one thread per fd. */
+ FD_CLR(i, src);
+ }
+ else {
+ FD_CLR(i, dst);
+ }
+ }
+ }
}
-void
-thread_schedule()
+static int
+find_bad_fds(dst, src, max)
+ fd_set *dst, *src;
+ int max;
{
- thread_t next; /* OK */
- thread_t th;
- thread_t curr;
+ int i, test = Qfalse;
- select_err:
- thread_pending = 0;
- if (curr_thread == curr_thread->next) return;
+ for (i=0; i<=max; i++) {
+ if (FD_ISSET(i, src) && !FD_ISSET(i, dst)) {
+ FD_CLR(i, src);
+ test = Qtrue;
+ }
+ }
+ return test;
+}
+
+void
+rb_thread_schedule()
+{
+ rb_thread_t next; /* OK */
+ rb_thread_t th;
+ rb_thread_t curr;
+ int found = 0;
+
+ fd_set readfds;
+ fd_set writefds;
+ fd_set exceptfds;
+ struct timeval delay_tv, *delay_ptr;
+ double delay, now; /* OK */
+ int n, max;
+ int need_select = 0;
+
+ rb_thread_pending = 0;
+ if (curr_thread == curr_thread->next
+ && curr_thread->status == THREAD_RUNNABLE)
+ return;
next = 0;
curr = curr_thread; /* starting thread */
@@ -5540,182 +7398,223 @@ thread_schedule()
curr = curr->prev;
}
- FOREACH_THREAD_FROM(curr, th) {
- if (th->status != THREAD_STOPPED && th->status != THREAD_KILLED) {
- next = th;
- break;
- }
- }
- END_FOREACH_FROM(curr, th);
+ again:
+ max = -1;
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptfds);
+ delay = DELAY_INFTY;
+ now = -1.0;
- if (num_waiting_on_join) {
- FOREACH_THREAD_FROM(curr, th) {
- if ((th->wait_for&WAIT_JOIN) && thread_dead(th->join)) {
- th->join = 0;
- th->wait_for &= ~WAIT_JOIN;
+ FOREACH_THREAD_FROM(curr, th) {
+ if (!found && th->status <= THREAD_RUNNABLE) {
+ found = 1;
+ }
+ if (th->status != THREAD_STOPPED) continue;
+ if (th->wait_for & WAIT_JOIN) {
+ if (rb_thread_dead(th->join)) {
th->status = THREAD_RUNNABLE;
- num_waiting_on_join--;
- if (!next) next = th;
+ found = 1;
}
}
- END_FOREACH_FROM(curr, th);
- }
-
- if (num_waiting_on_fd > 0 || num_waiting_on_timer > 0) {
- fd_set readfds;
- struct timeval delay_tv, *delay_ptr;
- double delay, now; /* OK */
-
- int n, max;
-
- do {
- max = 0;
- FD_ZERO(&readfds);
- if (num_waiting_on_fd > 0) {
- FOREACH_THREAD_FROM(curr, th) {
- if (th->wait_for & WAIT_FD) {
- FD_SET(th->fd, &readfds);
- if (th->fd > max) max = th->fd;
- }
- }
- END_FOREACH_FROM(curr, th);
+ if (th->wait_for & WAIT_FD) {
+ FD_SET(th->fd, &readfds);
+ if (max < th->fd) max = th->fd;
+ need_select = 1;
+ }
+ if (th->wait_for & WAIT_SELECT) {
+ copy_fds(&readfds, &th->readfds, th->fd);
+ copy_fds(&writefds, &th->writefds, th->fd);
+ copy_fds(&exceptfds, &th->exceptfds, th->fd);
+ if (max < th->fd) max = th->fd;
+ need_select = 1;
+ th->select_value = 0;
+ }
+ if (th->wait_for & WAIT_TIME) {
+ double th_delay;
+
+ if (now < 0.0) now = timeofday();
+ th_delay = th->delay - now;
+ if (th_delay <= 0.0) {
+ th->status = THREAD_RUNNABLE;
+ found = 1;
+ } else if (th_delay < delay) {
+ delay = th_delay;
+ need_select = 1;
}
-
- delay = DELAY_INFTY;
- if (num_waiting_on_timer > 0) {
- now = timeofday();
- FOREACH_THREAD_FROM(curr, th) {
- if (th->wait_for & WAIT_TIME) {
- if (th->delay <= now) {
- th->delay = 0.0;
- th->wait_for &= ~WAIT_TIME;
- th->status = THREAD_RUNNABLE;
- num_waiting_on_timer--;
- next = th;
- } else if (th->delay < delay) {
- delay = th->delay;
- }
+ if (th->delay == DELAY_INFTY) {
+ need_select = 1;
+ }
+ }
+ }
+ END_FOREACH_FROM(curr, th);
+
+ /* Do the select if needed */
+ if (need_select) {
+ /* Convert delay to a timeval */
+ /* If a thread is runnable, just poll */
+ if (found) {
+ delay_tv.tv_sec = 0;
+ delay_tv.tv_usec = 0;
+ delay_ptr = &delay_tv;
+ }
+ else if (delay == DELAY_INFTY) {
+ delay_ptr = 0;
+ }
+ else {
+ delay_tv.tv_sec = delay;
+ delay_tv.tv_usec = (delay - (double)delay_tv.tv_sec)*1e6;
+ delay_ptr = &delay_tv;
+ }
+
+ n = select(max+1, &readfds, &writefds, &exceptfds, delay_ptr);
+ if (n < 0) {
+ if (rb_trap_pending) rb_trap_exec();
+ if (errno == EINTR) goto again;
+ FOREACH_THREAD_FROM(curr, th) {
+ if (th->wait_for & WAIT_SELECT) {
+ int v = 0;
+
+ v |= find_bad_fds(&readfds, &th->readfds, th->fd);
+ v |= find_bad_fds(&writefds, &th->writefds, th->fd);
+ v |= find_bad_fds(&exceptfds, &th->exceptfds, th->fd);
+ if (v) {
+ th->select_value = n;
+ n = max;
}
}
- END_FOREACH_FROM(curr, th);
}
- /* Do the select if needed */
- if (num_waiting_on_fd > 0 || !next) {
- /* Convert delay to a timeval */
- /* If a thread is runnable, just poll */
- if (next) {
- delay_tv.tv_sec = 0;
- delay_tv.tv_usec = 0;
- delay_ptr = &delay_tv;
- }
- else if (delay == DELAY_INFTY) {
- delay_ptr = 0;
- }
- else {
- delay -= now;
- delay_tv.tv_sec = (unsigned int)delay;
- delay_tv.tv_usec = (delay - (double)delay_tv.tv_sec) * 1e6;
- delay_ptr = &delay_tv;
- }
-
- n = select(max+1, &readfds, 0, 0, delay_ptr);
- if (n < 0) {
- if (trap_pending) rb_trap_exec();
- goto select_err;
+ END_FOREACH_FROM(curr, th);
+ }
+ if (n > 0) {
+ now = -1.0;
+ /* Some descriptors are ready.
+ Make the corresponding threads runnable. */
+ FOREACH_THREAD_FROM(curr, th) {
+ if ((th->wait_for&WAIT_FD) && FD_ISSET(th->fd, &readfds)) {
+ /* Wake up only one thread per fd. */
+ FD_CLR(th->fd, &readfds);
+ th->status = THREAD_RUNNABLE;
+ th->fd = 0;
+ th->wait_for = 0;
+ found = 1;
}
- if (n > 0) {
- /* Some descriptors are ready.
- Make the corresponding threads runnable. */
- FOREACH_THREAD_FROM(curr, th) {
- if ((th->wait_for&WAIT_FD)
- && FD_ISSET(th->fd, &readfds)) {
- /* Wake up only one thread per fd. */
- FD_CLR(th->fd, &readfds);
- th->status = THREAD_RUNNABLE;
- th->fd = 0;
- th->wait_for &= ~WAIT_FD;
- num_waiting_on_fd--;
- if (!next) next = th; /* Found one. */
- }
- }
- END_FOREACH_FROM(curr, th);
+ if ((th->wait_for&WAIT_SELECT) &&
+ (match_fds(&readfds, &th->readfds, max) ||
+ match_fds(&writefds, &th->writefds, max) ||
+ match_fds(&exceptfds, &th->exceptfds, max))) {
+ /* Wake up only one thread per fd. */
+ th->status = THREAD_RUNNABLE;
+ th->wait_for = 0;
+ intersect_fds(&readfds, &th->readfds, max);
+ intersect_fds(&writefds, &th->writefds, max);
+ intersect_fds(&exceptfds, &th->exceptfds, max);
+ th->select_value = n;
+ found = 1;
}
}
- /* The delays for some of the threads should have expired.
- Go through the loop once more, to check the delays. */
- } while (!next && delay != DELAY_INFTY);
+ END_FOREACH_FROM(curr, th);
+ }
+ /* The delays for some of the threads should have expired.
+ Go through the loop once more, to check the delays. */
+ if (!found && delay != DELAY_INFTY)
+ goto again;
+ }
+
+ FOREACH_THREAD_FROM(curr, th) {
+ if (th->status == THREAD_TO_KILL) {
+ next = th;
+ break;
+ }
+ if (th->status == THREAD_RUNNABLE) {
+ if (!next || next->priority < th->priority)
+ next = th;
+ }
}
+ END_FOREACH_FROM(curr, th);
if (!next) {
- curr_thread->file = sourcefile;
- curr_thread->line = sourceline;
+ /* raise fatal error to main thread */
+ curr_thread->file = ruby_sourcefile;
+ curr_thread->line = ruby_sourceline;
FOREACH_THREAD_FROM(curr, th) {
- fprintf(stderr, "%s:%d:deadlock 0x%x: %d:%d %s\n",
- th->file, th->line, th->thread, th->status,
- th->wait_for, th==main_thread?"(main)":"");
+ fprintf(stderr, "deadlock 0x%lx: %d:%d %s - %s:%d\n",
+ th->thread, th->status,
+ th->wait_for, th==main_thread?"(main)":"",
+ th->file, th->line);
}
END_FOREACH_FROM(curr, th);
- /* raise fatal error to main thread */
- thread_deadlock();
- }
+ next = main_thread;
+ next->gid = 0;
+ rb_thread_ready(next);
+ next->status = THREAD_TO_KILL;
+ rb_thread_save_context(curr_thread);
+ rb_thread_deadlock();
+ }
+ next->wait_for = 0;
if (next->status == THREAD_RUNNABLE && next == curr_thread) {
return;
}
/* context switch */
if (curr == curr_thread) {
- thread_save_context(curr);
- if (setjmp(curr->context)) {
+ if (THREAD_SAVE_CONTEXT(curr)) {
return;
}
}
curr_thread = next;
if (next->status == THREAD_TO_KILL) {
- /* execute ensure-clause if any */
- thread_restore_context(next, 1);
+ if (!(next->flags & THREAD_TERMINATING)) {
+ next->flags |= THREAD_TERMINATING;
+ /* terminate; execute ensure-clause if any */
+ rb_thread_restore_context(next, RESTORE_FATAL);
+ }
}
- thread_restore_context(next, 0);
+ rb_thread_restore_context(next, RESTORE_NORMAL);
}
void
-thread_wait_fd(fd)
+rb_thread_wait_fd(fd)
int fd;
{
+ if (rb_thread_critical) return;
if (curr_thread == curr_thread->next) return;
+ if (curr_thread->status == THREAD_TO_KILL) return;
curr_thread->status = THREAD_STOPPED;
curr_thread->fd = fd;
- num_waiting_on_fd++;
- curr_thread->wait_for |= WAIT_FD;
- thread_schedule();
+ curr_thread->wait_for = WAIT_FD;
+ rb_thread_schedule();
}
-void
-thread_fd_writable(fd)
+int
+rb_thread_fd_writable(fd)
int fd;
{
- struct timeval zero;
- fd_set fds;
-
- if (curr_thread == curr_thread->next) return;
-
- zero.tv_sec = zero.tv_usec = 0;
- for (;;) {
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
- if (select(fd+1, 0, &fds, 0, &zero) == 1) break;
- thread_schedule();
- }
+ if (rb_thread_critical) return Qtrue;
+ if (curr_thread == curr_thread->next) return Qtrue;
+ if (curr_thread->status == THREAD_TO_KILL) return Qtrue;
+ curr_thread->status = THREAD_STOPPED;
+ FD_ZERO(&curr_thread->readfds);
+ FD_ZERO(&curr_thread->writefds);
+ FD_SET(fd, &curr_thread->writefds);
+ FD_ZERO(&curr_thread->exceptfds);
+ curr_thread->fd = fd+1;
+ curr_thread->wait_for = WAIT_SELECT;
+ rb_thread_schedule();
+ return Qfalse;
}
void
-thread_wait_for(time)
+rb_thread_wait_for(time)
struct timeval time;
{
double date;
- if (curr_thread == curr_thread->next) {
+ if (rb_thread_critical ||
+ curr_thread == curr_thread->next ||
+ curr_thread->status == THREAD_TO_KILL) {
int n;
#ifndef linux
double d, limit;
@@ -5726,14 +7625,21 @@ thread_wait_for(time)
n = select(0, 0, 0, 0, &time);
TRAP_END;
if (n == 0) return;
-
+ if (n < 0) {
+ switch (errno) {
+ case EINTR:
+ return;
+ default:
+ rb_sys_fail("sleep");
+ }
+ }
#ifndef linux
d = limit - timeofday();
time.tv_sec = (int)d;
time.tv_usec = (int)((d - (int)d)*1e6);
if (time.tv_usec < 0) {
- time.tv_usec += 1e6;
+ time.tv_usec += (long)1e6;
time.tv_sec -= 1;
}
if (time.tv_sec < 0) return;
@@ -5744,36 +7650,33 @@ thread_wait_for(time)
date = timeofday() + (double)time.tv_sec + (double)time.tv_usec*1e-6;
curr_thread->status = THREAD_STOPPED;
curr_thread->delay = date;
- num_waiting_on_timer++;
- curr_thread->wait_for |= WAIT_TIME;
- thread_schedule();
+ curr_thread->wait_for = WAIT_TIME;
+ rb_thread_schedule();
}
-void thread_sleep_forever();
+void rb_thread_sleep_forever _((void));
int
-thread_alone()
+rb_thread_alone()
{
return curr_thread == curr_thread->next;
}
int
-thread_select(max, read, write, except, timeout)
+rb_thread_select(max, read, write, except, timeout)
int max;
fd_set *read, *write, *except;
struct timeval *timeout;
{
double limit;
- struct timeval zero;
- fd_set r, *rp, w, *wp, x, *xp;
int n;
if (!read && !write && !except) {
if (!timeout) {
- thread_sleep_forever();
+ rb_thread_sleep_forever();
return 0;
}
- thread_wait_for(*timeout);
+ rb_thread_wait_for(*timeout);
return 0;
}
@@ -5782,7 +7685,9 @@ thread_select(max, read, write, except, timeout)
(double)timeout->tv_sec+(double)timeout->tv_usec*1e-6;
}
- if (curr_thread == curr_thread->next) { /* no other thread */
+ if (rb_thread_critical ||
+ curr_thread == curr_thread->next ||
+ curr_thread->status == THREAD_TO_KILL) {
#ifndef linux
struct timeval tv, *tvp = timeout;
@@ -5799,7 +7704,7 @@ thread_select(max, read, write, except, timeout)
double d = timeofday() - limit;
tv.tv_sec = (unsigned int)d;
- tv.tv_usec = (d - (double)tv.tv_sec) * 1e6;
+ tv.tv_usec = (long)((d-(double)tv.tv_sec)*1e6);
}
continue;
}
@@ -5819,138 +7724,191 @@ thread_select(max, read, write, except, timeout)
}
- for (;;) {
- zero.tv_sec = zero.tv_usec = 0;
- if (read) {rp = &r; r = *read;} else {rp = 0;}
- if (write) {wp = &w; w = *write;} else {wp = 0;}
- if (except) {xp = &x; x = *except;} else {xp = 0;}
- n = select(max, rp, wp, xp, &zero);
- if (n > 0) {
- /* write back fds */
- if (read) {*read = r;}
- if (write) {*write = w;}
- if (except) {*except = x;}
- return n;
- }
- if (n < 0 && errno != EINTR) {
- return n;
- }
- if (timeout) {
- if (timeout->tv_sec == 0 && timeout->tv_usec == 0) return 0;
- if (limit <= timeofday()) return 0;
- }
-
- thread_schedule();
- CHECK_INTS;
+ curr_thread->status = THREAD_STOPPED;
+ if (read) curr_thread->readfds = *read;
+ else FD_ZERO(&curr_thread->readfds);
+ if (write) curr_thread->writefds = *write;
+ else FD_ZERO(&curr_thread->writefds);
+ if (except) curr_thread->exceptfds = *except;
+ else FD_ZERO(&curr_thread->exceptfds);
+ curr_thread->fd = max;
+ curr_thread->wait_for = WAIT_SELECT;
+ if (timeout) {
+ curr_thread->delay = timeofday() +
+ (double)timeout->tv_sec + (double)timeout->tv_usec*1e-6;
+ curr_thread->wait_for |= WAIT_TIME;
}
+ rb_thread_schedule();
+ if (read) *read = curr_thread->readfds;
+ if (write) *write = curr_thread->writefds;
+ if (except) *except = curr_thread->exceptfds;
+ return curr_thread->select_value;
}
static VALUE
-thread_join(dmy, thread)
- VALUE dmy;
+rb_thread_join(thread)
VALUE thread;
{
- thread_t th = thread_check(thread);
+ rb_thread_t th = rb_thread_check(thread);
+ enum thread_status last_status = THREAD_RUNNABLE;
- if (thread_dead(th)) return thread;
- if ((th->wait_for & WAIT_JOIN) && th->join == curr_thread)
- Raise(eThreadError, "Thread.join: deadlock");
- curr_thread->status = THREAD_STOPPED;
- curr_thread->join = th;
- num_waiting_on_join++;
- curr_thread->wait_for |= WAIT_JOIN;
- thread_schedule();
+ if (rb_thread_critical) rb_thread_deadlock();
+ if (!rb_thread_dead(th)) {
+ if (th == curr_thread)
+ rb_raise(rb_eThreadError, "thread tried to join itself");
+ if ((th->wait_for & WAIT_JOIN) && th->join == curr_thread)
+ rb_raise(rb_eThreadError, "Thread#join: deadlock - mutual join");
+ if (curr_thread->status == THREAD_TO_KILL)
+ last_status = THREAD_TO_KILL;
+ curr_thread->status = THREAD_STOPPED;
+ curr_thread->join = th;
+ curr_thread->wait_for = WAIT_JOIN;
+ rb_thread_schedule();
+ curr_thread->status = last_status;
+ }
+
+ if (!NIL_P(th->errinfo) && (th->flags & THREAD_RAISED)) {
+ VALUE oldbt = get_backtrace(th->errinfo);
+ VALUE errat = make_backtrace();
+
+ if (TYPE(oldbt) == T_ARRAY && RARRAY(oldbt)->len > 0) {
+ rb_ary_unshift(errat, rb_ary_entry(oldbt, 0));
+ }
+ set_backtrace(th->errinfo, errat);
+ rb_exc_raise(th->errinfo);
+ }
return thread;
}
-static VALUE
-thread_current()
+VALUE
+rb_thread_current()
{
return curr_thread->thread;
}
-static VALUE
-thread_main()
+VALUE
+rb_thread_main()
{
return main_thread->thread;
}
-static VALUE
-thread_wakeup(thread)
+VALUE
+rb_thread_list()
+{
+ rb_thread_t th;
+ VALUE ary = rb_ary_new();
+
+ FOREACH_THREAD(th) {
+ switch (th->status) {
+ case THREAD_RUNNABLE:
+ case THREAD_STOPPED:
+ rb_ary_push(ary, th->thread);
+ default:
+ break;
+ }
+ }
+ END_FOREACH(th);
+
+ return ary;
+}
+
+VALUE
+rb_thread_wakeup(thread)
VALUE thread;
{
- thread_t th = thread_check(thread);
+ rb_thread_t th = rb_thread_check(thread);
- if (th->status == THREAD_KILLED) Raise(eThreadError, "killed thread");
- thread_ready(th);
+ if (th->status == THREAD_KILLED)
+ rb_raise(rb_eThreadError, "killed thread");
+ rb_thread_ready(th);
return thread;
}
-static VALUE
-thread_run(thread)
+VALUE
+rb_thread_run(thread)
VALUE thread;
{
- thread_wakeup(thread);
- if (!thread_critical) thread_schedule();
+ rb_thread_wakeup(thread);
+ if (!rb_thread_critical) rb_thread_schedule();
return thread;
}
static VALUE
-thread_kill(thread)
+rb_thread_kill(thread)
VALUE thread;
{
- thread_t th = thread_check(thread);
+ rb_thread_t th = rb_thread_check(thread);
+ if (th != curr_thread && th->safe < 4) {
+ rb_secure(4);
+ }
if (th->status == THREAD_TO_KILL || th->status == THREAD_KILLED)
return thread;
if (th == th->next || th == main_thread) rb_exit(0);
- thread_ready(th);
+ rb_thread_ready(th);
+ th->gid = 0;
th->status = THREAD_TO_KILL;
- thread_schedule();
- return Qnil; /* not reached */
+ if (!rb_thread_critical) rb_thread_schedule();
+ return thread;
}
static VALUE
-thread_s_kill(obj, th)
+rb_thread_s_kill(obj, th)
VALUE obj, th;
{
- return thread_kill(th);
+ return rb_thread_kill(th);
}
static VALUE
-thread_exit()
+rb_thread_exit()
{
- return thread_kill(curr_thread->thread);
+ return rb_thread_kill(curr_thread->thread);
}
static VALUE
-thread_pass()
+rb_thread_pass()
{
- thread_schedule();
+ rb_thread_schedule();
return Qnil;
}
-static VALUE
-thread_stop()
+VALUE
+rb_thread_stop()
{
- thread_critical = 0;
- curr_thread->status = THREAD_STOPPED;
+ enum thread_status last_status = THREAD_RUNNABLE;
+
+ rb_thread_critical = 0;
if (curr_thread == curr_thread->next) {
- Raise(eThreadError, "stopping only thread");
+ rb_raise(rb_eThreadError, "stopping only thread\n\tnote: use sleep to stop forever");
}
- thread_schedule();
+ if (curr_thread->status == THREAD_TO_KILL)
+ last_status = THREAD_TO_KILL;
+ curr_thread->status = THREAD_STOPPED;
+ rb_thread_schedule();
+ curr_thread->status = last_status;
return Qnil;
}
-struct timeval time_timeval();
+struct timeval rb_time_timeval();
void
-thread_sleep(sec)
+rb_thread_polling()
+{
+ if (curr_thread != curr_thread->next) {
+ curr_thread->status = THREAD_STOPPED;
+ curr_thread->delay = timeofday() + (double)0.06;
+ curr_thread->wait_for = WAIT_TIME;
+ rb_thread_schedule();
+ }
+}
+
+void
+rb_thread_sleep(sec)
int sec;
{
if (curr_thread == curr_thread->next) {
@@ -5959,113 +7917,159 @@ thread_sleep(sec)
TRAP_END;
return;
}
- thread_wait_for(time_timeval(INT2FIX(sec)));
+ rb_thread_wait_for(rb_time_timeval(INT2FIX(sec)));
}
+#if !defined HAVE_PAUSE
+# if defined _WIN32 && !defined __CYGWIN__
+# define pause() Sleep(INFINITE)
+# else
+# define pause() sleep(0x7fffffff)
+# endif
+#endif
+
void
-thread_sleep_forever()
+rb_thread_sleep_forever()
{
- if (curr_thread == curr_thread->next) {
+ if (curr_thread == curr_thread->next ||
+ curr_thread->status == THREAD_TO_KILL) {
TRAP_BEG;
- sleep((32767<<16)+32767);
+ pause();
TRAP_END;
return;
}
- num_waiting_on_timer++;
curr_thread->delay = DELAY_INFTY;
- curr_thread->wait_for |= WAIT_TIME;
+ curr_thread->wait_for = WAIT_TIME;
curr_thread->status = THREAD_STOPPED;
- thread_schedule();
+ rb_thread_schedule();
+}
+
+static VALUE
+rb_thread_priority(thread)
+ VALUE thread;
+{
+ return INT2NUM(rb_thread_check(thread)->priority);
+}
+
+static VALUE
+rb_thread_priority_set(thread, prio)
+ VALUE thread, prio;
+{
+ rb_thread_t th;
+
+ rb_secure(4);
+ th = rb_thread_check(thread);
+
+ th->priority = NUM2INT(prio);
+ rb_thread_schedule();
+ return thread;
+}
+
+static VALUE
+rb_thread_safe_level(thread)
+ VALUE thread;
+{
+ rb_thread_t th;
+
+ th = rb_thread_check(thread);
+ if (th == curr_thread) {
+ return INT2NUM(rb_safe_level());
+ }
+ return INT2NUM(th->safe);
}
static int thread_abort;
static VALUE
-thread_s_abort_exc()
+rb_thread_s_abort_exc()
{
- return thread_abort?TRUE:FALSE;
+ return thread_abort?Qtrue:Qfalse;
}
static VALUE
-thread_s_abort_exc_set(self, val)
+rb_thread_s_abort_exc_set(self, val)
VALUE self, val;
{
+ rb_secure(4);
thread_abort = RTEST(val);
return val;
}
static VALUE
-thread_abort_exc(thread)
+rb_thread_abort_exc(thread)
VALUE thread;
{
- thread_t th = thread_check(thread);
-
- return th->abort?TRUE:FALSE;
+ return rb_thread_check(thread)->abort?Qtrue:Qfalse;
}
static VALUE
-thread_abort_exc_set(thread, val)
+rb_thread_abort_exc_set(thread, val)
VALUE thread, val;
{
- thread_t th = thread_check(thread);
-
- th->abort = RTEST(val);
+ rb_secure(4);
+ rb_thread_check(thread)->abort = RTEST(val);
return val;
}
-static thread_t
-thread_alloc()
+#define THREAD_ALLOC(th) do {\
+ th = ALLOC(struct thread);\
+\
+ th->next = 0;\
+ th->prev = 0;\
+\
+ th->status = THREAD_RUNNABLE;\
+ th->result = 0;\
+ th->flags = 0;\
+\
+ th->stk_ptr = 0;\
+ th->stk_len = 0;\
+ th->stk_max = 0;\
+ th->wait_for = 0;\
+ FD_ZERO(&th->readfds);\
+ FD_ZERO(&th->writefds);\
+ FD_ZERO(&th->exceptfds);\
+ th->delay = 0.0;\
+ th->join = 0;\
+\
+ th->frame = 0;\
+ th->scope = 0;\
+ th->klass = 0;\
+ th->wrapper = 0;\
+ th->cref = ruby_cref;\
+ th->dyna_vars = ruby_dyna_vars;\
+ th->block = 0;\
+ th->iter = 0;\
+ th->tag = 0;\
+ th->tracing = 0;\
+ th->errinfo = Qnil;\
+ th->last_status = 0;\
+ th->last_line = 0;\
+ th->last_match = 0;\
+ th->abort = 0;\
+ th->priority = 0;\
+ th->gid = 1;\
+ th->locals = 0;\
+} while(0)
+
+static rb_thread_t
+rb_thread_alloc(klass)
+ VALUE klass;
{
- thread_t th;
-
- th = ALLOC(struct thread);
- th->status = THREAD_RUNNABLE;
+ rb_thread_t th;
+ struct RVarmap *vars;
- th->status = 0;
- th->result = 0;
- th->errinfo = Qnil;
- th->errat = Qnil;
+ THREAD_ALLOC(th);
+ th->thread = Data_Wrap_Struct(klass, thread_mark, thread_free, th);
- th->stk_ptr = 0;
- th->stk_len = 0;
- th->stk_max = 0;
- th->wait_for = 0;
- th->fd = 0;
- th->delay = 0.0;
- th->join = 0;
-
- th->frame = 0;
- th->scope = 0;
- th->klass = 0;
- th->dyna_vars = 0;
- th->block = 0;
- th->iter = 0;
- th->tag = 0;
- th->errat = 0;
- th->errinfo = 0;
- th->last_status = 0;
- th->last_line = 0;
- th->last_match = 0;
- th->abort = 0;
-
- th->thread = data_object_alloc(cThread, th, 0, thread_free);
-
- if (curr_thread) {
- th->prev = curr_thread;
- curr_thread->next->prev = th;
- th->next = curr_thread->next;
- curr_thread->next = th;
+ for (vars = th->dyna_vars; vars; vars = vars->next) {
+ if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
+ FL_SET(vars, DVAR_DONT_RECYCLE);
}
- else {
- curr_thread = th->prev = th->next = th;
- th->status = THREAD_RUNNABLE;
- }
-
return th;
}
-#if defined(HAVE_SETITIMER) && !defined(__BOW__)
+#if defined(HAVE_SETITIMER)
static void
catch_timer(sig)
int sig;
@@ -6073,322 +8077,724 @@ catch_timer(sig)
#if !defined(POSIX_SIGNAL) && !defined(BSD_SIGNAL)
signal(sig, catch_timer);
#endif
- if (!thread_critical) {
- if (trap_immediate) {
- thread_schedule();
+ if (!rb_thread_critical) {
+ if (rb_trap_immediate) {
+ rb_thread_schedule();
}
- else thread_pending = 1;
+ else rb_thread_pending = 1;
}
}
#else
-int thread_tick = THREAD_TICK;
+int rb_thread_tick = THREAD_TICK;
#endif
-VALUE
-thread_create(fn, arg)
+#define SCOPE_SHARED FL_USER1
+
+#if defined(HAVE_SETITIMER)
+static int thread_init = 0;
+
+void
+rb_thread_start_timer()
+{
+ struct itimerval tval;
+
+ if (!thread_init) return;
+ tval.it_interval.tv_sec = 0;
+ tval.it_interval.tv_usec = 10000;
+ tval.it_value = tval.it_interval;
+ setitimer(ITIMER_VIRTUAL, &tval, NULL);
+}
+
+void
+rb_thread_stop_timer()
+{
+ struct itimerval tval;
+
+ if (!thread_init) return;
+ tval.it_interval.tv_sec = 0;
+ tval.it_interval.tv_usec = 0;
+ tval.it_value = tval.it_interval;
+ setitimer(ITIMER_VIRTUAL, &tval, NULL);
+}
+#endif
+
+static VALUE
+rb_thread_start_0(fn, arg, th_arg)
VALUE (*fn)();
void *arg;
+ rb_thread_t th_arg;
{
- thread_t th = thread_alloc();
+ volatile rb_thread_t th = th_arg;
+ volatile VALUE thread = th->thread;
+ struct BLOCK* saved_block = 0;
+ enum thread_status status;
int state;
-#if defined(HAVE_SETITIMER) && !defined(__BOW__)
- static init = 0;
-
- if (!init) {
- struct itimerval tval;
-
+#if defined(HAVE_SETITIMER)
+ if (!thread_init) {
#ifdef POSIX_SIGNAL
posix_signal(SIGVTALRM, catch_timer);
#else
signal(SIGVTALRM, catch_timer);
#endif
- tval.it_interval.tv_sec = 0;
- tval.it_interval.tv_usec = 100000;
- tval.it_value = tval.it_interval;
- setitimer(ITIMER_VIRTUAL, &tval, NULL);
-
- init = 1;
+ thread_init = 1;
+ rb_thread_start_timer();
}
#endif
- thread_save_context(curr_thread);
- if (setjmp(curr_thread->context)) {
- return th->thread;
+ if (ruby_block) { /* should nail down higher scopes */
+ struct BLOCK dummy;
+
+ dummy.prev = ruby_block;
+ blk_copy_prev(&dummy);
+ saved_block = ruby_block = dummy.prev;
+ }
+ scope_dup(ruby_scope);
+ FL_SET(ruby_scope, SCOPE_SHARED);
+ if (THREAD_SAVE_CONTEXT(curr_thread)) {
+ return thread;
+ }
+
+ if (!th->next) {
+ /* merge in thread list */
+ th->prev = curr_thread;
+ curr_thread->next->prev = th;
+ th->next = curr_thread->next;
+ curr_thread->next = th;
+ th->priority = curr_thread->priority;
+ th->gid = curr_thread->gid;
}
PUSH_TAG(PROT_THREAD);
if ((state = EXEC_TAG()) == 0) {
- thread_save_context(th);
- if (setjmp(th->context) == 0) {
+ if (THREAD_SAVE_CONTEXT(th) == 0) {
curr_thread = th;
th->result = (*fn)(arg, th);
}
}
POP_TAG();
- if (state && th->status != THREAD_TO_KILL && !NIL_P(errinfo)) {
- if (state == TAG_FATAL || obj_is_kind_of(errinfo, eSystemExit)) {
- /* fatal error or global exit within this thread */
- /* need to stop whole script */
- main_thread->errat = errat;
- main_thread->errinfo = errinfo;
- thread_cleanup();
+ status = th->status;
+
+ while (saved_block) {
+ struct BLOCK *tmp = saved_block;
+
+ if (tmp->frame.argc > 0)
+ free(tmp->frame.argv);
+ saved_block = tmp->prev;
+ free(tmp);
+ }
+
+ if (th == main_thread) ruby_stop(state);
+ rb_thread_remove(th);
+ if (state && status != THREAD_TO_KILL && !NIL_P(ruby_errinfo)) {
+ th->flags |= THREAD_RAISED;
+ if (state == TAG_FATAL) {
+ /* fatal error within this thread, need to stop whole script */
+ main_thread->errinfo = ruby_errinfo;
+ rb_thread_cleanup();
+ }
+ else if (rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) {
+ if (th->safe >= 4) {
+ rb_raise(rb_eSecurityError, "Insecure exit at level %d",
+ ruby_safe_level);
+ }
+ /* delegate exception to main_thread */
+ rb_thread_raise(1, &ruby_errinfo, main_thread);
}
- else if (thread_abort || curr_thread->abort || RTEST(debug)) {
- f_abort();
+ else if (th->safe < 4 &&
+ (thread_abort || th->abort || RTEST(ruby_debug))) {
+ VALUE err = rb_exc_new(rb_eSystemExit, 0, 0);
+ error_print();
+ /* exit on main_thread */
+ rb_thread_raise(1, &err, main_thread);
}
else {
- curr_thread->errat = errat;
- curr_thread->errinfo = errinfo;
+ th->errinfo = ruby_errinfo;
}
}
- thread_remove();
- return 0;
+ rb_thread_schedule();
+ return 0; /* not reached */
+}
+
+VALUE
+rb_thread_create(fn, arg)
+ VALUE (*fn)();
+ void *arg;
+{
+ return rb_thread_start_0(fn, arg, rb_thread_alloc(rb_cThread));
+}
+
+int
+rb_thread_scope_shared_p()
+{
+ return FL_TEST(ruby_scope, SCOPE_SHARED);
}
static VALUE
-thread_yield(arg, th)
- int arg;
- thread_t th;
+rb_thread_yield(arg, th)
+ VALUE arg;
+ rb_thread_t th;
{
- scope_dup(the_block->scope);
- return rb_yield(th->thread);
+ scope_dup(ruby_block->scope);
+ return rb_yield_0(callargs(arg), 0, 0, Qtrue);
}
static VALUE
-thread_start()
+rb_thread_s_new(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
{
- if (!iterator_p()) {
- Raise(eThreadError, "must be called as iterator");
+ rb_thread_t th = rb_thread_alloc(klass);
+ volatile VALUE *pos;
+
+ pos = th->stk_pos;
+ rb_obj_call_init(th->thread, argc, argv);
+ if (th->stk_pos == 0) {
+ rb_raise(rb_eThreadError, "uninitialized thread - check `%s#initialize'",
+ rb_class2name(klass));
}
- return thread_create(thread_yield, 0);
+
+ return th->thread;
}
static VALUE
-thread_value(thread)
- VALUE thread;
+rb_thread_initialize(thread, args)
+ VALUE thread, args;
{
- thread_t th = thread_check(thread);
+ if (!rb_block_given_p()) {
+ rb_raise(rb_eThreadError, "must be called with a block");
+ }
+ return rb_thread_start_0(rb_thread_yield, args, rb_thread_check(thread));
+}
- thread_join(0, thread);
- if (!NIL_P(th->errinfo)) {
- errat = make_backtrace();
- ary_unshift(errat, ary_entry(th->errat, 0));
- sourcefile = 0; /* kludge to print errat */
- rb_raise(th->errinfo);
+static VALUE
+rb_thread_start(klass, args)
+ VALUE klass, args;
+{
+ if (!rb_block_given_p()) {
+ rb_raise(rb_eThreadError, "must be called with a block");
}
+ return rb_thread_start_0(rb_thread_yield, args, rb_thread_alloc(klass));
+}
+
+static VALUE
+rb_thread_value(thread)
+ VALUE thread;
+{
+ rb_thread_t th = rb_thread_check(thread);
+
+ rb_thread_join(thread);
return th->result;
}
static VALUE
-thread_status(thread)
+rb_thread_status(thread)
VALUE thread;
{
- thread_t th = thread_check(thread);
+ rb_thread_t th = rb_thread_check(thread);
- if (thread_dead(th)) {
- if (NIL_P(th->errinfo)) return FALSE;
- return Qnil;
+ if (rb_thread_dead(th)) {
+ if (!NIL_P(th->errinfo) && (th->flags & THREAD_RAISED))
+ return Qnil;
+ return Qfalse;
}
- return TRUE;
+ if (th->status == THREAD_STOPPED)
+ return rb_str_new2("sleep");
+ return rb_str_new2("run");
}
static VALUE
-thread_stop_p(thread)
+rb_thread_alive_p(thread)
VALUE thread;
{
- thread_t th = thread_check(thread);
+ rb_thread_t th = rb_thread_check(thread);
- if (thread_dead(th)) return TRUE;
- if (th->status == THREAD_STOPPED) return TRUE;
- return FALSE;
+ if (rb_thread_dead(th)) return Qfalse;
+ return Qtrue;
+}
+
+static VALUE
+rb_thread_stop_p(thread)
+ VALUE thread;
+{
+ rb_thread_t th = rb_thread_check(thread);
+
+ if (rb_thread_dead(th)) return Qtrue;
+ if (th->status == THREAD_STOPPED) return Qtrue;
+ return Qfalse;
}
static void
-thread_wait_other_threads()
+rb_thread_wait_other_threads()
{
/* wait other threads to terminate */
while (curr_thread != curr_thread->next) {
- thread_schedule();
+ rb_thread_schedule();
}
}
static void
-thread_cleanup()
+rb_thread_cleanup()
{
- thread_t th;
+ rb_thread_t th;
- if (curr_thread != curr_thread->next->prev) {
+ while (curr_thread->status == THREAD_KILLED) {
curr_thread = curr_thread->prev;
}
FOREACH_THREAD(th) {
if (th != curr_thread && th->status != THREAD_KILLED) {
+ rb_thread_ready(th);
+ th->gid = 0;
+ th->priority = 0;
th->status = THREAD_TO_KILL;
- th->wait_for = 0;
}
}
END_FOREACH(th);
}
-int thread_critical;
+int rb_thread_critical;
static VALUE
-thread_get_critical()
+rb_thread_critical_get()
{
- return thread_critical?TRUE:FALSE;
+ return rb_thread_critical?Qtrue:Qfalse;
}
static VALUE
-thread_set_critical(obj, val)
+rb_thread_critical_set(obj, val)
VALUE obj, val;
{
- thread_critical = RTEST(val);
+ rb_thread_critical = RTEST(val);
return val;
}
void
-thread_interrupt()
+rb_thread_interrupt()
{
- thread_critical = 0;
- thread_ready(main_thread);
+ rb_thread_critical = 0;
+ rb_thread_ready(main_thread);
if (curr_thread == main_thread) {
rb_interrupt();
}
- thread_save_context(curr_thread);
- if (setjmp(curr_thread->context)) {
+ if (THREAD_SAVE_CONTEXT(curr_thread)) {
+ return;
+ }
+ curr_thread = main_thread;
+ rb_thread_restore_context(curr_thread, RESTORE_INTERRUPT);
+}
+
+void
+rb_thread_signal_raise(sig)
+ char *sig;
+{
+ if (sig == 0) return; /* should not happen */
+ rb_thread_critical = 0;
+ if (curr_thread == main_thread) {
+ rb_thread_ready(curr_thread);
+ rb_raise(rb_eSignal, "SIG%s", sig);
+ }
+ rb_thread_ready(main_thread);
+ if (THREAD_SAVE_CONTEXT(curr_thread)) {
return;
}
+ th_signm = sig;
curr_thread = main_thread;
- thread_restore_context(curr_thread, 2);
+ rb_thread_restore_context(curr_thread, RESTORE_SIGNAL);
}
void
-thread_trap_eval(cmd, sig)
+rb_thread_trap_eval(cmd, sig)
VALUE cmd;
int sig;
{
- thread_critical = 0;
- if (!thread_dead(curr_thread)) {
- thread_ready(curr_thread);
+#if 0
+ rb_thread_critical = 0;
+ if (!rb_thread_dead(curr_thread)) {
+ rb_thread_ready(curr_thread);
rb_trap_eval(cmd, sig);
return;
}
- thread_ready(main_thread);
- thread_save_context(curr_thread);
- if (setjmp(curr_thread->context)) {
+ rb_thread_ready(main_thread);
+ if (THREAD_SAVE_CONTEXT(curr_thread)) {
return;
}
th_cmd = cmd;
th_sig = sig;
curr_thread = main_thread;
- thread_restore_context(curr_thread, 3);
+ rb_thread_restore_context(curr_thread, RESTORE_TRAP);
+#else
+ rb_thread_critical = 0;
+ if (!rb_thread_dead(curr_thread)) {
+ if (THREAD_SAVE_CONTEXT(curr_thread)) {
+ return;
+ }
+ }
+ rb_thread_ready(main_thread);
+ th_cmd = cmd;
+ th_sig = sig;
+ curr_thread = main_thread;
+ rb_thread_restore_context(curr_thread, RESTORE_TRAP);
+#endif
}
static VALUE
-thread_raise(argc, argv, thread)
+rb_thread_raise(argc, argv, th)
int argc;
VALUE *argv;
- VALUE thread;
+ rb_thread_t th;
{
- thread_t th = thread_check(thread);
-
- if (thread_dead(th)) return thread;
+ if (rb_thread_dead(th)) return Qnil;
if (curr_thread == th) {
- f_raise(argc, argv);
+ rb_f_raise(argc, argv);
}
- thread_save_context(curr_thread);
- if (setjmp(curr_thread->context)) {
- return thread;
+ if (THREAD_SAVE_CONTEXT(curr_thread)) {
+ return th->thread;
}
rb_scan_args(argc, argv, "11", &th_raise_argv[0], &th_raise_argv[1]);
- thread_ready(th);
+ rb_thread_ready(th);
curr_thread = th;
th_raise_argc = argc;
- th_raise_file = sourcefile;
- th_raise_line = sourceline;
- thread_restore_context(curr_thread, 4);
+ th_raise_file = ruby_sourcefile;
+ th_raise_line = ruby_sourceline;
+ rb_thread_restore_context(curr_thread, RESTORE_RAISE);
return Qnil; /* not reached */
}
-static thread_t loading_thread;
-static int loading_nest;
+static VALUE
+rb_thread_raise_m(argc, argv, thread)
+ int argc;
+ VALUE *argv;
+ VALUE thread;
+{
+ rb_thread_t th = rb_thread_check(thread);
-static int
-thread_loading(feature)
- char *feature;
+ if (ruby_safe_level > th->safe) {
+ rb_secure(4);
+ }
+ rb_thread_raise(argc, argv, th);
+ return Qnil; /* not reached */
+}
+
+VALUE
+rb_thread_local_aref(thread, id)
+ VALUE thread;
+ ID id;
{
- if (curr_thread != curr_thread->next && loading_thread) {
- while (loading_thread != curr_thread) {
- thread_schedule();
- CHECK_INTS;
+ rb_thread_t th;
+ VALUE val;
+
+ th = rb_thread_check(thread);
+ if (rb_safe_level() >= 4 && th != curr_thread) {
+ rb_raise(rb_eSecurityError, "Insecure: thread locals");
+ }
+ if (!th->locals) return Qnil;
+ if (st_lookup(th->locals, id, &val)) {
+ return val;
+ }
+ return Qnil;
+}
+
+static VALUE
+rb_thread_aref(thread, id)
+ VALUE thread, id;
+{
+ return rb_thread_local_aref(thread, rb_to_id(id));
+}
+
+VALUE
+rb_thread_local_aset(thread, id, val)
+ VALUE thread;
+ ID id;
+ VALUE val;
+{
+ rb_thread_t th = rb_thread_check(thread);
+
+ if (rb_safe_level() >= 4 && th != curr_thread) {
+ rb_raise(rb_eSecurityError, "Insecure: can't modify thread locals");
+ }
+ if (OBJ_FROZEN(thread)) rb_error_frozen("thread locals");
+
+ if (!th->locals) {
+ th->locals = st_init_numtable();
+ }
+ if (NIL_P(val)) {
+ st_delete(th->locals, &id, 0);
+ return Qnil;
+ }
+ st_insert(th->locals, id, val);
+
+ return val;
+}
+
+static VALUE
+rb_thread_aset(thread, id, val)
+ VALUE thread, id, val;
+{
+ return rb_thread_local_aset(thread, rb_to_id(id), val);
+}
+
+static VALUE
+rb_thread_key_p(thread, id)
+ VALUE thread, id;
+{
+ rb_thread_t th = rb_thread_check(thread);
+
+ if (!th->locals) return Qfalse;
+ if (st_lookup(th->locals, rb_to_id(id), 0))
+ return Qtrue;
+ return Qfalse;
+}
+
+static VALUE
+rb_thread_inspect(thread)
+ VALUE thread;
+{
+ char *cname = rb_class2name(CLASS_OF(thread));
+ rb_thread_t th = rb_thread_check(thread);
+ char *status;
+ VALUE str;
+
+ switch (th->status) {
+ case THREAD_RUNNABLE:
+ status = "run"; break;
+ case THREAD_STOPPED:
+ status = "sleep"; break;
+ case THREAD_TO_KILL:
+ status = "aborting"; break;
+ case THREAD_KILLED:
+ status = "dead"; break;
+ default:
+ status = "unknown"; break;
+ }
+ str = rb_str_new(0, strlen(cname)+7+16+9+1); /* 7:tags 16:addr 9:status 1:nul */
+ sprintf(RSTRING(str)->ptr, "#<%s:0x%lx %s>", cname, thread, status);
+ RSTRING(str)->len = strlen(RSTRING(str)->ptr);
+ OBJ_INFECT(str, thread);
+
+ return str;
+}
+
+void
+rb_thread_atfork()
+{
+#if 0 /* enable on 1.7 */
+ rb_thread_t th;
+
+ if (rb_thread_alone()) return;
+ FOREACH_THREAD(th) {
+ if (th != curr_thread) {
+ th->status = THREAD_KILLED;
+ }
+ }
+ END_FOREACH(th);
+ main_thread = curr_thread;
+ curr_thread->next = curr_thread;
+ curr_thread->prev = curr_thread;
+#endif
+}
+
+static VALUE rb_cCont;
+
+static VALUE
+rb_callcc(self)
+ VALUE self;
+{
+ volatile VALUE cont;
+ rb_thread_t th;
+ struct tag *tag;
+ struct RVarmap *vars;
+
+ THREAD_ALLOC(th);
+ cont = Data_Wrap_Struct(rb_cCont, thread_mark, thread_free, th);
+
+ scope_dup(ruby_scope);
+ for (tag=prot_tag; tag; tag=tag->prev) {
+ scope_dup(tag->scope);
+ }
+ if (ruby_block) {
+ struct BLOCK *block = ruby_block;
+
+ while (block) {
+ block->tag->flags |= BLOCK_DYNAMIC;
+ block = block->prev;
}
- if (rb_provided(feature)) return TRUE; /* no need to load */
}
+ th->thread = curr_thread->thread;
- loading_thread = curr_thread;
- loading_nest++;
+ for (vars = th->dyna_vars; vars; vars = vars->next) {
+ if (FL_TEST(vars, DVAR_DONT_RECYCLE)) break;
+ FL_SET(vars, DVAR_DONT_RECYCLE);
+ }
- return FALSE;
+ if (THREAD_SAVE_CONTEXT(th)) {
+ return th->result;
+ }
+ else {
+ return rb_yield(cont);
+ }
}
-static void
-thread_loading_done()
+static VALUE
+rb_cont_call(argc, argv, cont)
+ int argc;
+ VALUE *argv;
+ VALUE cont;
+{
+ rb_thread_t th = rb_thread_check(cont);
+
+ if (th->thread != curr_thread->thread) {
+ rb_raise(rb_eRuntimeError, "continuation called across threads");
+ }
+ switch (argc) {
+ case 0:
+ th->result = Qnil;
+ break;
+ case 1:
+ th->result = *argv;
+ break;
+ default:
+ th->result = rb_ary_new4(argc, argv);
+ break;
+ }
+
+ rb_thread_restore_context(th, RESTORE_NORMAL);
+ return Qnil;
+}
+
+struct thgroup {
+ int gid;
+};
+
+static VALUE
+thgroup_s_new(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
{
- if (--loading_nest == 0) {
- loading_thread = 0;
+ VALUE group;
+ struct thgroup *data;
+ static int serial = 1;
+
+ group = Data_Make_Struct(klass, struct thgroup, 0, free, data);
+ data->gid = serial++;
+
+ rb_obj_call_init(group, argc, argv);
+ return group;
+}
+
+static VALUE
+thgroup_list(group)
+ VALUE group;
+{
+ struct thgroup *data;
+ rb_thread_t th;
+ VALUE ary;
+
+ Data_Get_Struct(group, struct thgroup, data);
+ ary = rb_ary_new();
+
+ FOREACH_THREAD(th) {
+ if (th->gid == data->gid) {
+ rb_ary_push(ary, th->thread);
+ }
}
+ END_FOREACH(th);
+
+ return ary;
+}
+
+static VALUE
+thgroup_add(group, thread)
+ VALUE group, thread;
+{
+ rb_thread_t th;
+ struct thgroup *data;
+
+ rb_secure(4);
+ th = rb_thread_check(thread);
+ Data_Get_Struct(group, struct thgroup, data);
+
+ th->gid = data->gid;
+ return group;
}
void
Init_Thread()
{
- eThreadError = rb_define_class("ThreadError", eException);
- cThread = rb_define_class("Thread", cObject);
+ VALUE cThGroup;
- rb_define_singleton_method(cThread, "new", thread_start, 0);
- rb_define_singleton_method(cThread, "start", thread_start, 0);
- rb_define_singleton_method(cThread, "fork", thread_start, 0);
+ rb_eThreadError = rb_define_class("ThreadError", rb_eStandardError);
+ rb_cThread = rb_define_class("Thread", rb_cObject);
- rb_define_singleton_method(cThread, "stop", thread_stop, 0);
- rb_define_singleton_method(cThread, "kill", thread_s_kill, 1);
- rb_define_singleton_method(cThread, "exit", thread_exit, 0);
- rb_define_singleton_method(cThread, "pass", thread_pass, 0);
- rb_define_singleton_method(cThread, "join", thread_join, 1);
- rb_define_singleton_method(cThread, "current", thread_current, 0);
- rb_define_singleton_method(cThread, "main", thread_main, 0);
+ rb_define_singleton_method(rb_cThread, "new", rb_thread_s_new, -1);
+ rb_define_method(rb_cThread, "initialize", rb_thread_initialize, -2);
+ rb_define_singleton_method(rb_cThread, "start", rb_thread_start, -2);
+ rb_define_singleton_method(rb_cThread, "fork", rb_thread_start, -2);
- rb_define_singleton_method(cThread, "critical", thread_get_critical, 0);
- rb_define_singleton_method(cThread, "critical=", thread_set_critical, 1);
+ rb_define_singleton_method(rb_cThread, "stop", rb_thread_stop, 0);
+ rb_define_singleton_method(rb_cThread, "kill", rb_thread_s_kill, 1);
+ rb_define_singleton_method(rb_cThread, "exit", rb_thread_exit, 0);
+ rb_define_singleton_method(rb_cThread, "pass", rb_thread_pass, 0);
+ rb_define_singleton_method(rb_cThread, "current", rb_thread_current, 0);
+ rb_define_singleton_method(rb_cThread, "main", rb_thread_main, 0);
+ rb_define_singleton_method(rb_cThread, "list", rb_thread_list, 0);
- rb_define_singleton_method(cThread, "abort_on_exception", thread_s_abort_exc, 0);
- rb_define_singleton_method(cThread, "abort_on_exception=", thread_s_abort_exc_set, 1);
+ rb_define_singleton_method(rb_cThread, "critical", rb_thread_critical_get, 0);
+ rb_define_singleton_method(rb_cThread, "critical=", rb_thread_critical_set, 1);
- rb_define_method(cThread, "run", thread_run, 0);
- rb_define_method(cThread, "wakeup", thread_wakeup, 0);
- rb_define_method(cThread, "exit", thread_kill, 0);
- rb_define_method(cThread, "value", thread_value, 0);
- rb_define_method(cThread, "status", thread_status, 0);
- rb_define_method(cThread, "alive?", thread_status, 0);
- rb_define_method(cThread, "stop?", thread_stop_p, 0);
- rb_define_method(cThread, "raise", thread_raise, -1);
+ rb_define_singleton_method(rb_cThread, "abort_on_exception", rb_thread_s_abort_exc, 0);
+ rb_define_singleton_method(rb_cThread, "abort_on_exception=", rb_thread_s_abort_exc_set, 1);
- rb_define_method(cThread, "abort_on_exception", thread_abort_exc, 0);
- rb_define_method(cThread, "abort_on_exception=", thread_abort_exc_set, 1);
+ rb_define_method(rb_cThread, "run", rb_thread_run, 0);
+ rb_define_method(rb_cThread, "wakeup", rb_thread_wakeup, 0);
+ rb_define_method(rb_cThread, "kill", rb_thread_kill, 0);
+ rb_define_method(rb_cThread, "exit", rb_thread_kill, 0);
+ rb_define_method(rb_cThread, "value", rb_thread_value, 0);
+ rb_define_method(rb_cThread, "status", rb_thread_status, 0);
+ rb_define_method(rb_cThread, "join", rb_thread_join, 0);
+ rb_define_method(rb_cThread, "alive?", rb_thread_alive_p, 0);
+ rb_define_method(rb_cThread, "stop?", rb_thread_stop_p, 0);
+ rb_define_method(rb_cThread, "raise", rb_thread_raise_m, -1);
+
+ rb_define_method(rb_cThread, "abort_on_exception", rb_thread_abort_exc, 0);
+ rb_define_method(rb_cThread, "abort_on_exception=", rb_thread_abort_exc_set, 1);
+
+ rb_define_method(rb_cThread, "priority", rb_thread_priority, 0);
+ rb_define_method(rb_cThread, "priority=", rb_thread_priority_set, 1);
+ rb_define_method(rb_cThread, "safe_level", rb_thread_safe_level, 0);
+
+ rb_define_method(rb_cThread, "[]", rb_thread_aref, 1);
+ rb_define_method(rb_cThread, "[]=", rb_thread_aset, 2);
+ rb_define_method(rb_cThread, "key?", rb_thread_key_p, 1);
+
+ rb_define_method(rb_cThread, "inspect", rb_thread_inspect, 0);
/* allocate main thread */
- main_thread = thread_alloc();
+ main_thread = rb_thread_alloc(rb_cThread);
+ curr_thread = main_thread->prev = main_thread->next = main_thread;
+
+ rb_cCont = rb_define_class("Continuation", rb_cObject);
+ rb_undef_method(CLASS_OF(rb_cCont), "new");
+ rb_define_method(rb_cCont, "call", rb_cont_call, -1);
+ rb_define_global_function("callcc", rb_callcc, 0);
+
+ cThGroup = rb_define_class("ThreadGroup", rb_cObject);
+ rb_define_singleton_method(cThGroup, "new", thgroup_s_new, -1);
+ rb_define_method(cThGroup, "list", thgroup_list, 0);
+ rb_define_method(cThGroup, "add", thgroup_add, 1);
+ rb_define_const(cThGroup, "Default", thgroup_s_new(0, 0, cThGroup));
}
-#endif
static VALUE
-f_catch(dmy, tag)
+rb_f_catch(dmy, tag)
VALUE dmy, tag;
{
int state;
@@ -6398,7 +8804,7 @@ f_catch(dmy, tag)
t = rb_to_id(tag);
PUSH_TAG(t);
if ((state = EXEC_TAG()) == 0) {
- val = rb_yield(tag);
+ val = rb_yield_0(tag, 0, 0, 0);
}
else if (state == TAG_THROW && t == prot_tag->dst) {
val = prot_tag->retval;
@@ -6411,7 +8817,23 @@ f_catch(dmy, tag)
}
static VALUE
-f_throw(argc, argv)
+catch_i(tag)
+ ID tag;
+{
+ return rb_funcall(Qnil, rb_intern("catch"), 1, ID2SYM(tag));
+}
+
+VALUE
+rb_catch(tag, proc, data)
+ const char *tag;
+ VALUE (*proc)();
+ VALUE data;
+{
+ return rb_iterate(catch_i, rb_intern(tag), proc, data);
+}
+
+static VALUE
+rb_f_throw(argc, argv)
int argc;
VALUE *argv;
{
@@ -6427,28 +8849,37 @@ f_throw(argc, argv)
tt->dst = t;
break;
}
-#ifdef THREAD
if (tt->tag == PROT_THREAD) {
- Raise(eThreadError, "uncaught throw `%s' in thread 0x%x",
- rb_id2name(t),
- curr_thread);
+ rb_raise(rb_eThreadError, "uncaught throw `%s' in thread 0x%x",
+ rb_id2name(t),
+ curr_thread);
}
-#endif
tt = tt->prev;
}
if (!tt) {
- NameError("uncaught throw `%s'", rb_id2name(t));
+ rb_raise(rb_eNameError, "uncaught throw `%s'", rb_id2name(t));
}
return_value(value);
- trap_restore_mask();
+ rb_trap_restore_mask();
JUMP_TAG(TAG_THROW);
- /* not reached */
+}
+
+void
+rb_throw(tag, val)
+ const char *tag;
+ VALUE val;
+{
+ VALUE argv[2];
+ ID t = rb_intern(tag);
+
+ argv[0] = ID2SYM(t);
+ argv[1] = val;
+ rb_f_throw(2, argv);
}
static void
return_check()
{
-#ifdef THREAD
struct tag *tt = prot_tag;
while (tt) {
@@ -6456,10 +8887,9 @@ return_check()
break;
}
if (tt->tag == PROT_THREAD) {
- Raise(eThreadError, "return from within thread 0x%x",
- curr_thread);
+ rb_raise(rb_eThreadError, "return from within thread 0x%x",
+ curr_thread);
}
tt = tt->prev;
}
-#endif
}
diff --git a/ext/.cvsignore b/ext/.cvsignore
new file mode 100644
index 0000000000..d8b8a61d92
--- /dev/null
+++ b/ext/.cvsignore
@@ -0,0 +1 @@
+extmk.rb
diff --git a/ext/Setup b/ext/Setup
index 9e3a2474c3..039747115f 100644
--- a/ext/Setup
+++ b/ext/Setup
@@ -7,7 +7,9 @@
#fcntl
#kconv
#md5
+#pty
+#sdbm
#socket
-#tkutil
+#tk
#tcltklib
#gtk
diff --git a/ext/Setup.dj b/ext/Setup.dj
index 25adea2035..6c955cba1e 100644
--- a/ext/Setup.dj
+++ b/ext/Setup.dj
@@ -3,10 +3,13 @@ option nodynamic
#GD
#curses
dbm
+gdbm
#etc
fcntl
-kconv
+nkf
marshal
md5
+readline
+sdbm
#socket
#tkutil
diff --git a/ext/Setup.emx b/ext/Setup.emx
new file mode 100644
index 0000000000..dbb4b7a61c
--- /dev/null
+++ b/ext/Setup.emx
@@ -0,0 +1,16 @@
+option nodynamic
+
+#Win32API
+curses
+#dbm
+etc
+fcntl
+#gdbm
+md5
+nkf
+#pty
+#readline
+#sdbm
+socket
+#tcltklib
+#tk
diff --git a/ext/Setup.nt b/ext/Setup.nt
index b469709585..cd7969bb73 100644
--- a/ext/Setup.nt
+++ b/ext/Setup.nt
@@ -1,12 +1,19 @@
-option nodynamic
+#option nodynamic
#GD
+Win32API
#curses
#dbm
#etc
fcntl
-kconv
-#marshal
+#gdbm
+#gtk
+marshal
md5
+nkf
+#pty
+#readline
+sdbm
socket
-#tkutil
+#tcltklib
+#tk
diff --git a/ext/Win32API/Win32API.c b/ext/Win32API/Win32API.c
index f4cb5c726f..0ee28f05ac 100644
--- a/ext/Win32API/Win32API.c
+++ b/ext/Win32API/Win32API.c
@@ -2,9 +2,22 @@
Win32API - Ruby Win32 API Import Facility
*/
+#if !defined _MSC_VER && !defined NT
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
+#endif
+
+#if defined(_MSC_VER)
+#if defined(_M_ALPHA)
+#ifdef __cplusplus
+extern "C" { long __asm(char *,...); };
+#else
+long __asm(char *,...);
+#endif
+#pragma intrinsic(__asm)
+#endif
+#endif
#define _T_VOID 0
#define _T_NUMBER 1
@@ -46,61 +59,89 @@ Win32API_initialize(self, dllname, proc, import, export)
VALUE str;
VALUE a_import;
VALUE *ptr;
+ char *s;
int i;
int len;
int ex;
- hdll = GetModuleHandle(RSTRING(dllname)->ptr);
- if (!hdll) {
- hdll = LoadLibrary(RSTRING(dllname)->ptr);
- if (!hdll)
- Fail("LoadLibrary: %s\n", RSTRING(dllname)->ptr);
- Data_Wrap_Struct(self, 0, Win32API_FreeLibrary, hdll);
- }
+ Check_SafeStr(dllname);
+ Check_SafeStr(proc);
+ hdll = LoadLibrary(RSTRING(dllname)->ptr);
+ if (!hdll)
+ rb_raise(rb_eRuntimeError, "LoadLibrary: %s\n", RSTRING(dllname)->ptr);
+ rb_iv_set(self, "__hdll__", Data_Wrap_Struct(self, 0, Win32API_FreeLibrary, hdll));
hproc = GetProcAddress(hdll, RSTRING(proc)->ptr);
if (!hproc) {
- str = str_new3(proc);
- str = str_cat(str, "A", 1);
+ str = rb_str_new3(proc);
+ str = rb_str_cat(str, "A", 1);
hproc = GetProcAddress(hdll, RSTRING(str)->ptr);
if (!hproc)
- Fail("GetProcAddress: %s or %s\n",
+ rb_raise(rb_eRuntimeError, "GetProcAddress: %s or %s\n",
RSTRING(proc)->ptr, RSTRING(str)->ptr);
}
- rb_iv_set(self, "__dll__", INT2NUM((int)hdll));
+ rb_iv_set(self, "__dll__", UINT2NUM((unsigned long)hdll));
rb_iv_set(self, "__dllname__", dllname);
- rb_iv_set(self, "__proc__", INT2NUM((int)hproc));
-
- a_import = ary_new();
- ptr = RARRAY(import)->ptr;
- for (i = 0, len = RARRAY(import)->len; i < len; i++) {
- int c = *(char *)RSTRING(ptr[i])->ptr;
- switch (c) {
- case 'N': case 'n': case 'L': case 'l':
- ary_push(a_import, INT2FIX(_T_NUMBER));
- break;
- case 'P': case 'p':
- ary_push(a_import, INT2FIX(_T_POINTER));
- break;
- case 'I': case 'i':
- ary_push(a_import, INT2FIX(_T_INTEGER));
- break;
+ rb_iv_set(self, "__proc__", UINT2NUM((unsigned long)hproc));
+
+ a_import = rb_ary_new();
+ switch (TYPE(import)) {
+ case T_NIL:
+ break;
+ case T_ARRAY:
+ ptr = RARRAY(import)->ptr;
+ for (i = 0, len = RARRAY(import)->len; i < len; i++) {
+ Check_SafeStr(ptr[i]);
+ switch (*(char *)RSTRING(ptr[i])->ptr) {
+ case 'N': case 'n': case 'L': case 'l':
+ rb_ary_push(a_import, INT2FIX(_T_NUMBER));
+ break;
+ case 'P': case 'p':
+ rb_ary_push(a_import, INT2FIX(_T_POINTER));
+ break;
+ case 'I': case 'i':
+ rb_ary_push(a_import, INT2FIX(_T_INTEGER));
+ break;
+ }
}
+ break;
+ default:
+ Check_SafeStr(import);
+ s = RSTRING(import)->ptr;
+ for (i = 0, len = RSTRING(import)->len; i < len; i++) {
+ switch (*s++) {
+ case 'N': case 'n': case 'L': case 'l':
+ rb_ary_push(a_import, INT2FIX(_T_NUMBER));
+ break;
+ case 'P': case 'p':
+ rb_ary_push(a_import, INT2FIX(_T_POINTER));
+ break;
+ case 'I': case 'i':
+ rb_ary_push(a_import, INT2FIX(_T_INTEGER));
+ break;
+ }
+ }
+ break;
}
rb_iv_set(self, "__import__", a_import);
- switch (*RSTRING(export)->ptr) {
- case 'V': case 'v':
+ if (NIL_P(export)) {
ex = _T_VOID;
- break;
- case 'N': case 'n': case 'L': case 'l':
- ex = _T_NUMBER;
- break;
- case 'P': case 'p':
- ex = _T_POINTER;
- break;
- case 'I': case 'i':
- ex = _T_INTEGER;
- break;
+ } else {
+ Check_SafeStr(export);
+ switch (*RSTRING(export)->ptr) {
+ case 'V': case 'v':
+ ex = _T_VOID;
+ break;
+ case 'N': case 'n': case 'L': case 'l':
+ ex = _T_NUMBER;
+ break;
+ case 'P': case 'p':
+ ex = _T_POINTER;
+ break;
+ case 'I': case 'i':
+ ex = _T_INTEGER;
+ break;
+ }
}
rb_iv_set(self, "__export__", INT2FIX(ex));
@@ -109,8 +150,8 @@ Win32API_initialize(self, dllname, proc, import, export)
static VALUE
Win32API_Call(argc, argv, obj)
- VALUE argc;
- VALUE argv;
+ int argc;
+ VALUE *argv;
VALUE obj;
{
VALUE args;
@@ -122,7 +163,7 @@ Win32API_Call(argc, argv, obj)
ApiVoid *ApiFunctionVoid;
ApiInteger *ApiFunctionInteger;
- long lParam;
+ long lParam;
char *pParam;
VALUE Return;
@@ -133,53 +174,80 @@ Win32API_Call(argc, argv, obj)
VALUE import_type;
int nimport, timport, texport, i;
int items;
+ int ret;
items = rb_scan_args(argc, argv, "0*", &args);
obj_proc = rb_iv_get(obj, "__proc__");
- ApiFunction = (FARPROC)NUM2INT(obj_proc);
+ ApiFunction = (FARPROC)NUM2ULONG(obj_proc);
obj_import = rb_iv_get(obj, "__import__");
obj_export = rb_iv_get(obj, "__export__");
- nimport = RARRAY(obj_import)->len;
+ nimport = RARRAY(obj_import)->len;
texport = FIX2INT(obj_export);
if (items != nimport)
- Fail("Wrong number of parameters: expected %d, got %d.\n",
+ rb_raise(rb_eRuntimeError, "Wrong number of parameters: expected %d, got %d.\n",
nimport, items);
if (0 < nimport) {
for (i = nimport - 1; 0 <= i; i--) {
VALUE str;
- import_type = ary_entry(obj_import, i);
+ import_type = rb_ary_entry(obj_import, i);
timport = FIX2INT(import_type);
switch (timport) {
case _T_NUMBER:
case _T_INTEGER:
- lParam = NUM2INT(ary_entry(args, i));
+ lParam = NUM2ULONG(rb_ary_entry(args, i));
#if defined(_MSC_VER) || defined(__LCC__)
+#if defined(_M_IX86)
_asm {
mov eax, lParam
push eax
}
-#elif defined(__CYGWIN32__) || defined(__MINGW32__)
+#elif defined(_M_ALPHA)
+ __asm(
+ "ldl r0, 0(%0);"
+ "stq r0, -(sp);"
+ , lParam
+ );
+#else
+#error
+#endif
+#elif defined __GNUC__
asm volatile ("pushl %0" :: "g" (lParam));
#else
#error
#endif
break;
case _T_POINTER:
- str = ary_entry(args, i);
- Check_Type(str, T_STRING);
- str_modify(str);
- pParam = RSTRING(str)->ptr;
+ str = rb_ary_entry(args, i);
+ if (NIL_P(str)) {
+ pParam = 0;
+ } else if (FIXNUM_P(str)){
+ pParam = (char *)NUM2ULONG(str);
+ } else {
+ Check_Type(str, T_STRING);
+ rb_str_modify(str);
+ pParam = RSTRING(str)->ptr;
+ }
#if defined(_MSC_VER) || defined(__LCC__)
+#if defined(_M_IX86)
_asm {
- mov eax, dword ptr pParam
+ mov eax, pParam
push eax
}
-#elif defined(__CYGWIN32__) || defined(__MINGW32__)
+#elif defined(_M_ALPHA)
+ __asm(
+ "ldl r0, 0(%0);"
+ "stq r0, -(sp);"
+ , pParam
+ );
+#else
+#error
+#endif
+#elif defined __GNUC__
asm volatile ("pushl %0" :: "g" (pParam));
#else
#error
@@ -187,9 +255,24 @@ Win32API_Call(argc, argv, obj)
break;
}
}
-
}
+#if defined __GNUC__
+ asm volatile ("call *%1" : "=r" (ret) : "g" (ApiFunction));
+ switch (texport) {
+ case _T_NUMBER:
+ case _T_INTEGER:
+ Return = INT2NUM(ret);
+ break;
+ case _T_POINTER:
+ Return = rb_str_new2((char *)ret);
+ break;
+ case _T_VOID:
+ default:
+ Return = INT2NUM(0);
+ break;
+ }
+#else
switch (texport) {
case _T_NUMBER:
ApiFunctionNumber = (ApiNumber *) ApiFunction;
@@ -197,7 +280,7 @@ Win32API_Call(argc, argv, obj)
break;
case _T_POINTER:
ApiFunctionPointer = (ApiPointer *) ApiFunction;
- Return = str_new2((char *)ApiFunctionPointer());
+ Return = rb_str_new2((char *)ApiFunctionPointer());
break;
case _T_INTEGER:
ApiFunctionInteger = (ApiInteger *) ApiFunction;
@@ -210,13 +293,14 @@ Win32API_Call(argc, argv, obj)
Return = INT2NUM(0);
break;
}
+#endif
return Return;
}
void
Init_Win32API()
{
- VALUE cWin32API = rb_define_class("Win32API", cObject);
+ VALUE cWin32API = rb_define_class("Win32API", rb_cObject);
rb_define_method(cWin32API, "initialize", Win32API_initialize, 4);
rb_define_method(cWin32API, "call", Win32API_Call, -1);
rb_define_alias(cWin32API, "Call", "call");
diff --git a/ext/Win32API/depend b/ext/Win32API/depend
new file mode 100644
index 0000000000..b224bb66c9
--- /dev/null
+++ b/ext/Win32API/depend
@@ -0,0 +1 @@
+Win32API.o : Win32API.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/Win32API/extconf.rb b/ext/Win32API/extconf.rb
index 78b5f6a1e8..5e42f62558 100644
--- a/ext/Win32API/extconf.rb
+++ b/ext/Win32API/extconf.rb
@@ -1,7 +1,7 @@
-if PLATFORM =~ /win32/i
- $:.unshift '../..'
- require 'rbconfig'
- include Config
- $CFLAGS = "-fno-defer-pop" if /gcc/ =~ CONFIG['CC']
+case RUBY_PLATFORM
+when /cygwin/,/mingw/
+ $CFLAGS = "-fno-defer-pop -fno-omit-frame-pointer"
+ create_makefile("Win32API")
+when /win32/
create_makefile("Win32API")
end
diff --git a/ext/aix_ld.rb b/ext/aix_ld.rb
deleted file mode 100644
index 1058977b88..0000000000
--- a/ext/aix_ld.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-#! /usr/local/bin/ruby
-
-def older(file1, file2)
- if !File.exist?(file1) then
- return TRUE
- end
- if !File.exist?(file2) then
- return FALSE
- end
- if File.mtime(file1) < File.mtime(file2)
- return TRUE
- end
- return FALSE
-end
-
-target = ARGV.shift
-unless target =~ /\.so/
- STDERR.printf "wrong suffix specified\n"
- exit 1
-end
-base = File.basename(target, ".so")
-entry="Init_#{base}"
-ldargs = "-e#{entry} -bI:../ruby.imp -bM:SRE -T512 -H512 -lc"
-
-def uniq(data)
- last=nil
- data.delete_if do |name|
- if last == name
- TRUE
- else
- last = name
- FALSE
- end
- end
-end
-
-def extract(nm, out)
- data = nm.readlines.collect{|line|
- line = line.split
- case line[1]
- when "B", "D", "T"
- line[2]
- else
- next
- end
- }.sort!
- uniq(data)
- exp = open(out, "w")
- for line in data
- exp.printf "%s\n", line
- end
- exp.close
- nm.close
-end
-if older("../ruby.imp", "../../miniruby")
-# nm = open("|/usr/ccs/bin/nm -Bex ../../*.o")
-# nm = open("|/usr/ccs/bin/nm -Bex ../../*.o")
- nm = open("|nm ../../*.o")
- extract(nm, "../ruby.imp")
-end
-
-objs = Dir["*.o"].join(" ")
-#nm = open("|/usr/ccs/bin/nm -Bex #{objs}")
-nm = open("|nm #{objs}")
-extract(nm, "#{base}.exp")
-
-#system format("/usr/ccs/bin/ld %s %s ",ldargs,ARGV.join(' '))
-#system "/bin/rm -f #{base}.exp"
-#system "chmod o-rwx ${base}.so"
-
-p format("/usr/ccs/bin/ld %s %s ",ldargs,ARGV.join(' '))
-p "/bin/rm -f #{base}.exp"
-p "chmod o-rwx ${base}.so"
diff --git a/ext/aix_mksym.rb b/ext/aix_mksym.rb
new file mode 100644
index 0000000000..7e1af283dc
--- /dev/null
+++ b/ext/aix_mksym.rb
@@ -0,0 +1,33 @@
+
+def uniq(data)
+ last=nil
+ data.delete_if do |name|
+ if last == name
+ TRUE
+ else
+ last = name
+ FALSE
+ end
+ end
+end
+
+def extract(nm, out)
+ data = nm.readlines.collect{|line|
+ line = line.split
+ case line[1]
+ when "B", "D"
+ line[0]
+ else
+ next
+ end
+ }.compact!.sort!
+ uniq(data)
+ exp = open(out, "w")
+ exp.printf "#!\n"
+ for line in data
+ exp.printf "%s\n", line
+ end
+ exp.close
+ nm.close
+end
+extract(open("|/usr/ccs/bin/nm -p ../libruby.a"), "../ruby.imp")
diff --git a/ext/configsub.rb b/ext/configsub.rb
new file mode 100644
index 0000000000..315cdaf868
--- /dev/null
+++ b/ext/configsub.rb
@@ -0,0 +1,32 @@
+#!./miniruby -ps
+
+BEGIN {
+ CONFIG = {}
+
+ VERSION.scan(/(\d+)\.(\d+)\.(\d+)/) do
+ # overridden if config.status has version
+ CONFIG['MAJOR'] = $1
+ CONFIG['MINOR'] = $2
+ CONFIG['TEENY'] = $3
+ end
+
+ File.foreach($config || "config.status") do |$_|
+ next if /^#/
+ if /^s%@(\w+)@%(.*)%g/
+ name = $1
+ val = $2 || ""
+ next if /^(INSTALL|DEFS|configure_input|srcdir)$/ =~ name
+ val.gsub!(/\$\{([^{}]+)\}/) { "$(#{$1})" }
+ CONFIG[name] = val
+ end
+ end
+
+ CONFIG['top_srcdir'] = File.expand_path($srcdir || ".")
+ CONFIG['RUBY_INSTALL_NAME'] = $install_name if $install_name
+ CONFIG['RUBY_SO_NAME'] = $so_name if $so_name
+ $defout = open($output, 'w') if $output
+}
+
+gsub!(/@(\w+)@/) {CONFIG[$1] || $&}
+
+# vi:set sw=2:
diff --git a/ext/curses/.cvsignore b/ext/curses/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/curses/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/curses/MANIFEST b/ext/curses/MANIFEST
index db5e54ffe8..e1a25d962d 100644
--- a/ext/curses/MANIFEST
+++ b/ext/curses/MANIFEST
@@ -1,5 +1,6 @@
MANIFEST
curses.c
+depend
extconf.rb
hello.rb
rain.rb
diff --git a/ext/curses/curses.c b/ext/curses/curses.c
index 4c29202277..4a8c46f483 100644
--- a/ext/curses/curses.c
+++ b/ext/curses/curses.c
@@ -10,18 +10,31 @@
#else
# ifdef HAVE_NCURSES_CURSES_H
# include <ncurses/curses.h>
+#else
+# ifdef HAVE_CURSES_COLR_CURSES_H
+# include <varargs.h>
+# include <curses_colr/curses.h>
# else
# include <curses.h>
-# if defined(__NetBSD__) && !defined(_maxx)
+# if (defined(__bsdi__) || defined(__NetBSD__) || defined(__APPLE__) ) && !defined(_maxx)
# define _maxx maxx
# endif
-# if defined(__NetBSD__) && !defined(_maxy)
+# if (defined(__bsdi__) || defined(__NetBSD__) || defined(__APPLE__)) && !defined(_maxy)
# define _maxy maxy
# endif
+# if (defined(__bsdi__) || defined(__NetBSD__) || defined(__APPLE__)) && !defined(_begx)
+# define _begx begx
+# endif
+# if (defined(__bsdi__) || defined(__NetBSD__) || defined(__APPLE__)) && !defined(_begy)
+# define _begy begy
+# endif
# endif
#endif
+#endif
+#include "stdio.h"
#include "ruby.h"
+#include "rubyio.h"
static VALUE mCurses;
static VALUE cWindow;
@@ -35,7 +48,7 @@ struct windata {
static void
no_window()
{
- Fail("already closed window");
+ rb_raise(rb_eRuntimeError, "already closed window");
}
#define GetWINDOW(obj, winp) {\
@@ -63,7 +76,7 @@ prep_window(class, window)
struct windata *winp;
if (window == NULL) {
- Fail("failed to create window");
+ rb_raise(rb_eRuntimeError, "failed to create window");
}
obj = Data_Make_Struct(class, struct windata, 0, free_window, winp);
@@ -80,7 +93,7 @@ curses_init_screen()
{
initscr();
if (stdscr == 0) {
- Fail("cannot initialize curses");
+ rb_raise(rb_eRuntimeError, "cannot initialize curses");
}
clear();
rb_stdscr = prep_window(cWindow, stdscr);
@@ -123,9 +136,9 @@ curses_closed()
{
#ifdef HAVE_ISENDWIN
if (isendwin()) {
- return TRUE;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
#else
rb_notimplement();
#endif
@@ -149,12 +162,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;
}
@@ -246,7 +263,9 @@ static VALUE
curses_flash(obj)
VALUE obj;
{
+#ifdef HAVE_FLASH
flash();
+#endif
return Qnil;
}
@@ -327,7 +346,9 @@ curses_addstr(obj, str)
VALUE obj;
VALUE str;
{
- addstr(STR2CSTR(str));
+ if (!NIL_P(str)) {
+ addstr(STR2CSTR(str));
+ }
return Qnil;
}
@@ -336,6 +357,7 @@ static VALUE
curses_getch(obj)
VALUE obj;
{
+ rb_read_check(stdin);
return CHR2FIX(getch());
}
@@ -345,8 +367,10 @@ curses_getstr(obj)
VALUE obj;
{
char rtn[1024]; /* This should be big enough.. I hope */
+
+ rb_read_check(stdin);
getstr(rtn);
- return str_taint(str_new2(rtn));
+ return rb_tainted_str_new2(rtn);
}
/* def delch */
@@ -363,7 +387,9 @@ static VALUE
curses_deleteln(obj)
VALUE obj;
{
+#ifdef HAVE_DELETELN
deleteln();
+#endif
return Qnil;
}
@@ -381,42 +407,48 @@ curses_cols()
/*-------------------------- class Window --------------------------*/
-/* def new(lines, cols, top, left) */
+/* def new(h, w, top, left) */
static VALUE
-window_s_new(class, lines, cols, top, left)
+window_s_new(class, h, w, top, left)
VALUE class;
- VALUE lines;
- VALUE cols;
+ VALUE h;
+ VALUE w;
VALUE top;
VALUE left;
{
- VALUE w;
+ VALUE win;
WINDOW *window;
+ VALUE args[4];
- window = newwin(NUM2INT(lines), NUM2INT(cols), NUM2INT(top), NUM2INT(left));
+ window = newwin(NUM2INT(h), NUM2INT(w), NUM2INT(top), NUM2INT(left));
wclear(window);
- w = prep_window(class, window);
- obj_call_init(w);
+ win = prep_window(class, window);
+ args[0] = h; args[1] = w; args[2] = top; args[3] = left;
- return w;
+ return win;
}
-/* def subwin(lines, cols, top, left) */
+/* def subwin(h, w, top, left) */
static VALUE
-window_subwin(obj, lines, cols, top, left)
+window_subwin(obj, h, w, top, left)
VALUE obj;
- VALUE lines;
- VALUE cols;
+ VALUE h;
+ VALUE w;
VALUE top;
VALUE left;
{
struct windata *winp;
WINDOW *window;
+ VALUE win;
+ VALUE args[4];
GetWINDOW(obj, winp);
- window = subwin(winp->window, NUM2INT(lines), NUM2INT(cols),
+ window = subwin(winp->window, NUM2INT(h), NUM2INT(w),
NUM2INT(top), NUM2INT(left));
- return prep_window(cWindow, window);
+ win = prep_window(cWindow, window);
+ args[0] = h; args[1] = w; args[2] = top; args[3] = left;
+
+ return win;
}
/* def close */
@@ -675,11 +707,12 @@ window_addstr(obj, str)
VALUE obj;
VALUE str;
{
- struct windata *winp;
-
- GetWINDOW(obj, winp);
- waddstr(winp->window, STR2CSTR(str));
-
+ if (!NIL_P(str)) {
+ struct windata *winp;
+
+ GetWINDOW(obj, winp);
+ waddstr(winp->window, STR2CSTR(str));
+ }
return Qnil;
}
@@ -700,6 +733,7 @@ window_getch(obj)
{
struct windata *winp;
+ rb_read_check(stdin);
GetWINDOW(obj, winp);
return CHR2FIX(wgetch(winp->window));
}
@@ -713,8 +747,9 @@ window_getstr(obj)
char rtn[1024]; /* This should be big enough.. I hope */
GetWINDOW(obj, winp);
+ rb_read_check(stdin);
wgetstr(winp->window, rtn);
- return str_taint(str_new2(rtn));
+ return rb_tainted_str_new2(rtn);
}
/* def delch */
@@ -734,10 +769,12 @@ static VALUE
window_deleteln(obj)
VALUE obj;
{
+#ifdef HAVE_WDELETELN
struct windata *winp;
GetWINDOW(obj, winp);
wdeleteln(winp->window);
+#endif
return Qnil;
}
@@ -780,7 +817,7 @@ Init_curses()
rb_define_module_function(mCurses, "lines", curses_lines, 0);
rb_define_module_function(mCurses, "cols", curses_cols, 0);
- cWindow = rb_define_class_under(mCurses, "Window", cObject);
+ cWindow = rb_define_class_under(mCurses, "Window", rb_cObject);
rb_define_singleton_method(cWindow, "new", window_s_new, 4);
rb_define_method(cWindow, "subwin", window_subwin, 4);
rb_define_method(cWindow, "close", window_close, 0);
diff --git a/ext/curses/depend b/ext/curses/depend
new file mode 100644
index 0000000000..ecb79e512d
--- /dev/null
+++ b/ext/curses/depend
@@ -0,0 +1 @@
+curses.o: curses.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/curses/extconf.rb b/ext/curses/extconf.rb
index 9b28437843..c16ab00f28 100644
--- a/ext/curses/extconf.rb
+++ b/ext/curses/extconf.rb
@@ -1,20 +1,26 @@
-$CFLAGS="-I/usr/include/ncurses -I/usr/local/include/ncurses"
-$LDFLAGS="-L/usr/local/lib"
-make=FALSE
+require 'mkmf'
+
+dir_config('curses')
+dir_config('ncurses')
+dir_config('termcap')
+
+make=false
+have_library("mytinfo", "tgetent") if /bow/ =~ RUBY_PLATFORM
if have_header("ncurses.h") and have_library("ncurses", "initscr")
- make=TRUE
+ make=true
elsif have_header("ncurses/curses.h") and have_library("ncurses", "initscr")
- make=TRUE
+ make=true
+elsif have_header("curses_colr/curses.h") and have_library("cur_colr", "initscr")
+ make=true
else
- $CFLAGS=nil
have_library("termcap", "tgetent")
if have_library("curses", "initscr")
- make=TRUE
+ make=true
end
end
-if make then
- for f in ["isendwin", "ungetch", "beep"]
+if make
+ for f in %w(isendwin ungetch beep doupdate flash deleteln wdeleteln)
have_func(f)
end
create_makefile("curses")
diff --git a/ext/cygwin32_ld.rb b/ext/cygwin32_ld.rb
deleted file mode 100644
index a9c8e21cb0..0000000000
--- a/ext/cygwin32_ld.rb
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/usr/local/bin/ruby
-require '../../rbconfig'
-include Config
-
-args = ARGV.join(" ")
-
-objs = []
-flags = []
-libname = ''
-Init = "../init"
-
-path = ''
-
-def writeInit
- out = open("#{Init}.c", "w")
-
- out.print %q@
-#include <windows.h>
-#include <stdio.h>
-
-extern struct _reent *__imp_reent_data;
-WINAPI dll_entry(int a, int b, int c)
-{
- _impure_ptr =__imp_reent_data;
- return 1;
-}
-main(){}
-//void impure_setup(struct _reent *_impure_ptrMain)
-//{
-// _impure_ptr =__imp_reent_data;
-//}
-@
- out.close
-end
-
-def xsystem cmd
- print cmd, "\n"
- system cmd
-end
-
-if args =~ /-o (\w+)\.dll/i
- libname = $1
- # Check for path:
- if libname =~ /(\w+\/)(\w+)$/
- path = $1
- libname = $2
- end
- for arg in ARGV
- case arg
- when /\.[oa]$/i
- objs.push(arg)
- when /-o/, /\w+\.dll/i
- ;
- else
- flags << arg
- end
- end
-
- writeInit unless FileTest.exist?("#{Init}.c")
- unless FileTest.exist?("#{Init}.o") and
- File.mtime("#{Init}.c") < File.mtime("#{Init}.o")
- xsystem "gcc -c #{Init}.c -o #{Init}.o"
- end
-
- command = "echo EXPORTS > #{libname}.def"
- xsystem command
-# xsystem "echo impure_setup >> #{libname}.def"
- xsystem "nm --extern-only " + objs.join(" ") +
- " | sed -n '/^........ [CDT] _/s///p' >> #{libname}.def"
-
- command = "gcc -nostdlib -o junk.o -Wl,--base-file,#{libname}.base,--dll " +
- objs.join(" ") + " #{Init}.o "
- command.concat(flags.join(" ") +
- " -Wl,-e,_dll_entry@12 -lcygwin -lkernel32 #{CONFIG['srcdir']}/libruby.a")
- xsystem command
-
- command = "dlltool --as=as --dllname #{libname}.dll --def #{libname}.def --base-file #{libname}.base --output-exp #{libname}.exp"
- xsystem command
-
- command = "gcc -s -nostdlib -o #{libname}.dll -Wl,--dll #{libname}.exp " +
- objs.join(" ") + " #{Init}.o "
- command.concat(flags.join(" ") +
- " -Wl,-e,_dll_entry@12 -lcygwin -lkernel32 #{CONFIG['srcdir']}/libruby.a")
- xsystem command
- File.unlink "junk.o" if FileTest.exist? "junk.o"
-
-else
- # no special processing, just call ld
- xsystem "ld #{args}"
-end
diff --git a/ext/dbm/.cvsignore b/ext/dbm/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/dbm/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c
index 2ecc725ecb..b0446d1060 100644
--- a/ext/dbm/dbm.c
+++ b/ext/dbm/dbm.c
@@ -6,19 +6,23 @@
$Date$
created at: Mon Jan 24 15:59:52 JST 1994
- Copyright (C) 1995-1998 Yukihiro Matsumoto
+ Copyright (C) 1995-2001 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
+#ifdef HAVE_CDEFS_H
+# include <cdefs.h>
+#endif
+#ifdef HAVE_SYS_CDEFS_H
+# include <sys/cdefs.h>
+#endif
#include <ndbm.h>
#include <fcntl.h>
#include <errno.h>
-VALUE cDBM;
-
-extern VALUE mEnumerable;
+VALUE cDBM, rb_eDBMError;
struct dbmdata {
int di_size;
@@ -28,11 +32,12 @@ struct dbmdata {
static void
closed_dbm()
{
- Fail("closed DBM file");
+ rb_raise(rb_eRuntimeError, "closed DBM file");
}
#define GetDBM(obj, dbmp) {\
Data_Get_Struct(obj, struct dbmdata, dbmp);\
+ if (dbmp == 0) closed_dbm();\
if (dbmp->di_dbm == 0) closed_dbm();\
}
@@ -40,21 +45,35 @@ static void
free_dbm(dbmp)
struct dbmdata *dbmp;
{
- if (dbmp->di_dbm) dbm_close(dbmp->di_dbm);
- free(dbmp);
+ if (dbmp) {
+ if (dbmp->di_dbm) dbm_close(dbmp->di_dbm);
+ free(dbmp);
+ }
}
+static VALUE fdbm_close _((VALUE));
+
static VALUE
-fdbm_s_open(argc, argv, class)
+fdbm_s_new(argc, argv, klass)
int argc;
VALUE *argv;
- VALUE class;
+ VALUE klass;
+{
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);
+ rb_obj_call_init(obj, argc, argv);
+ return obj;
+}
+
+static VALUE
+fdbm_initialize(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
{
VALUE file, vmode;
DBM *dbm;
struct dbmdata *dbmp;
int mode;
- VALUE obj;
if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
mode = 0666; /* default value */
@@ -65,25 +84,48 @@ fdbm_s_open(argc, argv, class)
else {
mode = NUM2INT(vmode);
}
+ file = rb_str_to_str(file);
Check_SafeStr(file);
dbm = 0;
- if (mode >= 0)
+ if (mode >= 0) {
dbm = dbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode);
- if (!dbm)
- dbm = dbm_open(RSTRING(file)->ptr, O_RDWR, mode);
- if (!dbm)
- dbm = dbm_open(RSTRING(file)->ptr, O_RDONLY, mode);
+ }
+ if (!dbm) {
+ dbm = dbm_open(RSTRING(file)->ptr, O_RDWR, 0);
+ }
+ if (!dbm) {
+ dbm = dbm_open(RSTRING(file)->ptr, O_RDONLY, 0);
+ }
if (!dbm) {
if (mode == -1) return Qnil;
rb_sys_fail(RSTRING(file)->ptr);
}
- obj = Data_Make_Struct(class,struct dbmdata,0,free_dbm,dbmp);
+ dbmp = ALLOC(struct dbmdata);
+ DATA_PTR(obj) = dbmp;
dbmp->di_dbm = dbm;
dbmp->di_size = -1;
- obj_call_init(obj);
+
+ return obj;
+}
+
+static VALUE
+fdbm_s_open(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);
+
+ if (NIL_P(fdbm_initialize(argc, argv, obj))) {
+ return Qnil;
+ }
+
+ if (rb_block_given_p()) {
+ return rb_ensure(rb_yield, obj, fdbm_close, obj);
+ }
return obj;
}
@@ -94,8 +136,7 @@ fdbm_close(obj)
{
struct dbmdata *dbmp;
- Data_Get_Struct(obj, struct dbmdata, dbmp);
- if (dbmp->di_dbm == 0) closed_dbm();
+ GetDBM(obj, dbmp);
dbm_close(dbmp->di_dbm);
dbmp->di_dbm = 0;
@@ -103,14 +144,14 @@ fdbm_close(obj)
}
static VALUE
-fdbm_fetch(obj, keystr)
- VALUE obj, keystr;
+fdbm_fetch(obj, keystr, ifnone)
+ VALUE obj, keystr, ifnone;
{
datum key, value;
struct dbmdata *dbmp;
DBM *dbm;
- Check_Type(keystr, T_STRING);
+ keystr = rb_str_to_str(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
@@ -118,9 +159,58 @@ fdbm_fetch(obj, keystr)
dbm = dbmp->di_dbm;
value = dbm_fetch(dbm, key);
if (value.dptr == 0) {
- return Qnil;
+ if (ifnone == Qnil && rb_block_given_p())
+ return rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
+ return ifnone;
+ }
+ return rb_tainted_str_new(value.dptr, value.dsize);
+}
+
+static VALUE
+fdbm_aref(obj, keystr)
+ VALUE obj, keystr;
+{
+ return fdbm_fetch(obj, keystr, Qnil);
+}
+
+static VALUE
+fdbm_fetch_m(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE keystr, valstr, ifnone;
+
+ rb_scan_args(argc, argv, "11", &keystr, &ifnone);
+ valstr = fdbm_fetch(obj, keystr, ifnone);
+ if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
+ rb_raise(rb_eIndexError, "key not found");
+
+ return valstr;
+}
+
+static VALUE
+fdbm_index(obj, valstr)
+ VALUE obj, valstr;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ valstr = rb_str_to_str(valstr);
+ val.dptr = RSTRING(valstr)->ptr;
+ val.dsize = RSTRING(valstr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ val = dbm_fetch(dbm, key);
+ if (val.dsize == RSTRING(valstr)->len &&
+ memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0) {
+ return rb_tainted_str_new(key.dptr, key.dsize);
+ }
}
- return str_taint(str_new(value.dptr, value.dsize));
+ return Qnil;
}
static VALUE
@@ -132,9 +222,9 @@ fdbm_indexes(argc, argv, obj)
VALUE new;
int i;
- new = ary_new2(argc);
+ new = rb_ary_new2(argc);
for (i=0; i<argc; i++) {
- ary_push(new, fdbm_fetch(obj, argv[i]));
+ rb_ary_push(new, fdbm_fetch(obj, argv[i]));
}
return new;
@@ -149,7 +239,7 @@ fdbm_delete(obj, keystr)
DBM *dbm;
rb_secure(4);
- Check_Type(keystr, T_STRING);
+ keystr = rb_str_to_str(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
@@ -158,13 +248,13 @@ fdbm_delete(obj, keystr)
value = dbm_fetch(dbm, key);
if (value.dptr == 0) {
- if (iterator_p()) rb_yield(keystr);
+ if (rb_block_given_p()) rb_yield(keystr);
return Qnil;
}
if (dbm_delete(dbm, key)) {
dbmp->di_size = -1;
- Fail("dbm_delete failed");
+ rb_raise(rb_eDBMError, "dbm_delete failed");
}
else if (dbmp->di_size >= 0) {
dbmp->di_size--;
@@ -184,15 +274,16 @@ fdbm_shift(obj)
rb_secure(4);
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
+ dbmp->di_size = -1;
key = dbm_firstkey(dbm);
if (!key.dptr) return Qnil;
val = dbm_fetch(dbm, key);
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
dbm_delete(dbm, key);
- keystr = str_taint(str_new(key.dptr, key.dsize));
- valstr = str_taint(str_new(val.dptr, val.dsize));
- return assoc_new(keystr, valstr);
+ return rb_assoc_new(keystr, valstr);
}
static VALUE
@@ -203,20 +294,35 @@ fdbm_delete_if(obj)
struct dbmdata *dbmp;
DBM *dbm;
VALUE keystr, valstr;
+ VALUE ret, ary = rb_ary_new();
+ int i, status = 0, n;
rb_secure(4);
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
+ n = dbmp->di_size;
+ dbmp->di_size = -1;
+
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
- keystr = str_taint(str_new(key.dptr, key.dsize));
- valstr = str_taint(str_new(val.dptr, val.dsize));
- if (RTEST(rb_yield(assoc_new(keystr, valstr)))) {
- if (dbm_delete(dbm, key)) {
- Fail("dbm_delete failed");
- }
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
+ if (status != 0) goto delete;
+ if (RTEST(ret)) rb_ary_push(ary, keystr);
+ }
+ delete:
+ for (i = 0; i < RARRAY(ary)->len; i++) {
+ keystr = RARRAY(ary)->ptr[i];
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+ if (dbm_delete(dbm, key)) {
+ rb_raise(rb_eDBMError, "dbm_delete failed");
}
}
+ if (status) rb_jump_tag(status);
+ if (n > 0) dbmp->di_size = n - RARRAY(ary)->len;
+
return obj;
}
@@ -232,11 +338,16 @@ fdbm_clear(obj)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
dbmp->di_size = -1;
- for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- if (dbm_delete(dbm, key)) {
- Fail("dbm_delete failed");
- }
+ while (key = dbm_firstkey(dbm), key.dptr) {
+ do {
+ if (dbm_delete(dbm, key)) {
+ rb_raise(rb_eDBMError, "dbm_delete failed");
+ }
+ key = dbm_nextkey(dbm);
+ } while (key.dptr);
}
+ dbmp->di_size = 0;
+
return obj;
}
@@ -248,17 +359,17 @@ fdbm_invert(obj)
struct dbmdata *dbmp;
DBM *dbm;
VALUE keystr, valstr;
- VALUE hash = hash_new();
+ VALUE hash = rb_hash_new();
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
- keystr = str_taint(str_new(key.dptr, key.dsize));
- valstr = str_taint(str_new(val.dptr, val.dsize));
- hash_aset(hash, valstr, keystr);
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ rb_hash_aset(hash, valstr, keystr);
}
- return obj;
+ return hash;
}
static VALUE
@@ -276,7 +387,7 @@ update_i(pair, dbm)
{
Check_Type(pair, T_ARRAY);
if (RARRAY(pair)->len < 2) {
- ArgError("pair must be [key, value]");
+ rb_raise(rb_eArgError, "pair must be [key, value]");
}
fdbm_store(dbm, RARRAY(pair)->ptr[0], RARRAY(pair)->ptr[1]);
return Qnil;
@@ -307,32 +418,25 @@ fdbm_store(obj, keystr, valstr)
struct dbmdata *dbmp;
DBM *dbm;
- if (valstr == Qnil) {
- fdbm_delete(obj, keystr);
- return Qnil;
- }
-
rb_secure(4);
- keystr = obj_as_string(keystr);
+ keystr = rb_obj_as_string(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
- if (NIL_P(valstr)) return fdbm_delete(obj, keystr);
-
- valstr = obj_as_string(valstr);
+ valstr = rb_obj_as_string(valstr);
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
- Data_Get_Struct(obj, struct dbmdata, dbmp);
+ GetDBM(obj, dbmp);
dbmp->di_size = -1;
dbm = dbmp->di_dbm;
if (dbm_store(dbm, key, val, DBM_REPLACE)) {
-#ifdef HAVE_DBM_CLAERERR
+#ifdef HAVE_DBM_CLEARERR
dbm_clearerr(dbm);
#endif
- if (errno == EPERM) rb_sys_fail(Qnil);
- Fail("dbm_store failed");
+ if (errno == EPERM) rb_sys_fail(0);
+ rb_raise(rb_eDBMError, "dbm_store failed");
}
return valstr;
@@ -347,7 +451,7 @@ fdbm_length(obj)
DBM *dbm;
int i = 0;
- Data_Get_Struct(obj, struct dbmdata, dbmp);
+ GetDBM(obj, dbmp);
if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
dbm = dbmp->di_dbm;
@@ -368,7 +472,7 @@ fdbm_empty_p(obj)
DBM *dbm;
int i = 0;
- Data_Get_Struct(obj, struct dbmdata, dbmp);
+ GetDBM(obj, dbmp);
if (dbmp->di_size < 0) {
dbm = dbmp->di_dbm;
@@ -379,8 +483,8 @@ fdbm_empty_p(obj)
else {
i = dbmp->di_size;
}
- if (i == 0) return TRUE;
- return FALSE;
+ if (i == 0) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -395,7 +499,7 @@ fdbm_each_value(obj)
dbm = dbmp->di_dbm;
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
- rb_yield(str_taint(str_new(val.dptr, val.dsize)));
+ rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
}
return obj;
}
@@ -411,7 +515,7 @@ fdbm_each_key(obj)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- rb_yield(str_taint(str_new(key.dptr, key.dsize)));
+ rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
}
return obj;
}
@@ -430,9 +534,9 @@ fdbm_each_pair(obj)
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
- keystr = str_taint(str_new(key.dptr, key.dsize));
- valstr = str_taint(str_new(val.dptr, val.dsize));
- rb_yield(assoc_new(keystr, valstr));
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ rb_yield(rb_assoc_new(keystr, valstr));
}
return obj;
@@ -450,9 +554,9 @@ fdbm_keys(obj)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- ary = ary_new();
+ ary = rb_ary_new();
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
- ary_push(ary, str_taint(str_new(key.dptr, key.dsize)));
+ rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
}
return ary;
@@ -470,10 +574,10 @@ fdbm_values(obj)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- ary = ary_new();
+ ary = rb_ary_new();
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
- ary_push(ary, str_taint(str_new(val.dptr, val.dsize)));
+ rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
}
return ary;
@@ -487,15 +591,15 @@ fdbm_has_key(obj, keystr)
struct dbmdata *dbmp;
DBM *dbm;
- Check_Type(keystr, T_STRING);
+ keystr = rb_str_to_str(keystr);
key.dptr = RSTRING(keystr)->ptr;
key.dsize = RSTRING(keystr)->len;
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
val = dbm_fetch(dbm, key);
- if (val.dptr) return TRUE;
- return FALSE;
+ if (val.dptr) return Qtrue;
+ return Qfalse;
}
static VALUE
@@ -506,7 +610,7 @@ fdbm_has_value(obj, valstr)
struct dbmdata *dbmp;
DBM *dbm;
- Check_Type(valstr, T_STRING);
+ valstr = rb_str_to_str(valstr);
val.dptr = RSTRING(valstr)->ptr;
val.dsize = RSTRING(valstr)->len;
@@ -516,9 +620,9 @@ fdbm_has_value(obj, valstr)
val = dbm_fetch(dbm, key);
if (val.dsize == RSTRING(valstr)->len &&
memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
- return TRUE;
+ return Qtrue;
}
- return FALSE;
+ return Qfalse;
}
static VALUE
@@ -533,26 +637,62 @@ fdbm_to_a(obj)
GetDBM(obj, dbmp);
dbm = dbmp->di_dbm;
- ary = ary_new();
+ ary = rb_ary_new();
for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
val = dbm_fetch(dbm, key);
- ary_push(ary, assoc_new(str_taint(str_new(key.dptr, key.dsize)),
- str_taint(str_new(val.dptr, val.dsize))));
+ rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
+ rb_tainted_str_new(val.dptr, val.dsize)));
}
return ary;
}
+static VALUE
+fdbm_to_hash(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE hash;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ hash = rb_hash_new();
+ for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
+ val = dbm_fetch(dbm, key);
+ rb_hash_aset(hash, rb_tainted_str_new(key.dptr, key.dsize),
+ rb_tainted_str_new(val.dptr, val.dsize));
+ }
+
+ return hash;
+}
+
+static VALUE
+fdbm_reject(obj)
+ VALUE obj;
+{
+ return rb_hash_delete_if(fdbm_to_hash(obj));
+}
+
+void
Init_dbm()
{
- cDBM = rb_define_class("DBM", cObject);
- rb_include_module(cDBM, mEnumerable);
+ cDBM = rb_define_class("DBM", rb_cObject);
+ rb_eDBMError = rb_define_class("DBMError", rb_eStandardError);
+ rb_include_module(cDBM, rb_mEnumerable);
+ rb_define_singleton_method(cDBM, "new", fdbm_s_new, -1);
rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1);
- rb_define_singleton_method(cDBM, "new", fdbm_s_open, -1);
+
+ rb_define_method(cDBM, "initialize", fdbm_initialize, -1);
rb_define_method(cDBM, "close", fdbm_close, 0);
- rb_define_method(cDBM, "[]", fdbm_fetch, 1);
+ rb_define_method(cDBM, "[]", fdbm_aref, 1);
+ rb_define_method(cDBM, "fetch", fdbm_fetch_m, -1);
rb_define_method(cDBM, "[]=", fdbm_store, 2);
+ rb_define_method(cDBM, "store", fdbm_store, 2);
+ rb_define_method(cDBM, "index", fdbm_index, 1);
rb_define_method(cDBM, "indexes", fdbm_indexes, -1);
rb_define_method(cDBM, "indices", fdbm_indexes, -1);
rb_define_method(cDBM, "length", fdbm_length, 0);
@@ -564,9 +704,11 @@ Init_dbm()
rb_define_method(cDBM, "each_pair", fdbm_each_pair, 0);
rb_define_method(cDBM, "keys", fdbm_keys, 0);
rb_define_method(cDBM, "values", fdbm_values, 0);
- rb_define_method(cDBM, "shift", fdbm_shift, 1);
+ rb_define_method(cDBM, "shift", fdbm_shift, 0);
rb_define_method(cDBM, "delete", fdbm_delete, 1);
rb_define_method(cDBM, "delete_if", fdbm_delete_if, 0);
+ rb_define_method(cDBM, "reject!", fdbm_delete_if, 0);
+ rb_define_method(cDBM, "reject", fdbm_reject, 0);
rb_define_method(cDBM, "clear", fdbm_clear, 0);
rb_define_method(cDBM,"invert", fdbm_invert, 0);
rb_define_method(cDBM,"update", fdbm_update, 1);
@@ -574,9 +716,11 @@ Init_dbm()
rb_define_method(cDBM, "include?", fdbm_has_key, 1);
rb_define_method(cDBM, "has_key?", fdbm_has_key, 1);
+ rb_define_method(cDBM, "member?", fdbm_has_key, 1);
rb_define_method(cDBM, "has_value?", fdbm_has_value, 1);
rb_define_method(cDBM, "key?", fdbm_has_key, 1);
rb_define_method(cDBM, "value?", fdbm_has_value, 1);
rb_define_method(cDBM, "to_a", fdbm_to_a, 0);
+ rb_define_method(cDBM, "to_hash", fdbm_to_hash, 0);
}
diff --git a/ext/dbm/depend b/ext/dbm/depend
index d7f1f419d4..5fae80b096 100644
--- a/ext/dbm/depend
+++ b/ext/dbm/depend
@@ -1 +1 @@
-dbm.o: dbm.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
+dbm.o: dbm.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/dbm/extconf.rb b/ext/dbm/extconf.rb
index 595640737d..9ce235a2b5 100644
--- a/ext/dbm/extconf.rb
+++ b/ext/dbm/extconf.rb
@@ -1,6 +1,13 @@
-$LDFLAGS = "-L/usr/local/lib"
-have_library("gdbm", "dbm_open") or have_library("dbm", "dbm_open")
-if have_func("dbm_open")
- have_func("dbm_clearerr")
+require 'mkmf'
+
+dir_config("dbm")
+if have_library("gdbm", "dbm_open")
+ gdbm = true
+end
+gdbm or have_library("db", "dbm_open") or have_library("dbm", "dbm_open")
+have_header("cdefs.h")
+have_header("sys/cdefs.h")
+if have_header("ndbm.h") and have_func("dbm_open")
+ have_func("dbm_clearerr") unless gdbm
create_makefile("dbm")
end
diff --git a/ext/etc/.cvsignore b/ext/etc/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/etc/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/etc/MANIFEST b/ext/etc/MANIFEST
index a0f521b386..79fb1ff34c 100644
--- a/ext/etc/MANIFEST
+++ b/ext/etc/MANIFEST
@@ -1,5 +1,6 @@
MANIFEST
etc.c
-etc.doc
+etc.txt
+etc.txt.jp
depend
extconf.rb
diff --git a/ext/etc/depend b/ext/etc/depend
index fb3318a0c6..ac706477b0 100644
--- a/ext/etc/depend
+++ b/ext/etc/depend
@@ -1 +1 @@
-etc.o : etc.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
+etc.o : etc.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/etc/etc.c b/ext/etc/etc.c
index 203df635c1..ee0cd529e4 100644
--- a/ext/etc/etc.c
+++ b/ext/etc/etc.c
@@ -10,6 +10,11 @@
#include "ruby.h"
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
#ifdef HAVE_GETPWENT
#include <pwd.h>
#endif
@@ -37,7 +42,7 @@ etc_getlogin(obj)
#endif
if (login)
- return str_new2(login);
+ return rb_tainted_str_new2(login);
return Qnil;
}
@@ -47,34 +52,36 @@ setup_passwd(pwd)
struct passwd *pwd;
{
if (pwd == 0) rb_sys_fail("/etc/passwd");
- return struct_new(sPasswd,
- str_new2(pwd->pw_name),
- str_new2(pwd->pw_passwd),
- INT2FIX(pwd->pw_uid),
- INT2FIX(pwd->pw_gid),
- str_new2(pwd->pw_gecos),
- str_new2(pwd->pw_dir),
- str_new2(pwd->pw_shell),
+ return rb_struct_new(sPasswd,
+ rb_tainted_str_new2(pwd->pw_name),
+ rb_tainted_str_new2(pwd->pw_passwd),
+ INT2FIX(pwd->pw_uid),
+ INT2FIX(pwd->pw_gid),
+#ifdef PW_GECOS
+ rb_tainted_str_new2(pwd->pw_gecos),
+#endif
+ rb_tainted_str_new2(pwd->pw_dir),
+ rb_tainted_str_new2(pwd->pw_shell),
#ifdef PW_CHANGE
- INT2FIX(pwd->pw_change),
+ INT2FIX(pwd->pw_change),
#endif
#ifdef PW_QUOTA
- INT2FIX(pwd->pw_quota),
+ INT2FIX(pwd->pw_quota),
#endif
#ifdef PW_AGE
- INT2FIX(pwd->pw_age),
+ INT2FIX(pwd->pw_age),
#endif
#ifdef PW_CLASS
- str_new2(pwd->pw_class),
+ rb_tainted_str_new2(pwd->pw_class),
#endif
#ifdef PW_COMMENT
- str_new2(pwd->pw_comment),
+ rb_tainted_str_new2(pwd->pw_comment),
#endif
#ifdef PW_EXPIRE
- INT2FIX(pwd->pw_expire),
+ INT2FIX(pwd->pw_expire),
#endif
- 0 /*dummy*/
- );
+ 0 /*dummy*/
+ );
}
#endif
@@ -96,7 +103,7 @@ etc_getpwuid(argc, argv, obj)
uid = getuid();
}
pwd = getpwuid(uid);
- if (pwd == 0) Fail("can't find user for %d", uid);
+ if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %d", uid);
return setup_passwd(pwd);
#else
return Qnil;
@@ -112,7 +119,7 @@ etc_getpwnam(obj, nam)
Check_Type(nam, T_STRING);
pwd = getpwnam(RSTRING(nam)->ptr);
- if (pwd == 0) Fail("can't find user for %s", RSTRING(nam)->ptr);
+ if (pwd == 0) rb_raise(rb_eArgError, "can't find user for %s", RSTRING(nam)->ptr);
return setup_passwd(pwd);
#else
return Qnil;
@@ -123,10 +130,10 @@ static VALUE
etc_passwd(obj)
VALUE obj;
{
-#if defined(HAVE_GETPWENT)
+#ifdef HAVE_GETPWENT
struct passwd *pw;
- if (iterator_p()) {
+ if (rb_block_given_p()) {
setpwent();
while (pw = getpwent()) {
rb_yield(setup_passwd(pw));
@@ -134,12 +141,11 @@ etc_passwd(obj)
endpwent();
return obj;
}
- pw = getpwent();
- if (pw == 0) Fail("can't fetch next -- /etc/passwd");
- return setup_passwd(pw);
-#else
- return Qnil;
+ if (pw = getpwent()) {
+ return setup_passwd(pw);
+ }
#endif
+ return Qnil;
}
#ifdef HAVE_GETGRENT
@@ -150,17 +156,17 @@ setup_group(grp)
VALUE mem;
char **tbl;
- mem = ary_new();
+ mem = rb_ary_new();
tbl = grp->gr_mem;
while (*tbl) {
- ary_push(mem, str_new2(*tbl));
+ rb_ary_push(mem, rb_tainted_str_new2(*tbl));
tbl++;
}
- return struct_new(sGroup,
- str_new2(grp->gr_name),
- str_new2(grp->gr_passwd),
- INT2FIX(grp->gr_gid),
- mem);
+ return rb_struct_new(sGroup,
+ rb_tainted_str_new2(grp->gr_name),
+ rb_tainted_str_new2(grp->gr_passwd),
+ INT2FIX(grp->gr_gid),
+ mem);
}
#endif
@@ -174,7 +180,7 @@ etc_getgrgid(obj, id)
gid = NUM2INT(id);
grp = getgrgid(gid);
- if (grp == 0) Fail("can't find group for %d", gid);
+ if (grp == 0) rb_raise(rb_eArgError, "can't find group for %d", gid);
return setup_group(grp);
#else
return Qnil;
@@ -190,7 +196,7 @@ etc_getgrnam(obj, nam)
Check_Type(nam, T_STRING);
grp = getgrnam(RSTRING(nam)->ptr);
- if (grp == 0) Fail("can't find group for %s", RSTRING(nam)->ptr);
+ if (grp == 0) rb_raise(rb_eArgError, "can't find group for %s", RSTRING(nam)->ptr);
return setup_group(grp);
#else
return Qnil;
@@ -204,7 +210,7 @@ etc_group(obj)
#ifdef HAVE_GETGRENT
struct group *grp;
- if (iterator_p()) {
+ if (rb_block_given_p()) {
setgrent();
while (grp = getgrent()) {
rb_yield(setup_group(grp));
@@ -212,10 +218,11 @@ etc_group(obj)
endgrent();
return obj;
}
- return setup_group(getgrent());
-#else
- return Qnil;
+ if (grp = getgrent()) {
+ return setup_group(grp);
+ }
#endif
+ return Qnil;
}
static VALUE mEtc;
@@ -235,32 +242,35 @@ Init_etc()
rb_define_module_function(mEtc, "getgrnam", etc_getgrnam, 1);
rb_define_module_function(mEtc, "group", etc_group, 0);
- sPasswd = struct_define("Passwd",
- "name", "passwd", "uid", "gid",
- "gecos", "dir", "shell",
+ sPasswd = rb_struct_define("Passwd",
+ "name", "passwd", "uid", "gid",
+#ifdef PW_GECOS
+ "gecos",
+#endif
+ "dir", "shell",
#ifdef PW_CHANGE
- "change",
+ "change",
#endif
#ifdef PW_QUOTA
- "quota",
+ "quota",
#endif
#ifdef PW_AGE
- "age",
+ "age",
#endif
#ifdef PW_CLASS
- "class",
+ "class",
#endif
#ifdef PW_COMMENT
- "comment",
+ "comment",
#endif
#ifdef PW_EXPIRE
- "expire",
+ "expire",
#endif
- 0);
+ 0);
rb_global_variable(&sPasswd);
#ifdef HAVE_GETGRENT
- sGroup = struct_define("Group", "name", "passwd", "gid", "mem", 0);
+ sGroup = rb_struct_define("Group", "name", "passwd", "gid", "mem", 0);
rb_global_variable(&sGroup);
#endif
}
diff --git a/ext/etc/etc.txt b/ext/etc/etc.txt
new file mode 100644
index 0000000000..9801dc0e02
--- /dev/null
+++ b/ext/etc/etc.txt
@@ -0,0 +1,72 @@
+.\" etc.doc - -*- Indented-Text -*- created at: Fri Jul 14 00:47:15 JST 1995
+
+** Etc(Module)
+
+The module to retrieve information under /etc directory. Available
+only on UNIX platforms. All operations defined in this module are
+module functions, so that you can include Etc module into your class.
+
+Module Function:
+
+ getlogin
+
+ returns login name of the user. It this fails, try getpwuid().
+
+ getpwnam(name)
+
+ searches in /etc/passwd file (or equivalent database), and
+ returns password entry for the user. The return value is an
+ passwd structure, which has members described below.
+
+ struct passwd
+ name # user name(string)
+ passwd # encrypted password(string)
+ uid # user ID(integer)
+ gid # group ID(integer)
+ gecos # gecos field(string)
+ dir # home directory(string)
+ shell # login shell(string)
+ # members below are optional
+ change # password change time(integer)
+ quota # quota value(integer)
+ age # password age(integer)
+ class # user access class(string)
+ comment # comment(string)
+ expire # account expiration time(integer)
+ end
+
+ See getpwnam(3) for detail.
+
+ getpwuid([uid])
+
+ returns passwd entry for the specified user id. If uid is
+ ommitted, use the value from getuid(). See getpwuid(3) for
+ detail.
+
+ getgrgid(gid)
+
+ searches in /etc/group file (or equivalent database), and
+ returns group entry for the group id. The return value is an
+ group structure, which has members described below.
+
+ struct group
+ name # group name(string)
+ passwd # group password(string)
+ gid # group ID(integer)
+ mem # array of the group member names
+ end
+
+ See getgrgid(3) for detail.
+
+ getgrnam(name)
+
+ returns the group entry for the specified name. The return
+ value is the group structure. See getgrnam(3) for detail.
+
+ group
+
+ iterates over all group entries.
+
+ passwd
+
+ iterates over all passwd entries.
diff --git a/ext/etc/etc.doc b/ext/etc/etc.txt.jp
index 2af895c9de..8191f4886b 100644
--- a/ext/etc/etc.doc
+++ b/ext/etc/etc.txt.jp
@@ -5,8 +5,7 @@
/etc¥Ç¥£¥ì¥¯¥È¥ê°Ê²¼¤Î¾ðÊó¤òÆÀ¤ë¤¿¤á¤Î¥â¥¸¥å¡¼¥ë¡¥¥¯¥é¥¹¤Ë¥¤¥ó¥¯¥ë¡¼¥É
¤·¤Æ»È¤¦¤³¤È¤â¤Ç¤­¤ë¡¥
-Methods:
-Single Methods:
+Module Function:
getlogin
diff --git a/ext/etc/extconf.rb b/ext/etc/extconf.rb
index 884de93ec8..6fe8810464 100644
--- a/ext/etc/extconf.rb
+++ b/ext/etc/extconf.rb
@@ -1,7 +1,31 @@
+require 'mkmf'
+
+def etc_grep_header(field)
+ f = open("conftest.c", "w")
+ f.print <<EOF
+#include <pwd.h>
+EOF
+ f.close
+ begin
+ if xsystem("#{CPP} | egrep #{field}")
+ $defs.push(format("-D%s", field.upcase))
+ end
+ ensure
+ system "rm -f conftest.c"
+ end
+end
+
have_library("sun", "getpwnam") # NIS (== YP) interface for IRIX 4
a = have_func("getlogin")
b = have_func("getpwent")
c = have_func("getgrent")
if a or b or c
+ etc_grep_header("pw_gecos")
+ etc_grep_header("pw_change")
+ etc_grep_header("pw_quota")
+ etc_grep_header("pw_age")
+ etc_grep_header("pw_class")
+ etc_grep_header("pw_comment") unless /cygwin/ === RUBY_PLATFORM
+ etc_grep_header("pw_expire")
create_makefile("etc")
end
diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in
index fbc455840c..9e454cc429 100644
--- a/ext/extmk.rb.in
+++ b/ext/extmk.rb.in
@@ -1,81 +1,91 @@
#! /usr/local/bin/ruby
+# -*- ruby -*-
-$".push 'mkmf.rb' #"
+$".push 'mkmf.rb'
+ORIG_LIBPATH = ENV['LIB']
if ARGV[0] == 'static'
- $force_static = TRUE
+ $force_static = true
ARGV.shift
elsif ARGV[0] == 'install'
- $install = TRUE
+ $install = true
+ $destdir = ARGV[1] || ''
ARGV.shift
elsif ARGV[0] == 'clean'
- $clean = TRUE
+ $clean = "clean"
+ ARGV.shift
+elsif ARGV[0] == 'distclean'
+ $clean = "distclean"
+ ARGV.shift
+elsif ARGV[0] == 'realclean'
+ $clean = "realclean"
ARGV.shift
end
+SRC_EXT = ["c", "cc", "m", "cxx", "cpp", "C"]
$extlist = []
-$cache_mod = FALSE;
-$lib_cache = {}
-$func_cache = {}
-$hdr_cache = {}
-$topdir = "@top_srcdir@"
-if $topdir !~ "^/"
+$includedir = "@includedir@".gsub(/\$\{prefix\}|\$\(prefix\)/,'@prefix@')
+
+$top_srcdir = "@top_srcdir@"
+if $top_srcdir !~ "^/"
# get absolute path
- save = Dir.pwd
- Dir.chdir $topdir
- $topdir = Dir.pwd
- Dir.chdir save
+ $top_srcdir = File.expand_path($top_srcdir)
end
-$dots = if "@INSTALL@" =~ /^\// then "" else "#{$topdir}/ext/" end
-
-if File.exist?("config.cache") then
- f = open("config.cache", "r")
- while f.gets
- case $_
- when /^lib: (.+) (yes|no)/
- $lib_cache[$1] = $2
- when /^func: ([\w_]+) (yes|no)/
- $func_cache[$1] = $2
- when /^hdr: (.+) (yes|no)/
- $hdr_cache[$1] = $2
- end
+# get absolute path
+$topdir = File.expand_path("..")
+
+$:.replace [$top_srcdir, $top_srcdir+"/lib", "."]
+
+require 'find'
+
+def rm_f(*files)
+ targets = []
+ for file in files
+ targets.concat Dir[file]
+ end
+ if not targets.empty?
+ File::chmod 0777, *targets
+ File::unlink *targets
end
- f.close
end
def older(file1, file2)
if !File.exist?(file1) then
- return TRUE
+ return true
end
if !File.exist?(file2) then
- return FALSE
+ return false
end
if File.mtime(file1) < File.mtime(file2)
- return TRUE
+ return true
end
- return FALSE
+ return false
end
-if PLATFORM == "m68k-human"
-CFLAGS = "@CFLAGS@".gsub(/-c..-stack=[0-9]+ */, '')
-LINK = "@CC@ -o conftest -I#{$topdir} " + CFLAGS + " %s @LDFLAGS@ %s conftest.c @LIBS@ %s"
-CPP = "@CPP@ @CPPFLAGS@ -I#{$topdir} " + CFLAGS + " %s conftest.c"
+if RUBY_PLATFORM == "m68k-human"
+ CFLAGS = "@CFLAGS@".gsub(/-c..-stack=[0-9]+ */, '')
else
-CFLAGS = "@CFLAGS@"
-LINK = "@CC@ -o conftest -I#{$topdir} " + CFLAGS + " %s @LDFLAGS@ %s conftest.c %s"
-CPP = "@CPP@ @CPPFLAGS@ -I#{$topdir} " + CFLAGS + " %s conftest.c"
+ CFLAGS = "@CFLAGS@"
end
+LINK = "@CC@ -o conftest -I#$topdir -I#$top_srcdir #{CFLAGS} -I#$includedir @LDFLAGS@ %s %s %s conftest.c %s %s @LIBS@"
+CPP = "@CPP@ @CPPFLAGS@ -I#$topdir -I#$top_srcdir #{CFLAGS} -I#$includedir %s %s %s conftest.c"
-if /win32|djgpp|mingw32/i =~ PLATFORM
- $null = open("nul", "w")
+if FileTest.readable? 'nul'
+ $null = open('nul', 'w')
+elsif FileTest.readable? '/dev/null'
+ $null = open('/dev/null', 'w')
else
- $null = open("/dev/null", "w")
+ $null = open('test.log', 'w')
end
$orgerr = $stderr.dup
$orgout = $stdout.dup
def xsystem command
+ if $DEBUG
+ puts command
+ return system(command)
+ end
$stderr.reopen($null)
$stdout.reopen($null)
r = system(command)
@@ -84,123 +94,231 @@ def xsystem command
return r
end
-def try_link(libs)
- xsystem(format(LINK, $CFLAGS, $LDFLAGS, libs))
+def try_link0(src, opt="")
+ cfile = open("conftest.c", "w")
+ cfile.print src
+ cfile.close
+ ldflags = $LDFLAGS
+ if /mswin32/ =~ RUBY_PLATFORM and !$LIBPATH.empty?
+ ENV['LIB'] = ($LIBPATH + [ORIG_LIBPATH]).compact.join(';')
+ else
+ $LDFLAGS = ldflags.dup
+ $LIBPATH.each {|d| $LDFLAGS << " -L" + d}
+ end
+ begin
+ xsystem(format(LINK, $CFLAGS, $CPPFLAGS, $LDFLAGS, opt, $LOCAL_LIBS))
+ ensure
+ $LDFLAGS = ldflags
+ ENV['LIB'] = ORIG_LIBPATH if /mswin32/ =~ RUBY_PLATFORM
+ end
end
-def try_cpp
- xsystem(format(CPP, $CFLAGS))
+def try_link(src, opt="")
+ begin
+ try_link0(src, opt)
+ ensure
+ rm_f "conftest*"
+ end
end
-def have_library(lib, func)
- if $lib_cache[lib]
- if $lib_cache[lib] == "yes"
- if $libs
- $libs = "-l" + lib + " " + $libs
- else
- $libs = "-l" + lib
- end
- return TRUE
- else
- return FALSE
- end
+def try_cpp(src, opt="")
+ cfile = open("conftest.c", "w")
+ cfile.print src
+ cfile.close
+ begin
+ xsystem(format(CPP, $CFLAGS, $CPPFLAGS, opt))
+ ensure
+ rm_f "conftest*"
end
+end
+def egrep_cpp(pat, src, opt="")
cfile = open("conftest.c", "w")
- cfile.printf "\
-int main() { return 0; }
-int t() { %s(); return 0; }
-", func
+ cfile.print src
cfile.close
+ begin
+ xsystem(format(CPP+"|egrep #{pat}", $CFLAGS, $CPPFLAGS, opt))
+ ensure
+ rm_f "conftest*"
+ end
+end
+def try_run(src, opt="")
begin
- if $libs
- libs = "-l" + lib + " " + $libs
+ if try_link0(src, opt)
+ if xsystem("./conftest")
+ true
+ else
+ false
+ end
else
- libs = "-l" + lib
- end
- unless try_link(libs)
- $lib_cache[lib] = 'no'
- $cache_mod = TRUE
- return FALSE
+ nil
end
ensure
- system "rm -f conftest*"
+ rm_f "conftest*"
end
+end
- $libs = libs
- $lib_cache[lib] = 'yes'
- $cache_mod = TRUE
- return TRUE
+def install_rb(mfile, srcdir = nil)
+ libdir = "lib"
+ libdir = srcdir + "/" + libdir if srcdir
+ path = []
+ dir = []
+ if File.directory? libdir
+ Find.find(libdir) do |f|
+ next unless /\.rb$/ =~ f
+ f = f[libdir.length+1..-1]
+ path.push f
+ dir |= [File.dirname(f)]
+ end
+ end
+ for f in dir
+ next if f == "."
+ mfile.printf "\t@$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' $(DESTDIR)$(pkglibdir)/%s\n", f
+ end
+ for f in path
+ mfile.printf "\t@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0644, true)' $(srcdir)/lib/%s $(DESTDIR)$(pkglibdir)/%s\n", f, f
+ end
+end
+
+def append_library(libs, lib)
+ if /mswin32/ =~ RUBY_PLATFORM
+ lib + ".lib " + libs
+ else
+ "-l" + lib + " " + libs
+ end
end
-def have_func(func)
- if $func_cache[func]
- if $func_cache[func] == "yes"
- $defs.push(format("-DHAVE_%s", func.upcase))
- return TRUE
+def have_library(lib, func="main")
+ if func && func != ""
+ libs = append_library($libs, lib)
+ if /mswin32|mingw/ =~ RUBY_PLATFORM
+ r = try_link(<<"SRC", libs)
+#include <windows.h>
+#include <winsock.h>
+int main() { return 0; }
+int t() { #{func}(); return 0; }
+SRC
+ unless r
+ r = try_link(<<"SRC", libs)
+#include <windows.h>
+#include <winsock.h>
+int main() { return 0; }
+int t() { void ((*p)()); p = (void ((*)()))#{func}; return 0; }
+SRC
+ end
else
- return FALSE
+ r = try_link(<<"SRC", libs)
+int main() { return 0; }
+int t() { #{func}(); return 0; }
+SRC
+ end
+ unless r
+ return false
end
+ else
+ libs = append_library($libs, lib)
end
- cfile = open("conftest.c", "w")
- cfile.printf "\
-char %s();
+ $libs = libs
+ return true
+end
+
+def find_library(lib, func, *paths)
+ libpath = $LIBPATH
+ libs = append_library($libs, lib)
+ until try_link(<<"SRC", libs)
int main() { return 0; }
-int t() { %s(); return 0; }
-", func, func
- cfile.close
+int t() { #{func}(); return 0; }
+SRC
+ if paths.size == 0
+ $LIBPATH = libpath
+ return false
+ end
+ $LIBPATH = libpath | [paths.shift]
+ end
+ $libs = libs
+ return true
+end
+def have_func(func, header=nil)
libs = $libs
- libs = "" if libs == nil
-
- begin
- unless try_link(libs)
- $func_cache[func] = 'no'
- $cache_mod = TRUE
- return FALSE
+ src =
+ if /mswin32|mingw/ =~ RUBY_PLATFORM
+ r = <<"SRC"
+#include <windows.h>
+#include <winsock.h>
+SRC
+ else
+ ""
end
- ensure
- system "rm -f conftest*"
+ unless header.nil?
+ src << <<"SRC"
+#include <#{header}>
+SRC
+ end
+ r = try_link(src + <<"SRC", libs)
+int main() { return 0; }
+int t() { #{func}(); return 0; }
+SRC
+ unless r
+ r = try_link(src + <<"SRC", libs)
+int main() { return 0; }
+int t() { void ((*p)()); p = (void ((*)()))#{func}; return 0; }
+SRC
+ end
+ unless r
+ return false
end
$defs.push(format("-DHAVE_%s", func.upcase))
- $func_cache[func] = 'yes'
- $cache_mod = TRUE
- return TRUE
+ return true
end
def have_header(header)
- if $hdr_cache[header]
- if $hdr_cache[header] == "yes"
- header.tr!("a-z./\055", "A-Z___")
- $defs.push(format("-DHAVE_%s", header))
- return TRUE
- else
- return FALSE
+ unless try_cpp(<<"SRC")
+#include <#{header}>
+SRC
+ return false
+ end
+ header.tr!("a-z./\055", "A-Z___")
+ $defs.push(format("-DHAVE_%s", header))
+ return true
+end
+
+def arg_config(config, default=nil)
+ unless defined? $configure_args
+ $configure_args = {}
+ args = "@configure_args@"
+ if /mswin32|mingw/ =~ RUBY_PLATFORM and ENV["CONFIGURE_ARGS"]
+ args << " " << ENV["CONFIGURE_ARGS"]
+ end
+ for arg in args.split
+ next unless /^--/ =~ arg
+ if /=/ =~ arg
+ $configure_args[$`] = $'
+ else
+ $configure_args[arg] = true
+ end
end
end
+ $configure_args.fetch(config, default)
+end
- cfile = open("conftest.c", "w")
- cfile.printf "\
-#include <%s>
-", header
- cfile.close
+def with_config(config, default=nil)
+ unless /^--with-/ =~ config
+ config = '--with-' + config
+ end
+ arg_config(config, default)
+end
- begin
- unless try_cpp
- $hdr_cache[header] = 'no'
- $cache_mod = TRUE
- return FALSE
- end
- ensure
- system "rm -f conftest*"
+def enable_config(config, default=nil)
+ if arg_config("--enable-"+config, default)
+ true
+ elsif arg_config("--disable-"+config, false)
+ false
+ else
+ default
end
- $hdr_cache[header] = 'yes'
- header.tr!("a-z./\055", "A-Z___")
- $defs.push(format("-DHAVE_%s", header))
- $cache_mod = TRUE
- return TRUE
end
def create_header()
@@ -214,19 +332,78 @@ def create_header()
end
end
-def create_makefile(target)
+def dir_config(target, idefault=nil, ldefault=nil)
+ if idefault && ldefault == nil
+ default = idefault
+ idefault = default + "/include"
+ ldefault = default + "/lib"
+ end
+
+ dir = with_config(target + "-dir", default)
- if $libs and "@DLEXT@" == "o"
+ idir, ldir = if dir then [
+ dir + "/include",
+ dir + "/lib"
+ ] else [
+ with_config(target + "-include", idefault),
+ with_config(target + "-lib", ldefault)
+ ] end
+
+ if idir
+ idircflag = "-I" + idir
+ $CPPFLAGS += " " + idircflag unless $CPPFLAGS.split.include?(idircflag)
+ end
+
+ if ldir
+ $LIBPATH << ldir unless $LIBPATH.include?(ldir)
+ end
+
+ [idir, ldir]
+end
+
+def create_makefile(target)
+ $target = target
+ if target.rindex(%r!/!)
+ target = $'
+ target_prefix = "/"+$`
+ else
+ target_prefix = ""
+ end
+ rm_f "conftest*"
+ if "@DLEXT@" == $OBJEXT
libs = $libs.split
for lib in libs
- lib.sub!(/-l(.*)/, '"lib\1.a"')
+ lib.sub!(/-l(.*)/, %%"lib\\1.#{$LIBEXT}"%)
end
$defs.push(format("-DEXTLIB='%s'", libs.join(",")))
end
- $libs = "" unless $libs
- $srcdir = $topdir + "/ext/" + target
+ $DLDFLAGS = '@DLDFLAGS@'
+
+ if $configure_args['--enable-shared'] or "@LIBRUBY@" != "@LIBRUBY_A@"
+ $libs = "@LIBRUBYARG@ " + $libs
+ $LIBPATH.unshift $topdir
+ end
+
+ defflag = ''
+ if RUBY_PLATFORM =~ /cygwin|mingw/ and not $static
+ if not File.exist? target + '.def'
+ open(target + '.def', 'wb') do |f|
+ f.print "EXPORTS\n", "Init_", target, "\n"
+ end
+ end
+ defflag = "--def=" + target + ".def"
+ end
+
+ if RUBY_PLATFORM =~ /mswin32/
+ libpath = $LIBPATH.join(';')
+ else
+ $LIBPATH.each {|d| $DLDFLAGS << " -L" << d}
+ end
+
+ $srcdir = $top_srcdir + "/ext/" + $mdir
mfile = open("Makefile", "w")
+ mfile.binmode if /mingw/ =~ RUBY_PLATFORM
mfile.printf "\
SHELL = /bin/sh
@@ -235,108 +412,182 @@ SHELL = /bin/sh
srcdir = #{$srcdir}
VPATH = #{$srcdir}
-hdrdir = #{$topdir}
+topdir = #{$topdir}
+hdrdir = #{$top_srcdir}
CC = @CC@
-CFLAGS = %s -I#{$topdir} %s #$CFLAGS %s
-DLDFLAGS = @DLDFLAGS@ #$LDFLAGS
-LDSHARED = @LDSHARED@
-", if $static then "" else "@CCDLFLAGS@" end, CFLAGS, $defs.join(" ")
+CFLAGS = %s #{CFLAGS} #$CFLAGS
+CPPFLAGS = -I$(topdir) -I$(hdrdir) -I@includedir@ %s #$CPPFLAGS
+DLDFLAGS = #$DLDFLAGS #$LDFLAGS
+LDSHARED = @LDSHARED@ #{defflag}
+", if $static then "" else "@CCDLFLAGS@" end, $defs.join(" ")
+ mfile.puts "LIBPATH = #{libpath}" if libpath
+
+ mfile.puts ".SUFFIXES: .@OBJEXT@" unless "@OBJEXT@" == "o"
mfile.printf "\
-program_transform_name = -e @program_transform_name@
-RUBY_INSTALL_NAME = `t='$(program_transform_name)'; echo ruby | sed $$t`
+RUBY_INSTALL_NAME = @RUBY_INSTALL_NAME@
+RUBY_SO_NAME = @RUBY_SO_NAME@
prefix = @prefix@
exec_prefix = @exec_prefix@
-libdir = @libdir@/$(RUBY_INSTALL_NAME)/@arch@
+libdir = @libdir@
+#pkglibdir = $(libdir)/$(RUBY_INSTALL_NAME)/@MAJOR@.@MINOR@
+pkglibdir = $(libdir)/ruby/@MAJOR@.@MINOR@
+archdir = $(pkglibdir)/@arch@
@SET_MAKE@
#### End of system configuration section. ####
"
- mfile.printf "LOCAL_LIBS = %s\n", $local_libs if $local_libs
+ mfile.printf "LOCAL_LIBS = %s %s\n", $LOCAL_LIBS, $local_flags
mfile.printf "LIBS = %s\n", $libs
mfile.printf "OBJS = "
if !$objs then
$objs = []
- for f in Dir["#{$topdir}/ext/#{target}/*.{c,cc}"]
+ for f in Dir["#{$top_srcdir}/ext/#{$mdir}/*.{#{SRC_EXT.join(%q{,})}}"]
f = File.basename(f)
- f.sub!(/\.(c|cc)$/, ".o")
+ f.sub!(/(#{SRC_EXT.join(%q{|})})$/, $OBJEXT)
$objs.push f
end
+ else
+ for i in $objs
+ i.sub!(/\.o\z/, ".#{$OBJEXT}")
+ end
end
mfile.printf $objs.join(" ")
mfile.printf "\n"
- mfile.printf "\
-TARGET = %s.%s
+ ruby_interpreter = "$(topdir)/miniruby@EXEEXT@"
+ if /nmake/i =~ $make
+ ruby_interpreter = '$(topdir:/=\)\miniruby@EXEEXT@'
+ end
+ if defined? CROSS_COMPILING
+ ruby_interpreter = "@MINIRUBY@"
+ end
-INSTALL = %s@INSTALL@
+ mfile.printf <<EOS
+TARGET = #{target}
+DLLIB = $(TARGET).#{$static ? $LIBEXT : "@DLEXT@"}
-binsuffix = @binsuffix@
+RUBY = #{ruby_interpreter} -I$(topdir) -I$(hdrdir)/lib
+RM = $(RUBY) -r ftools -e "File::rm_f(*Dir[ARGV.join(' ')])"
-all: $(TARGET)
+EXEEXT = @EXEEXT@
-clean:; @rm -f *.o *.so *.sl
- @rm -f Makefile extconf.h conftest.*
- @rm -f core ruby$(binsuffix) *~
+all: $(DLLIB)
-realclean: clean
-", target,
- if $static then "o" else "@DLEXT@" end, $dots
+clean:; @$(RM) *.#{$OBJEXT} *.so *.sl *.#{$LIBEXT} $(DLLIB)
+ @$(RM) *.ilk *.exp *.pdb *.bak
- mfile.printf "\
+distclean: clean
+ @$(RM) Makefile extconf.h conftest.*
+ @$(RM) core ruby$(EXEEXT) *~
+
+realclean: distclean
+EOS
+
+ mfile.printf <<EOS
install:
-"
- if !$static
+ @$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' $(DESTDIR)$(libdir) $(DESTDIR)$(pkglibdir) $(DESTDIR)$(archdir)
+EOS
+ unless $static
mfile.printf "\
- @test -d $(libdir) || mkdir $(libdir)
- $(INSTALL) $(TARGET) $(libdir)/$(TARGET)
+ @$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0555, true)' $(DLLIB) $(DESTDIR)$(archdir)/$(DLLIB)
"
end
- for rb in Dir["lib/*.rb"]
- mfile.printf "\t$(INSTALL) %s @libdir@/$(RUBY_INSTALL_NAME)\n", rb
- end
+ install_rb(mfile, $srcdir)
mfile.printf "\n"
- if !$static && "@DLEXT@" != "o"
- mfile.printf "\
-$(TARGET): $(OBJS)
- $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LOCAL_LIBS) $(LIBS)
+ if /mswin32/ !~ RUBY_PLATFORM
+ mfile.puts "
+.c.@OBJEXT@:
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+
+.cc.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
+.cpp.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
+.cxx.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
+.C.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $<
"
- elsif not File.exist?(target + ".c") and not File.exist?(target + ".cc")
- if PLATFORM == "m68k-human"
- mfile.printf "\
-$(TARGET): $(OBJS)
- ar cru $(TARGET) $(OBJS)
+ elsif /nmake/i =~ $make
+ mfile.print "
+{$(srcdir)}.c{}.@OBJEXT@:
+ $(CC) -I. -I$(<D) $(CFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+.c.@OBJEXT@:
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+
+{$(srcdir)}.cc{}.@OBJEXT@:
+ $(CXX) -I. -I$(<D) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+.cc.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+{$(srcdir)}.cpp{}.@OBJEXT@:
+ $(CXX) -I. -I$(<D) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+.cpp.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+{$(srcdir)}.cxx{}.@OBJEXT@:
+ $(CXX) -I. -I$(<D) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
+.cxx.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(<:/=\\)
"
- elsif PLATFORM =~ "-nextstep"
- mfile.printf "\
-$(TARGET): $(OBJS)
- cc -r $(CFLAGS) -o $(TARGET) $(OBJS)
+ else
+ mfile.print "
+.c.@OBJEXT@:
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c $(subst /,\\\\,$<)
+
+.cc.@OBJEXT@ .cpp.@OBJEXT@ .cxx.@OBJEXT@ .C.@OBJEXT@:
+ $(CXX) $(CXXFLAGS) $(CPPFLAGS) -c $(subst /,\\\\,$<)
"
- elsif $static
+ end
+
+ if $static
+ if "@AR@" =~ /^lib\b/i
mfile.printf "\
-$(TARGET): $(OBJS)
- ld -r -o $(TARGET) $(OBJS)
+$(DLLIB): $(OBJS)
+ @AR@ /OUT:$(DLLIB) $(OBJS)
"
else
mfile.printf "\
-$(TARGET): $(OBJS)
- ld $(DLDFLAGS) -r -o $(TARGET) $(OBJS)
+$(DLLIB): $(OBJS)
+ @AR@ cru $(DLLIB) $(OBJS)
+ @-@RANLIB@ $(DLLIB) 2> /dev/null || true
"
end
+ elsif "@DLEXT@" != $OBJEXT
+ mfile.print "$(DLLIB): $(OBJS)\n"
+ if /mswin32/ =~ RUBY_PLATFORM
+ if /nmake/i =~ $make
+ mfile.print "\tset LIB=$(LIBPATH:/=\\);$(LIB)\n"
+ else
+ mfile.print "\tenv LIB='$(subst /,\\\\,$(LIBPATH));$(LIB)' \\\n"
+ end
+ end
+ mfile.print "\t$(LDSHARED) $(DLDFLAGS) -o $(DLLIB) $(OBJS) $(LIBS) $(LOCAL_LIBS)\n"
+ elsif RUBY_PLATFORM == "m68k-human"
+ mfile.printf "\
+$(DLLIB): $(OBJS)
+ ar cru $(DLLIB) $(OBJS)
+"
+ else
+ mfile.printf "\
+$(DLLIB): $(OBJS)
+ ld $(DLDFLAGS) -r -o $(DLLIB) $(OBJS)
+"
end
- if File.exist?("depend")
- dfile = open("depend", "r")
+ if File.exist?("#{$srcdir}/depend")
+ dfile = open("#{$srcdir}/depend", "r")
mfile.printf "###\n"
while line = dfile.gets()
- mfile.printf "%s", line
+ line.gsub!(/\.o\b/, ".#{$OBJEXT}")
+ line.gsub!(/(\s)([^\s\/]+\.[ch])/, '\1$(srcdir)/\2') if /nmake/i =~ $make
+ mfile.printf "%s", line.gsub('\$\(hdrdir\)/config.h', '$(topdir)/config.h')
end
dfile.close
end
@@ -347,76 +598,107 @@ def extmake(target)
if $force_static or $static_ext[target]
$static = target
else
- $static = FALSE
+ $static = false
end
- return if $nodynamic and not $static
+ unless $install or $clean
+ return if $nodynamic and not $static
+ end
- $local_libs = nil
- $libs = nil
+ $OBJEXT = "@OBJEXT@"
+ $LIBEXT = "a"
$objs = nil
- $CFLAGS = nil
- $LDFLAGS = nil
+ $libs = "@DLDLIBS@"
+ $local_flags = ""
+ if /mswin32/ =~ RUBY_PLATFORM
+ $LIBEXT = "lib"
+ $local_flags = "-link /INCREMENTAL:no /EXPORT:Init_$(TARGET)"
+ end
+ $LOCAL_LIBS = "" # to be assigned in extconf.rb
+ $CFLAGS = ""
+ $CPPFLAGS = ""
+ $LDFLAGS = ""
+ $LIBPATH = []
+
+ dir_config("opt")
begin
- system "mkdir " + target unless File.directory?(target)
+ Dir.mkdir target unless File.directory?(target)
Dir.chdir target
- if $static_ext.size > 0 ||
- !File.exist?("./Makefile") ||
- older("./Makefile", "#{$topdir}/ext/@setup@") ||
- older("./Makefile", "../extmk.rb") ||
- older("./Makefile", "#{$topdir}/ext/#{target}/extconf.rb")
- then
- $defs = []
- if File.exist?("#{$topdir}/ext/#{target}/extconf.rb")
- load "#{$topdir}/ext/#{target}/extconf.rb"
- else
- create_makefile(target);
+ $target = target
+ $mdir = target
+ unless $install or $clean
+ if $static_ext.size > 0 ||
+ !File.exist?("./Makefile") ||
+ older("./Makefile", "#{$top_srcdir}/ext/@setup@") ||
+ older("./Makefile", "../extmk.rb") ||
+ older("./Makefile", "#{$top_srcdir}/ext/#{target}/makefile.rb") ||
+ older("./Makefile", "#{$top_srcdir}/ext/#{target}/extconf.rb")
+ then
+ $defs = []
+ if File.exist?("#{$top_srcdir}/ext/#{target}/makefile.rb")
+ load "#{$top_srcdir}/ext/#{target}/makefile.rb"
+ elsif File.exist?("#{$top_srcdir}/ext/#{target}/extconf.rb")
+ load "#{$top_srcdir}/ext/#{target}/extconf.rb"
+ else
+ create_makefile(target)
+ end
end
end
if File.exist?("./Makefile")
if $static
- $extlist.push [$static,target]
+ $extlist.push [$static,$target]
end
if $install
- system "make install"
+ system "#{$make} install DESTDIR=#{$destdir}"
elsif $clean
- system "make clean"
+ system "#{$make} #{$clean}"
else
- system "make all"
+ unless system "#{$make} all"
+ if ENV["MAKEFLAGS"] != "k" and ENV["MFLAGS"] != "-k"
+ exit
+ end
+ end
end
end
if $static
- $extlibs += " " + $LDFLAGS if $LDFLAGS
- $extlibs += " " + $local_libs if $local_libs
- $extlibs += " " + $libs if $libs
+ $extlibs ||= ""
+ $extlibs += " " + $LDFLAGS unless $LDFLAGS == ""
+ $extlibs += " " + $libs unless $libs == ""
+ $extlibs += " " + $LOCAL_LIBS unless $LOCAL_LIBS == ""
end
ensure
+ rm_f "conftest*"
Dir.chdir ".."
end
end
+$make = ENV["MAKE"]
+$make ||= with_config("make-prog", "make")
+
# get static-link modules
$static_ext = {}
-for setup in ["@setup@", "#{$topdir}/ext/@setup@"]
+for setup in ["@setup@", "#{$top_srcdir}/ext/@setup@"]
if File.file? setup
f = open(setup)
- while f.gets()
- $_.chop!
- sub!(/#.*$/, '')
- next if /^\s*$/
- if /^option +nodynamic/
- $nodynamic = TRUE
+ while line = f.gets()
+ line.chomp!
+ line.sub!(/#.*$/, '')
+ next if /^\s*$/ =~ line
+ if /^option +nodynamic/ =~ line
+ $nodynamic = true
next
end
- $static_ext[$_.split[0]] = TRUE
+ target = line.split[0]
+ target = target.downcase if /mswin32/ =~ RUBY_PLATFORM
+ $static_ext[target] = true
end
f.close
break
end
end
-for d in Dir["#{$topdir}/ext/*"]
+for d in Dir["#{$top_srcdir}/ext/*"]
File.directory?(d) || next
File.file?(d + "/MANIFEST") || next
@@ -427,50 +709,47 @@ for d in Dir["#{$topdir}/ext/*"]
print "cleaning ", d, "\n"
else
print "compiling ", d, "\n"
+ if RUBY_PLATFORM =~ /-aix/ and older("../ruby.imp", "../miniruby")
+ load "#{$top_srcdir}/ext/aix_mksym.rb"
+ end
end
extmake(d)
end
-if $cache_mod
- f = open("config.cache", "w")
- for k,v in $lib_cache
- f.printf "lib: %s %s\n", k, v
- end
- for k,v in $func_cache
- f.printf "func: %s %s\n", k, v
- end
- for k,v in $hdr_cache
- f.printf "hdr: %s %s\n", k, v
- end
- f.close
+if $install or $clean
+ Dir.chdir ".."
+ exit
end
+$extinit = "" unless $extinit
+
+ruby = "@RUBY_INSTALL_NAME@@EXEEXT@"
+miniruby = "miniruby@EXEEXT@"
-exit if $install or $clean
-$extinit += ""
+$extobjs = "" unless $extobjs
if $extlist.size > 0
for s,t in $extlist
- f = format("%s/%s.o", s, t)
+ f = format("%s/%s.%s", s, t, $LIBEXT)
if File.exist?(f)
$extinit += format("\
\tInit_%s();\n\
-\trb_provide(\"%s.o\");\n\
+\trb_provide(\"%s.so\");\n\
", t, t)
$extobjs += "ext/"
$extobjs += f
$extobjs += " "
else
- FALSE
+ false
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
f.printf "}\n"
f.close
end
- if older("extinit.o", "extinit.c")
+ if older("extinit.#{$OBJEXT}", "extinit.c")
cmd = "@CC@ " + CFLAGS + " -c extinit.c"
print cmd, "\n"
system cmd or exit 1
@@ -478,20 +757,20 @@ if $extlist.size > 0
Dir.chdir ".."
- if older("ruby@binsuffix@", "#{$topdir}/ext/@setup@") or older("ruby@binsuffix@", "miniruby@binsuffix@")
- `rm -f ruby@binsuffix@`
+ if older(ruby, "#{$top_srcdir}/ext/@setup@") or older(ruby, miniruby)
+ rm_f ruby
end
- $extobjs = "ext/extinit.o " + $extobjs
- if PLATFORM == "m68k-human"
+ $extobjs = "ext/extinit.#{$OBJEXT} " + $extobjs
+ if RUBY_PLATFORM =~ /m68k-human|beos/
$extlibs.gsub!("-L/usr/local/lib", "") if $extlibs
end
- system format('make ruby@binsuffix@ EXTOBJS="%s" EXTLIBS="%s"', $extobjs, $extlibs)
+ system format(%[#{$make} #{ruby} EXTOBJS='%s' EXTLIBS='%s'], $extobjs, $extlibs)
else
Dir.chdir ".."
- if older("ruby@binsuffix@", "miniruby@binsuffix@")
- `rm -f ruby@binsuffix@`
- system("make ruby@binsuffix@")
+ if older(ruby, miniruby)
+ rm_f ruby
+ system("#{$make} #{ruby}")
end
end
diff --git a/ext/extmk.rb.nt b/ext/extmk.rb.nt
deleted file mode 100644
index 6792f2717b..0000000000
--- a/ext/extmk.rb.nt
+++ /dev/null
@@ -1,497 +0,0 @@
-#! /usr/local/bin/ruby
-
-if ARGV[0] == 'static'
- $force_static = TRUE
- ARGV.shift
-elsif ARGV[0] == 'install'
- $install = TRUE
- ARGV.shift
-elsif ARGV[0] == 'clean'
- $clean = TRUE
- ARGV.shift
-end
-
-$extlist = []
-
-$cache_mod = FALSE;
-$lib_cache = {}
-$func_cache = {}
-$hdr_cache = {}
-
-#$dllopt = '-MD'
-$dllopt = ''
-
-if File.exist?("config.cache") then
- f = open("config.cache", "r")
- while f.gets
- case $_
- when /^lib: ([\w_]+) (yes|no)/
- $lib_cache[$1] = $2
- when /^func: ([\w_]+) (yes|no)/
- $func_cache[$1] = $2
- when /^hdr: (.+) (yes|no)/
- $hdr_cache[$1] = $2
- end
- end
- f.close
-end
-
-def older(file1, file2)
- if !File.exist?(file1) then
- return TRUE
- end
- if !File.exist?(file2) then
- return FALSE
- end
- if File.mtime(file1) < File.mtime(file2)
- return TRUE
- end
- return FALSE
-end
-
-#LINK = "cl -o conftest.exe -I../.. -Zi -O -I. %s conftest.c %s > nul"
-LINK = "cl -o conftest.exe -Zi -O %s conftest.c %s > nul"
-CPP = "cl -E -I../.. -I../../missing -I../../win32 -I. -Zi -O %s conftest.c > nul"
-
-def try_link(libs)
- #print(format("try #{LINK}", $CFLAGS, $LDFLAGS, libs))
- #system(format(LINK, $CFLAGS, $LDFLAGS, libs))
- print(format("try #{LINK}\n", $CFLAGS, libs))
- system(format(LINK, $CFLAGS, libs))
-end
-
-def try_cpp
- system(format(CPP, $CFLAGS))
-end
-
-def have_library(lib, func)
- #print format("have_library(%s, %s)\n", lib, func)
- if $lib_cache[lib]
- if $lib_cache[lib] == "yes"
- if $libs#
- $libs = lib + ".lib " + $libs
- else
- $libs = lib + ".lib "
- end
- return TRUE
- else
- return FALSE
- end
- end
-
- cfile = open("conftest.c", "w")
- cfile.printf "\
-#include <windows.h>
-#include <winsock.h>
-int main() { return 0; }
-int t() { %s(); return 0; }
-", func
- cfile.close
-
- begin
- if $libs
- libs = lib + ".lib " + $libs
- else
- libs = lib + ".lib"
- end
- #print "libs=#{libs}\n"
- unless try_link(libs)
- #print "fail : #{libs}\n"
- $lib_cache[lib] = 'no'
- $cache_mod = TRUE
- return FALSE
- end
- ensure
- system "rm -f conftest*"
- end
-
- $libs = libs
- $lib_cache[lib] = 'yes'
- $cache_mod = TRUE
- return TRUE
-end
-
-def have_func(func)
- if $func_cache[func]
- if $func_cache[func] == "yes"
- $defs.push(format("-DHAVE_%s", func.upcase))
- return TRUE
- else
- return FALSE
- end
- end
-
- cfile = open("conftest.c", "w")
- cfile.printf "\
-#include <windows.h>
-#include <winsock.h>
-//char %s();
-int main() { return 0; }
-int t() { %s(); return 0; }
-", func, func
- cfile.close
-
- libs = $libs
- libs = "" if libs == nil
-
- begin
- #print "libs=#{libs}\n"
- unless try_link(libs)
- $func_cache[func] = 'no'
- $cache_mod = TRUE
- return FALSE
- end
- ensure
- system "rm -f conftest*"
- end
- $defs.push(format("-DHAVE_%s", func.upcase))
- $func_cache[func] = 'yes'
- $cache_mod = TRUE
- return TRUE
-end
-
-def have_header(header)
- if $hdr_cache[header]
- if $hdr_cache[header] == "yes"
- header.tr!("a-z./\055", "A-Z___")
- $defs.push(format("-DHAVE_%s", header))
- return TRUE
- else
- return FALSE
- end
- end
-
- cfile = open("conftest.c", "w")
- cfile.printf "\
-#include <%s>
-", header
- cfile.close
-
- begin
- unless try_cpp
- $hdr_cache[header] = 'no'
- $cache_mod = TRUE
- return FALSE
- end
- ensure
- system "rm -f conftest*"
- end
- $hdr_cache[header] = 'yes'
- header.tr!("a-z./\055", "A-Z___")
- $defs.push(format("-DHAVE_%s", header))
- $cache_mod = TRUE
- return TRUE
-end
-
-def create_header()
- if $defs.length > 0
- hfile = open("extconf.h", "w")
- for line in $defs
- line =~ /^-D(.*)/
- hfile.printf "#define %s 1\n", $1
- end
- hfile.close
- end
-end
-
-def create_makefile(target)
-
- if $libs and "obj" == "obj"
- libs = $libs.split
- for lib in libs
- lib.sub!(/(.*)/, '"\1.lib"') if /.lib$/ !~ lib
- end
- $defs.push(format("-DEXTLIB='%s'", libs.join(",")))
- end
- $libs = "" unless $libs
-
- mfile = open("Makefile", "w")
- mfile.printf "\
-SHELL = $(COMPSEC)
-
-#### Start of system configuration section. ####
-
-srcdir = .
-VPATH = .
-
-CC = cl
-
-CFLAGS = %s -I../.. -I../../missing -I../../win32 -I. -O -DNT %s #$CFLAGS %s
-
-RUBYLIB = ../../ruby.lib
-DLDFLAGS = /DLL
-LDSHARED =
-", if $static then "" else "-fpic" end, $dllopt, $defs.join(" ")
-
- if $force_static
- print "static\n"
- else
- print "non static\n"
- end
-
- mfile.printf "\
-
-libdir = /usr/local/lib/ruby/i386-mswin32
-
-
-#### End of system configuration section. ####
-"
- mfile.printf "LOCAL_LIBS = %s\n", $local_libs if $local_libs
- mfile.printf "LIBS = %s\n", $libs
- mfile.printf "OBJS = "
- if !$objs then
- $objs = Dir["*.c"]
- for f in $objs
- f.sub!(/\.c$/, ".obj")
- end
- end
- mfile.printf $objs.join(" ")
- mfile.printf "\n"
-
- dots = if "ginstall -c" =~ /^\// then "" else "../" end
- mfile.printf "\
-TARGET = %s.%s
-
-INSTALL = %sginstall -c
-
-DEFFILE = %s.def
-
-all: $(TARGET)
-
-clean:; @rm -f *.obj *.lib *.exp vc*.pdb *.bak *.def
- @rm -f Makefile extconf.h conftest.*
-
-realclean: clean
-", target,
- if $force_static then "lib" else "dll" end, dots, target
-
- if !$static
- mfile.printf "\
-
-install: $(libdir)/$(TARGET)
-
-$(libdir)/$(TARGET): $(TARGET)
- @test -d $(libdir) || mkdir $(libdir)
- $(INSTALL) $(TARGET) $(libdir)/$(TARGET)
-"
- else
- mfile.printf "\
-
-install:;
-"
- end
-
- if $force_static
- mfile.printf "\
-$(TARGET): $(OBJS)
- lib /OUT:$(TARGET) $(OBJS)
-"
- else
- mfile.printf "\
-$(DEFFILE):
- echo $(DEFFILE)
-
-$(TARGET): $(OBJS) $(DEFFILE)
- cl -DLL -o$(TARGET) $(OBJS) $(RUBYLIB) -link /DEF:$(DEFFILE)
-"
- end
-
- if File.exist?("depend")
- dfile = open("depend", "r")
- mfile.printf "###\n"
- while line = dfile.gets()
- mfile.printf "%s", line
- end
- dfile.close
- end
- mfile.close
- if $static
- #printf format("push %s,%s\n", $static, target); ##debug print##
- $extlist.push [$static,target]
- end
-end
-
-#template of .def file.
-def create_def(basename)
- defname = sprintf("%s.def", basename)
- f = open(defname, "w")
- f.printf "\
-LIBRARY %s.dll
-CODE LOADONCALL
-DATA LOADONCALL
-DESCRIPTION 'win32 %s.dll'
-EXPORTS
-
- Init_%s
-", basename, basename, basename
- f.close
-
-end
-
-def extmake(target)
- if $force_static or $static_ext[target]
- $static = target
- else
- $static = FALSE
- end
-
- return if $nodynamic and not $static
-
- $local_libs = nil
- $libs = nil
- $objs = nil
- $CFLAGS = nil
- $LDFLAGS = nil
-
- begin
- Dir.chdir target
- if $static_ext.size > 0 ||
- !File.exist?("./Makefile") ||
- older("./Makefile", "../Setup") ||
- older("./Makefile", "../extmk.rb") ||
- older("./Makefile", "./extconf.rb")
- then
- $defs = []
- if File.exist?("extconf.rb")
- load "extconf.rb"
- else
- create_makefile(target);
- end
- end
-
- if !File.exist?("#{target}.def")
- create_def(target)
- end
-
- if File.exist?("./Makefile")
- if $install
- system "nmake install"
- if File.directory? "./lib"
- for i in Dir["./lib/*.rb"]
- system "ginstall -c #{i} /usr/local/lib/ruby/i386-mswin32"
- end
- end
- elsif $clean
- system "nmake clean"
- else
- #print "!!!make!!!\n"
- system "nmake all"
- end
- end
- if $static
- #$extlibs = " "
- $extlibs += " " + $LDFLAGS if $LDFLAGS
- $extlibs += " " + $local_libs if $local_libs
- $extlibs += " " + $libs if $libs
- end
- ensure
- Dir.chdir ".."
- end
-end
-
-# get static-link modules
-$static_ext = {}
-if File.file? "./Setup"
- f = open("./Setup")
- while f.gets()
- $_.chop!
- sub!(/#.*$/, '')
- next if /^\s*$/
- #print $_, "\n"
-
- if /^option +nodynamic/
- $nodynamic = TRUE
- next
- end
- $static_ext[$_.split[0]] = TRUE
- end
- f.close
-end
-
-for d in Dir["*"]
- File.directory?(d) || next
- File.file?(d + "/MANIFEST") || next
-
- d = $1 if d =~ /\/([\/]*)$/
- if $install
- print "installing ", d, "\n"
- elsif $clean
- print "cleaning ", d, "\n"
- else
- print "compiling ", d, "\n"
- end
- extmake(d)
-end
-
-if $cache_mod
- f = open("config.cache", "w")
- for k,v in $lib_cache
- f.printf "lib: %s %s\n", k, v
- end
- for k,v in $func_cache
- f.printf "func: %s %s\n", k, v
- end
- for k,v in $hdr_cache
- f.printf "hdr: %s %s\n", k, v
- end
- f.close
-end
-
-exit if $install or $clean
-if $extlist.size > 0
- for s,t in $extlist
- #for s,t in $static_ext
- #f = format("%s/%s.obj", s, t)
- #f = format("%s/%s.obj", s, s)
- l = format("%s/%s.lib", s, s)
- if File.exist?(l)
- $extinit += format("\
-\tInit_%s();\n\
-\trb_provide(\"%s.o\");\n\
-", s, s)
- $extobjs += "ext/"
- #$extobjs += f # *.obj
- $extobjs += l # *.lib
- $extobjs += " "
- else
- FALSE
- end
- end
-
- if older("extinit.c", "Setup")
- f = open("extinit.c", "w")
- f.printf "void Init_ext() {\n"
- f.printf $extinit
- f.printf "}\n"
- f.close
- end
- if older("extinit.obj", "extinit.c")
- cmd = "cl -Zi -O -I. -c extinit.c"
- print cmd, "\n"
- system cmd or exit 1
- end
-
- Dir.chdir ".."
-
- if older("ruby.exe", "ext/Setup") or older("ruby.exe", "miniruby.exe")
- `rm -f ruby.exe`
- end
-
- $extobjs = "ext/extinit.obj " + $extobjs
- #$extlibs = ""
- #print "EXTLIBS=#{$extlibs}\n"
- $extlibs.gsub!("-L/usr/local/lib", "") if $extlibs
- $extlibs.gsub!(" +", " ") if $extlibs
- #print "EXTLIBS=#{$extlibs}\n"
-
- system format('nmake ruby.exe EXTOBJS="%s" EXTLIBS="%s"', $extobjs, $extlibs)
-else
- Dir.chdir ".."
- if older("ruby.exe", "miniruby.exe")
- `rm -f ruby.exe`
- `cp miniruby.exe ruby.exe`
- end
-end
-#Local variables:
-# mode: ruby
-#end:
diff --git a/ext/fcntl/.cvsignore b/ext/fcntl/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/fcntl/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/fcntl/depend b/ext/fcntl/depend
index a7915c7d92..10eab64a46 100644
--- a/ext/fcntl/depend
+++ b/ext/fcntl/depend
@@ -1 +1 @@
-fcntl.o: fcntl.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
+fcntl.o: fcntl.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/fcntl/fcntl.c b/ext/fcntl/fcntl.c
index 186f9ac893..80e0112e4c 100644
--- a/ext/fcntl/fcntl.c
+++ b/ext/fcntl/fcntl.c
@@ -34,6 +34,7 @@ pack up your own arguments to pass as args for locking functions, etc.
#include "ruby.h"
#include <fcntl.h>
+void
Init_fcntl()
{
VALUE mFcntl = rb_define_module("Fcntl");
diff --git a/ext/gdbm/.cvsignore b/ext/gdbm/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/gdbm/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/gdbm/MANIFEST b/ext/gdbm/MANIFEST
new file mode 100644
index 0000000000..f4a8796d18
--- /dev/null
+++ b/ext/gdbm/MANIFEST
@@ -0,0 +1,5 @@
+MANIFEST
+README
+depend
+extconf.rb
+gdbm.c
diff --git a/ext/gdbm/README b/ext/gdbm/README
new file mode 100644
index 0000000000..df7a261c68
--- /dev/null
+++ b/ext/gdbm/README
@@ -0,0 +1 @@
+gdbm ext-library for Ruby 1.3 or later
diff --git a/ext/gdbm/depend b/ext/gdbm/depend
new file mode 100644
index 0000000000..c080a81619
--- /dev/null
+++ b/ext/gdbm/depend
@@ -0,0 +1 @@
+gdbm.o: gdbm.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/gdbm/extconf.rb b/ext/gdbm/extconf.rb
new file mode 100644
index 0000000000..5a09492e5e
--- /dev/null
+++ b/ext/gdbm/extconf.rb
@@ -0,0 +1,7 @@
+require 'mkmf'
+
+dir_config("gdbm")
+if have_library("gdbm", "gdbm_open") and
+ have_header("gdbm.h")
+ create_makefile("gdbm")
+end
diff --git a/ext/gdbm/gdbm.c b/ext/gdbm/gdbm.c
new file mode 100644
index 0000000000..d43450229f
--- /dev/null
+++ b/ext/gdbm/gdbm.c
@@ -0,0 +1,978 @@
+/************************************************
+
+ gdbm.c -
+
+ $Author$
+ $Date$
+ modified at: Mon Jan 24 15:59:52 JST 1994
+
+************************************************/
+
+#include "ruby.h"
+
+#include <gdbm.h>
+#include <fcntl.h>
+#include <errno.h>
+
+static VALUE cGDBM, rb_eGDBMError;
+
+#define MY_BLOCK_SIZE (2048)
+#define MY_FATAL_FUNC (0)
+
+struct dbmdata {
+ int di_size;
+ GDBM_FILE di_dbm;
+};
+
+static void
+closed_dbm()
+{
+ rb_raise(rb_eRuntimeError, "closed GDBM file");
+}
+
+#define GetDBM(obj, dbmp) {\
+ Data_Get_Struct(obj, struct dbmdata, dbmp);\
+ if (dbmp == 0) closed_dbm();\
+ if (dbmp->di_dbm == 0) closed_dbm();\
+}
+
+static void
+free_dbm(dbmp)
+ struct dbmdata *dbmp;
+{
+ if (dbmp) {
+ if (dbmp->di_dbm) gdbm_close(dbmp->di_dbm);
+ free(dbmp);
+ }
+}
+
+static VALUE fgdbm_close _((VALUE));
+
+static VALUE
+fgdbm_s_new(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);
+ rb_obj_call_init(obj, argc, argv);
+ return obj;
+}
+
+static VALUE
+fgdbm_initialize(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE file, vmode, vflags;
+ GDBM_FILE dbm;
+ struct dbmdata *dbmp;
+ int mode, flags = 0;
+
+ if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) {
+ mode = 0666; /* default value */
+ }
+ else if (NIL_P(vmode)) {
+ mode = -1; /* return nil if DB not exist */
+ }
+ else {
+ mode = NUM2INT(vmode);
+ }
+
+ if (!NIL_P(vflags))
+ flags = NUM2INT(vflags);
+
+ file = rb_str_to_str(file);
+ Check_SafeStr(file);
+
+ dbm = 0;
+ if (mode >= 0)
+ dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
+ GDBM_WRCREAT|flags, mode, MY_FATAL_FUNC);
+ if (!dbm)
+ dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
+ GDBM_WRITER|flags, 0, MY_FATAL_FUNC);
+ if (!dbm)
+ dbm = gdbm_open(RSTRING(file)->ptr, MY_BLOCK_SIZE,
+ GDBM_READER|flags, 0, MY_FATAL_FUNC);
+
+ if (!dbm) {
+ if (mode == -1) return Qnil;
+
+ if (gdbm_errno == GDBM_FILE_OPEN_ERROR ||
+ gdbm_errno == GDBM_CANT_BE_READER ||
+ gdbm_errno == GDBM_CANT_BE_WRITER)
+ rb_sys_fail(RSTRING(file)->ptr);
+ else
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+
+ dbmp = ALLOC(struct dbmdata);
+ DATA_PTR(obj) = dbmp;
+ dbmp->di_dbm = dbm;
+ dbmp->di_size = -1;
+
+ return obj;
+}
+
+static VALUE
+fgdbm_s_open(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_dbm, 0);
+
+ if (NIL_P(fgdbm_initialize(argc, argv, obj))) {
+ return Qnil;
+ }
+
+ if (rb_block_given_p()) {
+ return rb_ensure(rb_yield, obj, fgdbm_close, obj);
+ }
+
+ return obj;
+}
+
+static VALUE
+fgdbm_close(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+
+ GetDBM(obj, dbmp);
+ gdbm_close(dbmp->di_dbm);
+ dbmp->di_dbm = 0;
+
+ return Qnil;
+}
+
+static VALUE
+rb_gdbm_fetch(dbm, key)
+ GDBM_FILE dbm;
+ datum key;
+{
+ datum val;
+ NEWOBJ(str, struct RString);
+ OBJSETUP(str, rb_cString, T_STRING);
+
+ val = gdbm_fetch(dbm, key);
+ if (val.dptr == 0)
+ return Qnil;
+
+ str->ptr = 0;
+ str->len = val.dsize;
+ str->orig = 0;
+ str->ptr = REALLOC_N(val.dptr,char,val.dsize+1);
+ str->ptr[str->len] = '\0';
+
+ OBJ_TAINT(str);
+ return (VALUE)str;
+}
+
+static VALUE
+rb_gdbm_fetch2(dbm, keystr)
+ GDBM_FILE dbm;
+ VALUE keystr;
+{
+ datum key;
+
+ keystr = rb_str_to_str(keystr);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ return rb_gdbm_fetch(dbm, key);
+}
+
+static VALUE
+rb_gdbm_fetch3(obj, keystr)
+ VALUE obj, keystr;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ return rb_gdbm_fetch2(dbm, keystr);
+}
+
+static VALUE
+rb_gdbm_firstkey(dbm)
+ GDBM_FILE dbm;
+{
+ datum key;
+ NEWOBJ(str, struct RString);
+ OBJSETUP(str, rb_cString, T_STRING);
+
+ key = gdbm_firstkey(dbm);
+ if (key.dptr == 0)
+ return Qnil;
+
+ str->ptr = 0;
+ str->len = key.dsize;
+ str->orig = 0;
+ str->ptr = REALLOC_N(key.dptr,char,key.dsize+1);
+ str->ptr[str->len] = '\0';
+
+ OBJ_TAINT(str);
+ return (VALUE)str;
+}
+
+static VALUE
+rb_gdbm_nextkey(dbm, keystr)
+ GDBM_FILE dbm;
+ VALUE keystr;
+{
+ datum key, key2;
+ NEWOBJ(str, struct RString);
+ OBJSETUP(str, rb_cString, T_STRING);
+
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+ key2 = gdbm_nextkey(dbm, key);
+ if (key2.dptr == 0)
+ return Qnil;
+
+ str->ptr = 0;
+ str->len = key2.dsize;
+ str->orig = 0;
+ str->ptr = REALLOC_N(key2.dptr,char,key2.dsize+1);
+ str->ptr[str->len] = '\0';
+
+ OBJ_TAINT(str);
+ return (VALUE)str;
+}
+
+static VALUE
+fgdbm_fetch(obj, keystr, ifnone)
+ VALUE obj, keystr, ifnone;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE valstr;
+
+ keystr = rb_str_to_str(keystr);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ valstr = rb_gdbm_fetch(dbm, key);
+ if (NIL_P(valstr)) {
+ if (ifnone == Qnil && rb_block_given_p())
+ return rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
+ return ifnone;
+ }
+ return valstr;
+}
+
+static VALUE
+fgdbm_aref(obj, keystr)
+ VALUE obj, keystr;
+{
+ return rb_gdbm_fetch3(obj, keystr);
+}
+
+static VALUE
+fgdbm_fetch_m(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE keystr, valstr, ifnone;
+
+ rb_scan_args(argc, argv, "11", &keystr, &ifnone);
+ valstr = fgdbm_fetch(obj, keystr, ifnone);
+ if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
+ rb_raise(rb_eIndexError, "key not found");
+
+ return valstr;
+}
+
+static VALUE
+fgdbm_index(obj, valstr)
+ VALUE obj, valstr;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE keystr, valstr2;
+
+ valstr = rb_str_to_str(valstr);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ valstr2 = rb_gdbm_fetch2(dbm, keystr);
+ if (!NIL_P(valstr2) &&
+ RSTRING(valstr)->len == RSTRING(valstr2)->len &&
+ memcmp(RSTRING(valstr)->ptr, RSTRING(valstr2)->ptr,
+ RSTRING(valstr)->len) == 0) {
+ return keystr;
+ }
+ }
+ return Qnil;
+}
+
+static VALUE
+fgdbm_indexes(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE new;
+ int i;
+
+ new = rb_ary_new2(argc);
+ for (i=0; i<argc; i++) {
+ rb_ary_push(new, rb_gdbm_fetch3(obj, argv[i]));
+ }
+
+ return new;
+}
+
+static VALUE
+rb_gdbm_delete(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ rb_secure(4);
+ keystr = rb_str_to_str(keystr);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ if (!gdbm_exists(dbm, key)) {
+ return Qnil;
+ }
+
+ if (gdbm_delete(dbm, key)) {
+ dbmp->di_size = -1;
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+ else if (dbmp->di_size >= 0) {
+ dbmp->di_size--;
+ }
+ return obj;
+}
+
+static VALUE
+fgdbm_delete(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ rb_secure(4);
+ keystr = rb_str_to_str(keystr);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ if (!gdbm_exists(dbm, key)) {
+ if (rb_block_given_p()) rb_yield(keystr);
+ return Qnil;
+ }
+
+ if (gdbm_delete(dbm, key)) {
+ dbmp->di_size = -1;
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+ else if (dbmp->di_size >= 0) {
+ dbmp->di_size--;
+ }
+ return obj;
+}
+
+static VALUE
+fgdbm_shift(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE keystr, valstr;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ keystr = rb_gdbm_firstkey(dbm);
+ if (NIL_P(keystr)) return Qnil;
+ valstr = rb_gdbm_fetch2(dbm, keystr);
+ rb_gdbm_delete(obj, keystr);
+
+ return rb_assoc_new(keystr, valstr);
+}
+
+static VALUE
+fgdbm_delete_if(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE keystr, valstr;
+ VALUE ret, ary = rb_ary_new();
+ int i, status = 0, n;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ n = dbmp->di_size;
+ dbmp->di_size = -1;
+
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ valstr = rb_gdbm_fetch2(dbm, keystr);
+ ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
+ if (status != 0) goto delete;
+ if (RTEST(ret)) rb_ary_push(ary, keystr);
+ else dbmp->di_size++;
+ }
+
+ delete:
+ for (i = 0; i < RARRAY(ary)->len; i++)
+ rb_gdbm_delete(obj, RARRAY(ary)->ptr[i]);
+ if (status) rb_jump_tag(status);
+ if (n > 0) dbmp->di_size = n - RARRAY(ary)->len;
+
+ return obj;
+}
+
+static VALUE
+fgdbm_clear(obj)
+ VALUE obj;
+{
+ datum key, nextkey;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ dbmp->di_size = -1;
+
+ while (key = gdbm_firstkey(dbm), key.dptr) {
+ for (; key.dptr; key = nextkey) {
+ nextkey = gdbm_nextkey(dbm, key);
+ if (gdbm_delete(dbm, key)) {
+ free(key.dptr);
+ if (nextkey.dptr) free(nextkey.dptr);
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+ free(key.dptr);
+ }
+ }
+ dbmp->di_size = 0;
+
+ return obj;
+}
+
+static VALUE
+fgdbm_invert(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE keystr, valstr;
+ VALUE hash = rb_hash_new();
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+ valstr = rb_gdbm_fetch2(dbm, keystr);
+
+ rb_hash_aset(hash, valstr, keystr);
+ }
+ return hash;
+}
+
+static VALUE
+each_pair(obj)
+ VALUE obj;
+{
+ return rb_funcall(obj, rb_intern("each_pair"), 0, 0);
+}
+
+static VALUE fgdbm_store _((VALUE,VALUE,VALUE));
+
+static VALUE
+update_i(pair, dbm)
+ VALUE pair, dbm;
+{
+ Check_Type(pair, T_ARRAY);
+ if (RARRAY(pair)->len < 2) {
+ rb_raise(rb_eArgError, "pair must be [key, value]");
+ }
+ fgdbm_store(dbm, RARRAY(pair)->ptr[0], RARRAY(pair)->ptr[1]);
+ return Qnil;
+}
+
+static VALUE
+fgdbm_update(obj, other)
+ VALUE obj, other;
+{
+ rb_iterate(each_pair, other, update_i, obj);
+ return obj;
+}
+
+static VALUE
+fgdbm_replace(obj, other)
+ VALUE obj, other;
+{
+ fgdbm_clear(obj);
+ rb_iterate(each_pair, other, update_i, obj);
+ return obj;
+}
+
+static VALUE
+fgdbm_store(obj, keystr, valstr)
+ VALUE obj, keystr, valstr;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ rb_secure(4);
+ keystr = rb_str_to_str(keystr);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ valstr = rb_str_to_str(valstr);
+ val.dptr = RSTRING(valstr)->ptr;
+ val.dsize = RSTRING(valstr)->len;
+
+ GetDBM(obj, dbmp);
+ dbmp->di_size = -1;
+ dbm = dbmp->di_dbm;
+ if (gdbm_store(dbm, key, val, GDBM_REPLACE)) {
+ if (errno == EPERM) rb_sys_fail(0);
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+
+ return valstr;
+}
+
+static VALUE
+fgdbm_length(obj)
+ VALUE obj;
+{
+ datum key, nextkey;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ int i = 0;
+
+ GetDBM(obj, dbmp);
+ if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
+ dbm = dbmp->di_dbm;
+
+ for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
+ nextkey = gdbm_nextkey(dbm, key);
+ free(key.dptr);
+ i++;
+ }
+ dbmp->di_size = i;
+
+ return INT2FIX(i);
+}
+
+static VALUE
+fgdbm_empty_p(obj)
+ VALUE obj;
+{
+ datum key, nextkey;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ GetDBM(obj, dbmp);
+ if (dbmp->di_size < 0) {
+ dbm = dbmp->di_dbm;
+
+ key = gdbm_firstkey(dbm);
+ if (key.dptr) {
+ free(key.dptr);
+ return Qfalse;
+ }
+ return Qtrue;
+ }
+
+ if (dbmp->di_size == 0) return Qtrue;
+ return Qfalse;
+}
+
+static VALUE
+fgdbm_each_value(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE keystr;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ rb_yield(rb_gdbm_fetch2(dbm, keystr));
+ }
+ return obj;
+}
+
+static VALUE
+fgdbm_each_key(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE keystr;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ rb_yield(rb_str_dup(keystr));
+ }
+ return obj;
+}
+
+static VALUE
+fgdbm_each_pair(obj)
+ VALUE obj;
+{
+ GDBM_FILE dbm;
+ struct dbmdata *dbmp;
+ VALUE keystr;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ rb_yield(rb_assoc_new(rb_str_dup(keystr),
+ rb_gdbm_fetch2(dbm, keystr)));
+ }
+
+ return obj;
+}
+
+static VALUE
+fgdbm_keys(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE keystr, ary;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ ary = rb_ary_new();
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ rb_ary_push(ary, keystr);
+ }
+
+ return ary;
+}
+
+static VALUE
+fgdbm_values(obj)
+ VALUE obj;
+{
+ datum key, nextkey;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE valstr, ary;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ ary = rb_ary_new();
+ for (key = gdbm_firstkey(dbm); key.dptr; key = nextkey) {
+ nextkey = gdbm_nextkey(dbm, key);
+ valstr = rb_gdbm_fetch(dbm, key);
+ free(key.dptr);
+ rb_ary_push(ary, valstr);
+ }
+
+ return ary;
+}
+
+static VALUE
+fgdbm_has_key(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ keystr = rb_str_to_str(keystr);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ if (gdbm_exists(dbm, key))
+ return Qtrue;
+ return Qfalse;
+}
+
+static VALUE
+fgdbm_has_value(obj, valstr)
+ VALUE obj, valstr;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE keystr, valstr2;
+
+ valstr = rb_str_to_str(valstr);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ valstr2 = rb_gdbm_fetch2(dbm, keystr);
+
+ if (!NIL_P(valstr2) &&
+ RSTRING(valstr)->len == RSTRING(valstr2)->len &&
+ memcmp(RSTRING(valstr)->ptr, RSTRING(valstr2)->ptr,
+ RSTRING(valstr)->len) == 0) {
+ return Qtrue;
+ }
+ }
+ return Qfalse;
+}
+
+static VALUE
+fgdbm_to_a(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE keystr, ary;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ ary = rb_ary_new();
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ rb_ary_push(ary, rb_assoc_new(rb_str_dup(keystr),
+ rb_gdbm_fetch2(dbm, keystr)));
+ }
+
+ return ary;
+}
+
+static VALUE
+fgdbm_reorganize(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ gdbm_reorganize(dbm);
+ return obj;
+}
+
+static VALUE
+fgdbm_sync(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ gdbm_sync(dbm);
+ return obj;
+}
+
+static VALUE
+fgdbm_set_cachesize(obj, val)
+ VALUE obj, val;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ int optval;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ optval = FIX2INT(val);
+ if (gdbm_setopt(dbm, GDBM_CACHESIZE, &optval, sizeof(optval)) == -1) {
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+ return val;
+}
+
+static VALUE
+fgdbm_set_fastmode(obj, val)
+ VALUE obj, val;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ int optval;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ optval = 0;
+ if (RTEST(val))
+ optval = 1;
+
+ if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) {
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+ return val;
+}
+
+static VALUE
+fgdbm_set_syncmode(obj, val)
+ VALUE obj, val;
+{
+#if !defined(GDBM_SYNCMODE)
+ fgdbm_set_fastmode(obj, RTEST(val) ? Qfalse : Qtrue);
+ return val;
+#else
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ int optval;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ optval = 0;
+ if (RTEST(val))
+ optval = 1;
+
+ if (gdbm_setopt(dbm, GDBM_FASTMODE, &optval, sizeof(optval)) == -1) {
+ rb_raise(rb_eGDBMError, "%s", gdbm_strerror(gdbm_errno));
+ }
+ return val;
+#endif
+}
+
+static VALUE
+fgdbm_to_hash(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+ GDBM_FILE dbm;
+ VALUE keystr, hash;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ hash = rb_hash_new();
+ for (keystr = rb_gdbm_firstkey(dbm); RTEST(keystr);
+ keystr = rb_gdbm_nextkey(dbm, keystr)) {
+
+ rb_hash_aset(hash, keystr, rb_gdbm_fetch2(dbm, keystr));
+ }
+
+ return hash;
+}
+
+static VALUE
+fgdbm_reject(obj)
+ VALUE obj;
+{
+ return rb_hash_delete_if(fgdbm_to_hash(obj));
+}
+
+void
+Init_gdbm()
+{
+ cGDBM = rb_define_class("GDBM", rb_cObject);
+ rb_eGDBMError = rb_define_class("GDBMError", rb_eStandardError);
+ rb_include_module(cGDBM, rb_mEnumerable);
+
+ rb_define_singleton_method(cGDBM, "new", fgdbm_s_new, -1);
+ rb_define_singleton_method(cGDBM, "open", fgdbm_s_open, -1);
+
+ rb_define_method(cGDBM, "initialize", fgdbm_initialize, -1);
+ rb_define_method(cGDBM, "close", fgdbm_close, 0);
+ rb_define_method(cGDBM, "[]", fgdbm_aref, 1);
+ rb_define_method(cGDBM, "fetch", fgdbm_fetch_m, -1);
+ rb_define_method(cGDBM, "[]=", fgdbm_store, 2);
+ rb_define_method(cGDBM, "store", fgdbm_store, 2);
+ rb_define_method(cGDBM, "index", fgdbm_index, 1);
+ rb_define_method(cGDBM, "indexes", fgdbm_indexes, -1);
+ rb_define_method(cGDBM, "indices", fgdbm_indexes, -1);
+ rb_define_method(cGDBM, "length", fgdbm_length, 0);
+ rb_define_alias(cGDBM, "size", "length");
+ rb_define_method(cGDBM, "empty?", fgdbm_empty_p, 0);
+ rb_define_method(cGDBM, "each", fgdbm_each_pair, 0);
+ rb_define_method(cGDBM, "each_value", fgdbm_each_value, 0);
+ rb_define_method(cGDBM, "each_key", fgdbm_each_key, 0);
+ rb_define_method(cGDBM, "each_pair", fgdbm_each_pair, 0);
+ rb_define_method(cGDBM, "keys", fgdbm_keys, 0);
+ rb_define_method(cGDBM, "values", fgdbm_values, 0);
+ rb_define_method(cGDBM, "shift", fgdbm_shift, 0);
+ rb_define_method(cGDBM, "delete", fgdbm_delete, 1);
+ rb_define_method(cGDBM, "delete_if", fgdbm_delete_if, 0);
+ rb_define_method(cGDBM, "reject!", fgdbm_delete_if, 0);
+ rb_define_method(cGDBM, "reject", fgdbm_reject, 0);
+ rb_define_method(cGDBM, "clear", fgdbm_clear, 0);
+ rb_define_method(cGDBM,"invert", fgdbm_invert, 0);
+ rb_define_method(cGDBM,"update", fgdbm_update, 1);
+ rb_define_method(cGDBM,"replace", fgdbm_replace, 1);
+ rb_define_method(cGDBM,"reorganize", fgdbm_reorganize, 0);
+ rb_define_method(cGDBM,"sync", fgdbm_sync, 0);
+ /* rb_define_method(cGDBM,"setopt", fgdbm_setopt, 2); */
+ rb_define_method(cGDBM,"cachesize=", fgdbm_set_cachesize, 1);
+ rb_define_method(cGDBM,"fastmode=", fgdbm_set_fastmode, 1);
+ rb_define_method(cGDBM,"syncmode=", fgdbm_set_syncmode, 1);
+
+ rb_define_method(cGDBM, "include?", fgdbm_has_key, 1);
+ rb_define_method(cGDBM, "has_key?", fgdbm_has_key, 1);
+ rb_define_method(cGDBM, "member?", fgdbm_has_key, 1);
+ rb_define_method(cGDBM, "has_value?", fgdbm_has_value, 1);
+ rb_define_method(cGDBM, "key?", fgdbm_has_key, 1);
+ rb_define_method(cGDBM, "value?", fgdbm_has_value, 1);
+
+ rb_define_method(cGDBM, "to_a", fgdbm_to_a, 0);
+ rb_define_method(cGDBM, "to_hash", fgdbm_to_hash, 0);
+
+ /* flags for gdbm_opn() */
+ /*
+ rb_define_const(cGDBM, "READER", INT2FIX(GDBM_READER));
+ rb_define_const(cGDBM, "WRITER", INT2FIX(GDBM_WRITER));
+ rb_define_const(cGDBM, "WRCREAT", INT2FIX(GDBM_WRCREAT));
+ rb_define_const(cGDBM, "NEWDB", INT2FIX(GDBM_NEWDB));
+ */
+ rb_define_const(cGDBM, "FAST", INT2FIX(GDBM_FAST));
+ /* this flag is obsolete in gdbm 1.8.
+ On gdbm 1.8, fast mode is default behavior. */
+
+ /* gdbm version 1.8 specific */
+#if defined(GDBM_SYNC)
+ rb_define_const(cGDBM, "SYNC", INT2FIX(GDBM_SYNC));
+#endif
+#if defined(GDBM_NOLOCK)
+ rb_define_const(cGDBM, "NOLOCK", INT2FIX(GDBM_NOLOCK));
+#endif
+ rb_define_const(cGDBM, "VERSION", rb_str_new2(gdbm_version));
+}
diff --git a/ext/kconv/MANIFEST b/ext/kconv/MANIFEST
deleted file mode 100644
index cb89e8239c..0000000000
--- a/ext/kconv/MANIFEST
+++ /dev/null
@@ -1,3 +0,0 @@
-MANIFEST
-depend
-kconv.c
diff --git a/ext/kconv/depend b/ext/kconv/depend
deleted file mode 100644
index 8f09d95130..0000000000
--- a/ext/kconv/depend
+++ /dev/null
@@ -1 +0,0 @@
-kconv.o: kconv.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/md5/.cvsignore b/ext/md5/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/md5/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/md5/MANIFEST b/ext/md5/MANIFEST
index e4f0004b4a..189a482afb 100644
--- a/ext/md5/MANIFEST
+++ b/ext/md5/MANIFEST
@@ -1,6 +1,8 @@
MANIFEST
depend
-md5.doc
+extconf.rb
+md5.txt
+md5.txt.jp
md5.h
md5c.c
md5init.c
diff --git a/ext/md5/depend b/ext/md5/depend
index abb2a47419..14427861f8 100644
--- a/ext/md5/depend
+++ b/ext/md5/depend
@@ -1,2 +1,2 @@
-md5c.o: md5c.c md5.h
-md5init.o: md5init.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h md5.h
+md5c.o: md5c.c md5.h $(topdir)/config.h
+md5init.o: md5init.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h md5.h
diff --git a/ext/md5/extconf.rb b/ext/md5/extconf.rb
new file mode 100644
index 0000000000..a57a976a39
--- /dev/null
+++ b/ext/md5/extconf.rb
@@ -0,0 +1,3 @@
+require 'mkmf'
+$CFLAGS += " -DHAVE_CONFIG_H"
+create_makefile('md5')
diff --git a/ext/md5/md5.doc b/ext/md5/md5.doc
deleted file mode 100644
index 2203404602..0000000000
--- a/ext/md5/md5.doc
+++ /dev/null
@@ -1,36 +0,0 @@
-.\" md5.doc - -*- Indented-Text -*- created at: Fri Aug 2 12:01:27 JST 1996
-
-** MD5(¥¯¥é¥¹)
-
-RFC1321¤Ëµ­½Ò¤µ¤ì¤Æ¤¤¤ëRSA Data Security, Inc. ¤Î MD5 Message-Digest
-Algorithm¤ò¼ÂÁõ¤¹¤ë¥¯¥é¥¹¡¥
-
-SuperClass: Object
-
-Class Methods:
-
- new([str])
- md5([str])
-
- ¿·¤·¤¤MD5¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤¹¤ë¡¥Ê¸»úÎó°ú¿ô¤¬Í¿¤¨¤é¤ì¤ë¤È¤½¤ì
- ¤òÄɲ乤ë(see update)¡¥
-
-Methods:
-
- clone
-
- MD5¥ª¥Ö¥¸¥§¥¯¥È¤ÎÊ£À½¤òºî¤ë
-
- digest
-
- º£¤Þ¤Ç¤ËÄɲä·¤¿Ê¸»úÎó¤ËÂФ¹¤ë¥Ï¥Ã¥·¥åÃͤò16¥Ð¥¤¥ÈŤÎʸ»úÎó¤Ç
- ÊÖ¤¹¡¥
-
- update(str)
-
- key¤ò¥­¡¼¤È¤¹¤ëÃͤòÊÖ¤¹¡¥
-
--------------------------------------------------------
-Local variables:
-fill-column: 70
-end:
diff --git a/ext/md5/md5.txt b/ext/md5/md5.txt
new file mode 100644
index 0000000000..1d58306cf5
--- /dev/null
+++ b/ext/md5/md5.txt
@@ -0,0 +1,50 @@
+.\" md5.doc - -*- Indented-Text -*- created at: Fri Aug 2 12:01:27 JST 1996
+
+** MD5(Class)
+
+A class to implement MD5 Message-Digest Algorithm by RSA Data
+Security, Inc., described in RFC1321.
+
+Superclass: Object
+
+Class Methods:
+
+ new([str])
+ md5([str])
+
+ Creates a new MD5 object. If a string argument is given, it
+ is added to the object. (see update.)
+
+Methods:
+
+ clone
+
+ Copies the MD5 object.
+
+ digest
+
+ Returns the MD5 hash of the added strings as a string of 16
+ bytes.
+
+ hexdigest
+
+ Returns the MD5 hash of the added strings as a string of 32
+ hexadecimal digits. This method is equal to:
+
+ def hexdigest
+ ret = ''
+ digest.each_byte {|i| ret << sprintf('%02x', i) }
+ ret
+ end
+
+ update(str)
+
+ Update the MD5 object with the string str. Repeated calls are
+ equivalent to a single call with the concatenation of all the
+ arguments, i.e. m.update(a); m.update(b) is equivalent to
+ m.update(a+b).
+
+-------------------------------------------------------
+Local variables:
+fill-column: 70
+end:
diff --git a/ext/md5/md5.txt.jp b/ext/md5/md5.txt.jp
new file mode 100644
index 0000000000..b71dd9bfc9
--- /dev/null
+++ b/ext/md5/md5.txt.jp
@@ -0,0 +1,50 @@
+.\" md5.doc - -*- Indented-Text -*- created at: Fri Aug 2 12:01:27 JST 1996
+
+** MD5(¥¯¥é¥¹)
+
+RFC1321¤Ëµ­½Ò¤µ¤ì¤Æ¤¤¤ëRSA Data Security, Inc. ¤Î MD5 Message-Digest
+Algorithm¤ò¼ÂÁõ¤¹¤ë¥¯¥é¥¹¡£
+
+Superclass: Object
+
+Class Methods:
+
+ new([str])
+ md5([str])
+
+ ¿·¤·¤¤MD5¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤¹¤ë¡¥Ê¸»úÎó°ú¿ô¤¬Í¿¤¨¤é¤ì¤ë¤È¤½¤ì
+ ¤òÄɲ乤ë(see update)¡£
+
+Methods:
+
+ clone
+
+ MD5¥ª¥Ö¥¸¥§¥¯¥È¤ÎÊ£À½¤òºî¤ë¡£
+
+ digest
+
+ º£¤Þ¤Ç¤ËÄɲä·¤¿Ê¸»úÎó¤ËÂФ¹¤ë¥Ï¥Ã¥·¥åÃͤò16¥Ð¥¤¥ÈŤÎʸ»úÎó¤Ç
+ ÊÖ¤¹¡£
+
+ hexdigest
+
+ º£¤Þ¤Ç¤ËÄɲä·¤¿Ê¸»úÎó¤ËÂФ¹¤ë¥Ï¥Ã¥·¥åÃͤò¡¢ASCII¥³¡¼¥É¤ò»È¤Ã¤Æ
+ 16¿Ê¿ô¤ÎÎó¤ò¼¨¤¹'fe5c2235f48d2bcc911afabea23cd5aa'¤Î¤è¤¦¤Ê32ʸ»ú
+ ¤Îʸ»úÎó¤Ë¥¨¥ó¥³¡¼¥É¤·¤ÆÊÖ¤¹¡£Ruby¤Ç½ñ¤¯¤È°Ê²¼¤ÈƱ¤¸¡£
+
+ def hexdigest
+ ret = ''
+ digest.each_byte {|i| ret << sprintf('%02x', i) }
+ ret
+ end
+
+ update(str)
+
+ MD5¥ª¥Ö¥¸¥§¥¯¥È¤Ëʸ»úÎó¤òÄɲ乤롣ʣ¿ô²óupdate¤ò¸Æ¤Ö¤³¤È¤Ïʸ
+ »úÎó¤òÏ¢·ë¤·¤Æupdate¤ò¸Æ¤Ö¤³¤È¤ÈÅù¤·¤¤¡£¤¹¤Ê¤ï¤Á m.update(a);
+ m.update(b) ¤Ï m.update(a+b) ¤ÈÅù²Á¤Ç¤¢¤ë¡£
+
+-------------------------------------------------------
+Local variables:
+fill-column: 70
+end:
diff --git a/ext/md5/md5init.c b/ext/md5/md5init.c
index 894f52a849..a57d5f8f30 100644
--- a/ext/md5/md5init.c
+++ b/ext/md5/md5init.c
@@ -29,8 +29,9 @@ md5_update(obj, str)
Data_Get_Struct(obj, MD5_CTX, md5);
MD5Update(md5, str->ptr, str->len);
- return Qnil;
+ return obj;
}
+
static VALUE
md5_digest(obj)
VALUE obj;
@@ -42,18 +43,36 @@ md5_digest(obj)
ctx = *md5;
MD5Final(digest, &ctx);
- return str_new(digest, 16);
+ return rb_str_new(digest, 16);
+}
+
+static VALUE
+md5_hexdigest(obj)
+ VALUE obj;
+{
+ MD5_CTX *md5, ctx;
+ unsigned char digest[16];
+ char buf[33];
+ int i;
+
+ Data_Get_Struct(obj, MD5_CTX, md5);
+ ctx = *md5;
+ MD5Final(digest, &ctx);
+
+ for (i=0; i<16; i++) {
+ sprintf(buf+i*2, "%02x", digest[i]);
+ }
+ return rb_str_new(buf, 32);
}
static VALUE
md5_clone(obj)
VALUE obj;
{
- VALUE clone;
MD5_CTX *md5, *md5_new;
Data_Get_Struct(obj, MD5_CTX, md5);
- obj = Data_Make_Struct(CLASS_OF(obj), MD5_CTX, 0, 0, md5_new);
+ obj = Data_Make_Struct(CLASS_OF(obj), MD5_CTX, 0, free, md5_new);
*md5_new = *md5;
return obj;
@@ -61,31 +80,35 @@ md5_clone(obj)
static VALUE
md5_new(argc, argv, class)
+ int argc;
+ VALUE* argv;
+ VALUE class;
{
- int i;
VALUE arg, obj;
MD5_CTX *md5;
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);
}
- obj_call_init(obj);
return obj;
}
+void
Init_md5()
{
- cMD5 = rb_define_class("MD5", cObject);
+ cMD5 = rb_define_class("MD5", rb_cObject);
rb_define_singleton_method(cMD5, "new", md5_new, -1);
+ rb_define_singleton_method(cMD5, "md5", md5_new, -1);
rb_define_method(cMD5, "update", md5_update, 1);
rb_define_method(cMD5, "digest", md5_digest, 0);
+ rb_define_method(cMD5, "hexdigest", md5_hexdigest, 0);
rb_define_method(cMD5, "clone", md5_clone, 0);
}
diff --git a/ext/nkf/.cvsignore b/ext/nkf/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/nkf/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/nkf/MANIFEST b/ext/nkf/MANIFEST
new file mode 100644
index 0000000000..5114a3762a
--- /dev/null
+++ b/ext/nkf/MANIFEST
@@ -0,0 +1,7 @@
+MANIFEST
+depend
+extconf.rb
+lib/kconv.rb
+nkf.c
+nkf1.7/nkf.c
+test.rb
diff --git a/ext/nkf/depend b/ext/nkf/depend
new file mode 100644
index 0000000000..13e32e6074
--- /dev/null
+++ b/ext/nkf/depend
@@ -0,0 +1 @@
+nkf.o : nkf.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h $(srcdir)/nkf1.7/nkf.c
diff --git a/ext/nkf/extconf.rb b/ext/nkf/extconf.rb
new file mode 100644
index 0000000000..710662f19c
--- /dev/null
+++ b/ext/nkf/extconf.rb
@@ -0,0 +1,2 @@
+require 'mkmf'
+create_makefile('nkf')
diff --git a/ext/nkf/lib/kconv.rb b/ext/nkf/lib/kconv.rb
new file mode 100644
index 0000000000..af6d82275f
--- /dev/null
+++ b/ext/nkf/lib/kconv.rb
@@ -0,0 +1,73 @@
+require 'nkf'
+
+module Kconv
+ AUTO = NKF::AUTO
+ JIS = NKF::JIS
+ EUC = NKF::EUC
+ SJIS = NKF::SJIS
+ BINARY = NKF::BINARY
+ NOCONV = NKF::NOCONV
+ UNKNOWN = NKF::UNKNOWN
+ def kconv(str, out_code, in_code = AUTO)
+ opt = '-'
+ case in_code
+ when NKF::JIS
+ opt << 'J'
+ when NKF::EUC
+ opt << 'E'
+ when NKF::SJIS
+ opt << 'S'
+ end
+
+ case out_code
+ when NKF::JIS
+ opt << 'j'
+ when NKF::EUC
+ opt << 'e'
+ when NKF::SJIS
+ opt << 's'
+ when NKF::NOCONV
+ return str
+ end
+
+ opt = '' if opt == '-'
+
+ NKF::nkf(opt, str)
+ end
+ module_function :kconv
+
+ def tojis(str)
+ NKF::nkf('-j', str)
+ end
+ module_function :tojis
+
+ def toeuc(str)
+ NKF::nkf('-e', str)
+ end
+ module_function :toeuc
+
+ def tosjis(str)
+ NKF::nkf('-s', str)
+ end
+ module_function :tosjis
+
+ def guess(str)
+ NKF::guess(str)
+ end
+ module_function :guess
+end
+
+class String
+ def kconv(out_code, in_code=Kconv::AUTO)
+ Kconv::kconv(self, out_code, in_code)
+ end
+ def tojis
+ NKF::nkf('-j', self)
+ end
+ def toeuc
+ NKF::nkf('-e', self)
+ end
+ def tosjis
+ NKF::nkf('-s', self)
+ end
+end
diff --git a/ext/nkf/nkf.c b/ext/nkf/nkf.c
new file mode 100644
index 0000000000..b59688cb03
--- /dev/null
+++ b/ext/nkf/nkf.c
@@ -0,0 +1,196 @@
+#include "ruby.h"
+
+#define _AUTO 0
+#define _JIS 1
+#define _EUC 2
+#define _SJIS 3
+#define _BINARY 4
+#define _NOCONV 4
+#define _UNKNOWN _AUTO
+
+#undef getc
+#undef ungetc
+#define getc(f) (input_ctr<i_len?input[input_ctr++]:-1)
+#define ungetc(c,f) input_ctr--
+
+#undef putchar
+#define putchar(c) rb_nkf_putchar(c)
+
+#define INCSIZE 32
+static int incsize;
+
+static unsigned char *input, *output;
+static int input_ctr, i_len;
+static int output_ctr, o_len;
+
+static VALUE dst;
+
+static int
+rb_nkf_putchar(c)
+ unsigned int c;
+{
+ if (output_ctr >= o_len) {
+ o_len += incsize;
+ rb_str_cat(dst, 0, incsize);
+ output = RSTRING(dst)->ptr;
+ incsize *= 2;
+ }
+ output[output_ctr++] = c;
+
+ return c;
+}
+
+#define PERL_XS 1
+#include "nkf1.7/nkf.c"
+
+static VALUE
+rb_nkf_kconv(obj, opt, src)
+ VALUE obj, opt, src;
+{
+ int i;
+ char *opt_ptr, *opt_end;
+ volatile VALUE v;
+
+ reinit();
+ opt_ptr = str2cstr(opt, &i);
+ opt_end = opt_ptr + i;
+ for (; opt_ptr < opt_end; opt_ptr++) {
+ if (*opt_ptr != '-') {
+ continue;
+ }
+ arguments(opt_ptr);
+ }
+
+ incsize = INCSIZE;
+
+ input_ctr = 0;
+ input = str2cstr(src, &i_len);
+ dst = rb_str_new(0, i_len*3 + 10);
+ v = dst;
+
+ output_ctr = 0;
+ output = RSTRING(dst)->ptr;
+ o_len = RSTRING(dst)->len;
+ *output = '\0';
+
+ if(iso8859_f && (oconv != j_oconv || !x0201_f )) {
+ iso8859_f = FALSE;
+ }
+
+ kanji_convert(NULL);
+ RSTRING(dst)->ptr[output_ctr] = '\0';
+ RSTRING(dst)->len = output_ctr;
+
+ return dst;
+}
+
+/*
+ * Character code detection - Algorithm described in:
+ * Ken Lunde. `Understanding Japanese Information Processing'
+ * Sebastopol, CA: O'Reilly & Associates.
+ */
+
+static VALUE
+rb_nkf_guess(obj, src)
+ VALUE obj, src;
+{
+ unsigned char *p;
+ unsigned char *pend;
+ int plen;
+ int sequence_counter = 0;
+
+ Check_Type(src, T_STRING);
+
+ p = str2cstr(src, &plen);
+ pend = p + plen;
+
+#define INCR do {\
+ p++;\
+ if (p==pend) return INT2FIX(_UNKNOWN);\
+ sequence_counter++;\
+ if (sequence_counter % 2 == 1 && *p != 0xa4)\
+ sequence_counter = 0;\
+ if (6 <= sequence_counter) {\
+ sequence_counter = 0;\
+ return INT2FIX(_EUC);\
+ }\
+} while (0)
+
+ if (*p == 0xa4)
+ sequence_counter = 1;
+
+ while (p<pend) {
+ if (*p == '\033') {
+ return INT2FIX(_JIS);
+ }
+ if (*p < '\006' || *p == 0x7f || *p == 0xff) {
+ return INT2FIX(_BINARY);
+ }
+ if (0x81 <= *p && *p <= 0x8d) {
+ return INT2FIX(_SJIS);
+ }
+ if (0x8f <= *p && *p <= 0x9f) {
+ return INT2FIX(_SJIS);
+ }
+ if (*p == 0x8e) { /* SS2 */
+ INCR;
+ if ((0x40 <= *p && *p <= 0x7e) ||
+ (0x80 <= *p && *p <= 0xa0) ||
+ (0xe0 <= *p && *p <= 0xfc))
+ return INT2FIX(_SJIS);
+ }
+ else if (0xa1 <= *p && *p <= 0xdf) {
+ INCR;
+ if (0xf0 <= *p && *p <= 0xfe)
+ return INT2FIX(_EUC);
+ if (0xe0 <= *p && *p <= 0xef) {
+ while (p < pend && *p >= 0x40) {
+ if (*p >= 0x81) {
+ if (*p <= 0x8d || (0x8f <= *p && *p <= 0x9f)) {
+ return INT2FIX(_SJIS);
+ }
+ else if (0xfd <= *p && *p <= 0xfe) {
+ return INT2FIX(_EUC);
+ }
+ }
+ INCR;
+ }
+ }
+ else if (*p <= 0x9f) {
+ return INT2FIX(_SJIS);
+ }
+ }
+ else if (0xf0 <= *p && *p <= 0xfe) {
+ return INT2FIX(_EUC);
+ }
+ else if (0xe0 <= *p && *p <= 0xef) {
+ INCR;
+ if ((0x40 <= *p && *p <= 0x7e) ||
+ (0x80 <= *p && *p <= 0xa0)) {
+ return INT2FIX(_SJIS);
+ }
+ if (0xfd <= *p && *p <= 0xfe) {
+ return INT2FIX(_EUC);
+ }
+ }
+ INCR;
+ }
+ return INT2FIX(_UNKNOWN);
+}
+
+void
+Init_nkf()
+{
+ VALUE mKconv = rb_define_module("NKF");
+
+ rb_define_module_function(mKconv, "nkf", rb_nkf_kconv, 2);
+ rb_define_module_function(mKconv, "guess", rb_nkf_guess, 1);
+
+ rb_define_const(mKconv, "AUTO", INT2FIX(_AUTO));
+ rb_define_const(mKconv, "JIS", INT2FIX(_JIS));
+ rb_define_const(mKconv, "EUC", INT2FIX(_EUC));
+ rb_define_const(mKconv, "SJIS", INT2FIX(_SJIS));
+ rb_define_const(mKconv, "BINARY", INT2FIX(_BINARY));
+ rb_define_const(mKconv, "NOCONV", INT2FIX(_NOCONV));
+ rb_define_const(mKconv, "UNKNOWN", INT2FIX(_UNKNOWN));
+}
diff --git a/ext/kconv/kconv.c b/ext/nkf/nkf1.7/nkf.c
index 5762e3531f..09419f40a7 100644
--- a/ext/kconv/kconv.c
+++ b/ext/nkf/nkf1.7/nkf.c
@@ -1,39 +1,31 @@
/** Network Kanji Filter. (PDS Version)
************************************************************************
** Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA)
-** Ï¢ÍíÀè¡§ ¡Ê³ô¡ËÉÙ»ÎÄ̸¦µæ½ê¡¡¥½¥Õ¥È£³¸¦¡¡»ÔÀî¡¡»ê
-** ¡ÊE-Mail Address: ichikawa@flab.fujitsu.co.jp¡Ë
-** Copyright (C) 1996
-** Ï¢ÍíÀè¡§ ΰµåÂç³Ø¾ðÊó¹©³Ø²Ê ²ÏÌî ¿¿¼£ mine/X0208 support
-** ¡ÊE-Mail Address: kono@ie.u-ryukyu.ac.jp¡Ë
-** Ï¢ÍíÀè¡§ COW for DOS & Win16 & Win32 & OS/2
-** ¡ÊE-Mail Address: GHG00637@niftyserve.or.jp¡Ë
-** ±ÄÍø¤òÌÜŪ¤È¤·¤Ê¤¤¸Â¤ê¡¢¤³¤Î¥½¡¼¥¹¤Î¤¤¤«¤Ê¤ë
-** Ê£¼Ì¡¤²þÊÑ¡¤½¤Àµ¤âµöÂú¤·¤Þ¤¹¡£¤½¤ÎºÝ¤Ë¤Ï¡¢¤³¤ÎÉôʬ¤ò»Ä¤¹¤³¤È¡£
-** ¤³¤Î¥×¥í¥°¥é¥à¤Ë¤Ä¤¤¤Æ¤ÏÆÃ¤Ë²¿¤ÎÊݾڤ⤷¤Ê¤¤¡¢°­¤·¤«¤é¤º¡£
+** $BO"Mm@h!'(B $B!J3t!KIY;NDL8&5f=j!!%=%U%H#38&!!;T@n!!;j(B
+** $B!J(BE-Mail Address: ichikawa@flab.fujitsu.co.jp$B!K(B
+** Copyright (C) 1996,1998
+** $BO"Mm@h!'(B $BN05eBg3X>pJs9)3X2J(B $B2OLn(B $B??<#(B mine/X0208 support
+** $B!J(BE-Mail Address: kono@ie.u-ryukyu.ac.jp$B!K(B
+** $BO"Mm@h!'(B COW for DOS & Win16 & Win32 & OS/2
+** $B!J(BE-Mail Address: GHG00637@niftyserve.or.p$B!K(B
+** $B$3$N%=!<%9$N$$$+$J$kJ#<L!$2~JQ!$=$@5$b5vBz$7$^$9!#$?$@$7!"(B
+** $B$=$N:]$K$O!"C/$,9W8%$7$?$r<($9$3$NItJ,$r;D$9$3$H!#(B
+** $B:FG[I[$d;(;o$NIUO?$J$I$NLd$$9g$o$;$bI,MW$"$j$^$;$s!#(B
+** $B$3$N%W%m%0%i%`$K$D$$$F$OFC$K2?$NJ]>Z$b$7$J$$!"0-$7$+$i$:!#(B
** Everyone is permitted to do anything on this program
-** including copying, modifying, improving
-** as long as you don't try to make money off it,
-** or pretend that you wrote it.
+** including copying, modifying, improving.
+** as long as you don't try to pretend that you wrote it.
** i.e., the above copyright notice has to appear in all copies.
+** You don't have to ask before copying or publishing.
** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE.
***********************************************************************/
-/***********************************************************************
-** 1996/03/10 modified for Kconv - by Ikuo Nakagawa
-***********************************************************************/
-/***********************************************************************
-** 1996/12/18 modified for kconv(ruby) - by matz@ruby.club.or.jp
-***********************************************************************/
-
static char *CopyRight =
- "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),1996 S. Kono, COW";
+ "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),1998 S. Kono, COW";
static char *Version =
- "1.62";
+ "1.7";
static char *Patchlevel =
- "5/9612/Shinji Kono, COW matz";
-
-#include "ruby.h"
+ "0/9711/Shinji Kono";
/*
**
@@ -76,27 +68,20 @@ static char *Patchlevel =
** c Add \r in line feed
**/
/******************************/
-/* ¥Ç¥Õ¥©¥ë¥È¤Î½ÐÎÏ¥³¡¼¥ÉÁªÂò */
+/* $B%G%U%)%k%H$N=PNO%3!<%IA*Br(B */
/* Select DEFAULT_CODE */
-#define DEFAULT_CODE_JIS
+#define DEFAULT_CODE_JIS
/* #define DEFAULT_CODE_SJIS */
/* #define DEFAULT_CODE_EUC */
/******************************/
-/* for Kconv: _AUTO, _EUC, _SJIS, _JIS */
-#define _AUTO 0
-#define _JIS 1
-#define _EUC 2
-#define _SJIS 3
-#define _BINARY 4
-#define _NOCONV 4
-#define _UNKNOWN _AUTO
-
#if (defined(__TURBOC__) || defined(LSI_C)) && !defined(MSDOS)
#define MSDOS
#endif
+#ifndef PERL_XS
#include <stdio.h>
+#endif
#if defined(MSDOS) || defined(__OS2__)
#include <stdlib.h>
@@ -126,10 +111,8 @@ static char *Patchlevel =
#include <windows.h>
#endif
-#ifndef FALSE
#define FALSE 0
#define TRUE 1
-#endif
/* state of output_mode and input_mode */
@@ -145,7 +128,7 @@ static char *Patchlevel =
#define NL 0x0a
#define ESC 0x1b
-#define SP 0x20
+#define SPACE 0x20
#define AT 0x40
#define SSP 0xa0
#define DEL 0x7f
@@ -165,25 +148,55 @@ static char *Patchlevel =
/* MIME preprocessor */
-#define _GETC() (*inptr ? (int)(*inptr++) : EOF)
-#define _UNGETC(c) (*--inptr = (c))
-#define PUTCHAR(c) (outlen + 1 < outsiz ? \
- ((outptr[outlen++] = (c)), (outptr[outlen] = '\0')) : EOF)
-#define GETC() ((!mime_mode)?_GETC():mime_getc())
-#define UNGETC(c) ((!mime_mode)?_UNGETC(c):mime_ungetc(c))
+#undef STRICT_MIME /* do stupid strict mime integrity check */
+#define GETC(p) ((!mime_mode)?getc(p):mime_getc(p))
+#define UNGETC(c,p) ((!mime_mode)?ungetc(c,p):mime_ungetc(c))
+
#ifdef EASYWIN /*Easy Win */
extern POINT _BufferSize;
#endif
+/* function prototype */
+
+#ifndef _
+# ifdef __STDC__
+# define _(args) args
+# else
+# define _(args) ()
+# endif
+#endif
+
+#ifndef PERL_XS
+static void noconvert _((FILE *f));
+static int mime_integrity _((FILE *f,unsigned char *p));
+static int usage _((void));
+static char stdibuf[IOBUF_SIZE];
+static char stdobuf[IOBUF_SIZE];
+static unsigned int mime_input = 0; /* undecoded */
+static int end_check;
+#endif
+
+static void kanji_convert _((FILE *f));
+static void h_conv _((FILE *f,int c2,int c1));
+static int push_hold_buf _((int c2,int c1));
+static void s_iconv _((int c2,int c1));
+static void e_oconv _((int c2,int c1));
+static void s_oconv _((int c2,int c1));
+static void j_oconv _((int c2,int c1));
+static int line_fold _((int c2,int c1));
+static int pre_convert _((int c1,int c2));
+static int mime_begin _((FILE *f));
+static int mime_getc _((FILE *f));
+static int mime_ungetc _((unsigned int c));
+static int base64decode _((int c));
+static void arguments _((char *c));
+static void reinit _((void));
+
/* buffers */
static unsigned char hold_buf[HOLD_SIZE*2];
static int hold_count;
-static unsigned char *inptr;
-static char *outptr;
-static int outsiz;
-static int outlen;
/* MIME preprocessor fifo */
@@ -193,15 +206,16 @@ static int outlen;
static unsigned char mime_buf[MIME_BUF_SIZE];
static unsigned int mime_top = 0;
static unsigned int mime_last = 0; /* decoded */
-static unsigned int mime_input = 0; /* undecoded */
/* flags */
static int unbuf_f = FALSE;
static int estab_f = FALSE;
+static int nop_f = FALSE;
+static int binmode_f = TRUE; /* binary mode */
static int rot_f = FALSE; /* rot14/43 mode */
static int input_f = FALSE; /* non fixed input code */
static int alpha_f = FALSE; /* convert JIx0208 alphbet to ASCII */
-static int mime_f = FALSE; /* convert MIME B base64 or Q */
+static int mime_f = TRUE; /* convert MIME B base64 or Q */
static int mimebuf_f = FALSE; /* MIME buffered input */
static int broken_f = FALSE; /* convert ESC-less broken JIS */
static int iso8859_f = FALSE; /* ISO8859 through */
@@ -218,30 +232,47 @@ static int c1_return;
/* fold parameter */
static int line = 0; /* chars in line */
static int prev = 0;
-static int fold_f = FALSE;
-static int fold_len = 0;
+static int fold_f = FALSE;
+static int fold_len = 0;
/* options */
-static char kanji_intro = DEFAULT_J,
+static char kanji_intro = DEFAULT_J,
ascii_intro = DEFAULT_R;
/* Folding */
+int line_fold();
#define FOLD_MARGIN 10
#define DEFAULT_FOLD 60
+/* converters */
+
+#ifdef DEFAULT_CODE_JIS
+# define DEFAULT_CONV j_oconv
+#endif
+#ifdef DEFAULT_CODE_SJIS
+# define DEFAULT_CONV s_oconv
+#endif
+#ifdef DEFAULT_CODE_EUC
+# define DEFAULT_CONV e_oconv
+#endif
+
+static void (*iconv) _((int c2,int c1));
+ /* s_iconv or oconv */
+static void (*oconv) _((int c2,int c1)) = DEFAULT_CONV;
+ /* [ejs]_oconv */
+
/* Global states */
-static int output_mode = ASCII, /* output kanji mode */
+static int output_mode = ASCII, /* output kanji mode */
input_mode = ASCII, /* input kanji mode */
shift_mode = FALSE; /* TRUE shift out, or X0201 */
-static int mime_mode = FALSE; /* MIME mode B base64, Q hex */
+static int mime_mode = FALSE; /* MIME mode B base64, Q hex */
-/* X0208 -> ASCII translation table */
/* X0201 / X0208 conversion tables */
/* X0201 kana conversion table */
/* 90-9F A0-DF */
-static unsigned char cv[]= {
+unsigned char cv[]= {
0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57,
0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21,
0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29,
@@ -263,7 +294,7 @@ static unsigned char cv[]= {
/* X0201 kana conversion table for daguten */
/* 90-9F A0-DF */
-static unsigned char dv[]= {
+unsigned char dv[]= {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@@ -284,7 +315,7 @@ static unsigned char dv[]= {
/* X0201 kana conversion table for han-daguten */
/* 90-9F A0-DF */
-static unsigned char ev[]= {
+unsigned char ev[]= {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@@ -306,7 +337,8 @@ static unsigned char ev[]= {
/* X0208 kigou conversion table */
/* 0x8140 - 0x819e */
-static unsigned char fv[] = {
+unsigned char fv[] = {
+
0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a,
0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00,
0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00,
@@ -322,179 +354,26 @@ static unsigned char fv[] = {
} ;
-/* This converts =?ISO-2022-JP?B?HOGE HOGE?= */
-
-static unsigned char *mime_pattern[] = {
- (unsigned char *)"\075?ISO-8859-1?Q?",
- (unsigned char *)"\075?ISO-2022-JP?B?",
- (unsigned char *)"\075?ISO-2022-JP?Q?",
- NULL
-};
-
-static int mime_encode[] = {
- 'Q', 'B', 'Q',
- 0
-};
+static int file_out = FALSE;
+static int add_cr = FALSE;
+static int del_cr = FALSE;
-static int add_cr = FALSE;
-static int del_cr = FALSE;
-
-static void (*iconv) _((register int c2,register int c1)); /* s_iconv or oconv */
-static void (*oconv) _((register int c2,register int c1)); /* [ejs]_oconv */
-static int do_kconv _((char *i, char *o, int siz, int out_code, int in_code));
-static void h_conv _((register int c2,register int c1));
-static int push_hold_buf _((int c2,int c1));
-static void s_iconv _((register int c2,register int c1));
-static void e_oconv _((register int c2,register int c1));
-static void s_oconv _((register int c2,register int c1));
-static void j_oconv _((register int c2,register int c1));
-static int fold _((register int c2,register int c1));
-static int pre_convert _((register int c1,register int c2));
-static int mime_begin _((void));
-static int mime_getc _((void));
-static int mime_ungetc _((unsigned int c));
-static int mime_integrity _((unsigned char *p));
-static int base64decode _((int c));
-
-#ifdef notdef
-main (argc, argv)
+#ifndef PERL_XS
+int
+main(argc, argv)
int argc;
char **argv;
{
- register FILE *fin;
- register char *cp;
+ FILE *fin;
+ char *cp;
#ifdef EASYWIN /*Easy Win */
_BufferSize.y = 400;/*Set Scroll Buffer Size*/
#endif
-#ifdef DEFAULT_CODE_JIS
- oconv = j_oconv; /* DEFAULT Code is JIS */
-#endif
-#ifdef DEFAULT_CODE_SJIS
- oconv = s_oconv; /* DEFAULT Code is S-JIS */
-#endif
-#ifdef DEFAULT_CODE_EUC
- oconv = e_oconv; /* DEFAULT Code is EUC */
-#endif
for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) {
cp = *argv;
- while (*cp) {
- switch (*cp++) {
- case 'b': /* buffered mode */
- unbuf_f = FALSE;
- continue;
- case 'u': /* non bufferd mode */
- unbuf_f = TRUE;
- continue;
- case 'j': /* JIS output */
- case 'n':
- oconv = j_oconv;
- continue;
- case 'e': /* AT&T EUC output */
- oconv = e_oconv;
- continue;
- case 's': /* SJIS output */
- oconv = s_oconv;
- continue;
- case 'l': /* ISO8859 Latin-1 support, no conversion */
- iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */
- input_f = LATIN1_INPUT;
- continue;
- case 'i': /* Kanji IN ESC-$-@/B */
- if(*cp=='@'||*cp=='B')
- kanji_intro = *cp++;
- continue;
- case 'o': /* ASCII IN ESC-(-J/B */
- if(*cp=='J'||*cp=='B'||*cp=='H')
- ascii_intro = *cp++;
- continue;
- case 'r':
- rot_f = TRUE;
- continue;
-#if defined(MSDOS) || defined(__OS2__)
- case 'T':
- binmode_f = FALSE;
- continue;
-#endif
- case 'v':
- usage();
- exit(1);
- break;
- /* Input code assumption */
- case 'J': /* JIS input */
- case 'E': /* AT&T EUC input */
- input_f = JIS_INPUT;
- continue;
- case 'S': /* MS Kanji input */
- input_f = SJIS_INPUT;
- if(x0201_f==NO_X0201) x0201_f=TRUE;
- continue;
- case 'Z': /* Convert X0208 alphabet to asii */
- /* bit:0 Convert X0208
- bit:1 Convert Kankaku to one space
- bit:2 Convert Kankaku to two spaces
- */
- if('9'>= *cp && *cp>='0')
- alpha_f |= 1<<(*cp++ -'0');
- else
- alpha_f |= TRUE;
- continue;
- case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */
- x0201_f = FALSE; /* No X0201->X0208 conversion */
- /* accept X0201
- ESC-(-I in JIS, EUC, MS Kanji
- SI/SO in JIS, EUC, MS Kanji
- SSO in EUC, JIS, not in MS Kanji
- MS Kanji (0xa0-0xdf)
- output X0201
- ESC-(-I in JIS (0x20-0x5f)
- SSO in EUC (0xa0-0xdf)
- 0xa0-0xd in MS Kanji (0xa0-0xdf)
- */
- continue;
- case 'X': /* Assume X0201 kana */
- /* Default value is NO_X0201 for EUC/MS-Kanji mix */
- x0201_f = TRUE;
- continue;
- case 'f': /* folding -f60 or -f */
- fold_f = TRUE;
- fold_len = atoi(cp);
- if(!(0<fold_len && fold_len<BUFSIZ))
- fold_len = DEFAULT_FOLD;
- while('0'<= *cp && *cp <='9') cp++;
- continue;
- case 'm': /* MIME support */
- mime_f = TRUE;
- if(*cp=='B'||*cp=='Q') {
- mime_mode = *cp++;
- mimebuf_f = FIXED_MIME;
- }
- continue;
- case 'B': /* Broken JIS support */
- /* bit:0 no ESC JIS
- bit:1 allow any x on ESC-(-x or ESC-$-x
- bit:2 reset to ascii on NL
- */
- if('9'>= *cp && *cp>='0')
- broken_f |= 1<<(*cp++ -'0');
- else
- broken_f |= TRUE;
- continue;
- case 'O':/* for Output file */
- file_out = TRUE;
- continue;
- case 'c':/* add cr code */
- add_cr = TRUE;
- continue;
- case 'd':/* delete cr code */
- del_cr = TRUE;
- continue;
- default:
- /* bogus option but ignored */
- continue;
- }
- }
+ arguments(cp);
}
if(iso8859_f && (oconv != j_oconv || !x0201_f )) {
@@ -511,9 +390,9 @@ main (argc, argv)
#endif
if(unbuf_f)
- setbuf (stdout, (char *) NULL);
+ setbuf(stdout, (char *) NULL);
else
- setvbuffer (stdout, stdobuf, IOBUF_SIZE);
+ setvbuffer(stdout, stdobuf, IOBUF_SIZE);
if(argc == 0) {
if(binmode_f == TRUE)
@@ -522,25 +401,28 @@ main (argc, argv)
#else
setbinmode(stdin);
#endif
- setvbuffer (stdin, stdibuf, IOBUF_SIZE);
- convert (stdin);
+ setvbuffer(stdin, stdibuf, IOBUF_SIZE);
+ if(nop_f)
+ noconvert(stdin);
+ else
+ kanji_convert(stdin);
} else {
while (argc--) {
- if((fin = fopen (*argv++, "r")) == NULL) {
- perror (*--argv);
- return (-1);
+ if((fin = fopen(*argv++, "r")) == NULL) {
+ perror(*--argv);
+ return(-1);
} else {
/* reopen file for stdout */
if(file_out == TRUE){
if(argc == 1 ) {
if(freopen(*argv++, "w", stdout) == NULL) {
- perror (*--argv);
+ perror(*--argv);
return (-1);
}
argc--;
} else {
if(freopen("nkf.out", "w", stdout) == NULL) {
- perror (*--argv);
+ perror(*--argv);
return (-1);
}
}
@@ -560,9 +442,12 @@ main (argc, argv)
#else
setbinmode(fin);
#endif
- setvbuffer (fin, stdibuf, IOBUF_SIZE);
- convert (fin);
- fclose (fin);
+ setvbuffer(fin, stdibuf, IOBUF_SIZE);
+ if(nop_f)
+ noconvert(fin);
+ else
+ kanji_convert(fin);
+ fclose(fin);
}
}
}
@@ -577,60 +462,162 @@ main (argc, argv)
#endif
return (0);
}
-#endif /* notdef */
+#endif
+
+static void
+arguments(cp)
+ char *cp;
+{
+ while (*cp) {
+ switch (*cp++) {
+ case 'b': /* buffered mode */
+ unbuf_f = FALSE;
+ continue;
+ case 'u': /* non bufferd mode */
+ unbuf_f = TRUE;
+ continue;
+ case 't': /* transparent mode */
+ nop_f = TRUE;
+ continue;
+ case 'j': /* JIS output */
+ case 'n':
+ oconv = j_oconv;
+ continue;
+ case 'e': /* AT&T EUC output */
+ oconv = e_oconv;
+ continue;
+ case 's': /* SJIS output */
+ oconv = s_oconv;
+ continue;
+ case 'l': /* ISO8859 Latin-1 support, no conversion */
+ iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */
+ input_f = LATIN1_INPUT;
+ continue;
+ case 'i': /* Kanji IN ESC-$-@/B */
+ if(*cp=='@'||*cp=='B')
+ kanji_intro = *cp++;
+ continue;
+ case 'o': /* ASCII IN ESC-(-J/B */
+ if(*cp=='J'||*cp=='B'||*cp=='H')
+ ascii_intro = *cp++;
+ continue;
+ case 'r':
+ rot_f = TRUE;
+ continue;
+#if defined(MSDOS) || defined(__OS2__)
+ case 'T':
+ binmode_f = FALSE;
+ continue;
+#endif
+#ifndef PERL_XS
+ case 'v':
+ usage();
+ exit(1);
+ break;
+#endif
+ /* Input code assumption */
+ case 'J': /* JIS input */
+ case 'E': /* AT&T EUC input */
+ input_f = JIS_INPUT;
+ continue;
+ case 'S': /* MS Kanji input */
+ input_f = SJIS_INPUT;
+ if(x0201_f==NO_X0201) x0201_f=TRUE;
+ continue;
+ case 'Z': /* Convert X0208 alphabet to asii */
+ /* bit:0 Convert X0208
+ bit:1 Convert Kankaku to one space
+ bit:2 Convert Kankaku to two spaces
+ */
+ if('9'>= *cp && *cp>='0')
+ alpha_f |= 1<<(*cp++ -'0');
+ else
+ alpha_f |= TRUE;
+ continue;
+ case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */
+ x0201_f = FALSE; /* No X0201->X0208 conversion */
+ /* accept X0201
+ ESC-(-I in JIS, EUC, MS Kanji
+ SI/SO in JIS, EUC, MS Kanji
+ SSO in EUC, JIS, not in MS Kanji
+ MS Kanji (0xa0-0xdf)
+ output X0201
+ ESC-(-I in JIS (0x20-0x5f)
+ SSO in EUC (0xa0-0xdf)
+ 0xa0-0xd in MS Kanji (0xa0-0xdf)
+ */
+ continue;
+ case 'X': /* Assume X0201 kana */
+ /* Default value is NO_X0201 for EUC/MS-Kanji mix */
+ x0201_f = TRUE;
+ continue;
+ case 'f': /* folding -f60 or -f */
+ fold_f = TRUE;
+ fold_len = atoi(cp);
+ if(!(0<fold_len && fold_len<BUFSIZ))
+ fold_len = DEFAULT_FOLD;
+ while('0'<= *cp && *cp <='9') cp++;
+ continue;
+ case 'm': /* MIME support */
+ mime_f = TRUE;
+ if(*cp=='B'||*cp=='Q') {
+ mime_mode = *cp++;
+ mimebuf_f = FIXED_MIME;
+ } else if (*cp=='0') {
+ mime_f = FALSE;
+ }
+ continue;
+ case 'M': /* MIME output */
+ oconv = j_oconv; /* sorry... not yet done.. */
+ continue;
+ case 'B': /* Broken JIS support */
+ /* bit:0 no ESC JIS
+ bit:1 allow any x on ESC-(-x or ESC-$-x
+ bit:2 reset to ascii on NL
+ */
+ if('9'>= *cp && *cp>='0')
+ broken_f |= 1<<(*cp++ -'0');
+ else
+ broken_f |= TRUE;
+ continue;
+#ifndef PERL_XS
+ case 'O':/* for Output file */
+ file_out = TRUE;
+ continue;
+#endif
+ case 'c':/* add cr code */
+ add_cr = TRUE;
+ continue;
+ case 'd':/* delete cr code */
+ del_cr = TRUE;
+ continue;
+ default:
+ /* bogus option but ignored */
+ continue;
+ }
+ }
+}
-static int
-do_kconv(i, o, siz, out_code, in_code)
- char *i;
- char *o;
- int siz, out_code, in_code;
+#ifndef PERL_XS
+static void
+noconvert(f)
+ FILE *f;
{
- register int c1,
- c2;
+ int c;
- c2 = 0;
+ while ((c = getc(f)) != EOF)
+ putchar(c);
+}
+#endif
- if (siz <= 0) {
- return 0;
- }
- *o = '\0';
-
- inptr = (unsigned char *)i; /* input buffer */
- outptr = o; /* output buffer */
- outsiz = siz; /* output buffer size */
- outlen = 0; /* current length of output string */
- x0201_f = TRUE; /* don't assume JISX0201 kana */
- rot_f = FALSE; /* rot14/43 mode */
- input_f = FALSE; /* non fixed input code */
- alpha_f = FALSE; /* convert JISX0208 alphbet to ASCII */
- mime_f = TRUE; /* convert MIME base64 */
- broken_f = FALSE; /* convert ESC-less broken JIS */
-
- switch (out_code) {
- case _SJIS:
- oconv = s_oconv;
- break;
- case _EUC:
- oconv = e_oconv;
- break;
- default:
- oconv = j_oconv;
- break;
- }
- switch (in_code) {
- case _SJIS:
- input_f = SJIS_INPUT;
- x0201_f = TRUE;
- break;
- case _EUC:
- case _JIS:
- input_f = JIS_INPUT;
- break;
- default:
- input_f = FALSE;
- break;
- }
+static void
+kanji_convert(f)
+ FILE *f;
+{
+ int c1, c2;
+
+ c2 = 0;
if(input_f == JIS_INPUT || input_f == LATIN1_INPUT) {
estab_f = TRUE; iconv = oconv;
@@ -642,23 +629,12 @@ do_kconv(i, o, siz, out_code, in_code)
input_mode = ASCII;
output_mode = ASCII;
shift_mode = FALSE;
- mime_mode = FALSE;
#define NEXT continue /* no output, get next */
#define SEND ; /* output c1 and c2, get next */
#define LAST break /* end of loop, go closing */
- while ((c1 = GETC()) != EOF) {
- if(!c2 && !input_mode && c1<DEL && !mime_mode && !output_mode
- && !shift_mode && !fold_f && !rot_f) {
- /* plain ASCII tight loop, no conversion and no fold */
- while(c1!='=' && c1!=SO && c1!=EOF &&
- c1!=ESC && c1!='$' && c1<DEL && c1!='\r' && c1!='\n') {
- PUTCHAR(c1);
- c1 = _GETC();
- }
- if(c1==EOF) LAST;
- }
+ while ((c1 = GETC(f)) != EOF) {
if(c2) {
/* second byte */
if(c2 > DEL) {
@@ -667,7 +643,7 @@ do_kconv(i, o, siz, out_code, in_code)
/* in case of not established yet */
if(c1 > SSP) {
/* It is still ambiguious */
- h_conv (c2, c1);
+ h_conv(f, c2, c1);
c2 = 0;
NEXT;
} else if(c1 < AT) {
@@ -692,7 +668,7 @@ do_kconv(i, o, siz, out_code, in_code)
} else
/* 7 bit code */
/* it might be kanji shitfted */
- if((c1 == DEL) || (c1 <= SP)) {
+ if((c1 == DEL) || (c1 <= SPACE)) {
/* ignore bogus first code */
c2 = 0;
NEXT;
@@ -731,20 +707,20 @@ do_kconv(i, o, siz, out_code, in_code)
if(x0201_f) {
if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
/* look ahead for X0201/X0208conversion */
- if((c2 = GETC()) == EOF) {
+ if((c2 = GETC(f)) == EOF) {
(*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
LAST;
- } else if(c2==(0xde)) { /* ÂùÅÀ */
+ } else if(c2==(0xde)) { /* $BByE@(B */
(*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
c2=0;
NEXT;
} else if(c2==(0xdf)&&ev[(c1-SSP)*2]) {
- /* ȾÂùÅÀ */
+ /* $BH>ByE@(B */
(*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
c2=0;
NEXT;
}
- UNGETC(c2); c2 = 0;
+ UNGETC(c2,f); c2 = 0;
}
(*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
NEXT;
@@ -758,29 +734,29 @@ do_kconv(i, o, siz, out_code, in_code)
c2 = 0;
NEXT;
} */
- c1 = GETC(); /* skip SSO */
+ c1 = GETC(f); /* skip SSO */
euc_1byte_check:
if(x0201_f && SSP<=c1 && c1<0xe0) {
if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
- if((c2 = GETC()) == EOF) {
+ if((c2 = GETC(f)) == EOF) {
(*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
LAST;
}
- /* forward lookup ÂùÅÀ/ȾÂùÅÀ */
+ /* forward lookup $BByE@(B/$BH>ByE@(B */
if(c2 != SSO) {
- UNGETC(c2); c2 = 0;
+ UNGETC(c2,f); c2 = 0;
(*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
NEXT;
- } else if((c2 = GETC()) == EOF) {
+ } else if((c2 = GETC(f)) == EOF) {
(*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
(*oconv)(0,SSO);
LAST;
- } else if(c2==(0xde)) { /* ÂùÅÀ */
+ } else if(c2==(0xde)) { /* $BByE@(B */
(*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
c2=0;
NEXT;
} else if(c2==(0xdf)&&ev[(c1-SSP)*2]) {
- /* ȾÂùÅÀ */
+ /* $BH>ByE@(B */
(*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
c2=0;
NEXT;
@@ -807,7 +783,7 @@ do_kconv(i, o, siz, out_code, in_code)
NEXT;
}
}
- } else if((c1 > SP) && (c1 != DEL)) {
+ } else if((c1 > SPACE) && (c1 != DEL)) {
/* in case of Roman characters */
if(shift_mode) {
c1 |= 0x80;
@@ -815,20 +791,20 @@ do_kconv(i, o, siz, out_code, in_code)
if(x0201_f && (!iso8859_f||input_mode==X0201) &&
SSP<=c1 && c1<0xe0 ) {
if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) {
- if((c2 = GETC()) == EOF) {
+ if((c2 = GETC(f)) == EOF) {
(*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
LAST;
- } else if(c2==(0xde&0x7f)) { /* ÂùÅÀ */
+ } else if(c2==(0xde&0x7f)) { /* $BByE@(B */
(*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]);
c2=0;
NEXT;
} else if(c2==(0xdf&0x7f)&&ev[(c1-SSP)*2]) {
- /* ȾÂùÅÀ */
+ /* $BH>ByE@(B */
(*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]);
c2=0;
NEXT;
}
- UNGETC(c2); c2 = 0;
+ UNGETC(c2,f); c2 = 0;
}
(*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]);
NEXT;
@@ -837,15 +813,15 @@ do_kconv(i, o, siz, out_code, in_code)
} else if(c1 == '(' && broken_f && input_mode == X0208
&& !mime_mode ) {
/* Try to recover missing escape */
- if((c1 = GETC()) == EOF) {
- (*oconv) (0, '(');
+ if((c1 = GETC(f)) == EOF) {
+ (*oconv)(0, '(');
LAST;
} else {
if(c1 == 'B' || c1 == 'J' || c1 == 'H') {
input_mode = ASCII; shift_mode = FALSE;
NEXT;
} else {
- (*oconv) (0, '(');
+ (*oconv)(0, '(');
/* do not modify various input_mode */
/* It can be vt100 sequence */
SEND;
@@ -857,24 +833,24 @@ do_kconv(i, o, siz, out_code, in_code)
NEXT;
/* goto next_byte */
} else if(c1 == '=' && mime_f && !mime_mode ) {
- if((c1 = _GETC()) == EOF) {
- (*oconv) (0, '=');
+ if((c1 = getc(f)) == EOF) {
+ (*oconv)(0, '=');
LAST;
} else if(c1 == '?') {
- /* =? is mime conversion start sequence */
- if(mime_begin() == EOF) /* check in detail */
+ /* =? is mime conversiooon start sequence */
+ if(mime_begin(f) == EOF) /* check in detail */
LAST;
else
NEXT;
} else {
- (*oconv) (0, '=');
- _UNGETC(c1);
+ (*oconv)(0, '=');
+ ungetc(c1,f);
NEXT;
}
} else if(c1 == '$' && broken_f && !mime_mode) {
/* try to recover missing escape */
- if((c1 = GETC()) == EOF) {
- (*oconv) (0, '$');
+ if((c1 = GETC(f)) == EOF) {
+ (*oconv)(0, '$');
LAST;
} else if(c1 == '@'|| c1 == 'B') {
/* in case of Kanji in ESC sequence */
@@ -883,8 +859,8 @@ do_kconv(i, o, siz, out_code, in_code)
NEXT;
} else {
/* sorry */
- (*oconv) (0, '$');
- (*oconv) (0, c1);
+ (*oconv)(0, '$');
+ (*oconv)(0, c1);
NEXT;
}
} else
@@ -895,34 +871,52 @@ do_kconv(i, o, siz, out_code, in_code)
} else if(c1 == SO) {
shift_mode = TRUE;
NEXT;
- } else if(c1 == ESC ) {
- if((c1 = GETC()) == EOF) {
- (*oconv) (0, ESC);
+ } else if(c1 == ESC) {
+ if((c1 = GETC(f)) == EOF) {
+ (*oconv)(0, ESC);
LAST;
} else if(c1 == '$') {
- if((c1 = GETC()) == EOF) {
- (*oconv) (0, ESC);
- (*oconv) (0, '$');
+ if((c1 = GETC(f)) == EOF) {
+ (*oconv)(0, ESC);
+ (*oconv)(0, '$');
LAST;
} else if(c1 == '@'|| c1 == 'B') {
/* This is kanji introduction */
input_mode = X0208;
shift_mode = FALSE;
NEXT;
+ } else if(c1 == '(') {
+ if((c1 = GETC(f)) == EOF) {
+ (*oconv)(0, ESC);
+ (*oconv)(0, '$');
+ (*oconv)(0, '(');
+ LAST;
+ } else if(c1 == '@'|| c1 == 'B') {
+ /* This is kanji introduction */
+ input_mode = X0208;
+ shift_mode = FALSE;
+ NEXT;
+ } else {
+ (*oconv)(0, ESC);
+ (*oconv)(0, '$');
+ (*oconv)(0, '(');
+ (*oconv)(0, c1);
+ NEXT;
+ }
} else if(broken_f&0x2) {
input_mode = X0208;
shift_mode = FALSE;
NEXT;
} else {
- (*oconv) (0, ESC);
- (*oconv) (0, '$');
- (*oconv) (0, c1);
+ (*oconv)(0, ESC);
+ (*oconv)(0, '$');
+ (*oconv)(0, c1);
NEXT;
}
} else if(c1 == '(') {
- if((c1 = GETC()) == EOF) {
- (*oconv) (0, ESC);
- (*oconv) (0, '(');
+ if((c1 = GETC(f)) == EOF) {
+ (*oconv)(0, ESC);
+ (*oconv)(0, '(');
LAST;
} else {
if(c1 == 'I') {
@@ -937,15 +931,15 @@ do_kconv(i, o, siz, out_code, in_code)
input_mode = ASCII; shift_mode = FALSE;
NEXT;
} else {
- (*oconv) (0, ESC);
- (*oconv) (0, '(');
+ (*oconv)(0, ESC);
+ (*oconv)(0, '(');
/* maintain various input_mode here */
SEND;
}
}
} else {
/* lonely ESC */
- (*oconv) (0, ESC);
+ (*oconv)(0, ESC);
SEND;
}
} else if(c1 == NL && broken_f&4) {
@@ -956,26 +950,27 @@ do_kconv(i, o, siz, out_code, in_code)
}
/* send: */
if(input_mode == X0208)
- (*oconv) (c2, c1); /* this is JIS, not SJIS/EUC case */
+ (*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */
else
- (*iconv) (c2, c1); /* can be EUC/SJIS */
+ (*iconv)(c2, c1); /* can be EUC/SJIS */
c2 = 0;
continue;
/* goto next_word */
}
/* epilogue */
- (*iconv) (EOF, 0);
- return outlen;
+ (*iconv)(EOF, 0);
}
+
+
static void
-h_conv (c2, c1)
- register int c1,
- c2;
+h_conv(f, c2, c1)
+ FILE *f;
+ int c1, c2;
{
- register int wc;
+ int wc;
/** it must NOT be in the kanji shifte sequence */
@@ -983,10 +978,10 @@ h_conv (c2, c1)
/** and it must be after 2 byte 8bit code */
hold_count = 0;
- push_hold_buf (c2, c1);
+ push_hold_buf(c2, c1);
c2 = 0;
- while ((c1 = GETC()) != EOF) {
+ while ((c1 = GETC(f)) != EOF) {
if(c2) {
/* second byte */
if(!estab_f) {
@@ -1029,7 +1024,7 @@ h_conv (c2, c1)
SEND;
}
/* send: */
- if((push_hold_buf (c2, c1) == EOF) || estab_f)
+ if((push_hold_buf(c2, c1) == EOF) || estab_f)
break;
c2 = 0;
continue;
@@ -1047,7 +1042,7 @@ h_conv (c2, c1)
for (wc = 0; wc < hold_count; wc += 2) {
c2 = hold_buf[wc];
c1 = hold_buf[wc+1];
- (*iconv) (c2, c1);
+ (*iconv)(c2, c1);
}
return;
}
@@ -1055,9 +1050,8 @@ h_conv (c2, c1)
static int
-push_hold_buf (c2, c1)
- int c2,
- c1;
+push_hold_buf(c2, c1)
+ int c2, c1;
{
if(hold_count >= HOLD_SIZE*2)
return (EOF);
@@ -1068,8 +1062,8 @@ push_hold_buf (c2, c1)
static void
-s_iconv (c2, c1)
- register int c2,
+s_iconv(c2, c1)
+ int c2,
c1;
{
if((c2 == EOF) || (c2 == 0)) {
@@ -1077,30 +1071,29 @@ s_iconv (c2, c1)
} else {
c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394);
if(c1 < 0x9f)
- c1 = c1 - ((c1 > DEL) ? SP : 0x1f);
+ c1 = c1 - ((c1 > DEL) ? SPACE : 0x1f);
else {
c1 = c1 - 0x7e;
c2++;
}
}
- (*oconv) (c2, c1);
+ (*oconv)(c2, c1);
}
static void
-e_oconv (c2, c1)
- register int c2,
- c1;
+e_oconv(c2, c1)
+ int c2, c1;
{
c2 = pre_convert(c1,c2); c1 = c1_return;
if(fold_f) {
- switch(fold(c2,c1)) {
+ switch(line_fold(c2,c1)) {
case '\n':
if(add_cr == TRUE) {
- PUTCHAR('\r');
+ putchar('\r');
c1 = '\n';
}
- PUTCHAR('\n');
+ putchar('\n');
break;
case 0: return;
case '\r':
@@ -1113,46 +1106,46 @@ e_oconv (c2, c1)
}
}
if(c2==DOUBLE_SPACE) {
- PUTCHAR(' '); PUTCHAR(' ');
+ putchar(' '); putchar(' ');
return;
}
if(c2 == EOF)
return;
else if(c2 == 0 && (c1&0x80)) {
- PUTCHAR(SSO); PUTCHAR(c1);
+ putchar(SSO); putchar(c1);
} else if(c2 == 0) {
if(c1 == '\n' && add_cr == TRUE)
- PUTCHAR('\r');
+ putchar('\r');
if(c1 != '\r')
- PUTCHAR(c1);
+ putchar(c1);
else if(del_cr == FALSE)
- PUTCHAR(c1);
+ putchar(c1);
} else {
if((c1<0x20 || 0x7e<c1) ||
(c2<0x20 || 0x7e<c2)) {
estab_f = FALSE;
return; /* too late to rescue this char */
}
- PUTCHAR(c2 | 0x080);
- PUTCHAR(c1 | 0x080);
+ putchar(c2 | 0x080);
+ putchar(c1 | 0x080);
}
+ return;
}
static void
-s_oconv (c2, c1)
- register int c2,
- c1;
+s_oconv(c2, c1)
+ int c2, c1;
{
c2 = pre_convert(c1,c2); c1 = c1_return;
if(fold_f) {
- switch(fold(c2,c1)) {
+ switch(line_fold(c2,c1)) {
case '\n':
if(add_cr == TRUE) {
- PUTCHAR('\r');
+ putchar('\r');
c1 = '\n';
}
- PUTCHAR('\n');
+ putchar('\n');
break;
case '\r':
c1 = '\n'; c2 = 0;
@@ -1165,48 +1158,49 @@ s_oconv (c2, c1)
}
}
if(c2==DOUBLE_SPACE) {
- PUTCHAR(' '); PUTCHAR(' ');
+ putchar(' '); putchar(' ');
return;
}
if(c2 == EOF)
return;
else if(c2 == 0) {
if(c1 == '\n' && add_cr == TRUE)
- PUTCHAR('\r');
+ putchar('\r');
if(c1 != '\r')
- PUTCHAR(c1);
+ putchar(c1);
else if(del_cr == FALSE)
- PUTCHAR(c1);
+ putchar(c1);
} else {
if((c1<0x20 || 0x7e<c1) ||
(c2<0x20 || 0x7e<c2)) {
estab_f = FALSE;
return; /* too late to rescue this char */
}
- PUTCHAR((((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1)));
- PUTCHAR((c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e)));
+ putchar((((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1)));
+ putchar((c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e)));
}
+ return;
}
+
static void
-j_oconv (c2, c1)
- register int c2,
- c1;
+j_oconv(c2, c1)
+ int c2, c1;
{
c2 = pre_convert(c1,c2); c1 = c1_return;
if(fold_f) {
- switch(fold(c2,c1)) {
+ switch(line_fold(c2,c1)) {
case '\n':
if(output_mode) {
- PUTCHAR(ESC);
- PUTCHAR('(');
- PUTCHAR(ascii_intro);
+ putchar(ESC);
+ putchar('(');
+ putchar(ascii_intro);
}
if(add_cr == TRUE) {
- PUTCHAR('\r');
+ putchar('\r');
c1 = '\n';
}
- PUTCHAR('\n');
+ putchar('\n');
output_mode = ASCII;
break;
case '\r':
@@ -1221,16 +1215,16 @@ j_oconv (c2, c1)
}
if(c2 == EOF) {
if(output_mode) {
- PUTCHAR(ESC);
- PUTCHAR('(');
- PUTCHAR(ascii_intro);
+ putchar(ESC);
+ putchar('(');
+ putchar(ascii_intro);
}
} else if(c2 == 0 && (c1 & 0x80)) {
if(input_mode==X0201 || !iso8859_f) {
if(output_mode!=X0201) {
- PUTCHAR(ESC);
- PUTCHAR('(');
- PUTCHAR('I');
+ putchar(ESC);
+ putchar('(');
+ putchar('I');
output_mode = X0201;
}
c1 &= 0x7f;
@@ -1239,56 +1233,58 @@ j_oconv (c2, c1)
/* Can we convert in 7bit form using ESC-'-'-A ?
Is this popular? */
}
- PUTCHAR(c1);
+ putchar(c1);
} else if(c2 == 0) {
if(output_mode) {
- PUTCHAR(ESC);
- PUTCHAR('(');
- PUTCHAR(ascii_intro);
+ putchar(ESC);
+ putchar('(');
+ putchar(ascii_intro);
output_mode = ASCII;
}
if(c1 == '\n' && add_cr == TRUE)
- PUTCHAR('\r');
+ putchar('\r');
if(c1 != '\r')
- PUTCHAR(c1);
+ putchar(c1);
else if(del_cr == FALSE)
- PUTCHAR(c1);
+ putchar(c1);
} else if(c2 == DOUBLE_SPACE) {
if(output_mode) {
- PUTCHAR(ESC);
- PUTCHAR('(');
- PUTCHAR(ascii_intro);
+ putchar(ESC);
+ putchar('(');
+ putchar(ascii_intro);
output_mode = ASCII;
}
- PUTCHAR(' ');
+ putchar(' ');
if(c1 == '\n' && add_cr == TRUE)
- PUTCHAR('\r');
+ putchar('\r');
if(c1 != '\r')
- PUTCHAR(c1);
+ putchar(c1);
else if(del_cr == FALSE)
- PUTCHAR(c1);
+ putchar(c1);
} else {
if(output_mode != X0208) {
- PUTCHAR(ESC);
- PUTCHAR('$');
- PUTCHAR(kanji_intro);
+ putchar(ESC);
+ putchar('$');
+ putchar(kanji_intro);
output_mode = X0208;
}
if(c1<0x20 || 0x7e<c1)
return;
if(c2<0x20 || 0x7e<c2)
return;
- PUTCHAR(c2);
+ putchar(c2);
if(c1 == '\n' && add_cr == TRUE)
- PUTCHAR('\r');
+ putchar('\r');
if(c1 != '\r')
- PUTCHAR(c1);
+ putchar(c1);
else if(del_cr == FALSE)
- PUTCHAR(c1);
+ putchar(c1);
}
+ return;
}
+
#define rot13(c) ( \
( c < 'A' ) ? c: \
(c <= 'M') ? (c + 13): \
@@ -1306,8 +1302,9 @@ j_oconv (c2, c1)
c \
)
+
/*
- Return value of fold()
+ Return value of line_fold()
\n add newline and output char
\r add newline and output nothing
@@ -1327,8 +1324,8 @@ j_oconv (c2, c1)
*/
static int
-fold(c2,c1)
-register int c2,c1;
+line_fold(c2,c1)
+int c2,c1;
{
int prev0;
if(c1=='\r')
@@ -1403,11 +1400,11 @@ register int c2,c1;
}
/* simple kinsoku rules return 1 means no folding */
if(c2==0) {
- if(c1==0xde) return 1; /* ¡«*/
- if(c1==0xdf) return 1; /* ¡¬*/
- if(c1==0xa4) return 1; /* ¡£*/
- if(c1==0xa3) return 1; /* ¡¤*/
- if(c1==0xa1) return 1; /* ¡×*/
+ if(c1==0xde) return 1; /* $B!+(B*/
+ if(c1==0xdf) return 1; /* $B!,(B*/
+ if(c1==0xa4) return 1; /* $B!#(B*/
+ if(c1==0xa3) return 1; /* $B!$(B*/
+ if(c1==0xa1) return 1; /* $B!W(B*/
if(c1==0xb0) return 1; /* - */
if(SSP<=c1 && c1<=0xdf) { /* X0201 */
line = 1;
@@ -1433,16 +1430,16 @@ register int c2,c1;
return 1; /* default no fold in ASCII */
} else {
if(c2=='!') {
- if(c1=='"') return 1; /* ¡¢ */
- if(c1=='#') return 1; /* ¡£ */
- if(c1=='$') return 1; /* ¡¤ */
- if(c1=='%') return 1; /* ¡¥ */
- if(c1=='\'') return 1; /* ¡Ü */
- if(c1=='(') return 1; /* ¡¨ */
- if(c1==')') return 1; /* ¡© */
- if(c1=='*') return 1; /* ¡ª */
- if(c1=='+') return 1; /* ¡« */
- if(c1==',') return 1; /* ¡¬ */
+ if(c1=='"') return 1; /* $B!"(B */
+ if(c1=='#') return 1; /* $B!#(B */
+ if(c1=='$') return 1; /* $B!$(B */
+ if(c1=='%') return 1; /* $B!%(B */
+ if(c1=='\'') return 1; /* $B!\(B */
+ if(c1=='(') return 1; /* $B!((B */
+ if(c1==')') return 1; /* $B!)(B */
+ if(c1=='*') return 1; /* $B!*(B */
+ if(c1=='+') return 1; /* $B!+(B */
+ if(c1==',') return 1; /* $B!,(B */
}
line = 2;
return '\n'; /* add one new line before this character */
@@ -1451,7 +1448,7 @@ register int c2,c1;
static int
pre_convert(c1,c2)
-register int c1,c2;
+ int c1,c2;
{
if(c2) c1 &= 0x7f;
c1_return = c1;
@@ -1490,27 +1487,49 @@ register int c1,c2;
}
-static int iso8859_f_save;
+#ifdef STRICT_MIME
+/* This converts */
+
+unsigned char *mime_pattern[] = {
+ (unsigned char *)"\075?ISO-8859-1?Q?",
+ (unsigned char *)"\075?ISO-2022-JP?B?",
+ (unsigned char *)"\075?ISO-2022-JP?Q?",
+ (unsigned char *)"\075?JAPANESE_EUC?B?",
+ (unsigned char *)"\075?SHIFT_JIS?B?",
+ NULL
+};
+
+int mime_encode[] = {
+ 'Q', 'B', 'Q',
+ 0
+};
+#endif
+
+#define MAXRECOVER 20
+int iso8859_f_save;
+
+#ifdef STRICT_MIME
#define nkf_toupper(c) (('a'<=c && c<='z')?(c-('a'-'A')):c)
/* I don't trust portablity of toupper */
static int
-mime_begin()
+mime_begin(f)
+ FILE *f;
{
int c1;
int i,j,k;
unsigned char *p,*q;
- int r[20]; /* recovery buffer, max mime pattern lenght */
+ int r[MAXRECOVER]; /* recovery buffer, max mime pattern lenght */
mime_mode = FALSE;
- /* =? has been checked */
+ /* =? has been checked */
j = 0;
p = mime_pattern[j];
r[0]='='; r[1]='?';
for(i=2;p[i]>' ';i++) { /* start at =? */
- if( ((r[i] = c1 = _GETC())==EOF) || nkf_toupper(c1) != p[i] ) {
+ if( ((((r[i] = c1 = getc(f))==EOF) || nkf_toupper(c1) != p[i] ) {
/* pattern fails, try next one */
q = p;
while (p = mime_pattern[++j]) {
@@ -1520,34 +1539,92 @@ mime_begin()
}
if(p) continue; /* found next one, continue */
/* all fails, output from recovery buffer */
- _UNGETC(c1);
+ ungetc(c1,f);
for(j=0;j<i;j++) {
(*oconv)(0,r[j]);
}
return c1;
}
}
+ mime_mode = mime_encode[j];
iso8859_f_save = iso8859_f;
if(j==0) {
iso8859_f = TRUE;
}
- mime_mode = mime_encode[j];
if(mime_mode=='B') {
mimebuf_f = unbuf_f;
if(!unbuf_f) {
/* do MIME integrity check */
- return mime_integrity(mime_pattern[j]);
+ return mime_integrity(f,mime_pattern[j]);
}
}
mimebuf_f = TRUE;
return c1;
}
-#define mime_getc0() (mimebuf_f?_GETC():Fifo(mime_input++))
-#define mime_ungetc0(c) (mimebuf_f?_UNGETC(c):mime_input--)
+#define mime_getc0(f) (mimebuf_f?getc(f):Fifo(mime_input++))
+#define mime_ungetc0(c,f) (mimebuf_f?ungetc(c,f):mime_input--)
+
+#else
+static int
+mime_begin(f)
+FILE *f;
+{
+ int c1;
+ int i,j;
+ int r[MAXRECOVER]; /* recovery buffer, max mime pattern lenght */
+
+ mime_mode = FALSE;
+ /* =? has been checked */
+ j = 0;
+ r[0]='='; r[1]='?';
+ for(i=2;i<MAXRECOVER;i++) { /* start at =? */
+ /* We accept any charcter type even if it is breaked by new lines */
+ if( (r[i] = c1 = getc(f))==EOF) break;
+ if(c1=='=') break;
+ if(c1<' '&& c1!='\r' && c1!='\n') break;
+ if(c1=='?') {
+ i++;
+ if(!(i<MAXRECOVER) || (r[i] = c1 = getc(f))==EOF) break;
+ if(c1=='b'||c1=='B') {
+ mime_mode = 'B';
+ } else if(c1=='q'||c1=='Q') {
+ mime_mode = 'Q';
+ } else {
+ break;
+ }
+ i++;
+ if(!(i<MAXRECOVER) || (r[i] = c1 = getc(f))==EOF) break;
+ if(c1=='?') {
+ break;
+ } else {
+ mime_mode = FALSE;
+ }
+ break;
+ }
+ }
+ if(!mime_mode || c1==EOF || i==MAXRECOVER) {
+ ungetc(c1,f);
+ if (i == MAXRECOVER)
+ i--;
+ for(j=0;j<i;j++) {
+ (*oconv)(0,r[j]);
+ }
+ return c1;
+ }
+ iso8859_f_save = iso8859_f;
+ /* do no MIME integrity check */
+ return c1; /* used only for checking EOF */
+}
+
+#define mime_getc0(f) getc(f)
+#define mime_ungetc0(c,f) ungetc(c,f)
+
+#endif
static int
-mime_getc()
+mime_getc(f)
+ FILE *f;
{
int c1, c2, c3, c4, cc;
int t1, t2, t3, t4, mode, exit_mode;
@@ -1561,26 +1638,26 @@ mime_getc()
else
exit_mode = FALSE;
if(mime_mode == 'Q') {
- if((c1 = mime_getc0()) == EOF) return (EOF);
+ if((c1 = mime_getc0(f)) == EOF) return (EOF);
if(c1=='_') return ' ';
if(c1!='=' && c1!='?')
return c1;
mime_mode = exit_mode; /* prepare for quit */
if(c1<=' ') return c1;
- if((c2 = mime_getc0()) == EOF) return (EOF);
+ if((c2 = mime_getc0(f)) == EOF) return (EOF);
if(c2<=' ') return c2;
if(c1=='?'&&c2=='=') {
/* end Q encoding */
input_mode = exit_mode;
iso8859_f = iso8859_f_save;
- return _GETC();
+ return getc(f);
}
if(c1=='?') {
mime_mode = 'Q'; /* still in MIME */
- mime_ungetc0(c2);
+ mime_ungetc0(c2,f);
return c1;
}
- if((c3 = mime_getc0()) == EOF) return (EOF);
+ if((c3 = mime_getc0(f)) == EOF) return (EOF);
if(c2<=' ') return c2;
mime_mode = 'Q'; /* still in MIME */
#define hex(c) (('0'<=c&&c<='9')?(c-'0'):\
@@ -1590,7 +1667,7 @@ mime_getc()
if(mime_mode != 'B') {
mime_mode = FALSE;
- return _GETC();
+ return getc(f);
}
@@ -1605,11 +1682,11 @@ mime_getc()
mode = mime_mode;
mime_mode = exit_mode; /* prepare for quit */
- while ((c1 = mime_getc0())<=' ') {
+ while ((c1 = mime_getc0(f))<=' ') {
if(c1==EOF)
return (EOF);
}
- if((c2 = mime_getc0())<=' ') {
+ if((c2 = mime_getc0(f))<=' ') {
if(c2==EOF)
return (EOF);
if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;
@@ -1617,16 +1694,16 @@ mime_getc()
}
if((c1 == '?') && (c2 == '=')) {
input_mode = ASCII;
- while((c1 = _GETC())==' ' /* || c1=='\n' || c1=='\r' */);
+ while((c1 = getc(f))==' ' /* || c1=='\n' || c1=='\r' */);
return c1;
}
- if((c3 = mime_getc0())<=' ') {
+ if((c3 = mime_getc0(f))<=' ') {
if(c3==EOF)
return (EOF);
if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;
return c3;
}
- if((c4 = mime_getc0())<=' ') {
+ if((c4 = mime_getc0(f))<=' ') {
if(c4==EOF)
return (EOF);
if(mimebuf_f!=FIXED_MIME) input_mode = ASCII;
@@ -1659,27 +1736,28 @@ mime_getc()
static int
mime_ungetc(c)
-unsigned int c;
+ unsigned int c;
{
Fifo(mime_last++) = c;
return c;
}
-
-static int
-mime_integrity(p)
-unsigned char *p;
+#ifdef STRICT_MIME
+int
+mime_integrity(f,p)
+ FILE *f;
+ unsigned char *p;
{
int c,d;
unsigned int q;
- /* In buffered mode, read until =? or NL or buffer full
+ /* In buffered mode, read until =? or NL or buffer fffull
*/
mime_input = mime_top;
mime_last = mime_top;
while(*p) Fifo(mime_input++) = *p++;
d = 0;
q = mime_input;
- while((c=_GETC())!=EOF) {
+ while((c=getc(f))!=EOF) {
if(((mime_input-mime_top)&MIME_BUF_MASK)==0) break;
if(c=='=' && d=='?') {
/* checked. skip header, start decode */
@@ -1700,10 +1778,11 @@ unsigned char *p;
mime_mode = 1; /* no decode on Fifo last in mime_getc */
return 1;
}
+#endif
static int
base64decode(c)
- int c;
+ int c;
{
int i;
if(c > '@')
@@ -1720,7 +1799,37 @@ base64decode(c)
return (i);
}
-#ifdef notdef
+static void
+reinit()
+{
+ unbuf_f = FALSE;
+ estab_f = FALSE;
+ nop_f = FALSE;
+ binmode_f = TRUE;
+ rot_f = FALSE;
+ input_f = FALSE;
+ alpha_f = FALSE;
+ mime_f = TRUE;
+ mimebuf_f = FALSE;
+ broken_f = FALSE;
+ iso8859_f = FALSE;
+ x0201_f = TRUE;
+ x0201_f = NO_X0201;
+ fold_f = FALSE;
+ kanji_intro = DEFAULT_J;
+ ascii_intro = DEFAULT_R;
+ oconv = DEFAULT_CONV;
+ output_mode = ASCII;
+ input_mode = ASCII;
+ shift_mode = FALSE;
+ mime_mode = FALSE;
+ file_out = FALSE;
+ add_cr = FALSE;
+ del_cr = FALSE;
+ line = 0;
+}
+
+#ifndef PERL_XS
int
usage()
{
@@ -1742,7 +1851,7 @@ usage()
fprintf(stderr,"o_ Output sequence to designate ASCII (DEFAULT B)\n");
fprintf(stderr,"r {de/en}crypt ROT13/47\n");
fprintf(stderr,"v Show this usage\n");
- fprintf(stderr,"m[BQ] MIME decode [B:base64 stream,Q:quoted stream]\n");
+ fprintf(stderr,"m[BQ0] MIME decode [B:base64,Q:quoted,0:no decode]\n");
fprintf(stderr,"l ISO8859-1 (Latin-1) support\n");
fprintf(stderr,"f Folding: -f60 or -f\n");
fprintf(stderr,"Z[0-2] Convert X0208 alphabet to ASCII 1: Kankaku to space,2: 2 spaces\n");
@@ -1770,211 +1879,10 @@ usage()
fprintf(stderr,"\n%s\n",CopyRight);
return 0;
}
-#endif /* notdef */
-
-static VALUE
-kconv_kconv(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE src, dst;
- VALUE in, out;
- int in_code, out_code;
- char *codename = 0;
-
- rb_scan_args(argc, argv, "12", &src, &out, &in);
- Check_Type(src, T_STRING);
-
- if (NIL_P(out)) {
- codename = rb_get_kcode();
- goto codeselect;
- }
- else if (TYPE(out) == T_STRING) {
- codename = RSTRING(out)->ptr;
- codeselect:
- switch (codename[0]) {
- case 'E': case 'e':
- out_code = _EUC;
- break;
- case 'S': case 's':
- out_code = _SJIS;
- break;
- case 'J': case 'j':
- default:
- out_code = _JIS;
- break;
- }
- }
- else {
- out_code = NUM2INT(out);
- if (out_code == _NOCONV) return (VALUE)src;
- }
- if (NIL_P(in)) {
- in_code = _AUTO;
- }
- else if (TYPE(in) == T_STRING) {
- switch (RSTRING(in)->ptr[0]) {
- case 'E': case 'e':
- in_code = _EUC;
- break;
- case 'S': case 's':
- in_code = _SJIS;
- break;
- case 'J': case 'j':
- in_code = _JIS;
- break;
- default:
- in_code = _AUTO;
- break;
- }
- }
- else {
- in_code = NUM2INT(in);
- if (in_code == _NOCONV) return (VALUE)src;
- }
-
- dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */
- RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, out_code, in_code);
-
- return dst;
-}
-
-static VALUE
-kconv_tojis(obj, src)
- VALUE obj, src;
-{
- VALUE dst;
-
- Check_Type(src, T_STRING);
-
- dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */
- RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _JIS, _AUTO);
-
- return dst;
-}
-
-static VALUE
-kconv_toeuc(obj, src)
- VALUE obj, src;
-{
- VALUE dst;
-
- Check_Type(src, T_STRING);
-
- dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */
- RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _EUC, _AUTO);
-
- return (VALUE)dst;
-}
-
-static VALUE
-kconv_tosjis(obj, src)
- VALUE obj, src;
-{
- VALUE dst;
-
- Check_Type(src, T_STRING);
-
- dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */
- RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _SJIS, _AUTO);
-
- return dst;
-}
-
-/*
- * Character code detection - Algorithm described in:
- * Ken Lunde. `Understanding Japanese Information Processing'
- * Sebastopol, CA: O'Reilly & Associates.
- */
-
-static VALUE
-kconv_guess(obj, src)
- VALUE obj, src;
-{
- unsigned char *p = RSTRING(src)->ptr;
- unsigned char *pend = p + RSTRING(src)->len;
-
-#define INCR {p++;if (p==pend) return INT2FIX(_UNKNOWN);}
-
- while (p<pend) {
- if (*p == '\033') {
- return INT2FIX(_JIS);
- }
- if ('\000' < *p && *p < '\006'
- || *p == 0x7f
- || *p == 0xdf) {
- return INT2FIX(_BINARY);
- }
- if (0x81 <= *p && *p <= 0x8d) {
- return INT2FIX(_SJIS);
- }
- if (*p == 0x8e) {
- INCR;
- if ((0x40 <= *p && *p <= 0x7e) ||
- (0x80 <= *p && *p <= 0xa0) ||
- (0xe0 <= *p && *p <= 0xfc))
- return INT2FIX(_SJIS);
- }
- if (0xa1 <= *p && *p <= 0xdf) {
- INCR;
- if (0xf0 <= *p && *p <= 0xfe)
- return INT2FIX(_EUC);
- if (0xe0 <= *p && *p <= 0xef) {
- while (*p >= 0x40) {
- if (*p >= 0x81) {
- if (0x8d <= *p || (0x8f <= *p && *p <= 0x9f)) {
- return INT2FIX(_SJIS);
- }
- else if (0xfd <= *p && *p <= 0xfe) {
- return INT2FIX(_EUC);
- }
- }
- }
- }
- if (*p <= 0x9f) {
- return INT2FIX(_SJIS);
- }
- }
- if (0xf0 <= *p && *p <= 0xfe) {
- return INT2FIX(_EUC);
- }
- if (0xe0 <= *p && *p <= 0xef) {
- INCR;
- if ((0x40 <= *p && *p <= 0x7e) ||
- (0x80 <= *p && *p <= 0xa0)) {
- return INT2FIX(_SJIS);
- }
- if (0xfd <= *p && *p <= 0xfe) {
- return INT2FIX(_EUC);
- }
- }
- p++;
- }
- return INT2FIX(_UNKNOWN);
-}
-
-void
-Init_kconv()
-{
- VALUE mKconv = rb_define_module("Kconv");
-
- rb_define_module_function(mKconv, "kconv", kconv_kconv, -1);
- rb_define_module_function(mKconv, "tojis", kconv_tojis, 1);
- rb_define_module_function(mKconv, "toeuc", kconv_toeuc, 1);
- rb_define_module_function(mKconv, "tosjis", kconv_tosjis, 1);
- rb_define_module_function(mKconv, "guess", kconv_guess, 1);
-
- rb_define_const(mKconv, "AUTO", INT2FIX(_AUTO));
- rb_define_const(mKconv, "JIS", INT2FIX(_JIS));
- rb_define_const(mKconv, "EUC", INT2FIX(_EUC));
- rb_define_const(mKconv, "SJIS", INT2FIX(_SJIS));
- rb_define_const(mKconv, "BINARY", INT2FIX(_BINARY));
- rb_define_const(mKconv, "NOCONV", INT2FIX(_NOCONV));
- rb_define_const(mKconv, "UNKNOWN", INT2FIX(_UNKNOWN));
-}
+#endif
/**
- ** ¥Ñ¥Ã¥ÁÀ©ºî¼Ô
+ ** $B%Q%C%A@):n<T(B
** void@merope.pleiades.or.jp (Kusakabe Youichi)
** NIDE Naoyuki <nide@ics.nara-wu.ac.jp>
** ohta@src.ricoh.co.jp (Junn Ohta)
@@ -1984,10 +1892,9 @@ Init_kconv()
** a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe)
** kono@ie.u-ryukyu.ac.jp (Shinji Kono)
** GHG00637@nifty-serve.or.jp (COW)
- ** j_kuro@pluto.ai.kyutech.ac.jp (Jun Kuroda)
**
- ** ºÇ½ª¹¹¿·Æü
- ** 1996.12.18
+ ** $B:G=*99?7F|(B
+ ** 1998.11.7
**/
/* end */
diff --git a/ext/nkf/test.rb b/ext/nkf/test.rb
new file mode 100644
index 0000000000..4519f8ba7e
--- /dev/null
+++ b/ext/nkf/test.rb
@@ -0,0 +1,318 @@
+$counter = 0
+def result(result, message = nil)
+ $counter += 1
+ printf("%s %d%s\n",
+ result ? 'ok' : 'no',
+ $counter,
+ message ? ' ... ' + message : '')
+end
+
+begin
+ require 'nkf'
+ include NKF
+rescue LoadError
+ result(false)
+end
+result(true)
+
+if nkf('-me', '1')
+ result(true);
+else
+ result(false);
+end
+
+output = nkf('-e', "\033\$@#1#3#2%B")
+if output
+ # print output, "\n"
+ result(true, output)
+else
+ result(false)
+end
+
+output = nkf('-Zj', "\033\$@#1#3#2%B")
+if output
+ # print output, "\n"
+ result(true, output)
+else
+ result(false)
+end
+
+output = "\244\306 " * 1024
+old = output.length
+output = nkf("-j", output)
+if output
+ # print output, "\n"
+ result(true, "#{old} #{output.length}")
+else
+ result(false)
+end
+
+
+$detail = false
+def test(opt, input, expect)
+ print "\nINPUT:\n", input if $detail
+ print "\nEXPECT:\n", expect if $detail
+ result = nkf(opt, input)
+ print "\nGOT:\n", result if $detail
+
+ print result == expect ? "Ok\n" : "Fail\n"
+ return result
+end
+
+# Basic Conversion
+print "\nBasic Conversion test\n\n"
+
+example = {}
+example['jis'] = <<'eofeof'.unpack('u')[0]
+M1FER<W0@4W1A9V4@&R1"(3DQ(3%^2R%+?D]3&RA"(%-E8V]N9"!3=&%G92`;
+M)$)0)TU:&RA"($AI<F%G86YA(!LD0B0B)"0D)B0H)"HD;R1R)',;*$(*2V%T
+M86MA;F$@&R1")2(E)"4F)2@E*B5O)7(E<QLH0B!+:6=O=2`;)$(A)B%G(S`C
+/029!)E@G(B=!*$`;*$(*
+eofeof
+#'
+
+example['sjis'] = <<'eofeof'.unpack('u')[0]
+M1FER<W0@4W1A9V4@@5B)0(F>ED"6GIAR(%-E8V]N9"!3=&%G92"8I9=Y($AI
+M<F%G86YA((*@@J*"I(*F@JB"[8+P@O$*2V%T86MA;F$@@T&#0X-%@T>#28./
+>@Y*#DR!+:6=O=2"!18&'@D^"8(._@]:$081@A+X*
+eofeof
+#'
+
+example['euc'] = <<'eofeof'.unpack('u')[0]
+M1FER<W0@4W1A9V4@H;FQH;'^RZ'+_L_3(%-E8V]N9"!3=&%G92#0I\W:($AI
+M<F%G86YA(*2BI*2DIJ2HI*JD[Z3RI/,*2V%T86MA;F$@I:*EI*6FI:BEJJ7O
+>I?*E\R!+:6=O=2"AIJ'GH["CP:;!IMBGHJ?!J,`*
+eofeof
+#'
+
+example['amb'] = <<'eofeof'.unpack('u')[0]
+MI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&E
+MPK"QI<*PL:7"L+&EPK"QI<(*I<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*P
+ML:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<(*I<*PL:7"L+&E
+MPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"
+ML+&EPK"QI<(*I<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"Q
+MI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<(*I<*PL:7"L+&EPK"QI<*PL:7"
+ML+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<*PL:7"L+&EPK"QI<(*
+eofeof
+
+example['amb.euc'] = <<'eofeof'.unpack('u')[0]
+M&R1")4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25"
+M,#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&R1")4(P,25",#$E0C`Q)4(P,25"
+M,#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;
+M*$(*&R1")4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P
+M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&R1")4(P,25",#$E0C`Q)4(P
+M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
+M)4(;*$(*&R1")4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
+>)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*
+eofeof
+
+example['amb.sjis'] = <<'eofeof'.unpack('u')[0]
+M&RA))4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25"
+M,#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&RA))4(P,25",#$E0C`Q)4(P,25"
+M,#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;
+M*$(*&RA))4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P
+M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*&RA))4(P,25",#$E0C`Q)4(P
+M,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
+M)4(;*$(*&RA))4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q
+>)4(P,25",#$E0C`Q)4(P,25",#$E0C`Q)4(;*$(*
+eofeof
+
+example['x0201.sjis'] = <<'eofeof'.unpack('u')[0]
+MD5.*<(-*@TR#3H-0@U*#2X--@T^#48-3"I%3B7""8()A@F*"8X)D@F6"9H*!
+M@H*"@X*$@H6"AH*'"I%3BTR-AH%)@9>!E(&0@9.!3X&5@9:!:8%J@7R!>X&!
+M@6V!;H%O@7"!CPJ4O(IPMK>X/;FZMMZWWKC>N=ZZWH+&"I2\BG#*W\O?S-_-
+MW\[?M]^QW@K*W\O?S`IH86YK86MU(,K?R]_,I`K*W\O?S-VA"I2\BG""S(SC
+!"@!"
+eofeof
+#'
+
+example['x0201.euc'] = <<'eofeof'.unpack('u')[0]
+MP;2ST:6KI:VEKZ6QI;.EK*6NI;"ELJ6T"L&TL=&CP:/"H\.CQ*/%H\:CQZ/A
+MH^*CXZ/DH^6CYJ/G"L&TM:VYYJ&JH?>A]*'PH?.AL*'UH?:ARJ'+H=VAW*'A
+MH<ZASZ'0H=&A[PK(OK/1CK:.MXZX/8ZYCKJ.MH[>CK>.WHZXCMZ.N8[>CKJ.
+MWJ3("LB^L]&.RH[?CLN.WX[,CM^.S8[?CLZ.WXZWCM^.L8[>"H[*CM^.RX[?
+MCLP*:&%N:V%K=2".RH[?CLN.WX[,CJ0*CLJ.WX[+CM^.S([=CJ$*R+ZST:3.
+#N.4*
+eofeof
+#'
+
+example['x0201.jis'] = <<'eofeof'.unpack('u')[0]
+M&R1"030S424K)2TE+R4Q)3,E+"4N)3`E,B4T&RA""ALD0D$T,5$C02-"(T,C
+M1"-%(T8C1R-A(V(C8R-D(V4C9B-G&RA""ALD0D$T-2TY9B$J(7<A="%P(7,A
+M,"%U(78A2B%+(5TA7"%A(4XA3R%0(5$A;QLH0@H;)$)(/C-1&RA)-C<X&RA"
+M/1LH23DZ-EXW7CA>.5XZ7ALD0B1(&RA""ALD0D@^,U$;*$E*7TM?3%]-7TY?
+M-U\Q7ALH0@H;*$E*7TM?3!LH0@IH86YK86MU(!LH24I?2U],)!LH0@H;*$E*
+97TM?3%TA&RA""ALD0D@^,U$D3CAE&RA""@``
+eofeof
+#`
+
+example['x0201.sosi'] = <<'eofeof'.unpack('u')[0]
+M&R1"030S424K)2TE+R4Q)3,E+"4N)3`E,B4T&RA*"ALD0D$T,5$C02-"(T,C
+M1"-%(T8C1R-A(V(C8R-D(V4C9B-G&RA*"ALD0D$T-2TY9B$J(7<A="%P(7,A
+M,"%U(78A2B%+(5TA7"%A(4XA3R%0(5$A;QLH2@H;)$)(/C-1&RA*#C8W.`\;
+M*$H]#CDZ-EXW7CA>.5XZ7@\;)$(D2!LH2@H;)$)(/C-1&RA*#DI?2U],7TU?
+M3E\W7S%>#PH.2E]+7TP/&RA*"FAA;FMA:W4@#DI?2U],)`\;*$H*#DI?2U],
+672$/&RA*"ALD0D@^,U$D3CAE&RA""@``
+eofeof
+#"
+
+example['x0201.x0208'] = <<'eofeof'.unpack('u')[0]
+M&R1"030S424K)2TE+R4Q)3,E+"4N)3`E,B4T&RA""ALD0D$T,5$;*$)!0D-$
+M149'86)C9&5F9PH;)$)!-#4M.68;*$(A0",D)5XF*B@I+2L]6UU[?1LD0B%O
+M&RA""ALD0D@^,U$E*R4M)2\;*$(]&R1")3$E,R4L)2XE,"4R)30D2!LH0@H;
+M)$)(/C-1)5$E5"57)5HE724M(2PE(B$K&RA""ALD0B51)50E51LH0@IH86YK
+M86MU(!LD0B51)50E52$B&RA""ALD0B51)50E525S(2,;*$(*&R1"2#XS421.
+&.&4;*$(*
+eofeof
+#`
+
+example['mime.iso2022'] = <<'eofeof'.unpack('u')[0]
+M/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W96E23TI566Q/4U9)1WEH2S\]"CT_
+M:7-O+3(P,C(M2E`_0C]'>5)!3D5%-V5I4D]*55EL3U-624=Y:$L_/0H]/VES
+M;RTR,#(R+4I0/U$_/3%")$(D1B11/3%"*$)?96YD/ST*&R1`)#TD)B0K)$H;
+M*$H@/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W96E23U!Y:S=D:'-O4V<]/3\]
+M(&5N9"!O9B!L:6YE"CT_25-/+3(P,C(M2E`_0C]'>5)!3D5%-V5I4D]0>6LW
+M9&AS;U-G/3T_/2`]/TE33RTR,#(R+4I0/T(_1WE204Y%13=E:5)/4'EK-V1H
+M<V]39ST]/ST*0G)O:V5N(&-A<V4*/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W
+M96E23U!Y:S=D"FAS;U-G/3T_/2`]/TE33RTR,`HR,BU*4#]"/T=Y4D%.144W
+M96E23U!Y:S=D:'-O4V<]/3\]"CT_25-/+3(P,C(M2E`_0C]'>5)!3D5%-V5I
+44D]*55EL3QM;2U-624=Y:$L_/0H_
+eofeof
+#'
+
+example['mime.ans.strict'] = <<'eofeof'.unpack('u')[0]
+M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
+M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
+M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
+M/3])4T\M,C`R,BU*4#]"/T=Y4D%.144W96E23U!Y:S=D"FAS;U-G/3T_/2`]
+M/TE33RTR,`HR,BU*4#]"/T=Y4D%.144W96E23U!Y:S=D:'-O4V<]/3\]"CT_
+L25-/+3(P,C(M2E`_0C]'>5)!3D5%-V5I4D]*55EL3QM;2U-624=Y:$L_/0H_
+eofeof
+#'
+
+example['mime.unbuf.strict'] = <<'eofeof'.unpack('u')[0]
+M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
+M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
+M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
+M&R1"-$$[>B1./RD;*$)H<V]39ST]/ST@/3])4T\M,C`*,C(M2E`_0C]'>5)!
+M3D5%-V5I4D]0>6LW9&AS;U-G/3T_/0H;)$(T03MZ)$XE1ALH0EM+4U9)1WEH
+$2S\]"F5I
+eofeof
+
+example['mime.ans'] = <<'eofeof'.unpack('u')[0]
+M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
+M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
+M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
+M&R1"-$$[>B1./RD;*$)H<V]39ST]/ST@&R1"-$$[>B1./RD[=ALH0@H;)$(T
+603MZ)$XE1ALH0EM+4U9)1WEH2S\]"@`*
+eofeof
+#"
+
+example['mime.unbuf'] = <<'eofeof'.unpack('u')[0]
+M&R1"-$$[>B1.)48E.25(&RA""ALD0C1!.WHD3B5&)3DE2!LH0@H;)$(D1B11
+M&RA"(&5N9`H;)$(D/20F)"LD2ALH0B`;)$(T03MZ)$X_*3MV&RA"96YD(&]F
+M(&QI;F4*&R1"-$$[>B1./RD[=C1!.WHD3C\I.W8;*$(*0G)O:V5N(&-A<V4*
+M&R1"-$$[>B1./RD;*$)H<V]39ST]/ST@&R1"-$$[>B1./RD[=ALH0@H;)$(T
+603MZ)$XE1ALH0EM+4U9)1WEH2S\]"@`*
+eofeof
+#"
+
+example['mime.base64'] = <<'eofeof'.unpack('u')[0]
+M9W-M5"])3&YG<FU#>$I+-&=Q=4,S24LS9W%Q0E%:3TUI-39,,S0Q-&=S5T)1
+M43!+9VUA1%9O3T@*9S)+1%1O3'=K8C)1;$E+;V=Q2T-X24MG9W5M0W%*3EEG
+<<T=#>$E+9V=U;4,X64Q&9W)70S592VMG<6U""F=Q
+eofeof
+#"
+
+example['mime.base64.ans'] = <<'eofeof'.unpack('u')[0]
+M&R1")$M&?B1I)#LD1D0Z)"TD7B0Y)"PA(D5L-7XV83E9)$<A(ALH0@T*&R1"
+M(T<E-R5G)4,E+R1R0C\_="0J)"0D1B0B)&LD*D4Y)$,D1B0B)&LD<R1')#<D
+(9R0F)"L;*$(E
+eofeof
+#'
+
+example['mime.is8859'] = <<'eofeof'.unpack('u')[0]
+M/3])4T\M.#@U.2TQ/U$_*CU#-V%V83\_/2`*4&5E<B!4]G)N9W)E;@I,87-S
+M92!(:6QL97+X92!0971E<G-E;B`@7"`B36EN(&MA97!H97-T(&AA<B!F86%E
+M="!E="!F;V5L(2(*06%R:'5S(%5N:79E<G-I='DL($1%3DU!4DL@(%P@(DUI
+<;B!KYG!H97-T(&AA<B!FY65T(&5T(&;X;"$B"@!K
+eofeof
+
+example['mime.is8859.ans'] = <<'eofeof'.unpack('u')[0]
+M*L=A=F$_(`I0965R(%3V<FYG<F5N"DQA<W-E($AI;&QE<OAE(%!E=&5R<V5N
+M("!<(")-:6X@:V%E<&AE<W0@:&%R(&9A865T(&5T(&9O96PA(@I!87)H=7,@
+M56YI=F5R<VET>2P@1$5.34%22R`@7"`B36EN(&OF<&AE<W0@:&%R(&;E970@
+)970@9OAL(2(*
+eofeof
+#"
+
+print 'JIS to JIS ... '; test(' ', example['jis'], example['jis'])
+print 'JIS to SJIS... '; test('-s', example['jis'], example['sjis'])
+print 'JIS to EUC ... '; test('-e', example['jis'], example['euc'])
+
+print 'SJIS to JIS ... '; test('-j', example['sjis'], example['jis'])
+print 'SJIS to SJIS... '; test('-s', example['sjis'], example['sjis'])
+print 'SJIS to EUC ... '; test('-e', example['sjis'], example['euc'])
+
+print 'EUC to JIS ... '; test(' ', example['euc'], example['jis'])
+print 'EUC to SJIS... '; test('-s', example['euc'], example['sjis'])
+print 'EUC to EUC ... '; test('-e', example['euc'], example['euc'])
+
+
+# Ambigous Case
+print 'Ambiguous Case. '; test('' , example['amb'], example['amb.euc'])
+
+# Input assumption
+print 'SJIS Input assumption '
+test('-Sx', example['amb'], example['amb.sjis'])
+
+# X0201 ²¾Ì¾
+# X0201->X0208 conversion
+# X0208 aphabet -> ASCII
+# X0201 Áê¸ßÊÑ´¹
+
+print "\nX0201 test\n\n"
+
+# -X is necessary to allow X0201 in SJIS
+# -Z convert X0208 alphabet to ASCII
+print 'X0201 conversion: SJIS '
+test('-XZ', example['x0201.sjis'], example['x0201.x0208'])
+print 'X0201 conversion: JIS '
+test('-Z', example['x0201.jis'], example['x0201.x0208'])
+print 'X0201 conversion:SI/SO '
+test('-Z', example['x0201.sosi'], example['x0201.x0208'])
+print 'X0201 conversion: EUC '
+test('-Z', example['x0201.euc'], example['x0201.x0208'])
+# -x means X0201 output
+print 'X0201 output: SJIS '
+test('-xs', example['x0201.euc'], example['x0201.sjis'])
+print 'X0201 output: JIS '
+test('-xj', example['x0201.sjis'], example['x0201.jis'])
+print 'X0201 output: EUC '
+test('-xe', example['x0201.jis'], example['x0201.euc'])
+
+# MIME decode
+
+print "\nMIME test\n\n"
+
+# MIME ISO-2022-JP
+
+print "Next test is expeced to Fail.\n"
+
+print 'MIME decode (strict) '
+tmp = test('-m', example['mime.iso2022'], example['mime.ans.strict'])
+print 'MIME decode (nonstrict)'
+tmp = test('-m', example['mime.iso2022'], example['mime.ans'])
+# open(OUT,'>tmp1');print OUT pack('u',$tmp);close(OUT);
+# unbuf mode implies more pessimistic decode
+print 'MIME decode (unbuf) '
+test('-mu', example['mime.iso2022'], example['mime.unbuf'])
+print 'MIME decode (base64) '
+t = test('-mB', example['mime.base64'], example['mime.base64.ans'])
+
+# MIME ISO-8859-1
+
+# Without -l, ISO-8859-1 was handled as X0201.
+
+print 'MIME ISO-8859-1 (Q) '
+test('-ml', example['mime.is8859'], example['mime.is8859.ans'])
diff --git a/ext/pty/.cvsignore b/ext/pty/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/pty/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/pty/MANIFEST b/ext/pty/MANIFEST
new file mode 100644
index 0000000000..f46d611e5b
--- /dev/null
+++ b/ext/pty/MANIFEST
@@ -0,0 +1,12 @@
+MANIFEST
+README
+README.expect
+README.expect.jp
+README.jp
+depend
+expect_sample.rb
+extconf.rb
+lib/expect.rb
+pty.c
+script.rb
+shl.rb
diff --git a/ext/pty/README b/ext/pty/README
new file mode 100644
index 0000000000..a09469d39c
--- /dev/null
+++ b/ext/pty/README
@@ -0,0 +1,93 @@
+pty extension version 0.3 by A.ito
+
+1. Introduction
+
+This extension module adds ruby a functionality to execute an
+arbitrary command through pseudo tty (pty).
+
+2. Install
+
+Follow the instruction below.
+
+(1) Execute
+
+ ruby extconf.rb
+
+ then Makefile is generated.
+
+(3) Do make; make install.
+
+3. What you can do
+
+This extension module defines a module named PTY, which contains
+following module fungtions:
+
+ getpty(command)
+ spawn(command)
+
+ This function reserves a pty, executes command over the pty
+ and returns an array. The return value is an array with three
+ elements. The first element in the array is for reading and the
+ second for writing. The third element is the process ID of the
+ child process. If this function is called with an iterator block,
+ the array is passed to the block as block parameters, and the
+ function itself returns nil.
+
+ While the process spawned by this function is active, SIGCHLD
+ is captured to handle the change of the child process. When the
+ child process is suspended or finished, an exception is raised.
+ As all SIGCHLD signal is captured and processed by PTY module,
+ you can't use other function or method which spawns subprosesses
+ (including signal() and IO.popen()) while the PTY subprocesses
+ are active. Otherwise, unexpected exception will occur. To avoid
+ this problem, see protect_signal() below.
+
+ If this function is called with an iterator block, SIGCHLD signal
+ is captured only within the block. Therefore, it is risky to use
+ File objects for PTY subprocess outside the iterator block.
+
+
+ protect_signal
+
+ This function takes an iterator block. Within the iterator block,
+ no exception is raised even if any subprocess is terminated.
+ This function is used to enable functions like system() or IO.popen()
+ while PTY subprocess is active. For example,
+
+ PTY.spawn("command_foo") do |r,w|
+ ...
+ ...
+ PTY.protect_signal do
+ system "some other commands"
+ end
+ ...
+ end
+
+ disables to send exception when "some other commands" is
+ terminated.
+
+ reset_signal
+
+ Disables to handle SIGCHLD while PTY subprocess is active.
+
+
+4. License
+
+(C) Copyright 1998 by Akinori Ito.
+
+This software may be redistributed freely for this purpose, in full
+or in part, provided that this entire copyright notice is included
+on any copies of this software and applications and derivations thereof.
+
+This software is provided on an "as is" basis, without warranty of any
+kind, either expressed or implied, as to any matter including, but not
+limited to warranty of fitness of purpose, or merchantability, or
+results obtained from use of this software.
+
+5. Bug report
+
+Please feel free to send E-mail to
+
+ aito@ei5sun.yz.yamagata-u.ac.jp
+
+for any bug report, opinion, contribution, etc.
diff --git a/ext/pty/README.expect b/ext/pty/README.expect
new file mode 100644
index 0000000000..fddbb6fdad
--- /dev/null
+++ b/ext/pty/README.expect
@@ -0,0 +1,22 @@
+ README for expect
+ by A. Ito, 28 October, 1998
+
+ Expect library adds IO class a method called expect(), which
+does similar act to tcl's expect extension.
+
+The usage of the method is:
+
+ IO#expect(pattern,timeout=9999999)
+
+where `pattern' is an instance of String or Regexp and `timeout'
+is Fixnum, which can be omitted.
+ When the method is called without block, it waits until the
+input which matches the pattern is obtained from the IO or the time
+specified as the timeout passes. When the pattern is obtained from the
+IO, the method returns an array. The first element of the array is the
+entire string obtained from the IO until the pattern matches. The
+following elements indicates the specific pattern which matched to the
+anchor in the regular expression. If the method ends because of
+timeout, it returns nil.
+ When the method is called with block, the array is passed as
+the block parameter.
diff --git a/ext/pty/README.expect.jp b/ext/pty/README.expect.jp
new file mode 100644
index 0000000000..db84695ee5
--- /dev/null
+++ b/ext/pty/README.expect.jp
@@ -0,0 +1,21 @@
+ README for expect
+ by A. Ito, 28 October, 1998
+
+ Expect¥é¥¤¥Ö¥é¥ê¤Ï¡¤tcl ¤Î expect ¥Ñ¥Ã¥±¡¼¥¸¤È»÷¤¿¤è¤¦¤Êµ¡Ç½¤ò
+IO¥¯¥é¥¹¤ËÄɲä·¤Þ¤¹¡¥
+
+ Äɲ䵤ì¤ë¥á¥½¥Ã¥É¤Î»È¤¤Êý¤Ï¼¡¤ÎÄ̤ê¤Ç¤¹¡¥
+
+ IO#expect(pattern,timeout=9999999)
+
+pattern ¤Ï String ¤« Regexp ¤Î¥¤¥ó¥¹¥¿¥ó¥¹¡¤timeout ¤Ï Fixnum
+¤Î¥¤¥ó¥¹¥¿¥ó¥¹¤Ç¤¹¡¥timeout ¤Ï¾Êά¤Ç¤­¤Þ¤¹¡¥
+ ¤³¤Î¥á¥½¥Ã¥É¤¬¥Ö¥í¥Ã¥¯¤Ê¤·¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¡¤¤Þ¤º¥ì¥·¡¼¥Ð¤Ç¤¢¤ë
+IO¥ª¥Ö¥¸¥§¥¯¥È¤«¤é pattern ¤Ë¥Þ¥Ã¥Á¤¹¤ë¥Ñ¥¿¡¼¥ó¤¬ÆÉ¤ß¤³¤Þ¤ì¤ë
+¤Þ¤ÇÂÔ¤Á¤Þ¤¹¡¥¥Ñ¥¿¡¼¥ó¤¬ÆÀ¤é¤ì¤¿¤é¡¤¤½¤Î¥Ñ¥¿¡¼¥ó¤Ë´Ø¤¹¤ëÇÛÎó¤ò
+ÊÖ¤·¤Þ¤¹¡¥ÇÛÎó¤ÎºÇ½é¤ÎÍ×ÁǤϡ¤pattern ¤Ë¥Þ¥Ã¥Á¤¹¤ë¤Þ¤Ç¤ËÆÉ¤ß¤³
+¤Þ¤ì¤¿ÆâÍÆ¤Îʸ»úÎó¤Ç¤¹¡¥2ÈÖÌܰʹߤÎÍ×ÁǤϡ¤pattern ¤ÎÀµµ¬É½¸½
+¤ÎÃæ¤Ë¥¢¥ó¥«¡¼¤¬¤¢¤Ã¤¿¾ì¹ç¤Ë¡¤¤½¤Î¥¢¥ó¥«¡¼¤Ë¥Þ¥Ã¥Á¤¹¤ëÉôʬ¤Ç¤¹¡¥
+¤â¤·¥¿¥¤¥à¥¢¥¦¥È¤¬µ¯¤­¤¿¾ì¹ç¤Ï¡¤¤³¤Î¥á¥½¥Ã¥É¤Ïnil¤òÊÖ¤·¤Þ¤¹¡¥
+ ¤³¤Î¥á¥½¥Ã¥É¤¬¥Ö¥í¥Ã¥¯ÉÕ¤­¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¤Ë¤Ï¡¤¥Þ¥Ã¥Á¤·¤¿Í×ÁǤÎ
+ÇÛÎ󤬥֥í¥Ã¥¯°ú¿ô¤È¤·¤ÆÅϤµ¤ì¡¤¥Ö¥í¥Ã¥¯¤¬É¾²Á¤µ¤ì¤Þ¤¹¡¥
diff --git a/ext/pty/README.jp b/ext/pty/README.jp
new file mode 100644
index 0000000000..5ae4fb06a0
--- /dev/null
+++ b/ext/pty/README.jp
@@ -0,0 +1,89 @@
+pty ³ÈÄ¥¥â¥¸¥å¡¼¥ë version 0.3 by A.ito
+
+1. ¤Ï¤¸¤á¤Ë
+
+¤³¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ï¡¤²¾ÁÛtty (pty) ¤òÄ̤·¤ÆÅ¬Åö¤Ê¥³¥Þ¥ó¥É¤ò
+¼Â¹Ô¤¹¤ëµ¡Ç½¤ò ruby ¤ËÄ󶡤·¤Þ¤¹¡¥
+
+2. ¥¤¥ó¥¹¥È¡¼¥ë
+
+¼¡¤Î¤è¤¦¤Ë¤·¤Æ¥¤¥ó¥¹¥È¡¼¥ë¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+(1) ruby extconf.rb
+
+ ¤ò¼Â¹Ô¤¹¤ë¤È Makefile ¤¬À¸À®¤µ¤ì¤Þ¤¹¡¥
+
+(2) make; make install ¤ò¼Â¹Ô¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+3. ²¿¤¬¤Ç¤­¤ë¤«
+
+¤³¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ï¡¤PTY ¤È¤¤¤¦¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤·¤Þ¤¹¡¥¤½¤ÎÃæ
+¤Ë¤Ï¡¤¼¡¤Î¤è¤¦¤Ê¥â¥¸¥å¡¼¥ë´Ø¿ô¤¬´Þ¤Þ¤ì¤Æ¤¤¤Þ¤¹¡¥
+
+ getpty(command)
+ spawn(command)
+
+ ¤³¤Î´Ø¿ô¤Ï¡¤²¾ÁÛtty¤ò³ÎÊݤ·¡¤»ØÄꤵ¤ì¤¿¥³¥Þ¥ó¥É¤ò¤½¤Î²¾ÁÛtty
+ ¤Î¸þ¤³¤¦¤Ç¼Â¹Ô¤·¡¤ÇÛÎó¤òÊÖ¤·¤Þ¤¹¡¥Ìá¤êÃͤÏ3¤Ä¤ÎÍ×ÁǤ«¤é¤Ê¤ë
+ ÇÛÎó¤Ç¤¹¡¥ºÇ½é¤ÎÍ×ÁǤϲ¾ÁÛtty¤«¤éÆÉ¤ß½Ð¤¹¤¿¤á¤ÎIO¥ª¥Ö¥¸¥§¥¯¥È¡¤
+ 2ÈÖÌܤϽñ¤­¤³¤à¤¿¤á¤ÎIO¥ª¥Ö¥¸¥§¥¯¥È¡¤3ÈÖÌÜ¤Ï»Ò¥×¥í¥»¥¹¤Î¥×¥í
+ ¥»¥¹ID¤Ç¤¹¡¥¤³¤Î´Ø¿ô¤¬¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ð¤ì¤¿¾ì¹ç¡¤¤³¤ì¤é¤Î
+ Í×ÁǤϥ֥í¥Ã¥¯¥Ñ¥é¥á¡¼¥¿¤È¤·¤ÆÅϤµ¤ì¡¤´Ø¿ô¼«ÂΤÏnil¤òÊÖ¤·¤Þ¤¹¡¥
+
+ ¤³¤Î´Ø¿ô¤Ë¤è¤Ã¤Æºî¤é¤ì¤¿¥µ¥Ö¥×¥í¥»¥¹¤¬Æ°¤¤¤Æ¤¤¤ë´Ö¡¤»Ò¥×¥í¥»¥¹
+ ¤Î¾õÂÖ¤ò´Æ»ë¤¹¤ë¤¿¤á¤Ë SIGCHLD ¥·¥°¥Ê¥ë¤òÊ᪤·¤Þ¤¹¡¥»Ò¥×¥í¥»¥¹
+ ¤¬½ªÎ»¤·¤¿¤êÄä»ß¤·¤¿¾ì¹ç¤Ë¤Ï¡¤Îã³°¤¬È¯À¸¤·¤Þ¤¹¡¥¤³¤Î´Ö¡¤¤¹¤Ù¤Æ¤Î
+ SIGCHLD ¤¬ PTY ¥â¥¸¥å¡¼¥ë¤Î¥·¥°¥Ê¥ë¥Ï¥ó¥É¥é¤ËÊ᪤µ¤ì¤ë¤Î¤Ç¡¤
+ ¥µ¥Ö¥×¥í¥»¥¹¤òÀ¸À®¤¹¤ë¾¤Î´Ø¿ô(system() ¤È¤« IO.popen()¤Ê¤É)¤ò
+ »È¤¦¤È¡¤Í½´ü¤·¤Ê¤¤Îã³°¤¬È¯À¸¤¹¤ë¤³¤È¤¬¤¢¤ê¤Þ¤¹¡¥¤³¤ì¤òËɤ°¤¿¤á
+ ¤Ë¤Ï¡¤²¼µ­¤Îprotect_signal()¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+ ¤³¤Î´Ø¿ô¤¬¥Ö¥í¥Ã¥¯¥Ñ¥é¥á¡¼¥¿ÉÕ¤­¤Ç¸Æ¤Ð¤ì¤¿¾ì¹ç¤Ë¤Ï¡¤¤½¤Î¥Ö¥í¥Ã¥¯
+ ¤ÎÃæ¤Ç¤Î¤ß SIGCHLD ¤¬Ê᪤µ¤ì¤Þ¤¹¡¥¤·¤¿¤¬¤Ã¤Æ¡¤¥Ö¥í¥Ã¥¯¥Ñ¥é¥á¡¼¥¿
+ ¤È¤·¤ÆÅϤµ¤ì¤¿IO¥ª¥Ö¥¸¥§¥¯¥È¤ò¡¤¥Ö¥í¥Ã¥¯¤Î³°¤Ë»ý¤Á½Ð¤·¤Æ»È¤¦¤Î
+ ¤Ï´«¤á¤é¤ì¤Þ¤»¤ó¡¥
+
+
+ protect_signal
+
+ ¤³¤Î´Ø¿ô¤Ï¥¤¥Æ¥ì¡¼¥¿¤Ç¤¹¡¥¤³¤³¤Ç»ØÄꤵ¤ì¤¿¥Ö¥í¥Ã¥¯¤ÎÃæ¤Ç¤Ï¡¤
+ »Ò¥×¥í¥»¥¹¤¬½ªÎ»¤·¤Æ¤âÎã³°¤òȯÀ¸¤·¤Þ¤»¤ó¡¥¤³¤Î´Ø¿ô¤ò»È¤¦¤³¤È¤Ç¡¤
+ PTY¤Î»Ò¥×¥í¥»¥¹¤¬Æ°¤¤¤Æ¤¤¤ë´Ö¤Ç¤â¡¤system()¤ä IO.popen()¤Ê¤É¤Î
+ ´Ø¿ô¤ò°ÂÁ´¤Ë»È¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥Î㤨¤Ð¡¤
+
+ PTY.spawn("command_foo") do |r,w|
+ ...
+ ...
+ PTY.protect_signal do
+ system "some other commands"
+ end
+ ...
+ end
+
+ ¤³¤Î¤è¤¦¤Êµ­½Ò¤Ë¤è¤ê¡¤"some other commands" ¤¬½ªÎ»¤·¤¿¤È¤­¤Ë
+ Îã³°¤¬È¯À¸¤¹¤ë¤Î¤òËɤ²¤Þ¤¹¡¥
+
+ reset_signal
+
+ PTY ¤Î»Ò¥×¥í¥»¥¹¤¬Æ°¤¤¤Æ¤¤¤Æ¤â¡¤¤½¤Î¥×¥í¥»¥¹¤Î½ªÎ»»þ¤ËÎã³°¤¬È¯À¸
+ ¤·¤Ê¤¤¤è¤¦¤Ë¤·¤Þ¤¹¡¥
+
+4. ÍøÍѤˤĤ¤¤Æ
+
+°ËÆ£¾´Â§¤¬Ãøºî¸¢¤òÊÝÍ­¤·¤Þ¤¹¡¥
+
+¥½¡¼¥¹¥×¥í¥°¥é¥à¤Þ¤¿¤Ï¥É¥­¥å¥á¥ó¥È¤Ë¸µ¤ÎÃøºî¸¢É½¼¨¤¬²þÊѤµ¤ì¤º¤Ë
+ɽ¼¨¤µ¤ì¤Æ¤¤¤ë¾ì¹ç¤Ë¸Â¤ê¡¤Ã¯¤Ç¤â¡¤¤³¤Î¥½¥Õ¥È¥¦¥§¥¢¤ò̵½þ¤«¤ÄÃøºî
+¸¢¼Ô¤Ë̵ÃǤÇÍøÍÑ¡¦ÇÛÉÛ¡¦²þÊѤǤ­¤Þ¤¹¡¥ÍøÍÑÌÜŪ¤Ï¸ÂÄꤵ¤ì¤Æ¤¤¤Þ¤»
+¤ó¡¥
+
+¤³¤Î¥×¥í¥°¥é¥à¤ÎÍøÍÑ¡¦ÇÛÉÛ¤½¤Î¾¤³¤Î¥×¥í¥°¥é¥à¤Ë´Ø·¸¤¹¤ë¹Ô°Ù¤Ë¤è
+¤Ã¤ÆÀ¸¤¸¤¿¤¤¤«¤Ê¤ë»³²¤ËÂФ·¤Æ¤â¡¤ºî¼Ô¤Ï°ìÀÚÀÕǤ¤òÉ餤¤Þ¤»¤ó¡¥
+
+5. ¥Ð¥°Êó¹ðÅù
+
+¥Ð¥°¥ì¥Ý¡¼¥È¤Ï´¿·Þ¤·¤Þ¤¹¡¥
+
+ aito@ei5sun.yz.yamagata-u.ac.jp
+
+¤Þ¤ÇÅŻҥ᡼¥ë¤Ç¥Ð¥°¥ì¥Ý¡¼¥È¤ò¤ªÁ÷¤ê¤¯¤À¤µ¤¤¡¥
diff --git a/ext/pty/depend b/ext/pty/depend
new file mode 100644
index 0000000000..888be6c301
--- /dev/null
+++ b/ext/pty/depend
@@ -0,0 +1 @@
+pty.o: pty.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/pty/expect_sample.rb b/ext/pty/expect_sample.rb
new file mode 100644
index 0000000000..1311476c5d
--- /dev/null
+++ b/ext/pty/expect_sample.rb
@@ -0,0 +1,56 @@
+#
+# sample program of expect.rb
+#
+# by A. Ito
+#
+# This program reports the latest version of ruby interpreter
+# by connecting to ftp server at netlab.co.jp.
+#
+require 'pty'
+require 'expect'
+
+fnames = []
+PTY.spawn("ftp ftp.netlab.co.jp") do
+ |r_f,w_f,pid|
+ w_f.sync = true
+
+ $expect_verbose = true
+
+ r_f.expect(/^Name.*: /) do
+ w_f.print "ftp\n"
+ end
+
+ if !ENV['USER'].nil?
+ username = ENV['USER']
+ elsif !ENV['LOGNAME'].nil?
+ username = ENV['LOGNAME']
+ else
+ username = 'guest'
+ end
+
+ r_f.expect('word:') do
+ w_f.print username+"@\n"
+ end
+ r_f.expect("ftp> ") do
+ w_f.print "cd pub/lang/ruby\n"
+ end
+ r_f.expect("ftp> ") do
+ w_f.print "dir\n"
+ end
+
+ r_f.expect("ftp> ") do |output|
+ for x in output[0].split("\n")
+ if x =~ /(ruby.*\.tar\.gz)/ then
+ fnames.push $1
+ end
+ end
+ end
+ begin
+ w_f.print "quit\n"
+ rescue
+ end
+end
+
+print "The latest ruby interpreter is "
+print fnames.sort.pop
+print "\n"
diff --git a/ext/pty/extconf.rb b/ext/pty/extconf.rb
new file mode 100644
index 0000000000..ba2b44c70b
--- /dev/null
+++ b/ext/pty/extconf.rb
@@ -0,0 +1,12 @@
+require 'mkmf'
+
+if /mswin32|mingw/ !~ RUBY_PLATFORM
+ have_header("sys/stropts.h")
+ have_func("setresuid")
+ $CFLAGS << "-DHAVE_DEV_PTMX" if /cygwin/ === RUBY_PLATFORM
+ if have_func("openpty") or
+ have_func("_getpty") or
+ have_func("ioctl")
+ create_makefile('pty')
+ end
+end
diff --git a/ext/pty/lib/expect.rb b/ext/pty/lib/expect.rb
new file mode 100644
index 0000000000..54c69edadb
--- /dev/null
+++ b/ext/pty/lib/expect.rb
@@ -0,0 +1,36 @@
+$expect_verbose = false
+
+class IO
+ def expect(pat,timeout=9999999)
+ buf = ''
+ case pat
+ when String
+ e_pat = Regexp.new(Regexp.quote(pat))
+ when Regexp
+ e_pat = pat
+ end
+ while true
+ if IO.select([self],nil,nil,timeout).nil? then
+ result = nil
+ break
+ end
+ c = getc.chr
+ buf << c
+ if $expect_verbose
+ STDOUT.print c
+ STDOUT.flush
+ end
+ if buf =~ e_pat then
+ result = [buf,$1,$2,$3,$4,$5,$6,$7,$8,$9]
+ break
+ end
+ end
+ if iterator? then
+ yield result
+ else
+ return result
+ end
+ nil
+ end
+end
+
diff --git a/ext/pty/pty.c b/ext/pty/pty.c
new file mode 100644
index 0000000000..35e4080e62
--- /dev/null
+++ b/ext/pty/pty.c
@@ -0,0 +1,499 @@
+#include "config.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <pwd.h>
+#if !defined(HAVE_OPENPTY) && !defined(HAVE__GETPTY)
+#include <sys/ioctl.h>
+#endif
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#else
+#define WIFSTOPPED(status) (((status) & 0xff) == 0x7f)
+#endif
+#include <ctype.h>
+
+#include "ruby.h"
+#include "rubyio.h"
+
+#include <signal.h>
+#ifdef HAVE_SYS_STROPTS_H
+#include <sys/stropts.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#define DEVICELEN 16
+
+#if !defined(HAVE_OPENPTY)
+#ifdef __hpux
+char *MasterDevice = "/dev/ptym/pty%s",
+ *SlaveDevice = "/dev/pty/tty%s",
+ *deviceNo[] = {
+ "p0","p1","p2","p3","p4","p5","p6","p7",
+ "p8","p9","pa","pb","pc","pd","pe","pf",
+ "q0","q1","q2","q3","q4","q5","q6","q7",
+ "q8","q9","qa","qb","qc","qd","qe","qf",
+ "r0","r1","r2","r3","r4","r5","r6","r7",
+ "r8","r9","ra","rb","rc","rd","re","rf",
+ "s0","s1","s2","s3","s4","s5","s6","s7",
+ "s8","s9","sa","sb","sc","sd","se","sf",
+ "t0","t1","t2","t3","t4","t5","t6","t7",
+ "t8","t9","ta","tb","tc","td","te","tf",
+ "u0","u1","u2","u3","u4","u5","u6","u7",
+ "u8","u9","ua","ub","uc","ud","ue","uf",
+ "v0","v1","v2","v3","v4","v5","v6","v7",
+ "v8","v9","va","vb","vc","vd","ve","vf",
+ "w0","w1","w2","w3","w4","w5","w6","w7",
+ "w8","w9","wa","wb","wc","wd","we","wf",
+ 0,
+ };
+#else /* NOT HPUX */
+#ifdef _IBMESA /* AIX/ESA */
+char *MasterDevice = "/dev/ptyp%s",
+ *SlaveDevice = "/dev/ttyp%s",
+ *deviceNo[] = {
+"00","01","02","03","04","05","06","07","08","09","0a","0b","0c","0d","0e","0f",
+"10","11","12","13","14","15","16","17","18","19","1a","1b","1c","1d","1e","1f",
+"20","21","22","23","24","25","26","27","28","29","2a","2b","2c","2d","2e","2f",
+"30","31","32","33","34","35","36","37","38","39","3a","3b","3c","3d","3e","3f",
+"40","41","42","43","44","45","46","47","48","49","4a","4b","4c","4d","4e","4f",
+"50","51","52","53","54","55","56","57","58","59","5a","5b","5c","5d","5e","5f",
+"60","61","62","63","64","65","66","67","68","69","6a","6b","6c","6d","6e","6f",
+"70","71","72","73","74","75","76","77","78","79","7a","7b","7c","7d","7e","7f",
+"80","81","82","83","84","85","86","87","88","89","8a","8b","8c","8d","8e","8f",
+"90","91","92","93","94","95","96","97","98","99","9a","9b","9c","9d","9e","9f",
+"a0","a1","a2","a3","a4","a5","a6","a7","a8","a9","aa","ab","ac","ad","ae","af",
+"b0","b1","b2","b3","b4","b5","b6","b7","b8","b9","ba","bb","bc","bd","be","bf",
+"c0","c1","c2","c3","c4","c5","c6","c7","c8","c9","ca","cb","cc","cd","ce","cf",
+"d0","d1","d2","d3","d4","d5","d6","d7","d8","d9","da","db","dc","dd","de","df",
+"e0","e1","e2","e3","e4","e5","e6","e7","e8","e9","ea","eb","ec","ed","ee","ef",
+"f0","f1","f2","f3","f4","f5","f6","f7","f8","f9","fa","fb","fc","fd","fe","ff",
+ };
+#else
+char *MasterDevice = "/dev/pty%s",
+ *SlaveDevice = "/dev/tty%s",
+ *deviceNo[] = {
+ "p0","p1","p2","p3","p4","p5","p6","p7",
+ "p8","p9","pa","pb","pc","pd","pe","pf",
+ "q0","q1","q2","q3","q4","q5","q6","q7",
+ "q8","q9","qa","qb","qc","qd","qe","qf",
+ "r0","r1","r2","r3","r4","r5","r6","r7",
+ "r8","r9","ra","rb","rc","rd","re","rf",
+ 0,
+ };
+#endif /* _IBMESA */
+#endif /* HPUX */
+#endif /* !defined(HAVE_OPENPTY) */
+
+char SlaveName[DEVICELEN];
+
+extern int errno;
+
+#define MAX_PTY 16
+static int n_pty,last_pty;
+static int chld_pid[MAX_PTY];
+
+#ifndef HAVE_SETEUID
+# ifdef HAVE_SETREUID
+# define seteuid(e) setreuid(-1, (e))
+# else /* NOT HAVE_SETREUID */
+# ifdef HAVE_SETRESUID
+# define seteuid(e) setresuid(-1, (e), -1)
+# else /* NOT HAVE_SETRESUID */
+ /* I can't set euid. (;_;) */
+# endif /* HAVE_SETRESUID */
+# endif /* HAVE_SETREUID */
+#endif /* NO_SETEUID */
+
+struct pty_info {
+ int fd;
+ pid_t child_pid;
+};
+
+static void
+set_signal_action(action)
+ RETSIGTYPE (*action)();
+{
+#ifdef __hpux
+ struct sigvec sv;
+ /*
+ * signal SIGCHLD should be delivered on stop of the child
+ */
+ sv.sv_handler = action;
+ sv.sv_mask = sigmask(SIGCHLD);
+ sv.sv_flags = SV_BSDSIG;
+ sigvector(SIGCHLD, &sv, (struct sigvec *) 0);
+#else /* not HPUX */
+#if defined(SA_NOCLDSTOP)
+ struct sigaction sa;
+ /*
+ * signal SIGCHLD should be delivered on stop of the child
+ * (for SVR4)
+ */
+ sa.sa_handler = action;
+ sigemptyset(&sa.sa_mask);
+ sigaddset(&sa.sa_mask, SIGCHLD);
+ sa.sa_flags = 0; /* SA_NOCLDSTOP flag is removed */
+ sigaction(SIGCHLD, &sa, (struct sigaction *) 0);
+#else
+ signal(SIGCHLD,action);
+#endif
+#endif /* not HPUX */
+
+}
+
+static void
+reset_signal_action()
+{
+ set_signal_action(SIG_DFL);
+}
+
+static RETSIGTYPE
+chld_changed()
+{
+ int cpid;
+ int i,n = -1;
+ int statusp;
+
+ for (;;) {
+#ifdef HAVE_WAITPID
+ cpid = waitpid(-1, &statusp, WUNTRACED|WNOHANG);
+#else
+ cpid = wait3(&statusp, WUNTRACED|WNOHANG, 0);
+#endif
+ if (cpid == 0 || cpid == -1)
+ return;
+ for (i = 0; i < last_pty; i++) {
+ if (chld_pid[i] == cpid) {
+ n = i;
+ goto catched;
+ }
+ }
+ rb_raise(rb_eRuntimeError, "fork: %d", cpid);
+ }
+ catched:
+
+#ifdef IF_STOPPED
+ if (IF_STOPPED(statusp)) { /* suspend */
+ rb_raise(rb_eRuntimeError, "Stopped: %d",cpid);
+ }
+#else
+#ifdef WIFSTOPPED
+ if (WIFSTOPPED(statusp)) { /* suspend */
+ rb_raise(rb_eRuntimeError, "Stopped: %d",cpid);
+ }
+#else
+---->> Either IF_STOPPED or WIFSTOPPED is needed <<----
+#endif /* WIFSTOPPED */
+#endif /* IF_STOPPED */
+ if (n >= 0) {
+ chld_pid[n] = 0;
+ n_pty--;
+ if (n_pty == 0)
+ reset_signal_action();
+ }
+ rb_raise(rb_eRuntimeError, "Child_changed: %d",cpid);
+}
+
+static void getDevice _((int*, int*));
+
+static void
+establishShell(shellname, info)
+ char *shellname;
+ struct pty_info *info;
+{
+ static int i,j,master,slave,currentPid;
+ char *p,*getenv();
+ struct passwd *pwent;
+ RETSIGTYPE chld_changed();
+
+ if (shellname[0] == '\0') {
+ if ((p = getenv("SHELL")) != NULL) {
+ shellname = p;
+ }
+ else {
+ pwent = getpwuid(getuid());
+ if (pwent && pwent->pw_shell)
+ shellname = pwent->pw_shell;
+ else
+ shellname = "/bin/sh";
+ }
+ }
+ getDevice(&master,&slave);
+
+ currentPid = getpid();
+ set_signal_action(chld_changed);
+ if((i = vfork()) < 0) {
+ rb_sys_fail("fork failed");
+ }
+
+ if(i == 0) { /* child */
+ int argc;
+ char *argv[1024];
+ currentPid = getpid();
+
+ /*
+ * Set free from process group and controlling terminal
+ */
+#ifdef HAVE_SETSID
+ (void) setsid();
+#else /* HAS_SETSID */
+# ifdef HAVE_SETPGRP
+# ifdef SETGRP_VOID
+ if (setpgrp() == -1)
+ perror("setpgrp()");
+# else /* SETGRP_VOID */
+ if (setpgrp(0, currentPid) == -1)
+ rb_sys_fail("setpgrp()");
+ if ((i = open("/dev/tty", O_RDONLY)) < 0)
+ rb_sys_fail("/dev/tty");
+ else {
+ if (ioctl(i, TIOCNOTTY, (char *)0))
+ perror("ioctl(TIOCNOTTY)");
+ close(i);
+ }
+# endif /* SETGRP_VOID */
+# endif /* HAVE_SETPGRP */
+#endif /* HAS_SETSID */
+
+ /*
+ * obtain new controlling terminal
+ */
+#if defined(TIOCSCTTY)
+ close(master);
+ (void) ioctl(slave, TIOCSCTTY, (char *)0);
+ /* errors ignored for sun */
+#else
+ close(slave);
+ slave = open(SlaveName, O_RDWR);
+ if (slave < 0) {
+ perror("open: pty slave");
+ _exit(1);
+ }
+ close(master);
+#endif
+ dup2(slave,0);
+ dup2(slave,1);
+ dup2(slave,2);
+ close(slave);
+
+#if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRESUID)
+ seteuid(getuid());
+#endif
+
+ argc = 0;
+ for (i = 0; shellname[i];) {
+ while (isspace(shellname[i])) i++;
+ for (j = i; shellname[j] && !isspace(shellname[j]); j++);
+ argv[argc] = (char*)xmalloc(j-i+1);
+ strncpy(argv[argc],&shellname[i],j-i);
+ argv[argc][j-i] = 0;
+ i = j;
+ argc++;
+ }
+ argv[argc] = NULL;
+ execvp(argv[0],argv);
+ sleep(1);
+ _exit(1);
+ }
+
+ close(slave);
+
+ if (n_pty == last_pty) {
+ chld_pid[n_pty] = i;
+ n_pty++;
+ last_pty++;
+ }
+ else {
+ for (j = 0; j < last_pty; j++) {
+ if (chld_pid[j] == 0) {
+ chld_pid[j] = i;
+ n_pty++;
+ }
+ }
+ }
+ info->child_pid = i;
+ info->fd = master;
+}
+
+#ifdef HAVE_OPENPTY
+/*
+ * Use openpty(3) of 4.3BSD Reno and later,
+ * or the same interface function.
+ */
+static void
+getDevice(master,slave)
+ int *master,*slave;
+{
+ if (openpty(master, slave, SlaveName,
+ (struct termios *)0, (struct winsize *)0) == -1) {
+ rb_raise(rb_eRuntimeError, "openpty() failed");
+ }
+}
+#else /* HAVE_OPENPTY */
+#ifdef HAVE__GETPTY
+static void
+getDevice(master,slave)
+ int *master,*slave;
+{
+ char *name;
+
+ if (!(name = _getpty(master, O_RDWR, 0622, 0))) {
+ rb_raise(rb_eRuntimeError, "_getpty() failed");
+ }
+
+ *slave = open(name, O_RDWR);
+ strcpy(SlaveName, name);
+}
+#else /* HAVE__GETPTY */
+static void
+getDevice(master,slave)
+ int *master,*slave;
+{
+ char **p;
+ int i,j;
+ char MasterName[DEVICELEN];
+
+#ifdef HAVE_DEV_PTMX
+ char *pn;
+ void (*s)();
+
+ extern char *ptsname(int);
+ extern int unlockpt(int);
+ extern int grantpt(int);
+
+ if((i = open("/dev/ptmx", O_RDWR, 0)) != -1) {
+ s = signal(SIGCHLD, SIG_DFL);
+ if(grantpt(i) != -1) {
+ signal(SIGCHLD, s);
+ if(unlockpt(i) != -1) {
+ if((pn = ptsname(i)) != NULL) {
+ if((j = open(pn, O_RDWR, 0)) != -1) {
+#if defined I_PUSH && !defined linux
+ if(ioctl(j, I_PUSH, "ptem") != -1) {
+ if(ioctl(j, I_PUSH, "ldterm") != -1) {
+#endif
+ *master = i;
+ *slave = j;
+ strcpy(SlaveName, pn);
+ return;
+#if defined I_PUSH && !defined linux
+ }
+ }
+#endif
+ }
+ }
+ }
+ }
+ close(i);
+ }
+ rb_raise(rb_eRuntimeError, "Cannot get Master/Slave device");
+#else
+ for (p = deviceNo; *p != NULL; p++) {
+ sprintf(MasterName ,MasterDevice,*p);
+ if ((i = open(MasterName,O_RDWR,0)) >= 0) {
+ *master = i;
+ sprintf(SlaveName ,SlaveDevice,*p);
+ if ((j = open(SlaveName,O_RDWR,0)) >= 0) {
+ *slave = j;
+ chown(SlaveName, getuid(), getgid());
+ chmod(SlaveName, 0622);
+ return;
+ }
+ close(i);
+ }
+ }
+ rb_raise(rb_eRuntimeError, "Cannot get %s\n", SlaveDevice);
+#endif
+}
+#endif /* HAVE__GETPTY */
+#endif /* HAVE_OPENPTY */
+
+static void
+freeDevice()
+{
+ chmod(SlaveName, 0666);
+ chown(SlaveName, 0, 0);
+}
+
+/* ruby function: getpty */
+static VALUE
+pty_getpty(self, shell)
+ VALUE self, shell;
+{
+ VALUE res;
+ struct pty_info info;
+ OpenFile *wfptr,*rfptr;
+ NEWOBJ(rport, struct RFile);
+ NEWOBJ(wport, struct RFile);
+
+ if (n_pty == MAX_PTY+1) {
+ rb_raise(rb_eRuntimeError, "Too many ptys are open");
+ }
+
+ OBJSETUP(rport, rb_cFile, T_FILE);
+ MakeOpenFile(rport, rfptr);
+
+ OBJSETUP(wport, rb_cFile, T_FILE);
+ MakeOpenFile(wport, wfptr);
+
+ establishShell(RSTRING(shell)->ptr,&info);
+
+ rfptr->mode = rb_io_mode_flags("r");
+ rfptr->f = fdopen(info.fd, "r");
+ rfptr->path = strdup(RSTRING(shell)->ptr);
+
+ wfptr->mode = rb_io_mode_flags("w");
+ wfptr->f = fdopen(dup(info.fd), "w");
+ wfptr->path = strdup(RSTRING(shell)->ptr);
+
+ res = rb_ary_new2(2);
+ rb_ary_store(res,0,(VALUE)rport);
+ rb_ary_store(res,1,(VALUE)wport);
+ rb_ary_store(res,2,INT2FIX(info.child_pid));
+
+ if (rb_block_given_p()) {
+ rb_yield((VALUE)res);
+ reset_signal_action();
+ return Qnil;
+ }
+ else {
+ return (VALUE)res;
+ }
+}
+
+/* ruby function: protect_signal */
+static VALUE
+pty_protect(self)
+ VALUE self;
+{
+ reset_signal_action();
+ rb_yield(Qnil);
+ set_signal_action(chld_changed);
+ return self;
+}
+
+static VALUE
+pty_reset_signal(self)
+ VALUE self;
+{
+ reset_signal_action();
+ return self;
+}
+
+static VALUE cPTY;
+
+void
+Init_pty()
+{
+ cPTY = rb_define_module("PTY");
+ rb_define_module_function(cPTY,"getpty",pty_getpty,1);
+ rb_define_module_function(cPTY,"spawn",pty_getpty,1);
+ rb_define_module_function(cPTY,"protect_signal",pty_protect,0);
+ rb_define_module_function(cPTY,"reset_signal",pty_reset_signal,0);
+}
diff --git a/ext/pty/script.rb b/ext/pty/script.rb
new file mode 100644
index 0000000000..3084935637
--- /dev/null
+++ b/ext/pty/script.rb
@@ -0,0 +1,38 @@
+require 'pty'
+
+if ARGV.size == 0 then
+ ofile = "typescript"
+else
+ ofile = ARGV[0]
+end
+
+logfile = File.open(ofile,"a")
+
+system "stty -echo raw lnext ^_"
+
+PTY.spawn("/bin/csh") do
+ |r_pty,w_pty,pid|
+
+ Thread.new do
+ while true
+ w_pty.print STDIN.getc.chr
+ w_pty.flush
+ end
+ end
+
+ begin
+ while true
+ c = r_pty.sysread(512)
+ break if c.nil?
+ print c
+ STDOUT.flush
+ logfile.print c
+ end
+ rescue
+ # print $@,':',$!,"\n"
+ logfile.close
+ end
+end
+
+system "stty echo -raw lnext ^v"
+
diff --git a/ext/pty/shl.rb b/ext/pty/shl.rb
new file mode 100644
index 0000000000..0c04a2735c
--- /dev/null
+++ b/ext/pty/shl.rb
@@ -0,0 +1,96 @@
+#
+# old-fashioned 'shl' like program
+# by A. Ito
+#
+# commands:
+# c creates new shell
+# C-z suspends shell
+# p lists all shell
+# 0,1,... choose shell
+# q quit
+
+require 'pty'
+
+$shells = []
+$n_shells = 0
+
+$r_pty = nil
+$w_pty = nil
+
+def writer
+ PTY.protect_signal do
+ system "stty -echo raw"
+ end
+ begin
+ while true
+ c = STDIN.getc
+ if c == 26 then # C-z
+ $reader.raise(nil)
+ return 'Suspend'
+ end
+ $w_pty.print c.chr
+ $w_pty.flush
+ end
+ rescue
+ $reader.raise(nil)
+ return 'Exit'
+ ensure
+ PTY.protect_signal do
+ system "stty echo -raw"
+ end
+ end
+end
+
+$reader = Thread.new {
+ while true
+ begin
+ next if $r_pty.nil?
+ c = $r_pty.getc
+ if c.nil? then
+ Thread.stop
+ end
+ print c.chr
+ STDOUT.flush
+ rescue
+ Thread.stop
+ end
+ end
+}
+
+# $reader.raise(nil)
+
+
+while true
+ print ">> "
+ STDOUT.flush
+ case gets
+ when /^c/i
+ $shells[$n_shells] = PTY.spawn("/bin/csh")
+ $r_pty,$w_pty = $shells[$n_shells]
+ $n_shells += 1
+ $reader.run
+ if writer == 'Exit'
+ $n_shells -= 1
+ $shells[$n_shells] = nil
+ end
+ when /^p/i
+ for i in 0..$n_shells
+ unless $shells[i].nil?
+ print i,"\n"
+ end
+ end
+ when /^([0-9]+)/
+ n = $1.to_i
+ if $shells[n].nil?
+ print "\##{i} doesn't exist\n"
+ else
+ $r_pty,$w_pty = $shells[n]
+ $reader.run
+ if writer == 'Exit' then
+ $shells[n] = nil
+ end
+ end
+ when /^q/i
+ exit
+ end
+end
diff --git a/ext/readline/.cvsignore b/ext/readline/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/readline/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/readline/MANIFEST b/ext/readline/MANIFEST
new file mode 100644
index 0000000000..f8bfd1ea2c
--- /dev/null
+++ b/ext/readline/MANIFEST
@@ -0,0 +1,5 @@
+MANIFEST
+README
+depend
+extconf.rb
+readline.c
diff --git a/ext/readline/README b/ext/readline/README
new file mode 100644
index 0000000000..8a5fe9120f
--- /dev/null
+++ b/ext/readline/README
@@ -0,0 +1,55 @@
+GNU Readline Library¤òÍøÍѤ¹¤ë¤¿¤á¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ç¤¹¡£
+
+require "readline"
+include Readline
+
+line = readline("Prompt> ", TRUE)
+
+¤Î¤è¤¦¤Ë»ÈÍѤ·¤Æ¤¯¤À¤µ¤¤¡£
+
+[Readline]
+
+<¥â¥¸¥å¡¼¥ë´Ø¿ô>
+
+readline(prompt, add=nil)
+
+ °ì¹ÔÆþÎϤòÆÉ¤ß¹þ¤ß¤Þ¤¹¡£
+ add¤¬TRUE¤Î¾ì¹ç¡¢¥Ò¥¹¥È¥ê¤ËÆÉ¤ß¹þ¤ó¤Àʸ»úÎó¤òÄɲä·¤Þ¤¹¡£
+
+<¥¯¥é¥¹¥á¥½¥Ã¥É>
+
+completion_proc = proc
+
+ Êä´°»þ¤Îưºî¤ò·èÄꤹ¤ëProc¥ª¥Ö¥¸¥§¥¯¥È¤ò»ØÄꤷ¤Þ¤¹¡£
+ proc¤Ï°ú¿ô¤ËÆþÎÏʸ»úÎó¤ò¼è¤ê¡¢¸õÊäʸ»úÎó¤ÎÇÛÎó¤òÊÖ¤¹¤è¤¦¤Ë
+ ¤·¤Æ¤¯¤À¤µ¤¤¡£
+
+completion_proc
+
+ Êä´°»þ¤Îưºî¤ò·èÄꤹ¤ëProc¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤·¤Þ¤¹¡£
+
+completion_case_fold = case_fold
+
+ Êä´°»þ¤ËÂçʸ»ú¾®Ê¸»ú¤ò¶èÊ̤·¤Ê¤¤¾ì¹ç¡¢TRUE¤ò»ØÄꤷ¤Þ¤¹¡£
+
+completion_case_fold
+
+ Êä´°»þ¤ËÂçʸ»ú¾®Ê¸»ú¤ò¶èÊ̤·¤Ê¤¤¾ì¹ç¡¢TRUE¤òÊÖ¤·¤Þ¤¹¡£
+
+vi_editing_mode
+
+ VI¥â¡¼¥É¤Ë¤Ê¤ê¤Þ¤¹¡£
+
+emacs_editing_mode
+
+ Emacs¥â¡¼¥É¤Ë¤Ê¤ê¤Þ¤¹¡£
+
+<¥¯¥é¥¹Äê¿ô>
+
+HISTORY
+
+¥Ò¥¹¥È¥ê¤ËÂФ¹¤ëÁàºî¤Ï¤³¤ÎÄê¿ô¤òÄ̤·¤Æ¹Ô¤Ã¤Æ¤¯¤À¤µ¤¤¡£
+ÇÛÎó¤ÈƱ¤¸¤è¤¦¤Ë°·¤¨¤ë¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡£
+
+
+ \ No newline at end of file
diff --git a/ext/readline/depend b/ext/readline/depend
new file mode 100644
index 0000000000..6570c5a036
--- /dev/null
+++ b/ext/readline/depend
@@ -0,0 +1 @@
+readline.o: readline.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/readline/extconf.rb b/ext/readline/extconf.rb
new file mode 100644
index 0000000000..431ed213bb
--- /dev/null
+++ b/ext/readline/extconf.rb
@@ -0,0 +1,16 @@
+require "mkmf"
+
+dir_config("readline")
+have_library("user32", nil) if /cygwin/ === RUBY_PLATFORM
+have_library("ncurses", "tgetnum") or
+ have_library("termcap", "tgetnum") or
+ have_library("curses", "tgetnum")
+
+if have_header("readline/readline.h") and
+ have_header("readline/history.h") and
+ have_library("readline", "readline")
+ if have_func("rl_filename_completion_function")
+ $CFLAGS += "-DREADLINE_42_OR_LATER"
+ end
+ create_makefile("readline")
+end
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
new file mode 100644
index 0000000000..876207c224
--- /dev/null
+++ b/ext/readline/readline.c
@@ -0,0 +1,427 @@
+/* readline.c -- GNU Readline module
+ Copyright (C) 1997-1998 Shugo Maeda */
+
+#include <stdio.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include "ruby.h"
+#include "rubysig.h"
+
+static VALUE mReadline;
+
+#define TOLOWER(c) (isupper(c) ? tolower(c) : c)
+
+#define COMPLETION_PROC "completion_proc"
+#define COMPLETION_CASE_FOLD "completion_case_fold"
+
+#ifndef READLINE_42_OR_LATER
+# define rl_filename_completion_function filename_completion_function
+# define rl_username_completion_function username_completion_function
+# define rl_completion_matches completion_matches
+#endif
+
+static int
+readline_event()
+{
+ CHECK_INTS;
+ rb_thread_schedule();
+}
+
+static VALUE
+readline_readline(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
+{
+ VALUE tmp, add_hist, result;
+ char *prompt = NULL;
+ char *buff;
+
+ if (rb_scan_args(argc, argv, "02", &tmp, &add_hist) > 0) {
+ prompt = STR2CSTR(tmp);
+ }
+ buff = readline(prompt);
+ if (RTEST(add_hist) && buff) {
+ add_history(buff);
+ }
+ if (buff)
+ result = rb_str_new2(buff);
+ else
+ result = Qnil;
+ if (buff) free(buff);
+ return result;
+}
+
+static VALUE
+readline_s_set_completion_proc(self, proc)
+ VALUE self;
+ VALUE proc;
+{
+ if (!rb_respond_to(proc, rb_intern("call")))
+ rb_raise(rb_eArgError, "argument have to respond to `call'");
+ return rb_iv_set(mReadline, COMPLETION_PROC, proc);
+}
+
+static VALUE
+readline_s_get_completion_proc(self)
+ VALUE self;
+{
+ return rb_iv_get(mReadline, COMPLETION_PROC);
+}
+
+static VALUE
+readline_s_set_completion_case_fold(self, val)
+ VALUE self;
+ VALUE val;
+{
+ return rb_iv_set(mReadline, COMPLETION_CASE_FOLD, val);
+}
+
+static VALUE
+readline_s_get_completion_case_fold(self)
+ VALUE self;
+{
+ return rb_iv_get(mReadline, COMPLETION_CASE_FOLD);
+}
+
+static char **
+readline_attempted_completion_function(text, start, end)
+ char *text;
+ int start;
+ int end;
+{
+ VALUE proc, ary, temp;
+ char **result;
+ int case_fold;
+ int i, matches;
+
+ proc = rb_iv_get(mReadline, COMPLETION_PROC);
+ if (NIL_P(proc))
+ return NULL;
+ rl_attempted_completion_over = 1;
+ case_fold = RTEST(rb_iv_get(mReadline, COMPLETION_CASE_FOLD));
+ ary = rb_funcall(proc, rb_intern("call"), 1, rb_str_new2(text));
+ if (TYPE(ary) != T_ARRAY)
+ ary = rb_Array(ary);
+ matches = RARRAY(ary)->len;
+ if (matches == 0)
+ return NULL;
+ result = ALLOC_N(char *, matches + 2);
+ for (i = 0; i < matches; i++) {
+ temp = rb_obj_as_string(RARRAY(ary)->ptr[i]);
+ result[i + 1] = ALLOC_N(char, RSTRING(temp)->len + 1);
+ strcpy(result[i + 1], RSTRING(temp)->ptr);
+ }
+ result[matches + 1] = NULL;
+
+ if (matches == 1) {
+ result[0] = result[1];
+ result[1] = NULL;
+ } else {
+ register int i = 1;
+ int low = 100000;
+
+ while (i < matches) {
+ register int c1, c2, si;
+
+ if (case_fold) {
+ for (si = 0;
+ (c1 = TOLOWER(result[i][si])) &&
+ (c2 = TOLOWER(result[i + 1][si]));
+ si++)
+ if (c1 != c2) break;
+ } else {
+ for (si = 0;
+ (c1 = result[i][si]) &&
+ (c2 = result[i + 1][si]);
+ si++)
+ if (c1 != c2) break;
+ }
+
+ if (low > si) low = si;
+ i++;
+ }
+ result[0] = ALLOC_N(char, low + 1);
+ strncpy(result[0], result[1], low);
+ result[0][low] = '\0';
+ }
+
+ return result;
+}
+
+static VALUE
+readline_s_vi_editing_mode(self)
+ VALUE self;
+{
+ rl_vi_editing_mode(1,0);
+ return Qnil;
+}
+
+static VALUE
+readline_s_emacs_editing_mode(self)
+ VALUE self;
+{
+ rl_emacs_editing_mode(1,0);
+ return Qnil;
+}
+
+static VALUE
+hist_to_s(self)
+ VALUE self;
+{
+ return rb_str_new2("HISTORY");
+}
+
+static VALUE
+hist_get(self, index)
+ VALUE self;
+ VALUE index;
+{
+ HISTORY_STATE *state;
+ int i;
+
+ state = history_get_history_state();
+ i = NUM2INT(index);
+ if (i < 0 || i > state->length - 1) {
+ rb_raise(rb_eIndexError, "Invalid index");
+ }
+ return rb_str_new2(state->entries[i]->line);
+}
+
+static VALUE
+hist_set(self, index, str)
+ VALUE self;
+ VALUE index;
+ VALUE str;
+{
+ HISTORY_STATE *state;
+ int i;
+
+ state = history_get_history_state();
+ i = NUM2INT(index);
+ if (i < 0 || i > state->length - 1) {
+ rb_raise(rb_eIndexError, "Invalid index");
+ }
+ replace_history_entry(i, STR2CSTR(str), NULL);
+ return str;
+}
+
+static VALUE
+hist_push(self, str)
+ VALUE self;
+ VALUE str;
+{
+ add_history(STR2CSTR(str));
+ return self;
+}
+
+static VALUE
+hist_push_method(argc, argv, self)
+ int argc;
+ VALUE *argv;
+ VALUE self;
+{
+ VALUE str;
+
+ while (argc--) {
+ str = *argv++;
+ add_history(STR2CSTR(str));
+ }
+ return self;
+}
+
+static VALUE
+hist_pop(self)
+ VALUE self;
+{
+ HISTORY_STATE *state;
+ HIST_ENTRY *entry;
+
+ state = history_get_history_state();
+ if (state->length > 0) {
+ entry = remove_history(state->length - 1);
+ return rb_str_new2(entry->line);
+ } else {
+ return Qnil;
+ }
+}
+
+static VALUE
+hist_shift(self)
+ VALUE self;
+{
+ HISTORY_STATE *state;
+ HIST_ENTRY *entry;
+
+ state = history_get_history_state();
+ if (state->length > 0) {
+ entry = remove_history(0);
+ return rb_str_new2(entry->line);
+ } else {
+ return Qnil;
+ }
+}
+
+static VALUE
+hist_each(self)
+ VALUE self;
+{
+ HISTORY_STATE *state;
+ int i;
+
+ state = history_get_history_state();
+ for (i = 0; i < state->length; i++) {
+ rb_yield(rb_str_new2(state->entries[i]->line));
+ }
+ return self;
+}
+
+static VALUE
+hist_length(self)
+ VALUE self;
+{
+ HISTORY_STATE *state;
+
+ state = history_get_history_state();
+ return INT2NUM(state->length);
+}
+
+static VALUE
+hist_empty_p(self)
+ VALUE self;
+{
+ HISTORY_STATE *state;
+
+ state = history_get_history_state();
+ if (state->length == 0)
+ return Qtrue;
+ else
+ return Qfalse;
+}
+
+static VALUE
+hist_delete_at(self, index)
+ VALUE self;
+ VALUE index;
+{
+ HISTORY_STATE *state;
+ HIST_ENTRY *entry;
+ int i;
+
+ state = history_get_history_state();
+ i = NUM2INT(index);
+ if (i < 0 || i > state->length - 1) {
+ rb_raise(rb_eIndexError, "Invalid index");
+ }
+ entry = remove_history(NUM2INT(index));
+ return rb_str_new2(entry->line);
+}
+
+static VALUE
+filename_completion_proc_call(self, str)
+ VALUE self;
+ VALUE str;
+{
+ VALUE result;
+ char **matches;
+ int i;
+
+ matches = rl_completion_matches(STR2CSTR(str),
+ rl_filename_completion_function);
+ if (matches) {
+ result = rb_ary_new();
+ for (i = 0; matches[i]; i++) {
+ rb_ary_push(result, rb_str_new2(matches[i]));
+ free(matches[i]);
+ }
+ free(matches);
+ if (RARRAY(result)->len >= 2)
+ rb_ary_shift(result);
+ }
+ else {
+ result = Qnil;
+ }
+ return result;
+}
+
+static VALUE
+username_completion_proc_call(self, str)
+ VALUE self;
+ VALUE str;
+{
+ VALUE result;
+ char **matches;
+ int i;
+
+ matches = rl_completion_matches(STR2CSTR(str),
+ rl_username_completion_function);
+ if (matches) {
+ result = rb_ary_new();
+ for (i = 0; matches[i]; i++) {
+ rb_ary_push(result, rb_str_new2(matches[i]));
+ free(matches[i]);
+ }
+ free(matches);
+ if (RARRAY(result)->len >= 2)
+ rb_ary_shift(result);
+ }
+ else {
+ result = Qnil;
+ }
+ return result;
+}
+
+void
+Init_readline()
+{
+ VALUE histary, fcomp, ucomp;
+
+ using_history();
+
+ mReadline = rb_define_module("Readline");
+ rb_define_module_function(mReadline, "readline",
+ readline_readline, -1);
+ rb_define_singleton_method(mReadline, "completion_proc=",
+ readline_s_set_completion_proc, 1);
+ rb_define_singleton_method(mReadline, "completion_proc",
+ readline_s_get_completion_proc, 0);
+ rb_define_singleton_method(mReadline, "completion_case_fold=",
+ readline_s_set_completion_case_fold, 1);
+ rb_define_singleton_method(mReadline, "completion_case_fold",
+ readline_s_get_completion_case_fold, 0);
+ rb_define_singleton_method(mReadline, "vi_editing_mode",
+ readline_s_vi_editing_mode, 0);
+ rb_define_singleton_method(mReadline, "emacs_editing_mode",
+ readline_s_emacs_editing_mode, 0);
+
+ histary = rb_obj_alloc(rb_cObject);
+ rb_extend_object(histary, rb_mEnumerable);
+ rb_define_singleton_method(histary,"to_s", hist_to_s, 0);
+ rb_define_singleton_method(histary,"[]", hist_get, 1);
+ rb_define_singleton_method(histary,"[]=", hist_set, 2);
+ rb_define_singleton_method(histary,"<<", hist_push, 1);
+ rb_define_singleton_method(histary,"push", hist_push_method, -1);
+ rb_define_singleton_method(histary,"pop", hist_pop, 0);
+ rb_define_singleton_method(histary,"shift", hist_shift, 0);
+ rb_define_singleton_method(histary,"each", hist_each, 0);
+ rb_define_singleton_method(histary,"length", hist_length, 0);
+ rb_define_singleton_method(histary,"empty?", hist_empty_p, 0);
+ rb_define_singleton_method(histary,"delete_at", hist_delete_at, 1);
+ rb_define_const(mReadline, "HISTORY", histary);
+
+ fcomp = rb_obj_alloc(rb_cObject);
+ rb_define_singleton_method(fcomp, "call",
+ filename_completion_proc_call, 1);
+ rb_define_const(mReadline, "FILENAME_COMPLETION_PROC", fcomp);
+
+ ucomp = rb_obj_alloc(rb_cObject);
+ rb_define_singleton_method(ucomp, "call",
+ username_completion_proc_call, 1);
+ rb_define_const(mReadline, "USERNAME_COMPLETION_PROC", ucomp);
+
+ rl_attempted_completion_function
+ = (CPPFunction *) readline_attempted_completion_function;
+ rl_event_hook = readline_event;
+ rl_clear_signals();
+}
diff --git a/ext/sdbm/.cvsignore b/ext/sdbm/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/sdbm/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/sdbm/MANIFEST b/ext/sdbm/MANIFEST
new file mode 100644
index 0000000000..8888e69ad4
--- /dev/null
+++ b/ext/sdbm/MANIFEST
@@ -0,0 +1,6 @@
+MANIFEST
+_sdbm.c
+depend
+extconf.rb
+init.c
+sdbm.h
diff --git a/win32/sdbm.c b/ext/sdbm/_sdbm.c
index d2d2171875..92c96f26d0 100644
--- a/win32/sdbm.c
+++ b/ext/sdbm/_sdbm.c
@@ -8,12 +8,12 @@
*/
#ifndef lint
-/*char sdbm_rcsid[] = "$Id: sdbm.c,v 1.16 90/12/13 13:01:31 oz Exp $";*/
+/*char sdbm_rcsid[] = "$Id$";*/
#endif
#include "sdbm.h"
+#include "config.h"
-/*#include "tune.h"*/
/*
* sdbm - ndbm work-alike hashed database library
* tuning and portability constructs [not nearly enough]
@@ -22,11 +22,7 @@
#define BYTESIZ 8
-#ifdef SVID
-#include <unistd.h>
-#endif
-
-#ifdef __GO32__
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@@ -73,9 +69,9 @@ static void splpage proto((char *, char *, long));
static int duppair proto((char *, datum));
#endif
-#ifdef MSDOS
#include <stdio.h>
#include <stdlib.h>
+#ifdef MSDOS
#include <io.h>
#endif
#include <sys/types.h>
@@ -107,11 +103,9 @@ static int duppair proto((char *, datum));
/*
* externals
*/
-#ifndef sun
-#ifndef MSDOS
+#if !defined(sun) && !defined(MSDOS) && !defined(_WIN32)
extern int errno;
#endif
-#endif
/*
* forward
@@ -126,7 +120,7 @@ static int makroom proto((DBM *, long, int));
* useful macros
*/
#define bad(x) ((x).dptr == NULL || (x).dsize < 0)
-#define exhash(item) dbm_hash((item).dptr, (item).dsize)
+#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
#define ioerr(db) ((db)->flags |= DBM_IOERR)
#define OFF_PAG(off) (long) (off) * PBLKSIZ
@@ -149,7 +143,7 @@ static long masks[] = {
datum nullitem = {NULL, 0};
DBM *
-dbm_open(file, flags, mode)
+sdbm_open(file, flags, mode)
register char *file;
register int flags;
register int mode;
@@ -175,13 +169,13 @@ register int mode;
pagname = strcpy(dirname + strlen(dirname) + 1, file);
pagname = strcat(pagname, PAGFEXT);
- db = dbm_prep(dirname, pagname, flags, mode);
+ db = sdbm_prep(dirname, pagname, flags, mode);
free((char *) dirname);
return db;
}
DBM *
-dbm_prep(dirname, pagname, flags, mode)
+sdbm_prep(dirname, pagname, flags, mode)
char *dirname;
char *pagname;
int flags;
@@ -210,9 +204,7 @@ int mode;
* open the files in sequence, and stat the dirfile.
* If we fail anywhere, undo everything, return NULL.
*/
-#ifdef MSDOS
flags |= O_BINARY;
-#endif
if ((db->pagf = open(pagname, flags, mode)) > -1) {
if ((db->dirf = open(dirname, flags, mode)) > -1) {
/*
@@ -243,7 +235,7 @@ int mode;
}
void
-dbm_close(db)
+sdbm_close(db)
register DBM *db;
{
if (db == NULL)
@@ -256,7 +248,7 @@ register DBM *db;
}
datum
-dbm_fetch(db, key)
+sdbm_fetch(db, key)
register DBM *db;
datum key;
{
@@ -270,13 +262,13 @@ datum key;
}
int
-dbm_delete(db, key)
+sdbm_delete(db, key)
register DBM *db;
datum key;
{
if (db == NULL || bad(key))
return errno = EINVAL, -1;
- if (dbm_rdonly(db))
+ if (sdbm_rdonly(db))
return errno = EPERM, -1;
if (getpage(db, exhash(key))) {
@@ -296,7 +288,7 @@ datum key;
}
int
-dbm_store(db, key, val, flags)
+sdbm_store(db, key, val, flags)
register DBM *db;
datum key;
datum val;
@@ -307,7 +299,7 @@ int flags;
if (db == NULL || bad(key))
return errno = EINVAL, -1;
- if (dbm_rdonly(db))
+ if (sdbm_rdonly(db))
return errno = EPERM, -1;
need = key.dsize + val.dsize;
@@ -365,13 +357,13 @@ int need;
{
long newp;
char twin[PBLKSIZ];
-#ifdef MSDOS
+#if defined MSDOS || (defined _WIN32 && !defined __CYGWIN__)
char zer[PBLKSIZ];
+ long oldtail;
#endif
char *pag = db->pagbuf;
char *new = twin;
register int smax = SPLTMAX;
- long oldtail;
do {
/*
@@ -389,10 +381,10 @@ int need;
* write out the previous one, and copy the new one over, thus making
* it the current page. If not, simply write the new page, and we are
* still looking at the page of interest. current page is not updated
- * here, as dbm_store will do so, after it inserts the incoming pair.
+ * here, as sdbm_store will do so, after it inserts the incoming pair.
*/
-#ifdef MSDOS
+#if defined MSDOS || (defined _WIN32 && !defined __CYGWIN__)
/*
* Fill hole with 0 if made it.
* (hole is NOT read as 0)
@@ -458,7 +450,7 @@ int need;
* deletions aren't taken into account. (ndbm bug)
*/
datum
-dbm_firstkey(db)
+sdbm_firstkey(db)
register DBM *db;
{
if (db == NULL)
@@ -478,7 +470,7 @@ register DBM *db;
}
datum
-dbm_nextkey(db)
+sdbm_nextkey(db)
register DBM *db;
{
if (db == NULL)
@@ -634,14 +626,14 @@ register DBM *db;
*/
#ifndef lint
-/*char pair_rcsid[] = "$Id: sdbm.c,v 1.1.1.1.2.1 1998/01/16 12:36:12 matz Exp $";*/
+/*char pair_rcsid[] = "$Id$";*/
#endif
#ifndef BSD42
/*#include <memory.h>*/
#endif
-#define exhash(item) dbm_hash((item).dptr, (item).dsize)
+#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
/*
* forward
@@ -950,7 +942,7 @@ char *pag;
* 65587 even better.
*/
long
-dbm_hash(str, len)
+sdbm_hash(str, len)
register char *str;
register int len;
{
diff --git a/ext/sdbm/depend b/ext/sdbm/depend
new file mode 100644
index 0000000000..1d8b13d13f
--- /dev/null
+++ b/ext/sdbm/depend
@@ -0,0 +1,2 @@
+_sdbm.o: _sdbm.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
+init.o: init.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h
diff --git a/ext/sdbm/extconf.rb b/ext/sdbm/extconf.rb
new file mode 100644
index 0000000000..cc6c8cefd1
--- /dev/null
+++ b/ext/sdbm/extconf.rb
@@ -0,0 +1,3 @@
+require 'mkmf'
+
+create_makefile("sdbm")
diff --git a/ext/sdbm/init.c b/ext/sdbm/init.c
new file mode 100644
index 0000000000..458695fc2b
--- /dev/null
+++ b/ext/sdbm/init.c
@@ -0,0 +1,719 @@
+/************************************************
+
+ sdbminit.c -
+
+ $Author$
+ $Date$
+ created at: Fri May 7 08:34:24 JST 1999
+
+ Copyright (C) 1995-2001 Yukihiro Matsumoto
+
+************************************************/
+
+#include "ruby.h"
+
+#include "sdbm.h"
+#include <fcntl.h>
+#include <errno.h>
+
+static VALUE cSDBM;
+
+struct dbmdata {
+ int di_size;
+ DBM *di_dbm;
+};
+
+static void
+closed_sdbm()
+{
+ rb_raise(rb_eRuntimeError, "closed SDBM file");
+}
+
+#define GetDBM(obj, dbmp) {\
+ Data_Get_Struct(obj, struct dbmdata, dbmp);\
+ if (dbmp->di_dbm == 0) closed_sdbm();\
+}
+
+static void
+free_sdbm(dbmp)
+ struct dbmdata *dbmp;
+{
+
+ if (dbmp->di_dbm) sdbm_close(dbmp->di_dbm);
+ free(dbmp);
+}
+
+static VALUE
+fsdbm_close(obj)
+ VALUE obj;
+{
+ struct dbmdata *dbmp;
+
+ GetDBM(obj, dbmp);
+ sdbm_close(dbmp->di_dbm);
+ dbmp->di_dbm = 0;
+
+ return Qnil;
+}
+
+static VALUE
+fsdbm_initialize(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE file, vmode;
+ DBM *dbm;
+ struct dbmdata *dbmp;
+ int mode;
+
+ if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
+ mode = 0666; /* default value */
+ }
+ else if (NIL_P(vmode)) {
+ mode = -1; /* return nil if DB not exist */
+ }
+ else {
+ mode = NUM2INT(vmode);
+ }
+ file = rb_str_to_str(file);
+ Check_SafeStr(file);
+
+ dbm = 0;
+ if (mode >= 0)
+ dbm = sdbm_open(RSTRING(file)->ptr, O_RDWR|O_CREAT, mode);
+ if (!dbm)
+ dbm = sdbm_open(RSTRING(file)->ptr, O_RDWR, 0);
+ if (!dbm)
+ dbm = sdbm_open(RSTRING(file)->ptr, O_RDONLY, 0);
+
+ if (!dbm) {
+ if (mode == -1) return Qnil;
+ rb_sys_fail(RSTRING(file)->ptr);
+ }
+
+ dbmp = ALLOC(struct dbmdata);
+ DATA_PTR(obj) = dbmp;
+ dbmp->di_dbm = dbm;
+ dbmp->di_size = -1;
+
+ return obj;
+}
+
+static VALUE
+fsdbm_s_new(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_sdbm, 0);
+ rb_obj_call_init(obj, argc, argv);
+ return obj;
+}
+
+static VALUE
+fsdbm_s_open(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE obj = Data_Wrap_Struct(klass, 0, free_sdbm, 0);
+
+ if (NIL_P(fsdbm_initialize(argc, argv, obj))) {
+ return Qnil;
+ }
+
+ if (rb_block_given_p()) {
+ return rb_ensure(rb_yield, obj, fsdbm_close, obj);
+ }
+
+ return obj;
+}
+
+static VALUE
+fsdbm_fetch(obj, keystr, ifnone)
+ VALUE obj, keystr, ifnone;
+{
+ datum key, value;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ keystr = rb_str_to_str(keystr);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ value = sdbm_fetch(dbm, key);
+ if (value.dptr == 0) {
+ if (ifnone == Qnil && rb_block_given_p())
+ return rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
+ return ifnone;
+ }
+ return rb_tainted_str_new(value.dptr, value.dsize);
+}
+
+static VALUE
+fsdbm_aref(obj, keystr)
+ VALUE obj, keystr;
+{
+ return fsdbm_fetch(obj, keystr, Qnil);
+}
+
+static VALUE
+fsdbm_fetch_m(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE keystr, valstr, ifnone;
+
+ rb_scan_args(argc, argv, "11", &keystr, &ifnone);
+ valstr = fsdbm_fetch(obj, keystr, ifnone);
+ if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
+ rb_raise(rb_eIndexError, "key not found");
+
+ return valstr;
+}
+
+static VALUE
+fsdbm_index(obj, valstr)
+ VALUE obj, valstr;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ valstr = rb_str_to_str(valstr);
+ val.dptr = RSTRING(valstr)->ptr;
+ val.dsize = RSTRING(valstr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ if (val.dsize == RSTRING(valstr)->len &&
+ memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
+ return rb_tainted_str_new(key.dptr, key.dsize);
+ }
+ return Qnil;
+}
+
+static VALUE
+fsdbm_indexes(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
+{
+ VALUE new;
+ int i;
+
+ new = rb_ary_new2(argc);
+ for (i=0; i<argc; i++) {
+ rb_ary_push(new, fsdbm_fetch(obj, argv[i]));
+ }
+
+ return new;
+}
+
+static VALUE
+fsdbm_delete(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key, value;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ rb_secure(4);
+ keystr = rb_str_to_str(keystr);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ dbmp->di_size = -1;
+
+ value = sdbm_fetch(dbm, key);
+ if (value.dptr == 0) {
+ if (rb_block_given_p()) rb_yield(keystr);
+ return Qnil;
+ }
+
+ if (sdbm_delete(dbm, key)) {
+ dbmp->di_size = -1;
+ rb_raise(rb_eRuntimeError, "dbm_delete failed");
+ }
+ else if (dbmp->di_size >= 0) {
+ dbmp->di_size--;
+ }
+ return obj;
+}
+
+static VALUE
+fsdbm_shift(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE keystr, valstr;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ key = sdbm_firstkey(dbm);
+ if (!key.dptr) return Qnil;
+ val = sdbm_fetch(dbm, key);
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ sdbm_delete(dbm, key);
+ if (dbmp->di_size >= 0) {
+ dbmp->di_size--;
+ }
+
+ return rb_assoc_new(keystr, valstr);
+}
+
+static VALUE
+fsdbm_delete_if(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE keystr, valstr;
+ VALUE ret, ary = rb_ary_new();
+ int i, status = 0, n;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ n = dbmp->di_size;
+ dbmp->di_size = -1;
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
+ if (status != 0) goto delete;
+ if (RTEST(ret)) rb_ary_push(ary, keystr);
+ }
+ delete:
+ for (i = 0; i < RARRAY(ary)->len; i++) {
+ keystr = RARRAY(ary)->ptr[i];
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+ if (sdbm_delete(dbm, key)) {
+ rb_raise(rb_eRuntimeError, "sdbm_delete failed");
+ }
+ }
+ if (status) rb_jump_tag(status);
+ if (n > 0) dbmp->di_size = n - RARRAY(ary)->len;
+
+ return obj;
+}
+
+static VALUE
+fsdbm_clear(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ rb_secure(4);
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ dbmp->di_size = -1;
+ while (key = sdbm_firstkey(dbm), key.dptr) {
+ do {
+ if (sdbm_delete(dbm, key)) {
+ rb_raise(rb_eRuntimeError, "sdbm_delete failed");
+ }
+ key = sdbm_nextkey(dbm);
+ } while (key.dptr);
+ }
+ dbmp->di_size = 0;
+
+ return obj;
+}
+
+static VALUE
+fsdbm_invert(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE keystr, valstr;
+ VALUE hash = rb_hash_new();
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ rb_hash_aset(hash, valstr, keystr);
+ }
+ return hash;
+}
+
+static VALUE
+each_pair(obj)
+ VALUE obj;
+{
+ return rb_funcall(obj, rb_intern("each_pair"), 0, 0);
+}
+
+static VALUE fsdbm_store _((VALUE,VALUE,VALUE));
+
+static VALUE
+update_i(pair, dbm)
+ VALUE pair, dbm;
+{
+ Check_Type(pair, T_ARRAY);
+ if (RARRAY(pair)->len < 2) {
+ rb_raise(rb_eArgError, "pair must be [key, value]");
+ }
+ fsdbm_store(dbm, RARRAY(pair)->ptr[0], RARRAY(pair)->ptr[1]);
+ return Qnil;
+}
+
+static VALUE
+fsdbm_update(obj, other)
+ VALUE obj, other;
+{
+ rb_iterate(each_pair, other, update_i, obj);
+ return obj;
+}
+
+static VALUE
+fsdbm_replace(obj, other)
+ VALUE obj, other;
+{
+ fsdbm_clear(obj);
+ rb_iterate(each_pair, other, update_i, obj);
+ return obj;
+}
+
+static VALUE
+fsdbm_store(obj, keystr, valstr)
+ VALUE obj, keystr, valstr;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ if (valstr == Qnil) {
+ fsdbm_delete(obj, keystr);
+ return Qnil;
+ }
+
+ rb_secure(4);
+ keystr = rb_obj_as_string(keystr);
+
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ if (NIL_P(valstr)) return fsdbm_delete(obj, keystr);
+
+ valstr = rb_obj_as_string(valstr);
+ val.dptr = RSTRING(valstr)->ptr;
+ val.dsize = RSTRING(valstr)->len;
+
+ GetDBM(obj, dbmp);
+ dbmp->di_size = -1;
+ dbm = dbmp->di_dbm;
+ if (sdbm_store(dbm, key, val, DBM_REPLACE)) {
+#ifdef HAVE_DBM_CLAERERR
+ sdbm_clearerr(dbm);
+#endif
+ if (errno == EPERM) rb_sys_fail(0);
+ rb_raise(rb_eRuntimeError, "sdbm_store failed");
+ }
+
+ return valstr;
+}
+
+static VALUE
+fsdbm_length(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ int i = 0;
+
+ GetDBM(obj, dbmp);
+ if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
+ dbm = dbmp->di_dbm;
+
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ i++;
+ }
+ dbmp->di_size = i;
+
+ return INT2FIX(i);
+}
+
+static VALUE
+fsdbm_empty_p(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ int i = 0;
+
+ GetDBM(obj, dbmp);
+ if (dbmp->di_size < 0) {
+ dbm = dbmp->di_dbm;
+
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ i++;
+ }
+ }
+ else {
+ i = dbmp->di_size;
+ }
+ if (i == 0) return Qtrue;
+ return Qfalse;
+}
+
+static VALUE
+fsdbm_each_value(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ rb_yield(rb_tainted_str_new(val.dptr, val.dsize));
+ }
+ return obj;
+}
+
+static VALUE
+fsdbm_each_key(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ rb_yield(rb_tainted_str_new(key.dptr, key.dsize));
+ }
+ return obj;
+}
+
+static VALUE
+fsdbm_each_pair(obj)
+ VALUE obj;
+{
+ datum key, val;
+ DBM *dbm;
+ struct dbmdata *dbmp;
+ VALUE keystr, valstr;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ keystr = rb_tainted_str_new(key.dptr, key.dsize);
+ valstr = rb_tainted_str_new(val.dptr, val.dsize);
+ rb_yield(rb_assoc_new(keystr, valstr));
+ }
+
+ return obj;
+}
+
+static VALUE
+fsdbm_keys(obj)
+ VALUE obj;
+{
+ datum key;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE ary;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ ary = rb_ary_new();
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
+ }
+
+ return ary;
+}
+
+static VALUE
+fsdbm_values(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE ary;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ ary = rb_ary_new();
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
+ }
+
+ return ary;
+}
+
+static VALUE
+fsdbm_has_key(obj, keystr)
+ VALUE obj, keystr;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ keystr = rb_str_to_str(keystr);
+ key.dptr = RSTRING(keystr)->ptr;
+ key.dsize = RSTRING(keystr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ val = sdbm_fetch(dbm, key);
+ if (val.dptr) return Qtrue;
+ return Qfalse;
+}
+
+static VALUE
+fsdbm_has_value(obj, valstr)
+ VALUE obj, valstr;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+
+ valstr = rb_str_to_str(valstr);
+ val.dptr = RSTRING(valstr)->ptr;
+ val.dsize = RSTRING(valstr)->len;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ if (val.dsize == RSTRING(valstr)->len &&
+ memcmp(val.dptr, RSTRING(valstr)->ptr, val.dsize) == 0)
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE
+fsdbm_to_a(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE ary;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ ary = rb_ary_new();
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ rb_ary_push(ary, rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
+ rb_tainted_str_new(val.dptr, val.dsize)));
+ }
+
+ return ary;
+}
+
+static VALUE
+fsdbm_to_hash(obj)
+ VALUE obj;
+{
+ datum key, val;
+ struct dbmdata *dbmp;
+ DBM *dbm;
+ VALUE hash;
+
+ GetDBM(obj, dbmp);
+ dbm = dbmp->di_dbm;
+
+ hash = rb_hash_new();
+ for (key = sdbm_firstkey(dbm); key.dptr; key = sdbm_nextkey(dbm)) {
+ val = sdbm_fetch(dbm, key);
+ rb_hash_aset(hash, rb_tainted_str_new(key.dptr, key.dsize),
+ rb_tainted_str_new(val.dptr, val.dsize));
+ }
+
+ return hash;
+}
+
+static VALUE
+fsdbm_reject(obj)
+ VALUE obj;
+{
+ return rb_hash_delete_if(fsdbm_to_hash(obj));
+}
+
+void
+Init_sdbm()
+{
+ cSDBM = rb_define_class("SDBM", rb_cObject);
+ rb_include_module(cSDBM, rb_mEnumerable);
+
+ rb_define_singleton_method(cSDBM, "open", fsdbm_s_open, -1);
+ rb_define_singleton_method(cSDBM, "new", fsdbm_s_new, -1);
+ rb_define_method(cSDBM, "initialize", fsdbm_initialize, -1);
+ rb_define_method(cSDBM, "close", fsdbm_close, 0);
+ rb_define_method(cSDBM, "[]", fsdbm_aref, 1);
+ rb_define_method(cSDBM, "fetch", fsdbm_fetch_m, -1);
+ rb_define_method(cSDBM, "[]=", fsdbm_store, 2);
+ rb_define_method(cSDBM, "store", fsdbm_store, 2);
+ rb_define_method(cSDBM, "index", fsdbm_index, 1);
+ rb_define_method(cSDBM, "indexes", fsdbm_indexes, -1);
+ rb_define_method(cSDBM, "indices", fsdbm_indexes, -1);
+ rb_define_method(cSDBM, "length", fsdbm_length, 0);
+ rb_define_alias(cSDBM, "size", "length");
+ rb_define_method(cSDBM, "empty?", fsdbm_empty_p, 0);
+ rb_define_method(cSDBM, "each", fsdbm_each_pair, 0);
+ rb_define_method(cSDBM, "each_value", fsdbm_each_value, 0);
+ rb_define_method(cSDBM, "each_key", fsdbm_each_key, 0);
+ rb_define_method(cSDBM, "each_pair", fsdbm_each_pair, 0);
+ rb_define_method(cSDBM, "keys", fsdbm_keys, 0);
+ rb_define_method(cSDBM, "values", fsdbm_values, 0);
+ rb_define_method(cSDBM, "shift", fsdbm_shift, 0);
+ rb_define_method(cSDBM, "delete", fsdbm_delete, 1);
+ rb_define_method(cSDBM, "delete_if", fsdbm_delete_if, 0);
+ rb_define_method(cSDBM, "reject!", fsdbm_delete_if, 0);
+ rb_define_method(cSDBM, "reject", fsdbm_reject, 0);
+ rb_define_method(cSDBM, "clear", fsdbm_clear, 0);
+ rb_define_method(cSDBM,"invert", fsdbm_invert, 0);
+ rb_define_method(cSDBM,"update", fsdbm_update, 1);
+ rb_define_method(cSDBM,"replace", fsdbm_replace, 1);
+
+ rb_define_method(cSDBM, "include?", fsdbm_has_key, 1);
+ rb_define_method(cSDBM, "has_key?", fsdbm_has_key, 1);
+ rb_define_method(cSDBM, "member?", fsdbm_has_key, 1);
+ rb_define_method(cSDBM, "has_value?", fsdbm_has_value, 1);
+ rb_define_method(cSDBM, "key?", fsdbm_has_key, 1);
+ rb_define_method(cSDBM, "value?", fsdbm_has_value, 1);
+
+ rb_define_method(cSDBM, "to_a", fsdbm_to_a, 0);
+ rb_define_method(cSDBM, "to_hash", fsdbm_to_hash, 0);
+}
diff --git a/win32/sdbm.h b/ext/sdbm/sdbm.h
index 4b731c6574..ce8f54c4d4 100644
--- a/win32/sdbm.h
+++ b/ext/sdbm/sdbm.h
@@ -4,8 +4,8 @@
* author: oz@nexus.yorku.ca
* status: public domain.
*/
-#ifndef _NDBM_H_
-#define _NDBM_H_
+#ifndef _SDBM_H_
+#define _SDBM_H_
#define DBLKSIZ 4096
#define PBLKSIZ 1024
@@ -37,13 +37,13 @@ typedef struct {
/*
* utility macros
*/
-#define dbm_rdonly(db) ((db)->flags & DBM_RDONLY)
-#define dbm_error(db) ((db)->flags & DBM_IOERR)
+#define sdbm_rdonly(db) ((db)->flags & DBM_RDONLY)
+#define sdbm_error(db) ((db)->flags & DBM_IOERR)
-#define dbm_clearerr(db) ((db)->flags &= ~DBM_IOERR) /* ouch */
+#define sdbm_clearerr(db) ((db)->flags &= ~DBM_IOERR) /* ouch */
-#define dbm_dirfno(db) ((db)->dirf)
-#define dbm_pagfno(db) ((db)->pagf)
+#define sdbm_dirfno(db) ((db)->dirf)
+#define sdbm_pagfno(db) ((db)->pagf)
typedef struct {
char *dptr;
@@ -59,7 +59,7 @@ extern datum nullitem;
#endif
/*
- * flags to dbm_store
+ * flags to sdbm_store
*/
#define DBM_INSERT 0
#define DBM_REPLACE 1
@@ -67,18 +67,18 @@ extern datum nullitem;
/*
* ndbm interface
*/
-extern DBM *dbm_open proto((char *, int, int));
-extern void dbm_close proto((DBM *));
-extern datum dbm_fetch proto((DBM *, datum));
-extern int dbm_delete proto((DBM *, datum));
-extern int dbm_store proto((DBM *, datum, datum, int));
-extern datum dbm_firstkey proto((DBM *));
-extern datum dbm_nextkey proto((DBM *));
+extern DBM *sdbm_open proto((char *, int, int));
+extern void sdbm_close proto((DBM *));
+extern datum sdbm_fetch proto((DBM *, datum));
+extern int sdbm_delete proto((DBM *, datum));
+extern int sdbm_store proto((DBM *, datum, datum, int));
+extern datum sdbm_firstkey proto((DBM *));
+extern datum sdbm_nextkey proto((DBM *));
/*
* other
*/
-extern DBM *dbm_prep proto((char *, char *, int, int));
-extern long dbm_hash proto((char *, int));
+extern DBM *sdbm_prep proto((char *, char *, int, int));
+extern long sdbm_hash proto((char *, int));
-#endif /* _NDBM_H_ */
+#endif /* _SDBM_H_ */
diff --git a/ext/socket/.cvsignore b/ext/socket/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/socket/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/socket/MANIFEST b/ext/socket/MANIFEST
index d41d9e0b69..616d459d92 100644
--- a/ext/socket/MANIFEST
+++ b/ext/socket/MANIFEST
@@ -1,4 +1,8 @@
MANIFEST
+addrinfo.h
depend
extconf.rb
+getaddrinfo.c
+getnameinfo.c
+sockport.h
socket.c
diff --git a/ext/socket/addrinfo.h b/ext/socket/addrinfo.h
new file mode 100644
index 0000000000..6000a466ba
--- /dev/null
+++ b/ext/socket/addrinfo.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef ADDR_INFO_H
+#define ADDR_INFO_H
+#ifndef HAVE_GETADDRINFO
+
+/* special compatibility hack */
+#undef EAI_ADDRFAMILY
+#undef EAI_AGAIN
+#undef EAI_BADFLAGS
+#undef EAI_FAIL
+#undef EAI_FAMILY
+#undef EAI_MEMORY
+#undef EAI_NODATA
+#undef EAI_NONAME
+#undef EAI_SERVICE
+#undef EAI_SOCKTYPE
+#undef EAI_SYSTEM
+#undef EAI_BADHINTS
+#undef EAI_PROTOCOL
+#undef EAI_MAX
+
+#undef AI_PASSIVE
+#undef AI_CANONNAME
+#undef AI_NUMERICHOST
+#undef AI_ALL
+#undef AI_ADDRCONFIG
+#undef AI_V4MAPPED
+#undef AI_DEFAULT
+
+#undef NI_NOFQDN
+#undef NI_NUMERICHOST
+#undef NI_NAMEREQD
+#undef NI_NUMERICSERV
+#undef NI_DGRAM
+
+#define addrinfo addrinfo__compat
+#define getaddrinfo getaddrinfo__compat
+#define getnameinfo getnameinfo__compat
+#define freehostent freehostent__compat
+#define freeaddrinfo freeaddrinfo__compat
+
+#ifndef __P
+# ifdef HAVE_PROTOTYPES
+# define __P(args) args
+# else
+# define __P(args) ()
+# endif
+#endif
+
+/* special compatibility hack -- end*/
+
+
+/*
+ * Error return codes from getaddrinfo()
+ */
+#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */
+#define EAI_AGAIN 2 /* temporary failure in name resolution */
+#define EAI_BADFLAGS 3 /* invalid value for ai_flags */
+#define EAI_FAIL 4 /* non-recoverable failure in name resolution */
+#define EAI_FAMILY 5 /* ai_family not supported */
+#define EAI_MEMORY 6 /* memory allocation failure */
+#define EAI_NODATA 7 /* no address associated with hostname */
+#define EAI_NONAME 8 /* hostname nor servname provided, or not known */
+#define EAI_SERVICE 9 /* servname not supported for ai_socktype */
+#define EAI_SOCKTYPE 10 /* ai_socktype not supported */
+#define EAI_SYSTEM 11 /* system error returned in errno */
+#define EAI_BADHINTS 12
+#define EAI_PROTOCOL 13
+#define EAI_MAX 14
+
+/*
+ * Flag values for getaddrinfo()
+ */
+#define AI_PASSIVE 0x00000001 /* get address to use bind() */
+#define AI_CANONNAME 0x00000002 /* fill ai_canonname */
+#define AI_NUMERICHOST 0x00000004 /* prevent name resolution */
+/* valid flags for addrinfo */
+#define AI_MASK (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST)
+
+#define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
+#define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */
+#define AI_ADDRCONFIG 0x00000400 /* only if any address is assigned */
+#define AI_V4MAPPED 0x00000800 /* accept IPv4-mapped IPv6 address */
+/* special recommended flags for getipnodebyname */
+#define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
+
+/*
+ * Constants for getnameinfo()
+ */
+#define NI_MAXHOST 1025
+#define NI_MAXSERV 32
+
+/*
+ * Flag values for getnameinfo()
+ */
+#define NI_NOFQDN 0x00000001
+#define NI_NUMERICHOST 0x00000002
+#define NI_NAMEREQD 0x00000004
+#define NI_NUMERICSERV 0x00000008
+#define NI_DGRAM 0x00000010
+
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ size_t ai_addrlen; /* length of ai_addr */
+ char *ai_canonname; /* canonical name for hostname */
+ struct sockaddr *ai_addr; /* binary address */
+ struct addrinfo *ai_next; /* next structure in linked list */
+};
+
+extern int getaddrinfo __P((
+ const char *hostname, const char *servname,
+ const struct addrinfo *hints,
+ struct addrinfo **res));
+
+extern int getnameinfo __P((
+ const struct sockaddr *sa,
+ size_t salen,
+ char *host,
+ size_t hostlen,
+ char *serv,
+ size_t servlen,
+ int flags));
+
+extern void freehostent __P((struct hostent *));
+extern void freeaddrent __P((struct addrinfo *));
+extern char *gai_strerror __P((int));
+
+/* In case there is no definition of offsetof() provided - though any proper
+Standard C system should have one. */
+
+#ifndef offsetof
+#define offsetof(p_type,field) ((size_t)&(((p_type *)0)->field))
+#endif
+
+#endif
+#endif
diff --git a/ext/socket/depend b/ext/socket/depend
index 3d54fa073c..cca6d4e62a 100644
--- a/ext/socket/depend
+++ b/ext/socket/depend
@@ -1 +1,3 @@
-socket.o : socket.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h $(hdrdir)/io.h $(hdrdir)/sig.h
+socket.o : socket.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/rubyio.h $(hdrdir)/rubysig.h sockport.h
+getnameinfo.o: getnameinfo.c $(topdir)/config.h addrinfo.h sockport.h
+getaddrinfo.o: getaddrinfo.c $(topdir)/config.h addrinfo.h sockport.h
diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb
index bbda95cf83..7dadd70078 100644
--- a/ext/socket/extconf.rb
+++ b/ext/socket/extconf.rb
@@ -1,25 +1,346 @@
-$LDFLAGS = "-L/usr/local/lib"
-case PLATFORM
-when /mswin32/
+require 'mkmf'
+
+$LIBPATH << "/usr/local/lib" if File.directory?("/usr/local/lib")
+$CPPFLAGS += " -Dss_family=__ss_family -Dss_len=__ss_len"
+
+case RUBY_PLATFORM
+when /mswin32|mingw/
test_func = "WSACleanup"
have_library("wsock32", "WSACleanup")
-when /cygwin32/
+ have_func("closesocket")
+when /cygwin/
+# $LDFLAGS << " -L/usr/lib" if File.directory?("/usr/lib")
+# $CFLAGS << " -I/usr/include"
test_func = "socket"
+# have_library("bind", "gethostbyaddr")
+when /beos/
+ test_func = "socket"
+ have_library("net", "socket")
+ have_func("closesocket")
+when /i386-os2_emx/
+ test_func = "socket"
+ have_library("socket", "socket")
else
test_func = "socket"
+ have_library("nsl", "t_open")
have_library("socket", "socket")
- have_library("inet", "gethostbyname")
- have_library("nsl", "gethostbyname")
end
+
+$ipv6 = false
+if enable_config("ipv6", false)
+ if try_link(<<EOF)
+#include <sys/types.h>
+#include <sys/socket.h>
+main()
+{
+ socket(AF_INET6, SOCK_STREAM, 0);
+}
+EOF
+ $CFLAGS+=" -DENABLE_IPV6"
+ $ipv6 = true
+ end
+end
+
+$ipv6type = nil
+$ipv6lib = nil
+$ipv6libdir = nil
+$ipv6trylibc = nil
+if $ipv6
+ if egrep_cpp("yes", <<EOF)
+#include <netinet/in.h>
+#ifdef IPV6_INRIA_VERSION
+yes
+#endif
+EOF
+ $ipv6type = "inria"
+ $CFLAGS="-DINET6 "+$CFLAGS
+ elsif egrep_cpp("yes", <<EOF)
+#include <netinet/in.h>
+#ifdef __KAME__
+yes
+#endif
+EOF
+ $ipv6type = "kame"
+ $ipv6lib="inet6"
+ $ipv6libdir="/usr/local/v6/lib"
+ $ipv6trylibc=true
+ $CFLAGS="-DINET6 "+$CFLAGS
+ elsif File.directory? "/usr/inet6"
+ $ipv6type = "linux"
+ $ipv6lib="inet6"
+ $ipv6libdir="/usr/inet6/lib"
+ $CFLAGS="-DINET6 -I/usr/inet6/include "+$CFLAGS
+ elsif egrep_cpp("yes", <<EOF)
+#include <sys/param.h>
+#ifdef _TOSHIBA_INET6
+yes
+#endif
+EOF
+ $ipv6type = "toshiba"
+ $ipv6lib="inet6"
+ $ipv6libdir="/usr/local/v6/lib"
+ $CFLAGS="-DINET6 "+$CFLAGS
+ elsif egrep_cpp("yes", <<EOF)
+#include </usr/local/v6/include/sys/v6config.h>
+#ifdef __V6D__
+yes
+#endif
+EOF
+ $ipv6type = "v6d"
+ $ipv6lib="v6"
+ $ipv6libdir="/usr/local/v6/lib"
+ $CFLAGS="-DINET6 -I/usr/local/v6/include "+$CFLAGS
+ elsif egrep_cpp("yes", <<EOF)
+#include <sys/param.h>
+#ifdef _ZETA_MINAMI_INET6
+yes
+#endif
+EOF
+ $ipv6type = "zeta"
+ $ipv6lib="inet6"
+ $ipv6libdir="/usr/local/v6/lib"
+ $CFLAGS="-DINET6 "+$CFLAGS
+ else
+ $ipv6lib=with_config("ipv6-lib", nil)
+ $ipv6libdir=with_config("ipv6-libdir", nil)
+ $CFLAGS="-DINET6 "+$CFLAGS
+ end
+
+ if $ipv6lib
+ if File.directory? $ipv6libdir and File.exist? "#{$ipv6libdir}/lib#{$ipv6lib}.a"
+ $LOCAL_LIBS = " -L#$ipv6libdir -l#$ipv6lib"
+ elsif !$ipv6trylibc
+ print <<EOS
+
+Fatal: no #$ipv6lib library found. cannot continue.
+You need to fetch lib#{$ipv6lib}.a from appropriate
+ipv6 kit and compile beforehand.
+EOS
+ exit
+ end
+ end
+end
+
+ if try_link(<<EOF)
+#include <sys/types.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+int
+main()
+{
+ struct sockaddr_in sin;
+
+ sin.sin_len;
+ return 0;
+}
+EOF
+ $CFLAGS="-DHAVE_SIN_LEN "+$CFLAGS
+end
+
+ if try_link(<<EOF)
+#include <sys/types.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/socket.h>
+int
+main()
+{
+ struct sockaddr_storage ss;
+
+ ss.ss_family;
+ return 0;
+}
+EOF
+ $CFLAGS="-DHAVE_SOCKADDR_STORAGE "+$CFLAGS
+end
+
+ if try_link(<<EOF)
+#include <sys/types.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+int
+main()
+{
+ struct sockaddr sa;
+
+ sa.sa_len;
+ return 0;
+}
+EOF
+ $CFLAGS="-DHAVE_SA_LEN "+$CFLAGS
+end
+
+have_header("netinet/tcp.h") if not /cygwin/ === RUBY_PLATFORM # for cygwin 1.1.5
+have_header("netinet/udp.h")
+
+$getaddr_info_ok = false
+if not enable_config("wide-getaddrinfo", false) and try_run(<<EOF)
+#include <sys/types.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#ifndef AF_LOCAL
+#define AF_LOCAL AF_UNIX
+#endif
+
+main()
+{
+ int passive, gaierr, inet4 = 0, inet6 = 0;
+ struct addrinfo hints, *ai, *aitop;
+ char straddr[INET6_ADDRSTRLEN], strport[16];
+
+ for (passive = 0; passive <= 1; passive++) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = passive ? AI_PASSIVE : 0;
+ hints.ai_socktype = SOCK_STREAM;
+ if ((gaierr = getaddrinfo(NULL, "54321", &hints, &aitop)) != 0) {
+ (void)gai_strerror(gaierr);
+ goto bad;
+ }
+ for (ai = aitop; ai; ai = ai->ai_next) {
+ if (ai->ai_family == AF_LOCAL) continue;
+ if (ai->ai_addr == NULL ||
+ ai->ai_addrlen == 0 ||
+ getnameinfo(ai->ai_addr, ai->ai_addrlen,
+ straddr, sizeof(straddr), strport, sizeof(strport),
+ NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
+ goto bad;
+ }
+ if (strcmp(strport, "54321") != 0) {
+ goto bad;
+ }
+ switch (ai->ai_family) {
+ case AF_INET:
+ if (passive) {
+ if (strcmp(straddr, "0.0.0.0") != 0) {
+ goto bad;
+ }
+ } else {
+ if (strcmp(straddr, "127.0.0.1") != 0) {
+ goto bad;
+ }
+ }
+ inet4++;
+ break;
+ case AF_INET6:
+ if (passive) {
+ if (strcmp(straddr, "::") != 0) {
+ goto bad;
+ }
+ } else {
+ if (strcmp(straddr, "::1") != 0) {
+ goto bad;
+ }
+ }
+ inet6++;
+ break;
+ case AF_UNSPEC:
+ goto bad;
+ break;
+ default:
+ /* another family support? */
+ break;
+ }
+ }
+ }
+
+ if (!(inet4 == 0 || inet4 == 2))
+ goto bad;
+ if (!(inet6 == 0 || inet6 == 2))
+ goto bad;
+
+ if (aitop)
+ freeaddrinfo(aitop);
+ exit(0);
+
+ bad:
+ if (aitop)
+ freeaddrinfo(aitop);
+ exit(1);
+}
+EOF
+ $getaddr_info_ok = true
+end
+if $ipv6 and not $getaddr_info_ok
+ print <<EOS
+
+Fatal: --enable-ipv6 is specified, and your OS seems to support IPv6 feature.
+But your getaddrinfo() and getnameinfo() are appeared to be broken. Sorry,
+you cannot compile IPv6 socket classes with broken these functions.
+EOS
+ exit
+end
+
+case with_config("lookup-order-hack", "UNSPEC")
+when "INET"
+ $CFLAGS="-DLOOKUP_ORDER_HACK_INET "+$CFLAGS
+when "INET6"
+ $CFLAGS="-DLOOKUP_ORDER_HACK_INET6 "+$CFLAGS
+when "UNSPEC"
+ # nothing special
+else
+ print <<EOS
+
+Fatal: invalid value for --with-lookup-order-hack (expected INET, INET6 or UNSPEC)
+EOS
+ exit
+end
+
+$objs = ["socket.#{$OBJEXT}"]
+
+if $getaddr_info_ok and have_func("getaddrinfo") and have_func("getnameinfo")
+ have_getaddrinfo = true
+end
+
+if have_getaddrinfo
+ $CFLAGS="-DHAVE_GETADDRINFO "+$CFLAGS
+else
+ $CFLAGS="-I. "+$CFLAGS
+ $objs += ["getaddrinfo.#{$OBJEXT}"]
+ $objs += ["getnameinfo.#{$OBJEXT}"]
+ have_func("inet_ntop") or have_func("inet_ntoa")
+ have_func("inet_pton") or have_func("inet_aton")
+ have_func("getservbyport")
+ have_header("arpa/inet.h")
+ have_header("arpa/nameser.h")
+ have_header("resolv.h")
+end
+
+if !try_link(<<EOF)
+#include <sys/types.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+int
+main()
+{
+ socklen_t len;
+ return 0;
+}
+EOF
+ $CFLAGS="-Dsocklen_t=int "+$CFLAGS
+end
+
have_header("sys/un.h")
+
if have_func(test_func)
have_func("hsterror")
unless have_func("gethostname")
have_func("uname")
end
- if ENV["SOCKS_SERVER"] # test if SOCKSsocket needed
- if have_library("socks", "Rconnect")
- $CFLAGS="-DSOCKS"
+ if ENV["SOCKS_SERVER"] or enable_config("socks", false)
+ if have_library("socks5", "SOCKSinit")
+ $CFLAGS+=" -DSOCKS5 -DSOCKS"
+ elsif have_library("socks", "Rconnect")
+ $CFLAGS+=" -DSOCKS"
end
end
create_makefile("socket")
diff --git a/ext/socket/getaddrinfo.c b/ext/socket/getaddrinfo.c
new file mode 100644
index 0000000000..d518017bc8
--- /dev/null
+++ b/ext/socket/getaddrinfo.c
@@ -0,0 +1,683 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
+ *
+ * Issues to be discussed:
+ * - Thread safe-ness must be checked.
+ * - Return values. There are nonstandard return values defined and used
+ * in the source code. This is because RFC2133 is silent about which error
+ * code must be returned for which situation.
+ * - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag.
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#ifndef NT
+#include <sys/param.h>
+#if defined(__BEOS__)
+# include <net/socket.h>
+#else
+# include <sys/socket.h>
+#endif
+#include <netinet/in.h>
+#if defined(HAVE_ARPA_INET_H)
+#include <arpa/inet.h>
+#endif
+#if defined(HAVE_ARPA_NAMESER_H)
+#include <arpa/nameser.h>
+#endif
+#include <netdb.h>
+#if defined(HAVE_RESOLV_H)
+#include <resolv.h>
+#endif
+#include <unistd.h>
+#else
+#include <winsock2.h>
+#include <io.h>
+#endif
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+
+#ifdef SOCKS5
+#include <socks.h>
+#endif
+
+#include "addrinfo.h"
+#include "sockport.h"
+
+#if defined(__KAME__) && defined(INET6)
+# define FAITH
+#endif
+
+#define SUCCESS 0
+#define ANY 0
+#define YES 1
+#define NO 0
+
+#ifdef FAITH
+static int translate = NO;
+static struct in6_addr faith_prefix = IN6ADDR_ANY_INIT;
+#endif
+
+static const char in_addrany[] = { 0, 0, 0, 0 };
+static const char in6_addrany[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+static const char in_loopback[] = { 127, 0, 0, 1 };
+static const char in6_loopback[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+};
+
+struct sockinet {
+ u_char si_len;
+ u_char si_family;
+ u_short si_port;
+};
+
+static struct afd {
+ int a_af;
+ int a_addrlen;
+ int a_socklen;
+ int a_off;
+ const char *a_addrany;
+ const char *a_loopback;
+} afdl [] = {
+#ifdef INET6
+#define N_INET6 0
+ {PF_INET6, sizeof(struct in6_addr),
+ sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr),
+ in6_addrany, in6_loopback},
+#define N_INET 1
+#else
+#define N_INET 0
+#endif
+ {PF_INET, sizeof(struct in_addr),
+ sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr),
+ in_addrany, in_loopback},
+ {0, 0, 0, 0, NULL, NULL},
+};
+
+#ifdef INET6
+#define PTON_MAX 16
+#else
+#define PTON_MAX 4
+#endif
+
+static int get_name __P((const char *, struct afd *,
+ struct addrinfo **, char *, struct addrinfo *,
+ int));
+static int get_addr __P((const char *, int, struct addrinfo **,
+ struct addrinfo *, int));
+static int str_isnumber __P((const char *));
+
+static char *ai_errlist[] = {
+ "success.",
+ "address family for hostname not supported.", /* EAI_ADDRFAMILY */
+ "temporary failure in name resolution.", /* EAI_AGAIN */
+ "invalid value for ai_flags.", /* EAI_BADFLAGS */
+ "non-recoverable failure in name resolution.", /* EAI_FAIL */
+ "ai_family not supported.", /* EAI_FAMILY */
+ "memory allocation failure.", /* EAI_MEMORY */
+ "no address associated with hostname.", /* EAI_NODATA */
+ "hostname nor servname provided, or not known.",/* EAI_NONAME */
+ "servname not supported for ai_socktype.", /* EAI_SERVICE */
+ "ai_socktype not supported.", /* EAI_SOCKTYPE */
+ "system error returned in errno.", /* EAI_SYSTEM */
+ "invalid value for hints.", /* EAI_BADHINTS */
+ "resolved protocol is unknown.", /* EAI_PROTOCOL */
+ "unknown error.", /* EAI_MAX */
+};
+
+#define GET_CANONNAME(ai, str) \
+if (pai->ai_flags & AI_CANONNAME) {\
+ if (((ai)->ai_canonname = (char *)malloc(strlen(str) + 1)) != NULL) {\
+ strcpy((ai)->ai_canonname, (str));\
+ } else {\
+ error = EAI_MEMORY;\
+ goto free;\
+ }\
+}
+
+#define GET_AI(ai, afd, addr, port) {\
+ char *p;\
+ if (((ai) = (struct addrinfo *)malloc(sizeof(struct addrinfo) +\
+ ((afd)->a_socklen)))\
+ == NULL) {\
+ error = EAI_MEMORY;\
+ goto free;\
+ }\
+ memcpy(ai, pai, sizeof(struct addrinfo));\
+ (ai)->ai_addr = (struct sockaddr *)((ai) + 1);\
+ memset((ai)->ai_addr, 0, (afd)->a_socklen);\
+ SET_SA_LEN((ai)->ai_addr, (ai)->ai_addrlen = (afd)->a_socklen);\
+ (ai)->ai_addr->sa_family = (ai)->ai_family = (afd)->a_af;\
+ ((struct sockinet *)(ai)->ai_addr)->si_port = port;\
+ p = (char *)((ai)->ai_addr);\
+ memcpy(p + (afd)->a_off, (addr), (afd)->a_addrlen);\
+}
+
+#define ERR(err) { error = (err); goto bad; }
+
+char *
+gai_strerror(ecode)
+ int ecode;
+{
+ if (ecode < 0 || ecode > EAI_MAX)
+ ecode = EAI_MAX;
+ return ai_errlist[ecode];
+}
+
+void
+freeaddrinfo(ai)
+ struct addrinfo *ai;
+{
+ struct addrinfo *next;
+
+ do {
+ next = ai->ai_next;
+ if (ai->ai_canonname)
+ free(ai->ai_canonname);
+ /* no need to free(ai->ai_addr) */
+ free(ai);
+ } while ((ai = next) != NULL);
+}
+
+static int
+str_isnumber(p)
+ const char *p;
+{
+ char *q = (char *)p;
+ while (*q) {
+ if (! isdigit(*q))
+ return NO;
+ q++;
+ }
+ return YES;
+}
+
+#ifndef HAVE_INET_PTON
+
+static int
+inet_pton(af, hostname, pton)
+ int af;
+ const char *hostname;
+ void *pton;
+{
+ struct in_addr in;
+
+#ifdef HAVE_INET_ATON
+ if (!inet_aton(hostname, &in))
+ return 0;
+#else
+ int d1, d2, d3, d4;
+ char ch;
+
+ if (sscanf(hostname, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 &&
+ 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 &&
+ 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
+ in.s_addr = htonl(
+ ((long) d1 << 24) | ((long) d2 << 16) |
+ ((long) d3 << 8) | ((long) d4 << 0));
+ }
+ else {
+ return 0;
+ }
+#endif
+ memcpy(pton, &in, sizeof(in));
+ return 1;
+}
+#endif
+
+int
+getaddrinfo(hostname, servname, hints, res)
+ const char *hostname, *servname;
+ const struct addrinfo *hints;
+ struct addrinfo **res;
+{
+ struct addrinfo sentinel;
+ struct addrinfo *top = NULL;
+ struct addrinfo *cur;
+ int i, error = 0;
+ char pton[PTON_MAX];
+ struct addrinfo ai;
+ struct addrinfo *pai;
+ u_short port;
+
+#ifdef FAITH
+ static int firsttime = 1;
+
+ if (firsttime) {
+ /* translator hack */
+ {
+ char *q = getenv("GAI");
+ if (q && inet_pton(AF_INET6, q, &faith_prefix) == 1)
+ translate = YES;
+ }
+ firsttime = 0;
+ }
+#endif
+
+ /* initialize file static vars */
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+ pai = &ai;
+ pai->ai_flags = 0;
+ pai->ai_family = PF_UNSPEC;
+ pai->ai_socktype = ANY;
+ pai->ai_protocol = ANY;
+ pai->ai_addrlen = 0;
+ pai->ai_canonname = NULL;
+ pai->ai_addr = NULL;
+ pai->ai_next = NULL;
+ port = ANY;
+
+ if (hostname == NULL && servname == NULL)
+ return EAI_NONAME;
+ if (hints) {
+ /* error check for hints */
+ if (hints->ai_addrlen || hints->ai_canonname ||
+ hints->ai_addr || hints->ai_next)
+ ERR(EAI_BADHINTS); /* xxx */
+ if (hints->ai_flags & ~AI_MASK)
+ ERR(EAI_BADFLAGS);
+ switch (hints->ai_family) {
+ case PF_UNSPEC:
+ case PF_INET:
+#ifdef INET6
+ case PF_INET6:
+#endif
+ break;
+ default:
+ ERR(EAI_FAMILY);
+ }
+ memcpy(pai, hints, sizeof(*pai));
+ switch (pai->ai_socktype) {
+ case ANY:
+ switch (pai->ai_protocol) {
+ case ANY:
+ break;
+ case IPPROTO_UDP:
+ pai->ai_socktype = SOCK_DGRAM;
+ break;
+ case IPPROTO_TCP:
+ pai->ai_socktype = SOCK_STREAM;
+ break;
+ default:
+#if defined(SOCK_RAW)
+ pai->ai_socktype = SOCK_RAW;
+#endif
+ break;
+ }
+ break;
+#if defined(SOCK_RAW)
+ case SOCK_RAW:
+ break;
+#endif
+ case SOCK_DGRAM:
+ if (pai->ai_protocol != IPPROTO_UDP &&
+ pai->ai_protocol != ANY)
+ ERR(EAI_BADHINTS); /*xxx*/
+ pai->ai_protocol = IPPROTO_UDP;
+ break;
+ case SOCK_STREAM:
+ if (pai->ai_protocol != IPPROTO_TCP &&
+ pai->ai_protocol != ANY)
+ ERR(EAI_BADHINTS); /*xxx*/
+ pai->ai_protocol = IPPROTO_TCP;
+ break;
+ default:
+ ERR(EAI_SOCKTYPE);
+ break;
+ }
+ }
+
+ /*
+ * service port
+ */
+ if (servname) {
+ if (str_isnumber(servname)) {
+ if (pai->ai_socktype == ANY) {
+ /* caller accept *ANY* socktype */
+ pai->ai_socktype = SOCK_DGRAM;
+ pai->ai_protocol = IPPROTO_UDP;
+ }
+ port = htons((unsigned short)atoi(servname));
+ } else {
+ struct servent *sp;
+ char *proto;
+
+ proto = NULL;
+ switch (pai->ai_socktype) {
+ case ANY:
+ proto = NULL;
+ break;
+ case SOCK_DGRAM:
+ proto = "udp";
+ break;
+ case SOCK_STREAM:
+ proto = "tcp";
+ break;
+ default:
+ fprintf(stderr, "panic!\n");
+ break;
+ }
+ if ((sp = getservbyname(servname, proto)) == NULL)
+ ERR(EAI_SERVICE);
+ port = sp->s_port;
+ if (pai->ai_socktype == ANY)
+ if (strcmp(sp->s_proto, "udp") == 0) {
+ pai->ai_socktype = SOCK_DGRAM;
+ pai->ai_protocol = IPPROTO_UDP;
+ } else if (strcmp(sp->s_proto, "tcp") == 0) {
+ pai->ai_socktype = SOCK_STREAM;
+ pai->ai_protocol = IPPROTO_TCP;
+ } else
+ ERR(EAI_PROTOCOL); /*xxx*/
+ }
+ }
+
+ /*
+ * hostname == NULL.
+ * passive socket -> anyaddr (0.0.0.0 or ::)
+ * non-passive socket -> localhost (127.0.0.1 or ::1)
+ */
+ if (hostname == NULL) {
+ struct afd *afd;
+ int s;
+
+ for (afd = &afdl[0]; afd->a_af; afd++) {
+ if (!(pai->ai_family == PF_UNSPEC
+ || pai->ai_family == afd->a_af)) {
+ continue;
+ }
+
+ /*
+ * filter out AFs that are not supported by the kernel
+ * XXX errno?
+ */
+ s = socket(afd->a_af, SOCK_DGRAM, 0);
+ if (s < 0)
+ continue;
+#if defined(HAVE_CLOSESOCKET)
+ closesocket(s);
+#else
+ close(s);
+#endif
+
+ if (pai->ai_flags & AI_PASSIVE) {
+ GET_AI(cur->ai_next, afd, afd->a_addrany, port);
+ /* xxx meaningless?
+ * GET_CANONNAME(cur->ai_next, "anyaddr");
+ */
+ } else {
+ GET_AI(cur->ai_next, afd, afd->a_loopback,
+ port);
+ /* xxx meaningless?
+ * GET_CANONNAME(cur->ai_next, "localhost");
+ */
+ }
+ cur = cur->ai_next;
+ }
+ top = sentinel.ai_next;
+ if (top)
+ goto good;
+ else
+ ERR(EAI_FAMILY);
+ }
+
+ /* hostname as numeric name */
+ for (i = 0; afdl[i].a_af; i++) {
+ if (inet_pton(afdl[i].a_af, hostname, pton)) {
+ u_long v4a;
+#ifdef INET6
+ u_char pfx;
+#endif
+
+ switch (afdl[i].a_af) {
+ case AF_INET:
+ v4a = ((struct in_addr *)pton)->s_addr;
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ pai->ai_flags &= ~AI_CANONNAME;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0 || v4a == IN_LOOPBACKNET)
+ pai->ai_flags &= ~AI_CANONNAME;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ pfx = ((struct in6_addr *)pton)->s6_addr8[0];
+ if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
+ pai->ai_flags &= ~AI_CANONNAME;
+ break;
+#endif
+ }
+
+ if (pai->ai_family == afdl[i].a_af ||
+ pai->ai_family == PF_UNSPEC) {
+ if (! (pai->ai_flags & AI_CANONNAME)) {
+ GET_AI(top, &afdl[i], pton, port);
+ goto good;
+ }
+ /*
+ * if AI_CANONNAME and if reverse lookup
+ * fail, return ai anyway to pacify
+ * calling application.
+ *
+ * XXX getaddrinfo() is a name->address
+ * translation function, and it looks strange
+ * that we do addr->name translation here.
+ */
+ get_name(pton, &afdl[i], &top, pton, pai, port);
+ goto good;
+ } else
+ ERR(EAI_FAMILY); /*xxx*/
+ }
+ }
+
+ if (pai->ai_flags & AI_NUMERICHOST)
+ ERR(EAI_NONAME);
+
+ /* hostname as alphabetical name */
+ error = get_addr(hostname, pai->ai_family, &top, pai, port);
+ if (error == 0) {
+ if (top) {
+ good:
+ *res = top;
+ return SUCCESS;
+ } else
+ error = EAI_FAIL;
+ }
+ free:
+ if (top)
+ freeaddrinfo(top);
+ bad:
+ *res = NULL;
+ return error;
+}
+
+static int
+get_name(addr, afd, res, numaddr, pai, port0)
+ const char *addr;
+ struct afd *afd;
+ struct addrinfo **res;
+ char *numaddr;
+ struct addrinfo *pai;
+ int port0;
+{
+ u_short port = port0 & 0xffff;
+ struct hostent *hp;
+ struct addrinfo *cur;
+ int error = 0;
+#ifdef INET6
+ int h_error;
+#endif
+
+#ifdef INET6
+ hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+#else
+ hp = gethostbyaddr(addr, afd->a_addrlen, AF_INET);
+#endif
+ if (hp && hp->h_name && hp->h_name[0] && hp->h_addr_list[0]) {
+ GET_AI(cur, afd, hp->h_addr_list[0], port);
+ GET_CANONNAME(cur, hp->h_name);
+ } else
+ GET_AI(cur, afd, numaddr, port);
+
+#ifdef INET6
+ if (hp)
+ freehostent(hp);
+#endif
+ *res = cur;
+ return SUCCESS;
+ free:
+ if (cur)
+ freeaddrinfo(cur);
+#ifdef INET6
+ if (hp)
+ freehostent(hp);
+#endif
+ /* bad: */
+ *res = NULL;
+ return error;
+}
+
+static int
+get_addr(hostname, af, res, pai, port0)
+ const char *hostname;
+ int af;
+ struct addrinfo **res;
+ struct addrinfo *pai;
+ int port0;
+{
+ u_short port = port0 & 0xffff;
+ struct addrinfo sentinel;
+ struct hostent *hp;
+ struct addrinfo *top, *cur;
+ struct afd *afd;
+ int i, error = 0, h_error;
+ char *ap;
+
+ top = NULL;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+#ifdef INET6
+ if (af == AF_UNSPEC) {
+ hp = getipnodebyname(hostname, AF_INET6,
+ AI_ADDRCONFIG|AI_ALL|AI_V4MAPPED, &h_error);
+ } else
+ hp = getipnodebyname(hostname, af, AI_ADDRCONFIG, &h_error);
+#else
+ hp = gethostbyname(hostname);
+ h_error = h_errno;
+#endif
+ if (hp == NULL) {
+ switch (h_error) {
+ case HOST_NOT_FOUND:
+ case NO_DATA:
+ error = EAI_NODATA;
+ break;
+ case TRY_AGAIN:
+ error = EAI_AGAIN;
+ break;
+ case NO_RECOVERY:
+ default:
+ error = EAI_FAIL;
+ break;
+ }
+ goto bad;
+ }
+
+ if ((hp->h_name == NULL) || (hp->h_name[0] == 0) ||
+ (hp->h_addr_list[0] == NULL))
+ ERR(EAI_FAIL);
+
+ for (i = 0; (ap = hp->h_addr_list[i]) != NULL; i++) {
+ switch (af) {
+#ifdef INET6
+ case AF_INET6:
+ afd = &afdl[N_INET6];
+ break;
+#endif
+#ifndef INET6
+ default: /* AF_UNSPEC */
+#endif
+ case AF_INET:
+ afd = &afdl[N_INET];
+ break;
+#ifdef INET6
+ default: /* AF_UNSPEC */
+ if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
+ ap += sizeof(struct in6_addr) -
+ sizeof(struct in_addr);
+ afd = &afdl[N_INET];
+ } else
+ afd = &afdl[N_INET6];
+ break;
+#endif
+ }
+#ifdef FAITH
+ if (translate && afd->a_af == AF_INET) {
+ struct in6_addr *in6;
+
+ GET_AI(cur->ai_next, &afdl[N_INET6], ap, port);
+ in6 = &((struct sockaddr_in6 *)cur->ai_next->ai_addr)->sin6_addr;
+ memcpy(&in6->s6_addr32[0], &faith_prefix,
+ sizeof(struct in6_addr) - sizeof(struct in_addr));
+ memcpy(&in6->s6_addr32[3], ap, sizeof(struct in_addr));
+ } else
+#endif /* FAITH */
+ GET_AI(cur->ai_next, afd, ap, port);
+ if (cur == &sentinel) {
+ top = cur->ai_next;
+ GET_CANONNAME(top, hp->h_name);
+ }
+ cur = cur->ai_next;
+ }
+#ifdef INET6
+ freehostent(hp);
+#endif
+ *res = top;
+ return SUCCESS;
+ free:
+ if (top)
+ freeaddrinfo(top);
+#ifdef INET6
+ if (hp)
+ freehostent(hp);
+#endif
+ bad:
+ *res = NULL;
+ return error;
+}
diff --git a/ext/socket/getnameinfo.c b/ext/socket/getnameinfo.c
new file mode 100644
index 0000000000..bd3bd129bf
--- /dev/null
+++ b/ext/socket/getnameinfo.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Issues to be discussed:
+ * - Thread safe-ness must be checked
+ * - Return values. There seems to be no standard for return value (RFC2133)
+ * but INRIA implementation returns EAI_xxx defined for getaddrinfo().
+ */
+
+#include "config.h"
+#include <sys/types.h>
+#ifndef NT
+#if defined(__BEOS__)
+# include <net/socket.h>
+#else
+# include <sys/socket.h>
+#endif
+#include <netinet/in.h>
+#if defined(HAVE_ARPA_INET_H)
+#include <arpa/inet.h>
+#endif
+#if defined(HAVE_ARPA_NAMESER_H)
+#include <arpa/nameser.h>
+#endif
+#include <netdb.h>
+#if defined(HAVE_RESOLV_H)
+#include <resolv.h>
+#endif
+#endif
+#ifdef NT
+#include <winsock2.h>
+#include <stdio.h>
+#define snprintf _snprintf
+#endif
+
+#include <string.h>
+#include <stddef.h>
+
+#ifdef SOCKS5
+#include <socks.h>
+#endif
+
+#include "addrinfo.h"
+#include "sockport.h"
+
+#define SUCCESS 0
+#define ANY 0
+#define YES 1
+#define NO 0
+
+struct sockinet {
+ u_char si_len;
+ u_char si_family;
+ u_short si_port;
+};
+
+static struct afd {
+ int a_af;
+ int a_addrlen;
+ int a_socklen;
+ int a_off;
+} afdl [] = {
+#ifdef INET6
+#define N_INET6 0
+ {PF_INET6, sizeof(struct in6_addr),
+ sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr)},
+#define N_INET 1
+#else
+#define N_INET 0
+#endif
+ {PF_INET, sizeof(struct in_addr),
+ sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr)},
+ {0, 0, 0, 0},
+};
+
+#define ENI_NOSOCKET 0
+#define ENI_NOSERVNAME 1
+#define ENI_NOHOSTNAME 2
+#define ENI_MEMORY 3
+#define ENI_SYSTEM 4
+#define ENI_FAMILY 5
+#define ENI_SALEN 6
+
+#ifndef HAVE_INET_NTOP
+static const char *
+inet_ntop(af, addr, numaddr, numaddr_len)
+ int af;
+ const void *addr;
+ char *numaddr;
+ size_t numaddr_len;
+{
+#ifdef HAVE_INET_NTOA
+ struct in_addr in;
+ memcpy(&in.s_addr, addr, sizeof(in.s_addr));
+ snprintf(numaddr, numaddr_len, "%s", inet_ntoa(in));
+#else
+ unsigned long x = ntohl(*(unsigned long*)addr);
+ snprintf(numaddr, numaddr_len, "%d.%d.%d.%d",
+ (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
+ (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
+#endif
+ return numaddr;
+}
+#endif
+
+int
+getnameinfo(sa, salen, host, hostlen, serv, servlen, flags)
+ const struct sockaddr *sa;
+ size_t salen;
+ char *host;
+ size_t hostlen;
+ char *serv;
+ size_t servlen;
+ int flags;
+{
+ struct afd *afd;
+ struct servent *sp;
+ struct hostent *hp;
+ u_short port;
+ int family, len, i;
+ char *addr, *p;
+ u_long v4a;
+#ifdef INET6
+ u_char pfx;
+#endif
+ int h_error;
+ char numserv[512];
+ char numaddr[512];
+
+ if (sa == NULL)
+ return ENI_NOSOCKET;
+
+ len = SA_LEN(sa);
+ if (len != salen) return ENI_SALEN;
+
+ family = sa->sa_family;
+ for (i = 0; afdl[i].a_af; i++)
+ if (afdl[i].a_af == family) {
+ afd = &afdl[i];
+ goto found;
+ }
+ return ENI_FAMILY;
+
+ found:
+ if (len != afd->a_socklen) return ENI_SALEN;
+
+ port = ((struct sockinet *)sa)->si_port; /* network byte order */
+ addr = (char *)sa + afd->a_off;
+
+ if (serv == NULL || servlen == 0) {
+ /* what we should do? */
+ } else if (flags & NI_NUMERICSERV) {
+ snprintf(numserv, sizeof(numserv), "%d", ntohs(port));
+ if (strlen(numserv) > servlen)
+ return ENI_MEMORY;
+ strcpy(serv, numserv);
+ } else {
+#if defined(HAVE_GETSERVBYPORT)
+ sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : "tcp");
+ if (sp) {
+ if (strlen(sp->s_name) > servlen)
+ return ENI_MEMORY;
+ strcpy(serv, sp->s_name);
+ } else
+ return ENI_NOSERVNAME;
+#else
+ return ENI_NOSERVNAME;
+#endif
+ }
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ v4a = ((struct sockaddr_in *)sa)->sin_addr.s_addr;
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ flags |= NI_NUMERICHOST;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0 || v4a == IN_LOOPBACKNET)
+ flags |= NI_NUMERICHOST;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ pfx = ((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr8[0];
+ if (pfx == 0 || pfx == 0xfe || pfx == 0xff)
+ flags |= NI_NUMERICHOST;
+ break;
+#endif
+ }
+ if (host == NULL || hostlen == 0) {
+ /* what should we do? */
+ } else if (flags & NI_NUMERICHOST) {
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return ENI_SYSTEM;
+ if (strlen(numaddr) > hostlen)
+ return ENI_MEMORY;
+ strcpy(host, numaddr);
+ } else {
+#ifdef INET6
+ hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+#else
+ hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+ h_error = h_errno;
+#endif
+
+ if (hp) {
+ if (flags & NI_NOFQDN) {
+ p = strchr(hp->h_name, '.');
+ if (p) *p = '\0';
+ }
+ if (strlen(hp->h_name) > hostlen) {
+#ifdef INET6
+ freehostent(hp);
+#endif
+ return ENI_MEMORY;
+ }
+ strcpy(host, hp->h_name);
+#ifdef INET6
+ freehostent(hp);
+#endif
+ } else {
+ if (flags & NI_NAMEREQD)
+ return ENI_NOHOSTNAME;
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return ENI_NOHOSTNAME;
+ if (strlen(numaddr) > hostlen)
+ return ENI_MEMORY;
+ strcpy(host, numaddr);
+ }
+ }
+ return SUCCESS;
+}
diff --git a/ext/socket/socket.c b/ext/socket/socket.c
index d35e029f34..e77e3d609f 100644
--- a/ext/socket/socket.c
+++ b/ext/socket/socket.c
@@ -6,15 +6,33 @@
$Date$
created at: Thu Mar 31 12:21:29 JST 1994
+ Copyright (C) 1993-2000 Yukihiro Matsumoto
+
************************************************/
#include "ruby.h"
-#include "io.h"
+#include "rubyio.h"
+#include "rubysig.h"
#include <stdio.h>
#include <sys/types.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
#ifndef NT
-#include <sys/socket.h>
+#if defined(__BEOS__)
+# include <net/socket.h>
+#else
+# include <sys/socket.h>
+#endif
#include <netinet/in.h>
+#ifdef HAVE_NETINET_TCP_H
+# include <netinet/tcp.h>
+#endif
+#ifdef HAVE_NETINET_UDP_H
+# include <netinet/udp.h>
+#endif
#include <netdb.h>
#endif
#include <errno.h>
@@ -22,7 +40,7 @@
#include <sys/un.h>
#endif
-#if defined(THREAD) && defined(HAVE_FCNTL)
+#if defined(HAVE_FCNTL)
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
@@ -33,45 +51,120 @@
#ifndef EWOULDBLOCK
#define EWOULDBLOCK EAGAIN
#endif
+#ifndef HAVE_GETADDRINFO
+# include "addrinfo.h"
+#endif
+#include "sockport.h"
-extern VALUE cIO;
-extern VALUE cInteger;
+static int do_not_reverse_lookup = 0;
-VALUE cBasicSocket;
-VALUE cIPsocket;
-VALUE cTCPsocket;
-VALUE cTCPserver;
-VALUE cUDPsocket;
+VALUE rb_cBasicSocket;
+VALUE rb_cIPSocket;
+VALUE rb_cTCPSocket;
+VALUE rb_cTCPServer;
+VALUE rb_cUDPSocket;
#ifdef AF_UNIX
-VALUE cUNIXsocket;
-VALUE cUNIXserver;
+VALUE rb_cUNIXSocket;
+VALUE rb_cUNIXServer;
#endif
-VALUE cSocket;
+VALUE rb_cSocket;
-extern VALUE eException;
-static VALUE eSocket;
+static VALUE rb_eSocket;
#ifdef SOCKS
-VALUE cSOCKSsocket;
+VALUE rb_cSOCKSSocket;
+#ifdef SOCKS5
+#include <socks.h>
+#else
void SOCKSinit();
int Rconnect();
#endif
-
-FILE *rb_fdopen();
-char *strdup();
+#endif
#define INET_CLIENT 0
#define INET_SERVER 1
#define INET_SOCKS 2
+#ifndef HAVE_SOCKADDR_STORAGE
+/*
+ * RFC 2553: protocol-independent placeholder for socket addresses
+ */
+#define _SS_MAXSIZE 128
+#define _SS_ALIGNSIZE (sizeof(double))
+#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(unsigned char) * 2)
+#define _SS_PAD2SIZE (_SS_MAXSIZE - sizeof(unsigned char) * 2 - \
+ _SS_PAD1SIZE - _SS_ALIGNSIZE)
+
+struct sockaddr_storage {
+#ifdef HAVE_SA_LEN
+ unsigned char ss_len; /* address length */
+ unsigned char ss_family; /* address family */
+#else
+ unsigned short ss_family;
+#endif
+ char __ss_pad1[_SS_PAD1SIZE];
+ double __ss_align; /* force desired structure storage alignment */
+ char __ss_pad2[_SS_PAD2SIZE];
+};
+#endif
+
+#if defined(INET6) && (defined(LOOKUP_ORDER_HACK_INET) || defined(LOOKUP_ORDER_HACK_INET6))
+#define LOOKUP_ORDERS 3
+static int lookup_order_table[LOOKUP_ORDERS] = {
+#if defined(LOOKUP_ORDER_HACK_INET)
+ PF_INET, PF_INET6, PF_UNSPEC,
+#elif defined(LOOKUP_ORDER_HACK_INET6)
+ PF_INET6, PF_INET, PF_UNSPEC,
+#else
+ /* should not happen */
+#endif
+};
+
+static int
+rb_getaddrinfo(nodename, servname, hints, res)
+ char *nodename;
+ char *servname;
+ struct addrinfo *hints;
+ struct addrinfo **res;
+{
+ struct addrinfo tmp_hints;
+ int i, af, error;
+
+ if (hints->ai_family != PF_UNSPEC) {
+ return getaddrinfo(nodename, servname, hints, res);
+ }
+
+ for (i = 0; i < LOOKUP_ORDERS; i++) {
+ af = lookup_order_table[i];
+ MEMCPY(&tmp_hints, hints, struct addrinfo, 1);
+ tmp_hints.ai_family = af;
+ error = getaddrinfo(nodename, servname, &tmp_hints, res);
+ if (error) {
+ if (tmp_hints.ai_family == PF_UNSPEC) {
+ break;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ return error;
+}
+#define getaddrinfo(node,serv,hints,res) rb_getaddrinfo((node),(serv),(hints),(res))
+#endif
+
#ifdef NT
static void
sock_finalize(fptr)
OpenFile *fptr;
{
- SOCKET s = fileno(fptr->f);
- free(fptr->f);
- free(fptr->f2);
+ SOCKET s;
+
+ if (!fptr->f) return;
+ s = get_osfhandle(fileno(fptr->f));
+ myfdclose(fptr->f);
+ if (fptr->f2) myfdclose(fptr->f2);
closesocket(s);
}
#endif
@@ -85,16 +178,17 @@ sock_new(class, fd)
NEWOBJ(sock, struct RFile);
OBJSETUP(sock, class, T_FILE);
- rb_secure(4);
MakeOpenFile(sock, fp);
fp->f = rb_fdopen(fd, "r");
#ifdef NT
fp->finalize = sock_finalize;
+ fd = myfddup(fd);
+#else
+ fd = dup(fd);
#endif
fp->f2 = rb_fdopen(fd, "w");
fp->mode = FMODE_READWRITE;
- io_unbuffered(fp);
- obj_call_init((VALUE)sock);
+ rb_io_synchronized(fp);
return (VALUE)sock;
}
@@ -109,15 +203,17 @@ bsock_shutdown(argc, argv, sock)
int how;
OpenFile *fptr;
- rb_secure(4);
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't shutdown socket");
+ }
rb_scan_args(argc, argv, "01", &howto);
if (howto == Qnil)
how = 2;
else {
how = NUM2INT(howto);
-#if 0
- if (how < 0 || 2 < how) how = 2;
-#endif
+ if (how < 0 || 2 < how) {
+ rb_raise(rb_eArgError, "`how' should be either 0, 1, 2");
+ }
}
GetOpenFile(sock, fptr);
if (shutdown(fileno(fptr->f), how) == -1)
@@ -127,9 +223,60 @@ bsock_shutdown(argc, argv, sock)
}
static VALUE
+bsock_close_read(sock)
+ VALUE sock;
+{
+ OpenFile *fptr;
+
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't close socket");
+ }
+ GetOpenFile(sock, fptr);
+ shutdown(fileno(fptr->f), 0);
+ if (fptr->f2 == 0) {
+ return rb_io_close(sock);
+ }
+ rb_thread_fd_close(fileno(fptr->f));
+ fptr->mode &= ~FMODE_READABLE;
+#ifdef NT
+ myfdclose(fptr->f);
+#else
+ fclose(fptr->f);
+#endif
+ fptr->f = fptr->f2;
+ fptr->f2 = 0;
+
+ return Qnil;
+}
+
+static VALUE
+bsock_close_write(sock)
+ VALUE sock;
+{
+ OpenFile *fptr;
+
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't close socket");
+ }
+ GetOpenFile(sock, fptr);
+ if (fptr->f2 == 0) {
+ return rb_io_close(sock);
+ }
+ shutdown(fileno(fptr->f2), 1);
+ fptr->mode &= ~FMODE_WRITABLE;
+#ifdef NT
+ myfdclose(fptr->f2);
+#else
+ fclose(fptr->f2);
+#endif
+ fptr->f2 = 0;
+
+ return Qnil;
+}
+
+static VALUE
bsock_setsockopt(sock, lev, optname, val)
- VALUE sock, lev, optname;
- struct RString *val;
+ VALUE sock, lev, optname, val;
{
int level, option;
OpenFile *fptr;
@@ -153,8 +300,7 @@ bsock_setsockopt(sock, lev, optname, val)
v = (char*)&i; vlen = sizeof(i);
break;
default:
- Check_Type(val, T_STRING);
- v = val->ptr; vlen = val->len;
+ v = rb_str2cstr(val, &vlen);
}
GetOpenFile(sock, fptr);
@@ -168,7 +314,9 @@ static VALUE
bsock_getsockopt(sock, lev, optname)
VALUE sock, lev, optname;
{
- int level, option, len;
+#if !defined(__BEOS__)
+ int level, option;
+ socklen_t len;
char *buf;
OpenFile *fptr;
@@ -181,7 +329,10 @@ bsock_getsockopt(sock, lev, optname)
if (getsockopt(fileno(fptr->f), level, option, buf, &len) < 0)
rb_sys_fail(fptr->path);
- return str_new(buf, len);
+ return rb_tainted_str_new(buf, len);
+#else
+ rb_notimplement();
+#endif
}
static VALUE
@@ -189,13 +340,13 @@ bsock_getsockname(sock)
VALUE sock;
{
char buf[1024];
- int len = sizeof buf;
+ socklen_t len = sizeof buf;
OpenFile *fptr;
GetOpenFile(sock, fptr);
if (getsockname(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
rb_sys_fail("getsockname(2)");
- return str_new(buf, len);
+ return rb_tainted_str_new(buf, len);
}
static VALUE
@@ -203,13 +354,13 @@ bsock_getpeername(sock)
VALUE sock;
{
char buf[1024];
- int len = sizeof buf;
+ socklen_t len = sizeof buf;
OpenFile *fptr;
GetOpenFile(sock, fptr);
if (getpeername(fileno(fptr->f), (struct sockaddr*)buf, &len) < 0)
rb_sys_fail("getpeername(2)");
- return str_new(buf, len);
+ return rb_tainted_str_new(buf, len);
}
static VALUE
@@ -218,42 +369,41 @@ bsock_send(argc, argv, sock)
VALUE *argv;
VALUE sock;
{
- struct RString *msg, *to;
+ VALUE msg, to;
VALUE flags;
OpenFile *fptr;
FILE *f;
int fd, n;
+ char *m, *t;
+ int mlen, tlen;
rb_secure(4);
rb_scan_args(argc, argv, "21", &msg, &flags, &to);
- Check_Type(msg, T_STRING);
-
GetOpenFile(sock, fptr);
- f = fptr->f2?fptr->f2:fptr->f;
+ f = GetWriteFile(fptr);
fd = fileno(f);
retry:
-#ifdef THREAD
- thread_fd_writable(fd);
-#endif
- if (RTEST(to)) {
- Check_Type(to, T_STRING);
- n = sendto(fd, msg->ptr, msg->len, NUM2INT(flags),
- (struct sockaddr*)to->ptr, to->len);
+ rb_thread_fd_writable(fd);
+ m = rb_str2cstr(msg, &mlen);
+ if (!NIL_P(to)) {
+ t = rb_str2cstr(to, &tlen);
+ n = sendto(fd, m, mlen, NUM2INT(flags),
+ (struct sockaddr*)t, tlen);
}
else {
- n = send(fd, msg->ptr, msg->len, NUM2INT(flags));
+ n = send(fd, m, mlen, NUM2INT(flags));
}
if (n < 0) {
switch (errno) {
case EINTR:
+ rb_thread_schedule();
+ goto retry;
case EWOULDBLOCK:
#if EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
-#ifdef THREAD
- thread_schedule();
-#endif
+ rb_thread_fd_writable(fd);
goto retry;
}
rb_sys_fail("send(2)");
@@ -261,48 +411,48 @@ bsock_send(argc, argv, sock)
return INT2FIX(n);
}
-static VALUE ipaddr _((struct sockaddr_in*));
+static VALUE ipaddr _((struct sockaddr *));
#ifdef HAVE_SYS_UN_H
-static VALUE unixaddr _((struct sockaddr_un*));
+static VALUE unixaddr _((struct sockaddr_un *));
#endif
enum sock_recv_type {
RECV_RECV, /* BasicSocket#recv(no from) */
- RECV_TCP, /* TCPsocket#recvfrom */
- RECV_UDP, /* UDPsocket#recvfrom */
- RECV_UNIX, /* UNIXsocket#recvfrom */
+ RECV_IP, /* IPSocket#recvfrom */
+ RECV_UNIX, /* UNIXSocket#recvfrom */
RECV_SOCKET, /* Socket#recvfrom */
};
static VALUE
-s_recv(sock, argc, argv, from)
+s_recvfrom(sock, argc, argv, from)
VALUE sock;
int argc;
VALUE *argv;
enum sock_recv_type from;
{
OpenFile *fptr;
- FILE f;
VALUE str;
char buf[1024];
- int fd, alen = sizeof buf;
+ socklen_t alen = sizeof buf;
VALUE len, flg;
- int flags;
+ int fd, flags;
rb_scan_args(argc, argv, "11", &len, &flg);
if (flg == Qnil) flags = 0;
else flags = NUM2INT(flg);
- str = str_new(0, NUM2INT(len));
-
GetOpenFile(sock, fptr);
+ if (rb_read_pending(fptr->f)) {
+ rb_raise(rb_eIOError, "recv for buffered IO");
+ }
fd = fileno(fptr->f);
-#ifdef THREAD
- thread_wait_fd(fd);
-#endif
- TRAP_BEG;
+
+ str = rb_tainted_str_new(0, NUM2INT(len));
+
+ rb_thread_wait_fd(fd);
retry:
+ TRAP_BEG;
RSTRING(str)->len = recvfrom(fd, RSTRING(str)->ptr, RSTRING(str)->len, flags,
(struct sockaddr*)buf, &alen);
TRAP_END;
@@ -310,42 +460,35 @@ s_recv(sock, argc, argv, from)
if (RSTRING(str)->len < 0) {
switch (errno) {
case EINTR:
+ rb_thread_schedule();
+ goto retry;
+
case EWOULDBLOCK:
#if EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
-#ifdef THREAD
- thread_schedule();
-#endif
+ rb_thread_wait_fd(fd);
goto retry;
}
rb_sys_fail("recvfrom(2)");
}
- str_taint(str);
+ rb_obj_taint(str);
switch (from) {
case RECV_RECV:
return (VALUE)str;
- case RECV_TCP:
+ case RECV_IP:
+#if 0
if (alen != sizeof(struct sockaddr_in)) {
- TypeError("sockaddr size differs - should not happen");
- }
- return assoc_new(str, ipaddr((struct sockaddr_in *)buf));
- case RECV_UDP:
- {
- VALUE addr = ipaddr((struct sockaddr_in *)buf);
-
- return assoc_new(str, assoc_new(RARRAY(addr)->ptr[2],
- RARRAY(addr)->ptr[1]));
+ rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
}
+#endif
+ return rb_assoc_new(str, ipaddr((struct sockaddr *)buf));
#ifdef HAVE_SYS_UN_H
case RECV_UNIX:
- if (alen != sizeof(struct sockaddr_un)) {
- TypeError("sockaddr size differs - should not happen");
- }
- return assoc_new(str, unixaddr((struct sockaddr_un *)buf));
+ return rb_assoc_new(str, unixaddr((struct sockaddr_un *)buf));
#endif
case RECV_SOCKET:
- return assoc_new(str, str_new(buf, alen));
+ return rb_assoc_new(str, rb_tainted_str_new(buf, alen));
}
}
@@ -355,21 +498,232 @@ bsock_recv(argc, argv, sock)
VALUE *argv;
VALUE sock;
{
- return s_recv(sock, argc, argv, RECV_RECV);
+ return s_recvfrom(sock, argc, argv, RECV_RECV);
+}
+
+static VALUE
+bsock_do_not_rev_lookup()
+{
+ return do_not_reverse_lookup?Qtrue:Qfalse;
+}
+
+static VALUE
+bsock_do_not_rev_lookup_set(self, val)
+{
+ do_not_reverse_lookup = RTEST(val);
+ return val;
+}
+
+static void
+mkipaddr0(addr, buf, len)
+ struct sockaddr *addr;
+ char *buf;
+ size_t len;
+{
+ int error;
+
+ error = getnameinfo(addr, SA_LEN(addr), buf, len, NULL, 0, NI_NUMERICHOST);
+ if (error) {
+ rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
+ }
+}
+
+static VALUE
+mkipaddr(addr)
+ struct sockaddr *addr;
+{
+ char buf[1024];
+
+ mkipaddr0(addr, buf, sizeof(buf));
+ return rb_tainted_str_new2(buf);
+}
+
+static void
+mkinetaddr(host, buf, len)
+ long host;
+ char *buf;
+ size_t len;
+{
+ struct sockaddr_in sin;
+
+ MEMZERO(&sin, struct sockaddr_in, 1);
+ sin.sin_family = AF_INET;
+ SET_SIN_LEN(&sin, sizeof(sin));
+ sin.sin_addr.s_addr = host;
+ mkipaddr0((struct sockaddr *)&sin, buf, len);
+}
+
+static struct addrinfo*
+ip_addrsetup(host, port)
+ VALUE host, port;
+{
+ struct addrinfo hints, *res;
+ char *hostp, *portp;
+ int error;
+ char hbuf[1024], pbuf[16];
+
+ if (NIL_P(host)) {
+ hostp = NULL;
+ }
+ else if (rb_obj_is_kind_of(host, rb_cInteger)) {
+ long i = NUM2LONG(host);
+
+ mkinetaddr(htonl(i), hbuf, sizeof(hbuf));
+ hostp = hbuf;
+ }
+ else {
+ char *name;
+
+ Check_SafeStr(host);
+ name = RSTRING(host)->ptr;
+ if (*name == 0) {
+ mkinetaddr(INADDR_ANY, hbuf, sizeof(hbuf));
+ }
+ else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
+ mkinetaddr(INADDR_BROADCAST, hbuf, sizeof(hbuf));
+ }
+ else if (strlen(name) >= sizeof(hbuf)) {
+ rb_raise(rb_eArgError, "hostname too long (%d)", strlen(name));
+ }
+ else {
+ strcpy(hbuf, name);
+ }
+ hostp = hbuf;
+ }
+ if (NIL_P(port)) {
+ portp = 0;
+ }
+ else if (FIXNUM_P(port)) {
+ snprintf(pbuf, sizeof(pbuf), "%ld", FIX2INT(port));
+ portp = pbuf;
+ }
+ else {
+ Check_SafeStr(port);
+ portp = STR2CSTR(port);
+ }
+
+ MEMZERO(&hints, struct addrinfo, 1);
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ error = getaddrinfo(hostp, portp, &hints, &res);
+ if (error) {
+ if (hostp && hostp[strlen(hostp)-1] == '\n') {
+ rb_raise(rb_eSocket, "newline at the end of hostname");
+ }
+ rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
+ }
+
+ return res;
+}
+
+static void
+setipaddr(name, addr)
+ VALUE name;
+ struct sockaddr *addr;
+{
+ struct addrinfo *res = ip_addrsetup(name, Qnil);
+
+ /* just take the first one */
+ memcpy(addr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+}
+
+static VALUE
+ipaddr(sockaddr)
+ struct sockaddr *sockaddr;
+{
+ VALUE family, port, addr1, addr2;
+ VALUE ary;
+ int error;
+ char hbuf[1024], pbuf[1024];
+
+ switch (sockaddr->sa_family) {
+ case AF_UNSPEC:
+ family = rb_str_new2("AF_UNSPEC");
+ break;
+ case AF_INET:
+ family = rb_str_new2("AF_INET");
+ break;
+#ifdef INET6
+ case AF_INET6:
+ family = rb_str_new2("AF_INET6");
+ break;
+#endif
+#ifdef AF_LOCAL
+ case AF_LOCAL:
+ family = rb_str_new2("AF_LOCAL");
+ break;
+#elif AF_UNIX
+ case AF_UNIX:
+ family = rb_str_new2("AF_UNIX");
+ break;
+#endif
+ default:
+ sprintf(pbuf, "unknown:%d", sockaddr->sa_family);
+ family = rb_str_new2(pbuf);
+ break;
+ }
+ if (!do_not_reverse_lookup) {
+ error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
+ NULL, 0, 0);
+ if (error) {
+ rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
+ }
+ addr1 = rb_tainted_str_new2(hbuf);
+ }
+ error = getnameinfo(sockaddr, SA_LEN(sockaddr), hbuf, sizeof(hbuf),
+ pbuf, sizeof(pbuf), NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error) {
+ rb_raise(rb_eSocket, "getnameinfo %s", gai_strerror(error));
+ }
+ addr2 = rb_tainted_str_new2(hbuf);
+ if (do_not_reverse_lookup) {
+ addr1 = addr2;
+ }
+ port = INT2FIX(atoi(pbuf));
+ ary = rb_ary_new3(4, family, port, addr1, addr2);
+
+ return ary;
}
-#if defined(THREAD) && defined(HAVE_FCNTL)
static int
-thread_connect(fd, sockaddr, len, type)
+ruby_socket(domain, type, proto)
+ int domain, type, proto;
+{
+ int fd;
+
+ fd = socket(domain, type, proto);
+ if (fd < 0) {
+ if (errno == EMFILE || errno == ENFILE) {
+ rb_gc();
+ fd = socket(domain, type, proto);
+ }
+ }
+ return fd;
+}
+
+static void
+thread_write_select(fd)
+ int fd;
+{
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+ rb_thread_select(fd+1, 0, &fds, 0, 0);
+}
+
+static int
+ruby_connect(fd, sockaddr, len, socks)
int fd;
struct sockaddr *sockaddr;
int len;
- int type;
+ int socks;
{
int status;
int mode;
- fd_set fds;
+#if defined(HAVE_FCNTL)
mode = fcntl(fd, F_GETFL, 0);
#ifdef O_NDELAY
@@ -381,10 +735,15 @@ thread_connect(fd, sockaddr, len, type)
# define NONBLOCKING O_NONBLOCK
#endif
#endif
+#ifdef SOCKS5
+ if (!socks)
+#endif
fcntl(fd, F_SETFL, mode|NONBLOCKING);
+#endif /* HAVE_FCNTL */
+
for (;;) {
-#ifdef SOCKS
- if (type == INET_SOCKS) {
+#if defined(SOCKS) && !defined(SOCKS5)
+ if (socks) {
status = Rconnect(fd, sockaddr, len);
}
else
@@ -394,146 +753,117 @@ thread_connect(fd, sockaddr, len, type)
}
if (status < 0) {
switch (errno) {
+ case EAGAIN:
#ifdef EINPROGRESS
case EINPROGRESS:
-#ifdef EAGAIN
- case EAGAIN:
#endif
- FD_ZERO(&fds);
- FD_SET(fd, &fds);
- thread_select(fd+1, 0, &fds, 0, 0, 0);
+ thread_write_select(fd);
continue;
-#endif
#ifdef EISCONN
case EISCONN:
-#endif
-#ifdef EALREADY
- case EALREADY:
-#endif
-#if defined(EISCONN) || defined(EALREADY)
status = 0;
errno = 0;
break;
#endif
}
}
- mode &= ~NONBLOCKING;
+#ifdef HAVE_FCNTL
fcntl(fd, F_SETFL, mode);
+#endif
return status;
}
}
-#endif
static VALUE
open_inet(class, h, serv, type)
VALUE class, h, serv;
int type;
{
- char *host;
- struct hostent *hostent, _hostent;
- struct servent *servent, _servent;
- struct protoent *protoent;
- struct sockaddr_in sockaddr;
+ struct addrinfo hints, *res, *res0;
int fd, status;
- int hostaddr, hostaddrPtr[2];
- int servport;
char *syscall;
- VALUE sock;
+ char pbuf[1024], *portp;
+ char *host;
+ int error;
if (h) {
Check_SafeStr(h);
host = RSTRING(h)->ptr;
- hostent = gethostbyname(host);
- if (hostent == NULL) {
- hostaddr = inet_addr(host);
- if (hostaddr == -1) {
- if (type == INET_SERVER && !strlen(host))
- hostaddr = INADDR_ANY;
- else {
-#ifdef HAVE_HSTRERROR
- extern int h_errno;
- Raise(eSocket, (char *)hstrerror(h_errno));
-#else
- Raise(eSocket, "host not found");
-#endif
- }
- }
- _hostent.h_addr_list = (char **)hostaddrPtr;
- _hostent.h_addr_list[0] = (char *)&hostaddr;
- _hostent.h_addr_list[1] = NULL;
- _hostent.h_length = sizeof(hostaddr);
- _hostent.h_addrtype = AF_INET;
- hostent = &_hostent;
- }
- }
- servent = NULL;
- if (FIXNUM_P(serv)) {
- servport = FIX2UINT(serv);
- goto setup_servent;
- }
- Check_Type(serv, T_STRING);
- servent = getservbyname(RSTRING(serv)->ptr, "tcp");
- if (servent == NULL) {
- servport = strtoul(RSTRING(serv)->ptr, 0, 0);
- if (servport == -1) {
- Raise(eSocket, "no such servce %s", RSTRING(serv)->ptr);
- }
- setup_servent:
- _servent.s_port = htons(servport);
- _servent.s_proto = "tcp";
- servent = &_servent;
}
- protoent = getprotobyname(servent->s_proto);
- if (protoent == NULL) {
- Raise(eSocket, "no such proto %s", servent->s_proto);
+ else {
+ host = NULL;
}
-
- fd = socket(AF_INET, SOCK_STREAM, protoent->p_proto);
-
- memset(&sockaddr, 0, sizeof(sockaddr));
- sockaddr.sin_family = AF_INET;
- if (h) {
- memcpy((char *)&(sockaddr.sin_addr.s_addr),
- (char *) hostent->h_addr_list[0],
- (size_t) hostent->h_length);
+ if (FIXNUM_P(serv)) {
+ snprintf(pbuf, sizeof(pbuf), "%ld", FIX2UINT(serv));
+ portp = pbuf;
}
else {
- sockaddr.sin_addr.s_addr = INADDR_ANY;
+ Check_SafeStr(serv);
+ if (RSTRING(serv)->len >= sizeof(pbuf))
+ rb_raise(rb_eArgError, "servicename too long (%d)", RSTRING(serv)->len);
+ strcpy(pbuf, RSTRING(serv)->ptr);
+ portp = pbuf;
}
- sockaddr.sin_port = servent->s_port;
-
+ MEMZERO(&hints, struct addrinfo, 1);
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
if (type == INET_SERVER) {
- status = 1;
- setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(char*)&status,sizeof(status));
- status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
- syscall = "bind(2)";
+ hints.ai_flags = AI_PASSIVE;
}
- else {
-#if defined(THREAD) && defined(HAVE_FCNTL)
- status = thread_connect(fd, (struct sockaddr*)&sockaddr,
- sizeof(sockaddr), type);
-#else
-#ifdef SOCKS
- if (type == INET_SOCKS) {
- status = Rconnect(fd, &sockaddr, sizeof(sockaddr));
+ error = getaddrinfo(host, portp, &hints, &res0);
+ if (error) {
+ rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
+ }
+
+ fd = -1;
+ for (res = res0; res; res = res->ai_next) {
+ status = ruby_socket(res->ai_family,res->ai_socktype,res->ai_protocol);
+ syscall = "socket(2)";
+ fd = status;
+ if (fd < 0) {
+ continue;
}
- else
-#endif
- {
- status = connect(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
+ if (type == INET_SERVER) {
+ status = 1;
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
+ (char*)&status, sizeof(status));
+ status = bind(fd, res->ai_addr, res->ai_addrlen);
+ syscall = "bind(2)";
+ }
+ else {
+ status = ruby_connect(fd, res->ai_addr, res->ai_addrlen,
+ (type == INET_SOCKS));
+ syscall = "connect(2)";
}
+
+ if (status < 0) {
+#if defined(HAVE_CLOSESOCKET)
+ closesocket(fd);
+#else
+ close(fd);
#endif
- syscall = "connect(2)";
+ fd = -1;
+ continue;
+ } else
+ break;
}
-
if (status < 0) {
- close (fd);
+ if (fd >= 0)
+#if defined(HAVE_CLOSESOCKET)
+ closesocket(fd);
+#else
+ close(fd);
+#endif
+ freeaddrinfo(res0);
rb_sys_fail(syscall);
}
- if (type == INET_SERVER) listen(fd, 5);
+
+ if (type == INET_SERVER)
+ listen(fd, 5);
/* create new instance */
+ freeaddrinfo(res0);
return sock_new(class, fd);
}
@@ -560,8 +890,138 @@ socks_s_open(class, host, serv)
Check_SafeStr(host);
return open_inet(class, host, serv, INET_SOCKS);
}
+
+#ifdef SOCKS5
+static VALUE
+socks_s_close(sock)
+ VALUE sock;
+{
+ OpenFile *fptr;
+
+ if (rb_safe_level() >= 4 && !OBJ_TAINTED(sock)) {
+ rb_raise(rb_eSecurityError, "Insecure: can't close socket");
+ }
+ GetOpenFile(sock, fptr);
+ shutdown(fileno(fptr->f), 2);
+ shutdown(fileno(fptr->f2), 2);
+ return rb_io_close(sock);
+}
+#endif
#endif
+/*
+ * NOTE: using gethostbyname() against AF_INET6 is a bad idea, as it
+ * does not initialize sin_flowinfo nor sin_scope_id properly.
+ */
+static VALUE
+tcp_s_gethostbyname(obj, host)
+ VALUE obj, host;
+{
+ struct sockaddr_storage addr;
+ struct hostent *h;
+ char **pch;
+ VALUE ary, names;
+
+ rb_secure(3);
+ if (rb_obj_is_kind_of(host, rb_cInteger)) {
+ long i = NUM2LONG(host);
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *)&addr;
+ MEMZERO(sin, struct sockaddr_in, 1);
+ sin->sin_family = AF_INET;
+ SET_SIN_LEN(sin, sizeof(*sin));
+ sin->sin_addr.s_addr = htonl(i);
+ }
+ else {
+ setipaddr(host, &addr);
+ }
+ switch (addr.ss_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *)&addr;
+ h = gethostbyaddr((char *)&sin->sin_addr,
+ sizeof(sin->sin_addr),
+ sin->sin_family);
+ break;
+ }
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6;
+ sin6 = (struct sockaddr_in6 *)&addr;
+ h = gethostbyaddr((char *)&sin6->sin6_addr,
+ sizeof(sin6->sin6_addr),
+ sin6->sin6_family);
+ break;
+ }
+#endif
+ default:
+ h = NULL;
+ }
+
+ if (h == NULL) {
+#ifdef HAVE_HSTERROR
+ extern int h_errno;
+ rb_raise(rb_eSocket, "%s", (char *)hsterror(h_errno));
+#else
+ rb_raise(rb_eSocket, "host not found");
+#endif
+ }
+ ary = rb_ary_new();
+ rb_ary_push(ary, rb_tainted_str_new2(h->h_name));
+ names = rb_ary_new();
+ rb_ary_push(ary, names);
+ for (pch = h->h_aliases; *pch; pch++) {
+ rb_ary_push(names, rb_tainted_str_new2(*pch));
+ }
+ rb_ary_push(ary, INT2NUM(h->h_addrtype));
+#ifdef h_addr
+ for (pch = h->h_addr_list; *pch; pch++) {
+ switch (addr.ss_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in sin;
+ MEMZERO(&sin, struct sockaddr_in, 1);
+ sin.sin_family = AF_INET;
+ SET_SIN_LEN(&sin, sizeof(sin));
+ memcpy((char *) &sin.sin_addr, *pch, h->h_length);
+ h = gethostbyaddr((char *)&sin.sin_addr,
+ sizeof(sin.sin_addr),
+ sin.sin_family);
+ rb_ary_push(ary, mkipaddr((struct sockaddr *)&sin));
+ break;
+ }
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 sin6;
+ MEMZERO(&sin6, struct sockaddr_in6, 1);
+ sin6.sin6_family = AF_INET;
+#ifdef SIN6_LEN
+ sin6.sin6_len = sizeof(sin6);
+#endif
+ memcpy((char *) &sin6.sin6_addr, *pch, h->h_length);
+ h = gethostbyaddr((char *)&sin6.sin6_addr,
+ sizeof(sin6.sin6_addr),
+ sin6.sin6_family);
+ rb_ary_push(ary, mkipaddr((struct sockaddr *)&sin6));
+ break;
+ }
+#endif
+ default:
+ h = NULL;
+ }
+ }
+#else
+ memcpy((char *)&addr.sin_addr, h->h_addr, h->h_length);
+ rb_ary_push(ary, mkipaddr((struct sockaddr *)&addr));
+#endif
+
+ return ary;
+}
+
static VALUE
tcp_svr_s_open(argc, argv, class)
int argc;
@@ -581,27 +1041,34 @@ s_accept(class, fd, sockaddr, len)
VALUE class;
int fd;
struct sockaddr *sockaddr;
- int *len;
+ socklen_t *len;
{
int fd2;
+ int retry = 0;
+ rb_secure(3);
retry:
-#ifdef THREAD
- thread_wait_fd(fd);
-#endif
+ rb_thread_wait_fd(fd);
TRAP_BEG;
fd2 = accept(fd, sockaddr, len);
TRAP_END;
if (fd2 < 0) {
switch (errno) {
+ case EMFILE:
+ case ENFILE:
+ if (retry) break;
+ rb_gc();
+ retry = 1;
+ goto retry;
case EINTR:
+ rb_thread_schedule();
+ goto retry;
+
case EWOULDBLOCK:
#if EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
-#ifdef THREAD
- thread_schedule();
-#endif
+ rb_thread_wait_fd(fd);
goto retry;
}
rb_sys_fail(0);
@@ -614,24 +1081,15 @@ tcp_accept(sock)
VALUE sock;
{
OpenFile *fptr;
- struct sockaddr_in from;
- int fromlen;
+ struct sockaddr_storage from;
+ socklen_t fromlen;
GetOpenFile(sock, fptr);
- fromlen = sizeof(struct sockaddr_in);
- return s_accept(cTCPsocket, fileno(fptr->f),
+ fromlen = sizeof(from);
+ return s_accept(rb_cTCPSocket, fileno(fptr->f),
(struct sockaddr*)&from, &fromlen);
}
-static VALUE
-tcp_recvfrom(argc, argv, sock)
- int argc;
- VALUE *argv;
- VALUE sock;
-{
- return s_recv(sock, argc, argv, RECV_TCP);
-}
-
#ifdef HAVE_SYS_UN_H
static VALUE
open_unix(class, path, server)
@@ -645,10 +1103,12 @@ open_unix(class, path, server)
OpenFile *fptr;
Check_SafeStr(path);
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if (fd < 0) rb_sys_fail("socket(2)");
+ fd = ruby_socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ rb_sys_fail("socket(2)");
+ }
- memset(&sockaddr, 0, sizeof(sockaddr));
+ MEMZERO(&sockaddr, struct sockaddr_un, 1);
sockaddr.sun_family = AF_UNIX;
strncpy(sockaddr.sun_path, path->ptr, sizeof(sockaddr.sun_path)-1);
sockaddr.sun_path[sizeof(sockaddr.sun_path)-1] = '\0';
@@ -657,11 +1117,15 @@ open_unix(class, path, server)
status = bind(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
}
else {
- status = connect(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr));
+ status = ruby_connect(fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr), 0);
}
if (status < 0) {
+#if defined(HAVE_CLOSESOCKET)
+ closesocket(fd);
+#else
close(fd);
+#endif
rb_sys_fail(sockaddr.sun_path);
}
@@ -675,94 +1139,19 @@ open_unix(class, path, server)
}
#endif
-static void
-setipaddr(name, addr)
- char *name;
- struct sockaddr_in *addr;
-{
- int d1, d2, d3, d4;
- char ch;
- struct hostent *hp;
- long x;
-
- if (name[0] == 0) {
- addr->sin_addr.s_addr = INADDR_ANY;
- }
- else if (name[0] == '<' && strcmp(name, "<broadcast>") == 0) {
- addr->sin_addr.s_addr = INADDR_BROADCAST;
- }
- else if (sscanf(name, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 &&
- 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 &&
- 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) {
- addr->sin_addr.s_addr = htonl(
- ((long) d1 << 24) | ((long) d2 << 16) |
- ((long) d3 << 8) | ((long) d4 << 0));
- }
- else {
- hp = gethostbyname(name);
- if (!hp) {
-#ifdef HAVE_HSTRERROR
- extern int h_errno;
- Raise(eSocket, (char *)hstrerror(h_errno));
-#else
- Raise(eSocket, "host not found");
-#endif
- }
- memcpy((char *) &addr->sin_addr, hp->h_addr, hp->h_length);
- }
-}
-
-static VALUE
-mkipaddr(x)
- unsigned long x;
-{
- char buf[16];
-
- x = ntohl(x);
- sprintf(buf, "%d.%d.%d.%d",
- (int) (x>>24) & 0xff, (int) (x>>16) & 0xff,
- (int) (x>> 8) & 0xff, (int) (x>> 0) & 0xff);
- return str_new2(buf);
-}
-
-static VALUE
-ipaddr(sockaddr)
- struct sockaddr_in *sockaddr;
-{
- VALUE family, port, addr1, addr2;
- VALUE ary;
- struct hostent *hostent;
-
- family = str_new2("AF_INET");
- hostent = gethostbyaddr((char*)&sockaddr->sin_addr.s_addr,
- sizeof(sockaddr->sin_addr),
- AF_INET);
- addr1 = 0;
- if (hostent) {
- addr1 = str_new2(hostent->h_name);
- }
- addr2 = mkipaddr(sockaddr->sin_addr.s_addr);
- if (!addr1) addr1 = addr2;
-
- port = INT2FIX(ntohs(sockaddr->sin_port));
- ary = ary_new3(4, family, port, addr1, addr2);
-
- return ary;
-}
-
static VALUE
ip_addr(sock)
VALUE sock;
{
OpenFile *fptr;
- struct sockaddr_in addr;
- int len = sizeof addr;
+ struct sockaddr_storage addr;
+ socklen_t len = sizeof addr;
GetOpenFile(sock, fptr);
if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
rb_sys_fail("getsockname(2)");
- return ipaddr(&addr);
+ return ipaddr((struct sockaddr *)&addr);
}
static VALUE
@@ -770,108 +1159,78 @@ ip_peeraddr(sock)
VALUE sock;
{
OpenFile *fptr;
- struct sockaddr_in addr;
- int len = sizeof addr;
+ struct sockaddr_storage addr;
+ socklen_t len = sizeof addr;
GetOpenFile(sock, fptr);
if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
rb_sys_fail("getpeername(2)");
- return ipaddr(&addr);
+ return ipaddr((struct sockaddr *)&addr);
+}
+
+static VALUE
+ip_recvfrom(argc, argv, sock)
+ int argc;
+ VALUE *argv;
+ VALUE sock;
+{
+ return s_recvfrom(sock, argc, argv, RECV_IP);
}
static VALUE
ip_s_getaddress(obj, host)
VALUE obj, host;
{
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
- if (obj_is_kind_of(host, cInteger)) {
- int i = NUM2INT(host);
- addr.sin_addr.s_addr = htonl(i);
- }
- else {
- Check_Type(host, T_STRING);
- setipaddr(RSTRING(host)->ptr, &addr);
- }
-
- return mkipaddr(addr.sin_addr.s_addr);
+ setipaddr(host, &addr);
+ return mkipaddr((struct sockaddr *)&addr);
}
static VALUE
-udp_s_open(class)
+udp_s_open(argc, argv, class)
+ int argc;
+ VALUE *argv;
VALUE class;
{
- return sock_new(class, socket(AF_INET, SOCK_DGRAM, 0));
-}
-
-static void
-udp_addrsetup(host, port, addr)
- VALUE host, port;
- struct sockaddr_in *addr;
-{
- struct hostent *hostent;
+ VALUE arg;
+ int socktype = AF_INET;
+ int fd;
- memset(addr, 0, sizeof(struct sockaddr_in));
- addr->sin_family = AF_INET;
- if (NIL_P(host)) {
- addr->sin_addr.s_addr = INADDR_ANY;
- }
- else if (obj_is_kind_of(host, cInteger)) {
- int i = NUM2INT(host);
- addr->sin_addr.s_addr = htonl(i);
+ rb_secure(3);
+ if (rb_scan_args(argc, argv, "01", &arg) == 1) {
+ socktype = NUM2INT(arg);
}
- else {
- Check_Type(host, T_STRING);
- setipaddr(RSTRING(host)->ptr, addr);
- }
- if (FIXNUM_P(port)) {
- addr->sin_port = htons(FIX2INT(port));
+ fd = ruby_socket(socktype, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ rb_sys_fail("socket(2) - udp");
}
- else {
- struct servent *servent;
-
- Check_Type(port, T_STRING);
- servent = getservbyname(RSTRING(port)->ptr, "udp");
- if (servent) {
- addr->sin_port = servent->s_port;
- }
- else {
- int port = strtoul(RSTRING(port)->ptr, 0, 0);
- if (port == -1) {
- Raise(eSocket, "no such servce %s", RSTRING(port)->ptr);
- }
- addr->sin_port = htons(port);
- }
- }
+ return sock_new(class, fd);
}
static VALUE
udp_connect(sock, host, port)
VALUE sock, host, port;
{
- struct sockaddr_in addr;
OpenFile *fptr;
+ int fd;
+ struct addrinfo *res0, *res;
- udp_addrsetup(host, port, &addr);
+ rb_secure(3);
GetOpenFile(sock, fptr);
- retry:
- if (connect(fileno(fptr->f), (struct sockaddr*)&addr, sizeof(addr))<0) {
- switch (errno) {
- case EINTR:
- case EWOULDBLOCK:
-#if EAGAIN != EWOULDBLOCK
- case EAGAIN:
-#endif
-#ifdef THREAD
- thread_schedule();
-#endif
- goto retry;
+ fd = fileno(fptr->f);
+ res0 = ip_addrsetup(host, port);
+ for (res = res0; res; res = res->ai_next) {
+ if (ruby_connect(fd, res->ai_addr, res->ai_addrlen, 0) >= 0) {
+ freeaddrinfo(res0);
+ return INT2FIX(0);
}
- rb_sys_fail("connect(2)");
}
+ freeaddrinfo(res0);
+ rb_sys_fail("connect(2)");
return INT2FIX(0);
}
@@ -879,14 +1238,21 @@ static VALUE
udp_bind(sock, host, port)
VALUE sock, host, port;
{
- struct sockaddr_in addr;
OpenFile *fptr;
+ struct addrinfo *res0, *res;
- udp_addrsetup(host, port, &addr);
+ rb_secure(3);
GetOpenFile(sock, fptr);
- if (bind(fileno(fptr->f), (struct sockaddr*)&addr, sizeof(addr))<0) {
- rb_sys_fail("bind(2)");
+ res0 = ip_addrsetup(host, port);
+ for (res = res0; res; res = res->ai_next) {
+ if (bind(fileno(fptr->f), res->ai_addr, res->ai_addrlen) < 0) {
+ continue;
+ }
+ freeaddrinfo(res0);
+ return INT2FIX(0);
}
+ freeaddrinfo(res0);
+ rb_sys_fail("bind(2)");
return INT2FIX(0);
}
@@ -897,49 +1263,49 @@ udp_send(argc, argv, sock)
VALUE sock;
{
VALUE mesg, flags, host, port;
- struct sockaddr_in addr;
OpenFile *fptr;
FILE *f;
int n;
+ char *m;
+ int mlen;
+ struct addrinfo *res0, *res;
- if (argc == 2) {
+ if (argc == 2 || argc == 3) {
return bsock_send(argc, argv, sock);
}
+ rb_secure(4);
rb_scan_args(argc, argv, "4", &mesg, &flags, &host, &port);
- Check_Type(mesg, T_STRING);
- udp_addrsetup(host, port, &addr);
GetOpenFile(sock, fptr);
- f = fptr->f2?fptr->f2:fptr->f;
- retry:
- n = sendto(fileno(f), RSTRING(mesg)->ptr, RSTRING(mesg)->len,
- NUM2INT(flags), (struct sockaddr*)&addr, sizeof(addr));
- if (n < 0) {
+ res0 = ip_addrsetup(host, port);
+ f = GetWriteFile(fptr);
+ m = rb_str2cstr(mesg, &mlen);
+ for (res = res0; res; res = res->ai_next) {
+ retry:
+ n = sendto(fileno(f), m, mlen, NUM2INT(flags), res->ai_addr,
+ res->ai_addrlen);
+ if (n >= 0) {
+ freeaddrinfo(res0);
+ return INT2FIX(n);
+ }
switch (errno) {
case EINTR:
+ rb_thread_schedule();
+ goto retry;
+
case EWOULDBLOCK:
#if EAGAIN != EWOULDBLOCK
case EAGAIN:
#endif
-#ifdef THREAD
- thread_schedule();
-#endif
+ rb_thread_fd_writable(fileno(f));
goto retry;
}
- rb_sys_fail("sendto(2)");
}
+ freeaddrinfo(res0);
+ rb_sys_fail("sendto(2)");
return INT2FIX(n);
}
-static VALUE
-udp_recvfrom(argc, argv, sock)
- int argc;
- VALUE *argv;
- VALUE sock;
-{
- return s_recv(sock, argc, argv, RECV_UDP);
-}
-
#ifdef HAVE_SYS_UN_H
static VALUE
unix_s_sock_open(sock, path)
@@ -957,12 +1323,12 @@ unix_path(sock)
GetOpenFile(sock, fptr);
if (fptr->path == 0) {
struct sockaddr_un addr;
- int len = sizeof(addr);
+ socklen_t len = sizeof(addr);
if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0)
rb_sys_fail(0);
fptr->path = strdup(addr.sun_path);
}
- return str_new2(fptr->path);
+ return rb_tainted_str_new2(fptr->path);
}
static VALUE
@@ -978,7 +1344,7 @@ unix_recvfrom(argc, argv, sock)
VALUE *argv;
VALUE sock;
{
- return s_recv(sock, argc, argv, RECV_UNIX);
+ return s_recvfrom(sock, argc, argv, RECV_UNIX);
}
static VALUE
@@ -987,11 +1353,11 @@ unix_accept(sock)
{
OpenFile *fptr;
struct sockaddr_un from;
- int fromlen;
+ socklen_t fromlen;
GetOpenFile(sock, fptr);
fromlen = sizeof(struct sockaddr_un);
- return s_accept(cUNIXsocket, fileno(fptr->f),
+ return s_accept(rb_cUNIXSocket, fileno(fptr->f),
(struct sockaddr*)&from, &fromlen);
}
@@ -999,7 +1365,8 @@ static VALUE
unixaddr(sockaddr)
struct sockaddr_un *sockaddr;
{
- return assoc_new(str_new2("AF_UNIX"),str_new2(sockaddr->sun_path));
+ return rb_assoc_new(rb_str_new2("AF_UNIX"),
+ rb_tainted_str_new2(sockaddr->sun_path));
}
static VALUE
@@ -1008,7 +1375,7 @@ unix_addr(sock)
{
OpenFile *fptr;
struct sockaddr_un addr;
- int len = sizeof addr;
+ socklen_t len = sizeof addr;
GetOpenFile(sock, fptr);
@@ -1023,7 +1390,7 @@ unix_peeraddr(sock)
{
OpenFile *fptr;
struct sockaddr_un addr;
- int len = sizeof addr;
+ socklen_t len = sizeof addr;
GetOpenFile(sock, fptr);
@@ -1041,6 +1408,7 @@ setup_domain_and_type(domain, dv, type, tv)
char *ptr;
if (TYPE(domain) == T_STRING) {
+ Check_SafeStr(domain);
ptr = RSTRING(domain)->ptr;
if (strcmp(ptr, "AF_INET") == 0)
*dv = AF_INET;
@@ -1060,8 +1428,10 @@ setup_domain_and_type(domain, dv, type, tv)
else if (strcmp(ptr, "AF_IMPLINK") == 0)
*dv = AF_IMPLINK;
#endif
+#ifdef PF_INET
else if (strcmp(ptr, "PF_INET") == 0)
*dv = PF_INET;
+#endif
#ifdef PF_UNIX
else if (strcmp(ptr, "PF_UNIX") == 0)
*dv = PF_UNIX;
@@ -1081,12 +1451,13 @@ setup_domain_and_type(domain, dv, type, tv)
*dv = PF_IPX;
#endif
else
- Raise(eSocket, "Unknown socket domain %s", ptr);
+ rb_raise(rb_eSocket, "Unknown socket domain %s", ptr);
}
else {
*dv = NUM2INT(domain);
}
if (TYPE(type) == T_STRING) {
+ Check_SafeStr(type);
ptr = RSTRING(type)->ptr;
if (strcmp(ptr, "SOCK_STREAM") == 0)
*tv = SOCK_STREAM;
@@ -1109,7 +1480,7 @@ setup_domain_and_type(domain, dv, type, tv)
*tv = SOCK_PACKET;
#endif
else
- Raise(eSocket, "Unknown socket type %s", ptr);
+ rb_raise(rb_eSocket, "Unknown socket type %s", ptr);
}
else {
*tv = NUM2INT(type);
@@ -1122,10 +1493,10 @@ sock_s_open(class, domain, type, protocol)
{
int fd;
int d, t;
- VALUE s;
+ rb_secure(3);
setup_domain_and_type(domain, &d, type, &t);
- fd = socket(d, t, NUM2INT(protocol));
+ fd = ruby_socket(d, t, NUM2INT(protocol));
if (fd < 0) rb_sys_fail("socket(2)");
return sock_new(class, fd);
@@ -1142,15 +1513,20 @@ static VALUE
sock_s_socketpair(class, domain, type, protocol)
VALUE class, domain, type, protocol;
{
-#if !defined(NT)
- int fd;
+#if !defined(NT) && !defined(__BEOS__) && !defined(__EMX__)
int d, t, sp[2];
setup_domain_and_type(domain, &d, type, &t);
- if (socketpair(d, t, NUM2INT(protocol), sp) < 0)
+ again:
+ if (socketpair(d, t, NUM2INT(protocol), sp) < 0) {
+ if (errno == EMFILE || errno == ENFILE) {
+ rb_gc();
+ goto again;
+ }
rb_sys_fail("socketpair(2)");
+ }
- return assoc_new(sock_new(class, sp[0]), sock_new(class, sp[1]));
+ return rb_assoc_new(sock_new(class, sp[0]), sock_new(class, sp[1]));
#else
rb_notimplement();
#endif
@@ -1161,24 +1537,14 @@ sock_connect(sock, addr)
VALUE sock, addr;
{
OpenFile *fptr;
+ int fd;
Check_Type(addr, T_STRING);
- str_modify(addr);
+ rb_str_modify(addr);
GetOpenFile(sock, fptr);
- retry:
- if (connect(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0) {
- switch (errno) {
- case EINTR:
- case EWOULDBLOCK:
-#if EAGAIN != EWOULDBLOCK
- case EAGAIN:
-#endif
-#ifdef THREAD
- thread_schedule();
-#endif
- goto retry;
- }
+ fd = fileno(fptr->f);
+ if (ruby_connect(fd, (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len, 0) < 0) {
rb_sys_fail("connect(2)");
}
@@ -1192,7 +1558,7 @@ sock_bind(sock, addr)
OpenFile *fptr;
Check_Type(addr, T_STRING);
- str_modify(addr);
+ rb_str_modify(addr);
GetOpenFile(sock, fptr);
if (bind(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0)
@@ -1207,6 +1573,7 @@ sock_listen(sock, log)
{
OpenFile *fptr;
+ rb_secure(4);
GetOpenFile(sock, fptr);
if (listen(fileno(fptr->f), NUM2INT(log)) < 0)
rb_sys_fail("listen(2)");
@@ -1220,7 +1587,7 @@ sock_recvfrom(argc, argv, sock)
VALUE *argv;
VALUE sock;
{
- return s_recv(sock, argc, argv, RECV_SOCKET);
+ return s_recvfrom(sock, argc, argv, RECV_SOCKET);
}
static VALUE
@@ -1228,14 +1595,14 @@ sock_accept(sock)
VALUE sock;
{
OpenFile *fptr;
- VALUE addr, sock2;
+ VALUE sock2;
char buf[1024];
- int len = sizeof buf;
+ socklen_t len = sizeof buf;
GetOpenFile(sock, fptr);
- sock2 = s_accept(cSocket,fileno(fptr->f),(struct sockaddr*)buf,&len);
+ sock2 = s_accept(rb_cSocket,fileno(fptr->f),(struct sockaddr*)buf,&len);
- return assoc_new(sock2, str_new(buf, len));
+ return rb_assoc_new(sock2, rb_tainted_str_new(buf, len));
}
#ifdef HAVE_GETHOSTNAME
@@ -1245,11 +1612,12 @@ sock_gethostname(obj)
{
char buf[1024];
+ rb_secure(3);
if (gethostname(buf, (int)sizeof buf - 1) < 0)
rb_sys_fail("gethostname");
buf[sizeof buf - 1] = '\0';
- return str_new2(buf);
+ return rb_tainted_str_new2(buf);
}
#else
#ifdef HAVE_UNAME
@@ -1260,10 +1628,11 @@ static VALUE
sock_gethostname(obj)
VALUE obj;
{
- struct utsname un;
+ struct utsname un;
- uname(&un);
- return str_new2(un.nodename);
+ rb_secure(3);
+ uname(&un);
+ return rb_tainted_str_new2(un.nodename);
}
#else
static VALUE
@@ -1279,55 +1648,104 @@ static VALUE
mkhostent(h)
struct hostent *h;
{
- struct sockaddr_in addr;
char **pch;
VALUE ary, names;
if (h == NULL) {
#ifdef HAVE_HSTRERROR
extern int h_errno;
- Raise(eSocket, (char *)hstrerror(h_errno));
+ rb_raise(rb_eSocket, "%s", (char *)hstrerror(h_errno));
#else
- Raise(eSocket, "host not found");
+ rb_raise(rb_eSocket, "host not found");
#endif
}
- ary = ary_new();
- ary_push(ary, str_new2(h->h_name));
- names = ary_new();
- ary_push(ary, names);
+ ary = rb_ary_new();
+ rb_ary_push(ary, rb_tainted_str_new2(h->h_name));
+ names = rb_ary_new();
+ rb_ary_push(ary, names);
for (pch = h->h_aliases; *pch; pch++) {
- ary_push(names, str_new2(*pch));
+ rb_ary_push(names, rb_tainted_str_new2(*pch));
}
- ary_push(ary, INT2FIX(h->h_length));
+ rb_ary_push(ary, INT2NUM(h->h_addrtype));
#ifdef h_addr
for (pch = h->h_addr_list; *pch; pch++) {
- ary_push(ary, str_new(*pch, h->h_length));
+ rb_ary_push(ary, rb_tainted_str_new(*pch, h->h_length));
}
#else
- ary_push(ary, str_new(h->h_addr, h->h_length));
+ rb_ary_push(ary, rb_tainted_str_new(h->h_addr, h->h_length));
#endif
return ary;
}
static VALUE
+mkaddrinfo(res0)
+ struct addrinfo *res0;
+{
+ VALUE base, ary;
+ struct addrinfo *res;
+
+ if (res0 == NULL) {
+ rb_raise(rb_eSocket, "host not found");
+ }
+ base = rb_ary_new();
+ for (res = res0; res; res = res->ai_next) {
+ ary = ipaddr(res->ai_addr);
+ rb_ary_push(ary, INT2FIX(res->ai_family));
+ rb_ary_push(ary, INT2FIX(res->ai_socktype));
+ rb_ary_push(ary, INT2FIX(res->ai_protocol));
+ rb_ary_push(base, ary);
+ }
+ return base;
+}
+
+/*
+ * NOTE: using gethostbyname() against AF_INET6 is a bad idea, as it
+ * does not initialize sin_flowinfo nor sin_scope_id properly.
+ */
+static VALUE
sock_s_gethostbyname(obj, host)
VALUE obj, host;
{
- struct sockaddr_in addr;
+ struct sockaddr_storage addr;
struct hostent *h;
- if (obj_is_kind_of(host, cInteger)) {
- int i = NUM2INT(host);
- addr.sin_addr.s_addr = htonl(i);
+ if (rb_obj_is_kind_of(host, rb_cInteger)) {
+ long i = NUM2LONG(host);
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *)&addr;
+ MEMZERO(sin, struct sockaddr_in, 1);
+ sin->sin_family = AF_INET;
+ SET_SIN_LEN(sin, sizeof(*sin));
+ sin->sin_addr.s_addr = htonl(i);
}
else {
- Check_Type(host, T_STRING);
- setipaddr(RSTRING(host)->ptr, &addr);
+ setipaddr(host, (struct sockaddr *)&addr);
+ }
+ switch (addr.ss_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *sin;
+ sin = (struct sockaddr_in *)&addr;
+ h = gethostbyaddr((char *)&sin->sin_addr,
+ sizeof(sin->sin_addr),
+ sin->sin_family);
+ break;
+ }
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sin6;
+ sin6 = (struct sockaddr_in6 *)&addr;
+ h = gethostbyaddr((char *)&sin6->sin6_addr,
+ sizeof(sin6->sin6_addr),
+ sin6->sin6_family);
+ break;
+ }
+#endif
+ default:
+ h = NULL;
}
- h = gethostbyaddr((char *)&addr.sin_addr,
- sizeof(addr.sin_addr),
- AF_INET);
return mkhostent(h);
}
@@ -1339,20 +1757,20 @@ sock_s_gethostbyaddr(argc, argv)
{
VALUE vaddr, vtype;
int type;
-
- struct sockaddr_in *addr;
+ int alen;
+ char *addr;
struct hostent *h;
- rb_scan_args(argc, argv, "11", &addr, &type);
- Check_Type(addr, T_STRING);
- if (!NIL_P(type)) {
+ rb_scan_args(argc, argv, "11", &vaddr, &vtype);
+ addr = rb_str2cstr(vaddr, &alen);
+ if (!NIL_P(vtype)) {
type = NUM2INT(vtype);
}
else {
type = AF_INET;
}
- h = gethostbyaddr(RSTRING(addr)->ptr, RSTRING(addr)->len, type);
+ h = gethostbyaddr(addr, alen, type);
return mkhostent(h);
}
@@ -1368,113 +1786,346 @@ sock_s_getservbyaname(argc, argv)
int port;
rb_scan_args(argc, argv, "11", &service, &protocol);
- Check_Type(service, T_STRING);
if (NIL_P(protocol)) proto = "tcp";
- else proto = RSTRING(protocol)->ptr;
+ else proto = STR2CSTR(protocol);
+
+ sp = getservbyname(STR2CSTR(service), proto);
+ if (sp) {
+ port = ntohs(sp->s_port);
+ }
+ else {
+ char *s = STR2CSTR(service);
+ char *end;
- sp = getservbyname(RSTRING(service)->ptr, proto);
- if (!sp) {
- Raise(eSocket, "service/proto not found");
+ port = strtoul(s, &end, 0);
+ if (*end != '\0') {
+ rb_raise(rb_eSocket, "no such servce %s/%s", s, proto);
+ }
}
- port = ntohs(sp->s_port);
return INT2FIX(port);
}
+static VALUE
+sock_s_getaddrinfo(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE host, port, family, socktype, protocol, flags, ret;
+ char hbuf[1024], pbuf[1024];
+ char *hptr, *pptr;
+ struct addrinfo hints, *res;
+ int error;
+
+ host = port = family = socktype = protocol = flags = Qnil;
+ rb_scan_args(argc, argv, "24", &host, &port, &family, &socktype, &protocol, &flags);
+ if (NIL_P(host)) {
+ hptr = NULL;
+ }
+ else {
+ strncpy(hbuf, STR2CSTR(host), sizeof(hbuf));
+ hbuf[sizeof(hbuf) - 1] = '\0';
+ hptr = hbuf;
+ }
+ if (NIL_P(port)) {
+ pptr = NULL;
+ }
+ else if (FIXNUM_P(port)) {
+ snprintf(pbuf, sizeof(pbuf), "%ld", FIX2INT(port));
+ pptr = pbuf;
+ }
+ else {
+ strncpy(pbuf, STR2CSTR(port), sizeof(pbuf));
+ pbuf[sizeof(pbuf) - 1] = '\0';
+ pptr = pbuf;
+ }
+
+ MEMZERO(&hints, struct addrinfo, 1);
+ if (NIL_P(family)) {
+ hints.ai_family = PF_UNSPEC;
+ }
+ else if (FIXNUM_P(family)) {
+ hints.ai_family = FIX2INT(family);
+ }
+ else if (strcmp(STR2CSTR(family), "AF_INET") == 0) {
+ hints.ai_family = PF_INET;
+ }
+#ifdef INET6
+ else if (strcmp(STR2CSTR(family), "AF_INET6") == 0) {
+ hints.ai_family = PF_INET6;
+ }
+#endif
+
+ if (!NIL_P(socktype)) {
+ hints.ai_socktype = NUM2INT(socktype);
+ }
+ if (!NIL_P(protocol)) {
+ hints.ai_protocol = NUM2INT(protocol);
+ }
+ if (!NIL_P(flags)) {
+ hints.ai_flags = NUM2INT(flags);
+ }
+ error = getaddrinfo(hptr, pptr, &hints, &res);
+ if (error) {
+ rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
+ }
+
+ ret = mkaddrinfo(res);
+ freeaddrinfo(res);
+ return ret;
+}
+
+static VALUE
+sock_s_getnameinfo(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE sa, af = Qnil, host = Qnil, port = Qnil, flags;
+ char *hptr, *pptr;
+ char hbuf[1024], pbuf[1024];
+ int fl;
+ struct addrinfo hints, *res = NULL, *r;
+ int error;
+ struct sockaddr_storage ss;
+ struct sockaddr *sap;
+ char *ep;
+
+ sa = flags = Qnil;
+ rb_scan_args(argc, argv, "11", &sa, &flags);
+
+ fl = 0;
+ if (!NIL_P(flags)) {
+ fl = NUM2INT(flags);
+ }
+ if (TYPE(sa) == T_STRING) {
+ if (sizeof(ss) < RSTRING(sa)->len) {
+ rb_raise(rb_eTypeError, "sockaddr length too big");
+ }
+ memcpy(&ss, RSTRING(sa)->ptr, RSTRING(sa)->len);
+ if (RSTRING(sa)->len != SA_LEN((struct sockaddr *)&ss)) {
+ rb_raise(rb_eTypeError, "sockaddr size differs - should not happen");
+ }
+ sap = (struct sockaddr *)&ss;
+ }
+ else if (TYPE(sa) == T_ARRAY) {
+ MEMZERO(&hints, struct addrinfo, 1);
+ if (RARRAY(sa)->len == 3) {
+ af = RARRAY(sa)->ptr[0];
+ port = RARRAY(sa)->ptr[1];
+ host = RARRAY(sa)->ptr[2];
+ }
+ else if (RARRAY(sa)->len >= 4) {
+ af = RARRAY(sa)->ptr[0];
+ port = RARRAY(sa)->ptr[1];
+ host = RARRAY(sa)->ptr[3];
+ if (NIL_P(host)) {
+ host = RARRAY(sa)->ptr[2];
+ }
+ else {
+ /*
+ * 4th element holds numeric form, don't resolve.
+ * see ipaddr().
+ */
+ hints.ai_flags |= AI_NUMERICHOST;
+ }
+ }
+ else {
+ rb_raise(rb_eArgError, "array size should be 3 or 4, %d given",
+ RARRAY(sa)->len);
+ }
+ /* host */
+ if (NIL_P(host)) {
+ hptr = NULL;
+ }
+ else {
+ strncpy(hbuf, STR2CSTR(host), sizeof(hbuf));
+ hbuf[sizeof(hbuf) - 1] = '\0';
+ hptr = hbuf;
+ }
+ /* port */
+ if (NIL_P(port)) {
+ strcpy(pbuf, "0");
+ pptr = NULL;
+ }
+ else if (FIXNUM_P(port)) {
+ snprintf(pbuf, sizeof(pbuf), "%ld", NUM2INT(port));
+ pptr = pbuf;
+ }
+ else {
+ strncpy(pbuf, STR2CSTR(port), sizeof(pbuf));
+ pbuf[sizeof(pbuf) - 1] = '\0';
+ pptr = pbuf;
+ }
+ hints.ai_socktype = (fl & NI_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
+ /* af */
+ if (NIL_P(af)) {
+ hints.ai_family = PF_UNSPEC;
+ }
+ else if (FIXNUM_P(af)) {
+ hints.ai_family = FIX2INT(af);
+ }
+ else if (strcmp(STR2CSTR(af), "AF_INET") == 0) {
+ hints.ai_family = PF_INET;
+ }
+#ifdef INET6
+ else if (strcmp(STR2CSTR(af), "AF_INET6") == 0) {
+ hints.ai_family = PF_INET6;
+ }
+#endif
+ error = getaddrinfo(hptr, pptr, &hints, &res);
+ if (error) goto error_exit_addr;
+ sap = res->ai_addr;
+ }
+ else {
+ rb_raise(rb_eTypeError, "expecting String or Array");
+ }
+
+ error = getnameinfo(sap, SA_LEN(sap), hbuf, sizeof(hbuf),
+ pbuf, sizeof(pbuf), fl);
+ if (error) goto error_exit_name;
+ if (res) {
+ for (r = res->ai_next; r; r = r->ai_next) {
+ char hbuf2[1024], pbuf2[1024];
+
+ sap = r->ai_addr;
+ error = getnameinfo(sap, SA_LEN(sap), hbuf2, sizeof(hbuf2),
+ pbuf2, sizeof(pbuf2), fl);
+ if (error) goto error_exit_name;
+ if (strcmp(hbuf, hbuf2) != 0|| strcmp(pbuf, pbuf2) != 0) {
+ freeaddrinfo(res);
+ rb_raise(rb_eSocket, "sockaddr resolved to multiple nodename");
+ }
+ }
+ freeaddrinfo(res);
+ }
+ return rb_assoc_new(rb_tainted_str_new2(hbuf), rb_tainted_str_new2(pbuf));
+
+ error_exit_addr:
+ if (res) freeaddrinfo(res);
+ rb_raise(rb_eSocket, "getaddrinfo: %s", gai_strerror(error));
+
+ error_exit_name:
+ if (res) freeaddrinfo(res);
+ rb_raise(rb_eSocket, "getnameinfo: %s", gai_strerror(error));
+}
+
static VALUE mConst;
static void
sock_define_const(name, value)
char *name;
- INT value;
+ int value;
{
- rb_define_const(cSocket, name, INT2FIX(value));
+ rb_define_const(rb_cSocket, name, INT2FIX(value));
rb_define_const(mConst, name, INT2FIX(value));
}
+void
Init_socket()
{
- eSocket = rb_define_class("SocketError", eException);
-
- cBasicSocket = rb_define_class("BasicSocket", cIO);
- rb_undef_method(CLASS_OF(cBasicSocket), "new");
- rb_undef_method(CLASS_OF(cBasicSocket), "open");
- rb_define_method(cBasicSocket, "shutdown", bsock_shutdown, -1);
- rb_define_method(cBasicSocket, "setsockopt", bsock_setsockopt, 3);
- rb_define_method(cBasicSocket, "getsockopt", bsock_getsockopt, 2);
- rb_define_method(cBasicSocket, "getsockname", bsock_getsockname, 0);
- rb_define_method(cBasicSocket, "getpeername", bsock_getpeername, 0);
- rb_define_method(cBasicSocket, "send", bsock_send, -1);
- rb_define_method(cBasicSocket, "recv", bsock_recv, -1);
-
- cIPsocket = rb_define_class("IPsocket", cBasicSocket);
- rb_define_method(cIPsocket, "addr", ip_addr, 0);
- rb_define_method(cIPsocket, "peeraddr", ip_peeraddr, 0);
- rb_define_singleton_method(cIPsocket, "getaddress", ip_s_getaddress, 1);
-
- cTCPsocket = rb_define_class("TCPsocket", cIPsocket);
- rb_define_singleton_method(cTCPsocket, "open", tcp_s_open, 2);
- rb_define_singleton_method(cTCPsocket, "new", tcp_s_open, 2);
- rb_define_method(cTCPsocket, "recvfrom", tcp_recvfrom, -1);
+ rb_eSocket = rb_define_class("SocketError", rb_eStandardError);
+
+ rb_cBasicSocket = rb_define_class("BasicSocket", rb_cIO);
+ rb_undef_method(CLASS_OF(rb_cBasicSocket), "new");
+ rb_undef_method(CLASS_OF(rb_cBasicSocket), "open");
+
+ rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup",
+ bsock_do_not_rev_lookup, 0);
+ rb_define_singleton_method(rb_cBasicSocket, "do_not_reverse_lookup=",
+ bsock_do_not_rev_lookup_set, 1);
+
+ rb_define_method(rb_cBasicSocket, "close_read", bsock_close_read, 0);
+ rb_define_method(rb_cBasicSocket, "close_write", bsock_close_write, 0);
+ rb_define_method(rb_cBasicSocket, "shutdown", bsock_shutdown, -1);
+ rb_define_method(rb_cBasicSocket, "setsockopt", bsock_setsockopt, 3);
+ rb_define_method(rb_cBasicSocket, "getsockopt", bsock_getsockopt, 2);
+ rb_define_method(rb_cBasicSocket, "getsockname", bsock_getsockname, 0);
+ rb_define_method(rb_cBasicSocket, "getpeername", bsock_getpeername, 0);
+ rb_define_method(rb_cBasicSocket, "send", bsock_send, -1);
+ rb_define_method(rb_cBasicSocket, "recv", bsock_recv, -1);
+
+ rb_cIPSocket = rb_define_class("IPSocket", rb_cBasicSocket);
+ rb_define_global_const("IPsocket", rb_cIPSocket);
+ rb_define_method(rb_cIPSocket, "addr", ip_addr, 0);
+ rb_define_method(rb_cIPSocket, "peeraddr", ip_peeraddr, 0);
+ rb_define_method(rb_cIPSocket, "recvfrom", ip_recvfrom, -1);
+ rb_define_singleton_method(rb_cIPSocket, "getaddress", ip_s_getaddress, 1);
+
+ rb_cTCPSocket = rb_define_class("TCPSocket", rb_cIPSocket);
+ rb_define_global_const("TCPsocket", rb_cTCPSocket);
+ rb_define_singleton_method(rb_cTCPSocket, "open", tcp_s_open, 2);
+ rb_define_singleton_method(rb_cTCPSocket, "new", tcp_s_open, 2);
+ rb_define_singleton_method(rb_cTCPSocket, "gethostbyname", tcp_s_gethostbyname, 1);
#ifdef SOCKS
- cSOCKSsocket = rb_define_class("SOCKSsocket", cTCPsocket);
- rb_define_singleton_method(cSOCKSsocket, "open", socks_s_open, 2);
- rb_define_singleton_method(cSOCKSsocket, "new", socks_s_open, 2);
+ rb_cSOCKSSocket = rb_define_class("SOCKSSocket", rb_cTCPSocket);
+ rb_define_global_const("SOCKSsocket", rb_cSOCKSSocket);
+ rb_define_singleton_method(rb_cSOCKSSocket, "open", socks_s_open, 2);
+ rb_define_singleton_method(rb_cSOCKSSocket, "new", socks_s_open, 2);
+#ifdef SOCKS5
+ rb_define_method(rb_cSOCKSSocket, "close", socks_s_close, 0);
+#endif
#endif
- cTCPserver = rb_define_class("TCPserver", cTCPsocket);
- rb_define_singleton_method(cTCPserver, "open", tcp_svr_s_open, -1);
- rb_define_singleton_method(cTCPserver, "new", tcp_svr_s_open, -1);
- rb_define_method(cTCPserver, "accept", tcp_accept, 0);
+ rb_cTCPServer = rb_define_class("TCPServer", rb_cTCPSocket);
+ rb_define_global_const("TCPserver", rb_cTCPServer);
+ rb_define_singleton_method(rb_cTCPServer, "open", tcp_svr_s_open, -1);
+ rb_define_singleton_method(rb_cTCPServer, "new", tcp_svr_s_open, -1);
+ rb_define_method(rb_cTCPServer, "accept", tcp_accept, 0);
- cUDPsocket = rb_define_class("UDPsocket", cIPsocket);
- rb_define_singleton_method(cUDPsocket, "open", udp_s_open, 0);
- rb_define_singleton_method(cUDPsocket, "new", udp_s_open, 0);
- rb_define_method(cUDPsocket, "connect", udp_connect, 2);
- rb_define_method(cUDPsocket, "bind", udp_bind, 2);
- rb_define_method(cUDPsocket, "send", udp_send, -1);
- rb_define_method(cUDPsocket, "recvfrom", udp_recvfrom, -1);
+ rb_cUDPSocket = rb_define_class("UDPSocket", rb_cIPSocket);
+ rb_define_global_const("UDPsocket", rb_cUDPSocket);
+ rb_define_singleton_method(rb_cUDPSocket, "open", udp_s_open, -1);
+ rb_define_singleton_method(rb_cUDPSocket, "new", udp_s_open, -1);
+ rb_define_method(rb_cUDPSocket, "connect", udp_connect, 2);
+ rb_define_method(rb_cUDPSocket, "bind", udp_bind, 2);
+ rb_define_method(rb_cUDPSocket, "send", udp_send, -1);
#ifdef HAVE_SYS_UN_H
- cUNIXsocket = rb_define_class("UNIXsocket", cBasicSocket);
- rb_define_singleton_method(cUNIXsocket, "open", unix_s_sock_open, 1);
- rb_define_singleton_method(cUNIXsocket, "new", unix_s_sock_open, 1);
- rb_define_method(cUNIXsocket, "path", unix_path, 0);
- rb_define_method(cUNIXsocket, "addr", unix_addr, 0);
- rb_define_method(cUNIXsocket, "peeraddr", unix_peeraddr, 0);
- rb_define_method(cUNIXsocket, "recvfrom", unix_recvfrom, -1);
-
- cUNIXserver = rb_define_class("UNIXserver", cUNIXsocket);
- rb_define_singleton_method(cUNIXserver, "open", unix_svr_s_open, 1);
- rb_define_singleton_method(cUNIXserver, "new", unix_svr_s_open, 1);
- rb_define_method(cUNIXserver, "accept", unix_accept, 0);
-#endif
-
- cSocket = rb_define_class("Socket", cBasicSocket);
- rb_define_singleton_method(cSocket, "open", sock_s_open, 3);
- rb_define_singleton_method(cSocket, "new", sock_s_open, 3);
- rb_define_singleton_method(cSocket, "for_fd", sock_s_for_fd, 1);
-
- rb_define_method(cSocket, "connect", sock_connect, 1);
- rb_define_method(cSocket, "bind", sock_bind, 1);
- rb_define_method(cSocket, "listen", sock_listen, 1);
- rb_define_method(cSocket, "accept", sock_accept, 0);
-
- rb_define_method(cSocket, "recvfrom", sock_recvfrom, -1);
-
- rb_define_singleton_method(cSocket, "socketpair", sock_s_socketpair, 3);
- rb_define_singleton_method(cSocket, "pair", sock_s_socketpair, 3);
- rb_define_singleton_method(cSocket, "gethostname", sock_gethostname, 0);
- rb_define_singleton_method(cSocket, "gethostbyname", sock_s_gethostbyname, 1);
- rb_define_singleton_method(cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
- rb_define_singleton_method(cSocket, "getservbyname", sock_s_getservbyaname, -1);
+ rb_cUNIXSocket = rb_define_class("UNIXSocket", rb_cBasicSocket);
+ rb_define_global_const("UNIXsocket", rb_cUNIXSocket);
+ rb_define_singleton_method(rb_cUNIXSocket, "open", unix_s_sock_open, 1);
+ rb_define_singleton_method(rb_cUNIXSocket, "new", unix_s_sock_open, 1);
+ rb_define_method(rb_cUNIXSocket, "path", unix_path, 0);
+ rb_define_method(rb_cUNIXSocket, "addr", unix_addr, 0);
+ rb_define_method(rb_cUNIXSocket, "peeraddr", unix_peeraddr, 0);
+ rb_define_method(rb_cUNIXSocket, "recvfrom", unix_recvfrom, -1);
+
+ rb_cUNIXServer = rb_define_class("UNIXServer", rb_cUNIXSocket);
+ rb_define_global_const("UNIXserver", rb_cUNIXServer);
+ rb_define_singleton_method(rb_cUNIXServer, "open", unix_svr_s_open, 1);
+ rb_define_singleton_method(rb_cUNIXServer, "new", unix_svr_s_open, 1);
+ rb_define_method(rb_cUNIXServer, "accept", unix_accept, 0);
+#endif
+
+ rb_cSocket = rb_define_class("Socket", rb_cBasicSocket);
+ rb_define_singleton_method(rb_cSocket, "open", sock_s_open, 3);
+ rb_define_singleton_method(rb_cSocket, "new", sock_s_open, 3);
+ rb_define_singleton_method(rb_cSocket, "for_fd", sock_s_for_fd, 1);
+
+ rb_define_method(rb_cSocket, "connect", sock_connect, 1);
+ rb_define_method(rb_cSocket, "bind", sock_bind, 1);
+ rb_define_method(rb_cSocket, "listen", sock_listen, 1);
+ rb_define_method(rb_cSocket, "accept", sock_accept, 0);
+
+ rb_define_method(rb_cSocket, "recvfrom", sock_recvfrom, -1);
+
+ rb_define_singleton_method(rb_cSocket, "socketpair", sock_s_socketpair, 3);
+ rb_define_singleton_method(rb_cSocket, "pair", sock_s_socketpair, 3);
+ rb_define_singleton_method(rb_cSocket, "gethostname", sock_gethostname, 0);
+ rb_define_singleton_method(rb_cSocket, "gethostbyname", sock_s_gethostbyname, 1);
+ rb_define_singleton_method(rb_cSocket, "gethostbyaddr", sock_s_gethostbyaddr, -1);
+ rb_define_singleton_method(rb_cSocket, "getservbyname", sock_s_getservbyaname, -1);
+ rb_define_singleton_method(rb_cSocket, "getaddrinfo", sock_s_getaddrinfo, -1);
+ rb_define_singleton_method(rb_cSocket, "getnameinfo", sock_s_getnameinfo, -1);
/* constants */
- mConst = rb_define_module_under(cSocket, "Constants");
+ mConst = rb_define_module_under(rb_cSocket, "Constants");
sock_define_const("SOCK_STREAM", SOCK_STREAM);
sock_define_const("SOCK_DGRAM", SOCK_DGRAM);
+#ifdef SOCK_RAW
sock_define_const("SOCK_RAW", SOCK_RAW);
+#endif
#ifdef SOCK_RDM
sock_define_const("SOCK_RDM", SOCK_RDM);
#endif
@@ -1486,7 +2137,9 @@ Init_socket()
#endif
sock_define_const("AF_INET", AF_INET);
+#ifdef PF_INET
sock_define_const("PF_INET", PF_INET);
+#endif
#ifdef AF_UNIX
sock_define_const("AF_UNIX", AF_UNIX);
sock_define_const("PF_UNIX", PF_UNIX);
@@ -1503,10 +2156,24 @@ Init_socket()
sock_define_const("AF_APPLETALK", AF_APPLETALK);
sock_define_const("PF_APPLETALK", PF_APPLETALK);
#endif
+#ifdef AF_UNSPEC
+ sock_define_const("AF_UNSPEC", AF_UNSPEC);
+ sock_define_const("PF_UNSPEC", PF_UNSPEC);
+#endif
+#ifdef AF_INET6
+ sock_define_const("AF_INET6", AF_INET6);
+#endif
+#ifdef PF_INET6
+ sock_define_const("PF_INET6", PF_INET6);
+#endif
sock_define_const("MSG_OOB", MSG_OOB);
+#ifdef MSG_PEEK
sock_define_const("MSG_PEEK", MSG_PEEK);
+#endif
+#ifdef MSG_DONTROUTE
sock_define_const("MSG_DONTROUTE", MSG_DONTROUTE);
+#endif
sock_define_const("SOL_SOCKET", SOL_SOCKET);
#ifdef SOL_IP
@@ -1550,7 +2217,9 @@ Init_socket()
#ifdef SO_RCVBUF
sock_define_const("SO_RCVBUF", SO_RCVBUF);
#endif
+#ifdef SO_KEEPALIVE
sock_define_const("SO_KEEPALIVE", SO_KEEPALIVE);
+#endif
#ifdef SO_OOBINLINE
sock_define_const("SO_OOBINLINE", SO_OOBINLINE);
#endif
@@ -1560,7 +2229,9 @@ Init_socket()
#ifdef SO_PRIORITY
sock_define_const("SO_PRIORITY", SO_PRIORITY);
#endif
+#ifdef SO_LINGER
sock_define_const("SO_LINGER", SO_LINGER);
+#endif
#ifdef SOPRI_INTERACTIVE
sock_define_const("SOPRI_INTERACTIVE", SOPRI_INTERACTIVE);
@@ -1605,4 +2276,95 @@ Init_socket()
#ifdef TCP_MAXSEG
sock_define_const("TCP_MAXSEG", TCP_MAXSEG);
#endif
+
+#ifdef EAI_ADDRFAMILY
+ sock_define_const("EAI_ADDRFAMILY", EAI_ADDRFAMILY);
+#endif
+#ifdef EAI_AGAIN
+ sock_define_const("EAI_AGAIN", EAI_AGAIN);
+#endif
+#ifdef EAI_BADFLAGS
+ sock_define_const("EAI_BADFLAGS", EAI_BADFLAGS);
+#endif
+#ifdef EAI_FAIL
+ sock_define_const("EAI_FAIL", EAI_FAIL);
+#endif
+#ifdef EAI_FAMILY
+ sock_define_const("EAI_FAMILY", EAI_FAMILY);
+#endif
+#ifdef EAI_MEMORY
+ sock_define_const("EAI_MEMORY", EAI_MEMORY);
+#endif
+#ifdef EAI_NODATA
+ sock_define_const("EAI_NODATA", EAI_NODATA);
+#endif
+#ifdef EAI_NONAME
+ sock_define_const("EAI_NONAME", EAI_NONAME);
+#endif
+#ifdef EAI_SERVICE
+ sock_define_const("EAI_SERVICE", EAI_SERVICE);
+#endif
+#ifdef EAI_SOCKTYPE
+ sock_define_const("EAI_SOCKTYPE", EAI_SOCKTYPE);
+#endif
+#ifdef EAI_SYSTEM
+ sock_define_const("EAI_SYSTEM", EAI_SYSTEM);
+#endif
+#ifdef EAI_BADHINTS
+ sock_define_const("EAI_BADHINTS", EAI_BADHINTS);
+#endif
+#ifdef EAI_PROTOCOL
+ sock_define_const("EAI_PROTOCOL", EAI_PROTOCOL);
+#endif
+#ifdef EAI_MAX
+ sock_define_const("EAI_MAX", EAI_MAX);
+#endif
+#ifdef AI_PASSIVE
+ sock_define_const("AI_PASSIVE", AI_PASSIVE);
+#endif
+#ifdef AI_CANONNAME
+ sock_define_const("AI_CANONNAME", AI_CANONNAME);
+#endif
+#ifdef AI_NUMERICHOST
+ sock_define_const("AI_NUMERICHOST", AI_NUMERICHOST);
+#endif
+#ifdef AI_MASK
+ sock_define_const("AI_MASK", AI_MASK);
+#endif
+#ifdef AI_ALL
+ sock_define_const("AI_ALL", AI_ALL);
+#endif
+#ifdef AI_V4MAPPED_CFG
+ sock_define_const("AI_V4MAPPED_CFG", AI_V4MAPPED_CFG);
+#endif
+#ifdef AI_ADDRCONFIG
+ sock_define_const("AI_ADDRCONFIG", AI_ADDRCONFIG);
+#endif
+#ifdef AI_V4MAPPED
+ sock_define_const("AI_V4MAPPED", AI_V4MAPPED);
+#endif
+#ifdef AI_DEFAULT
+ sock_define_const("AI_DEFAULT", AI_DEFAULT);
+#endif
+#ifdef NI_MAXHOST
+ sock_define_const("NI_MAXHOST", NI_MAXHOST);
+#endif
+#ifdef NI_MAXSERV
+ sock_define_const("NI_MAXSERV", NI_MAXSERV);
+#endif
+#ifdef NI_NOFQDN
+ sock_define_const("NI_NOFQDN", NI_NOFQDN);
+#endif
+#ifdef NI_NUMERICHOST
+ sock_define_const("NI_NUMERICHOST", NI_NUMERICHOST);
+#endif
+#ifdef NI_NAMEREQD
+ sock_define_const("NI_NAMEREQD", NI_NAMEREQD);
+#endif
+#ifdef NI_NUMERICSERV
+ sock_define_const("NI_NUMERICSERV", NI_NUMERICSERV);
+#endif
+#ifdef NI_DGRAM
+ sock_define_const("NI_DGRAM", NI_DGRAM);
+#endif
}
diff --git a/ext/socket/sockport.h b/ext/socket/sockport.h
new file mode 100644
index 0000000000..e1cddf53f4
--- /dev/null
+++ b/ext/socket/sockport.h
@@ -0,0 +1,76 @@
+/************************************************
+
+ sockport.h -
+
+ $Author$
+ $Date$
+ created at: Fri Apr 30 23:19:34 JST 1999
+
+************************************************/
+
+#ifndef SOCKPORT_H
+#define SOCKPORT_H
+
+#ifndef SA_LEN
+# ifdef HAVE_SA_LEN
+# define SA_LEN(sa) (sa)->sa_len
+# else
+# ifdef INET6
+# define SA_LEN(sa) \
+ (((sa)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) \
+ : sizeof(struct sockaddr))
+# else
+ /* by tradition, sizeof(struct sockaddr) covers most of the sockaddrs */
+# define SA_LEN(sa) (sizeof(struct sockaddr))
+# endif
+# endif
+#endif
+
+#ifdef HAVE_SA_LEN
+# define SET_SA_LEN(sa, len) (sa)->sa_len = (len)
+#else
+# define SET_SA_LEN(sa, len) (len)
+#endif
+
+#ifdef HAVE_SIN_LEN
+# define SIN_LEN(si) (si)->sin_len
+# define SET_SIN_LEN(si,len) (si)->sin_len = (len)
+#else
+# define SIN_LEN(si) sizeof(struct sockaddr_in)
+# define SET_SIN_LEN(si,len)
+#endif
+
+#ifndef IN_MULTICAST
+# define IN_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000)
+# define IN_MULTICAST(i) IN_CLASSD(i)
+#endif
+
+#ifndef IN_EXPERIMENTAL
+# define IN_EXPERIMENTAL(i) ((((long)(i)) & 0xe0000000) == 0xe0000000)
+#endif
+
+#ifndef IN_CLASSA_NSHIFT
+# define IN_CLASSA_NSHIFT 24
+#endif
+
+#ifndef IN_LOOPBACKNET
+# define IN_LOOPBACKNET 127
+#endif
+
+#ifndef AF_UNSPEC
+# define AF_UNSPEC 0
+#endif
+
+#ifndef PF_UNSPEC
+# define PF_UNSPEC AF_UNSPEC
+#endif
+
+#ifndef PF_INET
+# define PF_INET AF_INET
+#endif
+
+#if defined(HOST_NOT_FOUND) && !defined(h_errno) && !defined(__CYGWIN__)
+extern int h_errno;
+#endif
+
+#endif
diff --git a/ext/tcltklib/.cvsignore b/ext/tcltklib/.cvsignore
new file mode 100644
index 0000000000..f3c7a7c5da
--- /dev/null
+++ b/ext/tcltklib/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/ext/tcltklib/MANIFEST b/ext/tcltklib/MANIFEST