summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog1844
-rw-r--r--MANIFEST25
-rw-r--r--Makefile.in277
-rw-r--r--README26
-rw-r--r--README.EXT492
-rw-r--r--README.EXT.jp1168
-rw-r--r--README.jp46
-rw-r--r--ToDo33
-rw-r--r--array.c268
-rw-r--r--bignum.c94
-rw-r--r--class.c59
-rw-r--r--compar.c2
-rw-r--r--config.guess9
-rw-r--r--config.sub8
-rw-r--r--config_h.dj71
-rw-r--r--config_s.dj56
-rw-r--r--configure1474
-rw-r--r--configure.bat26
-rw-r--r--configure.in425
-rw-r--r--cygwin/GNUmakefile.in9
-rw-r--r--defines.h23
-rw-r--r--dir.c230
-rw-r--r--dln.c160
-rw-r--r--dln.h8
-rw-r--r--enum.c28
-rw-r--r--env.h4
-rw-r--r--error.c136
-rw-r--r--eval.c1591
-rw-r--r--file.c233
-rw-r--r--fnmatch.c243
-rw-r--r--fnmatch.h36
-rw-r--r--gc.c92
-rw-r--r--glob.c591
-rw-r--r--hash.c220
-rw-r--r--inits.c6
-rw-r--r--install-sh238
-rw-r--r--instruby.rb82
-rw-r--r--intern.h110
-rw-r--r--io.c1041
-rw-r--r--lex.c149
-rw-r--r--lib/Env.rb31
-rw-r--r--lib/README48
-rw-r--r--lib/cgi-lib.rb277
-rw-r--r--lib/complex.rb18
-rw-r--r--lib/date2.rb267
-rw-r--r--lib/debug.rb387
-rw-r--r--lib/delegate.rb10
-rw-r--r--lib/e2mmap.rb269
-rw-r--r--lib/final.rb41
-rw-r--r--lib/finalize.rb2
-rw-r--r--lib/ftools.rb28
-rw-r--r--lib/ftplib.rb87
-rw-r--r--lib/getoptlong.rb473
-rw-r--r--lib/getopts.rb18
-rw-r--r--lib/jcode.rb149
-rw-r--r--lib/mailread.rb2
-rw-r--r--lib/mathn.rb4
-rw-r--r--lib/matrix.rb130
-rw-r--r--lib/mkmf.rb436
-rw-r--r--lib/monitor.rb229
-rw-r--r--lib/mutex_m.rb226
-rw-r--r--lib/observer.rb4
-rw-r--r--lib/open3.rb55
-rw-r--r--lib/parsedate.rb23
-rw-r--r--lib/profile.rb55
-rw-r--r--lib/rational.rb2
-rw-r--r--lib/readbytes.rb36
-rw-r--r--lib/shellwords.rb2
-rw-r--r--lib/singleton.rb37
-rw-r--r--lib/sync.rb272
-rw-r--r--lib/telnet.rb636
-rw-r--r--lib/tempfile.rb94
-rw-r--r--lib/thread.rb68
-rw-r--r--lib/timeout.rb42
-rw-r--r--lib/tracer.rb2
-rw-r--r--lib/weakref.rb34
-rw-r--r--main.c9
-rw-r--r--marshal.c49
-rw-r--r--math.c2
-rw-r--r--misc/README5
-rw-r--r--misc/inf-ruby.el322
-rw-r--r--misc/ruby-mode.el724
-rw-r--r--misc/rubydb2x.el104
-rw-r--r--misc/rubydb3x.el113
-rw-r--r--missing/dup2.c69
-rw-r--r--missing/finite.c6
-rw-r--r--missing/fnmatch.c199
-rw-r--r--missing/fnmatch.h57
-rw-r--r--missing/isinf.c44
-rw-r--r--missing/isnan.c16
-rw-r--r--missing/memcmp.c21
-rw-r--r--missing/os2.c111
-rw-r--r--missing/strcasecmp.c1
-rw-r--r--missing/strchr.c45
-rw-r--r--missing/strftime.c30
-rw-r--r--missing/strncasecmp.c18
-rw-r--r--missing/strtod.c266
-rw-r--r--missing/vsnprintf.c1128
-rw-r--r--mkconfig.rb41
-rw-r--r--node.h22
-rw-r--r--numeric.c124
-rw-r--r--object.c157
-rw-r--r--pack.c787
-rw-r--r--parse.c7224
-rw-r--r--parse.y939
-rw-r--r--prec.c81
-rw-r--r--process.c154
-rw-r--r--random.c4
-rw-r--r--range.c201
-rw-r--r--re.c322
-rw-r--r--re.h2
-rw-r--r--regex.c5417
-rw-r--r--regex.h78
-rw-r--r--ruby.18
-rw-r--r--ruby.c225
-rw-r--r--ruby.h132
-rw-r--r--rubyio.h63
-rw-r--r--rubysig.h50
-rw-r--r--rubytest.rb20
-rw-r--r--sample/README56
-rw-r--r--sample/biorhythm.rb10
-rw-r--r--sample/cal.rb119
-rw-r--r--sample/fib.py10
-rw-r--r--sample/from.rb1
-rw-r--r--sample/goodfriday.rb35
-rw-r--r--sample/list.rb16
-rw-r--r--sample/mine.rb42
-rw-r--r--sample/rbc.rb8
-rw-r--r--sample/rcs.rb10
-rw-r--r--sample/rename.rb14
-rw-r--r--sample/sieve.rb21
-rw-r--r--sample/test.rb97
-rw-r--r--sample/trojan.rb3
-rw-r--r--sample/uumerge.rb4
-rw-r--r--signal.c131
-rw-r--r--sprintf.c32
-rw-r--r--st.c71
-rw-r--r--st.h2
-rw-r--r--string.c673
-rw-r--r--struct.c157
-rw-r--r--time.c490
-rw-r--r--top.sed14
-rw-r--r--util.c44
-rw-r--r--util.h30
-rw-r--r--variable.c125
-rw-r--r--version.c21
-rw-r--r--version.h6
-rw-r--r--win32/Makefile265
-rw-r--r--win32/config.h43
-rw-r--r--win32/config.status65
-rwxr-xr-xwin32/ntsetup.bat4
-rw-r--r--win32/ruby.def273
-rw-r--r--win32/sdbm.c981
-rw-r--r--win32/sdbm.h84
-rw-r--r--win32/win32.c192
-rw-r--r--win32/win32.h87
156 files changed, 21670 insertions, 18083 deletions
diff --git a/ChangeLog b/ChangeLog
index 6a317e294b..868572c52f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,1838 @@
+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 granteed 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 maintaind 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 retrun 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 unsed 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 safty 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 happend 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 contant 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/sockt/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): aboid 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 shuould 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): intialize 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 preverse 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 ommited.
+
+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 superclasse method with the value from
+ optinal 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 expandion moved to find_file.
+
+ * eval.c (find_file): tilde expandion 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): nagative length raises exception now.
+
+ * array.c (beg_len): if end == -1, it points end of the array.
+
+ * array.c (rb_ary_subseq): nagative 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 shoule not be
+ ommited 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 ommited.
+
+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
+ insinf, 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): accessng $~ 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 supprt
+ 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 realoc 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 classs. 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.
@@ -14,7 +1849,7 @@ Tue Jan 19 05:01:16 1999 Koji Arai <JCA02266@nifty.ne.jp>
* array.c (beg_len): round range value too much.
-Mon Jan 18 13:02:27 1999 Kuroda Jun <jkuro@dwe.co.j>
+Mon Jan 18 13:02:27 1999 Kuroda Jun <jkuro@dwe.co.jp>
* hash.c (env_keys): strchr() may return NULL.
@@ -435,7 +2270,7 @@ Sat Oct 31 23:18:34 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
* 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>
+Sat Oct 31 04:16:14 1998 Inaba Hiroto <inaba@st.rim.or.jp>
* string.c (str_aref): regexp index SEGVed.
@@ -662,7 +2497,6 @@ Fri Sep 4 11:27:40 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
* regex.c (re_search): wrong return value for \A.
->>>>>>> 1.1.1.2.2.154
Thu Sep 3 14:08:14 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
* version 1.1c4 released.
@@ -697,7 +2531,7 @@ Sat Aug 29 16:31:40 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
* regex.c (re_compile_pattern): mask \nnn over 256.
-Sat Aug 29 02:09:46 1998 1998 Koji Arai <JCA02266@nifty.ne.jp>
+Sat Aug 29 02:09:46 1998 Koji Arai <JCA02266@nifty.ne.jp>
* sprintf.c (f_sprintf): wrong buffer size check.
@@ -1285,7 +3119,7 @@ Thu May 14 14:03:16 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
* random.c (f_rand): use drand48 if possible.
-Wed May 13 19:05:20 1998 1998 MAEDA shugo <shugo@aianet.ne.jp>
+Wed May 13 19:05:20 1998 MAEDA shugo <shugo@aianet.ne.jp>
* BeOS patches for io.c, error.c and config.guess.
diff --git a/MANIFEST b/MANIFEST
index 5c697d612f..1b9e448360 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -1,4 +1,5 @@
COPYING
+COPYING.LIB
ChangeLog
MANIFEST
Makefile.in
@@ -28,10 +29,7 @@ env.h
error.c
eval.c
file.c
-fnmatch.c
-fnmatch.h
gc.c
-glob.c
hash.c
inits.c
install-sh
@@ -50,6 +48,7 @@ object.c
pack.c
parse.c
parse.y
+prec.c
process.c
random.c
range.c
@@ -77,14 +76,16 @@ variable.c
version.c
version.h
beos/ruby.def.in
+cygwin/GNUmakefile.in
ext/Setup
ext/Setup.dj
+ext/Setup.emx
ext/Setup.nt
ext/Setup.x68
-ext/aix_ld.rb
-ext/cygwin32_ld.rb
+ext/aix_mksym.rb
+ext/mswin32_extmk.rb
ext/extmk.rb.in
-ext/extmk.rb.nt
+lib/CGI.rb
lib/English.rb
lib/Env.rb
lib/README
@@ -142,16 +143,24 @@ missing/crypt.c
missing/dir.h
missing/dup2.c
missing/file.h
+missing/finite.c
missing/flock.c
+missing/fnmatch.c
+missing/fnmatch.h
+missing/isinf.c
+missing/isnan.c
missing/memcmp.c
missing/memmove.c
missing/mkdir.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
@@ -163,6 +172,8 @@ 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
@@ -196,6 +207,7 @@ sample/rbc.rb
sample/rcs.awk
sample/rcs.dat
sample/rcs.rb
+sample/rd2html.rb
sample/regx.rb
sample/sieve.rb
sample/svr.rb
@@ -206,6 +218,7 @@ sample/tsvr.rb
sample/uumerge.rb
win32/Makefile
win32/config.h
+win32/config.status
win32/ntsetup.bat
win32/ruby.def
win32/sdbm.c
diff --git a/Makefile.in b/Makefile.in
index 628b0e0778..865318ba70 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -14,105 +14,115 @@ AUTOCONF = autoconf
prefix = @prefix@
CFLAGS = @CFLAGS@ -I. -I@srcdir@ -I@includedir@
LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@
+XLDFLAGS = @XLDFLAGS@
EXTLIBS =
LIBS = @LIBS@ $(EXTLIBS)
MISSING = @LIBOBJS@ @ALLOCA@
-LDSHARED = @LDSHARED@
-DLDFLAGS = @DLDFLAGS@
+LDSHARED = @LIBRUBY_LDSHARED@
+DLDFLAGS = @LIBRUBY_DLDFLAGS@
SOLIBS = @SOLIBS@
-binsuffix = @binsuffix@
+RUBY_INSTALL_NAME=@RUBY_INSTALL_NAME@
+EXEEXT = @EXEEXT@
+PROGRAM=$(RUBY_INSTALL_NAME)$(EXEEXT)
#### End of system configuration section. ####
+MAJOR= @MAJOR@
+MINOR= @MINOR@
+TEENY= @TEENY@
+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) rbconfig.rb
+ @./miniruby$(EXEEXT) -Xext extmk.rb @EXTSTATIC@
-miniruby$(binsuffix): libruby.a $(MAINOBJ) dmyext.o
+miniruby$(EXEEXT): config.status $(LIBRUBY_A) $(MAINOBJ) dmyext.@OBJEXT@
@rm -f $@
- $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) dmyext.o libruby.a $(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) $(LIBRUBYARG) $(LIBS) -o $@
+ $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) -o $@
-libruby.a: $(OBJS) dmyext.o
- @AR@ rcu $@ $(OBJS) dmyext.o
+$(LIBRUBY_A): $(OBJS) dmyext.@OBJEXT@
+ @AR@ rcu $@ $(OBJS) dmyext.@OBJEXT@
@-@RANLIB@ $@ 2> /dev/null || true
-libruby.so: $(OBJS) dmyext.o
- $(LDSHARED) $(DLDFLAGS) $(SOLIBS) $(OBJS) dmyext.o -o $@
+$(LIBRUBY_SO): $(OBJS) dmyext.@OBJEXT@
+ $(LDSHARED) $(DLDFLAGS) $(SOLIBS) $(OBJS) dmyext.@OBJEXT@ -o $@
+ @-./miniruby -e 'ARGV.each{|link| File.delete link if File.exist? link; \
+ File.symlink "$(LIBRUBY_SO)", link}' \
+ $(LIBRUBY_ALIASES) || true
install: rbconfig.rb
- ./miniruby$(binsuffix) $(srcdir)/instruby.rb $(DESTDIR)
+ ./miniruby$(EXEEXT) $(srcdir)/instruby.rb $(DESTDIR)
-clean:; @rm -f $(OBJS) $(LIBRUBY) $(MAINOBJ) rbconfig.rb
- @rm -f ext/extinit.c ext/extinit.o dmyext.o
- @if test -f ./miniruby$(binsuffix); then \
- ./miniruby$(binsuffix) -Xext extmk.rb clean; \
- fi
+clean:; @rm -f $(OBJS) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY_ALIASES) $(MAINOBJ) rbconfig.rb
+ @rm -f ext/extinit.c ext/extinit.@OBJEXT@ dmyext.@OBJEXT@
+ @-./miniruby$(EXEEXT) -Xext 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 parse.c *~ core *.core gmon.out y.tab.c y.output
- @rm -f ruby$(binsuffix) miniruby$(binsuffix)
+ @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$(binsuffix)
- @./miniruby$(binsuffix) $(srcdir)/rubytest.rb
+test: miniruby$(EXEEXT)
+ @./miniruby$(EXEEXT) $(srcdir)/rubytest.rb
-rbconfig.rb: config.status miniruby$(binsuffix)
- @./miniruby$(binsuffix) $(srcdir)/mkconfig.rb rbconfig.rb
+rbconfig.rb: miniruby$(EXEEXT)
+ @./miniruby$(EXEEXT) $(srcdir)/mkconfig.rb rbconfig.rb
config.status: $(srcdir)/configure
$(SHELL) ./config.status --recheck
@@ -120,7 +130,7 @@ config.status: $(srcdir)/configure
$(srcdir)/configure: $(srcdir)/configure.in
cd $(srcdir) && $(AUTOCONF)
-.c.o:
+.c.@OBJEXT@:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
lex.c: keywords
@@ -130,100 +140,123 @@ parse.c: parse.y
$(YACC) $<
mv -f y.tab.c parse.c
-alloca.o: @srcdir@/missing/alloca.c
+alloca.@OBJEXT@: @srcdir@/missing/alloca.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/alloca.c
-crypt.o: @srcdir@/missing/crypt.c
+crypt.@OBJEXT@: @srcdir@/missing/crypt.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/crypt.c
-dup2.o: @srcdir@/missing/dup2.c
+dup2.@OBJEXT@: @srcdir@/missing/dup2.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/dup2.c
-flock.o: @srcdir@/missing/flock.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
-memcmp.o: @srcdir@/missing/memcmp.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
+
+memcmp.@OBJEXT@: @srcdir@/missing/memcmp.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/memcmp.c
-memmove.o: @srcdir@/missing/memmove.c
+memmove.@OBJEXT@: @srcdir@/missing/memmove.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/memmove.c
-mkdir.o: @srcdir@/missing/mkdir.c
+mkdir.@OBJEXT@: @srcdir@/missing/mkdir.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/mkdir.c
-vsnprintf.o: @srcdir@/missing/vsnprintf.c
+vsnprintf.@OBJEXT@: @srcdir@/missing/vsnprintf.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/vsnprintf.c
-strcasecmp.o: @srcdir@/missing/strcasecmp.c
+strcasecmp.@OBJEXT@: @srcdir@/missing/strcasecmp.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strcasecmp.c
-strchr.o: @srcdir@/missing/strchr.c
+strncasecmp.@OBJEXT@: @srcdir@/missing/strncasecmp.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strncasecmp.c
+
+strchr.@OBJEXT@: @srcdir@/missing/strchr.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strchr.c
-strdup.o: @srcdir@/missing/strdup.c
+strdup.@OBJEXT@: @srcdir@/missing/strdup.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strdup.c
-strerror.o: @srcdir@/missing/strerror.c
+strerror.@OBJEXT@: @srcdir@/missing/strerror.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strerror.c
-strftime.o: @srcdir@/missing/strftime.c
+strftime.@OBJEXT@: @srcdir@/missing/strftime.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strftime.c
-strstr.o: @srcdir@/missing/strstr.c
+strstr.@OBJEXT@: @srcdir@/missing/strstr.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strstr.c
-strtol.o: @srcdir@/missing/strtol.c
+strtod.@OBJEXT@: @srcdir@/missing/strtod.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strtod.c
+
+strtol.@OBJEXT@: @srcdir@/missing/strtol.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strtol.c
-strtoul.o: @srcdir@/missing/strtoul.c
+strtoul.@OBJEXT@: @srcdir@/missing/strtoul.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/strtoul.c
-nt.o: @srcdir@/missing/nt.c
+nt.@OBJEXT@: @srcdir@/missing/nt.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/nt.c
-x68.o: @srcdir@/missing/x68.c
+x68.@OBJEXT@: @srcdir@/missing/x68.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/x68.c
+os2.@OBJEXT@: @srcdir@/missing/os2.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/os2.c
+
+dl_os2.@OBJEXT@: @srcdir@/missing/dl_os2.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/dl_os2.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 rubysig.h st.h dln.h
-file.o: file.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h
-fnmatch.o: fnmatch.c config.h fnmatch.h
-gc.o: gc.c ruby.h config.h defines.h intern.h rubysig.h st.h node.h env.h re.h regex.h
-glob.o: config.h glob.c fnmatch.h
-hash.o: hash.c ruby.h config.h defines.h intern.h st.h rubysig.h
-inits.o: inits.c ruby.h config.h defines.h intern.h
-io.o: io.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h
-main.o: main.c ruby.h config.h defines.h intern.h
-marshal.o: marshal.c ruby.h config.h defines.h intern.h rubyio.h st.h
-math.o: math.c ruby.h config.h defines.h intern.h
-numeric.o: numeric.c ruby.h config.h defines.h intern.h
-object.o: object.c ruby.h config.h defines.h intern.h st.h
-pack.o: pack.c ruby.h config.h defines.h intern.h
-process.o: process.c ruby.h config.h defines.h intern.h rubysig.h st.h
-random.o: random.c ruby.h config.h defines.h intern.h
-range.o: range.c ruby.h config.h defines.h intern.h
-re.o: re.c ruby.h config.h defines.h intern.h re.h regex.h
-regex.o: regex.c config.h regex.h util.h
-ruby.o: ruby.c ruby.h config.h defines.h intern.h dln.h util.h
-signal.o: signal.c ruby.h config.h defines.h intern.h rubysig.h
-sprintf.o: sprintf.c ruby.h config.h defines.h intern.h
-st.o: st.c config.h st.h
-string.o: string.c ruby.h config.h defines.h intern.h re.h regex.h
-struct.o: struct.c ruby.h config.h defines.h intern.h
-time.o: time.c ruby.h config.h defines.h intern.h
-util.o: util.c 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
+bignum.@OBJEXT@: bignum.c ruby.h config.h defines.h intern.h
+class.@OBJEXT@: class.c ruby.h config.h defines.h intern.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
+error.@OBJEXT@: error.c ruby.h config.h defines.h intern.h env.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
+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
+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 util.h
+ruby.@OBJEXT@: ruby.c ruby.h config.h defines.h intern.h dln.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 dd93c592be..2a99cae28b 100644
--- a/README
+++ b/README
@@ -20,10 +20,28 @@ Perl). It is simple, straight-forward, and extensible.
* 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.netlab.co.jp:/home/cvs login
+ (Logging in to anonymous@cvs.netlab.co.jp)
+ CVS password: guest
+ $ cvs -d :pserver:anonymous@cvs.netlab.co.jp:/home/cvs checkout ruby
+
+* Mailing list
+
+There is a mailing list to talk about Ruby.
+To subscribe this list, please send the following phrase
+
+ subscribe Your-Last-Name Your-First-Name
+e.g.
+ subscribe Joseph Smith
+
+in the mail body (not subject) to the address <ruby-talk-ctl@netlab.co.jp>.
+
* How to compile and install
This is what you need to do to compile and install Ruby:
@@ -98,9 +116,9 @@ You can redistribute it and/or modify it under either the terms of the GPL
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 file 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
diff --git a/README.EXT b/README.EXT
index f169e54995..241d6fa8cd 100644
--- a/README.EXT
+++ b/README.EXT
@@ -1,8 +1,8 @@
.\" README.EXT - -*- Text -*- created at: Mon Aug 7 16:45:54 JST 1995
-This document explains how to make extention modules for Ruby.
+This document explains how to make extention 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
@@ -109,35 +109,29 @@ bugs.
1.4 Convert C data into VALUE
-VALUE¤Î¼ÂºÝ¤Î¹½Â¤¤Ï
+To convert C data to the values of Ruby:
- * FIXNUM¤Î¾ì¹ç
+ * FIXNUM
- 1bit±¦¥·¥Õ¥È¤·¤Æ¡¤LSB¤òΩ¤Æ¤ë¡¥
+ left shift 1 bit, and turn on LSB.
- * ¤½¤Î¾¤Î¥Ý¥¤¥ó¥¿¤Î¾ì¹ç
+ * Other pointer values
- ¤½¤Î¤Þ¤ÞVALUE¤Ë¥­¥ã¥¹¥È¤¹¤ë¡¥
+ cast to VALUE.
-¤È¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥¤è¤Ã¤Æ¡¤LSB¤ò¥Á¥§¥Ã¥¯¤¹¤ì¤ÐVALUE¤¬FIXNUM¤«¤É
-¤¦¤«¤ï¤«¤ë¤ï¤±¤Ç¤¹(¥Ý¥¤¥ó¥¿¤ÎLSB¤¬Î©¤Ã¤Æ¤¤¤Ê¤¤¤³¤È¤ò²¾Äꤷ¤Æ
-¤¤¤ë)¡¥
+You can determine whether VALUE is pointer or not, by checking LSB.
-¤Ç¤¹¤«¤é¡¤FIXNUM°Ê³°¤ÎRuby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Î¹½Â¤ÂΤÏñ¤ËVALUE
-¤Ë¥­¥ã¥¹¥È¤¹¤ë¤À¤±¤ÇVALUE¤ËÊÑ´¹½ÐÍè¤Þ¤¹¡¥¤¿¤À¤·¡¤Ç¤°Õ¤Î¹½Â¤
-ÂΤ¬VALUE¤Ë¥­¥ã¥¹¥È½ÐÍè¤ë¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡¥¥­¥ã¥¹¥È¤¹¤ë¤Î
-¤ÏRuby¤ÎÃΤäƤ¤¤ë¹½Â¤ÂÎ(ruby.h¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ëstruct RXxxx
-¤Î¤â¤Î)¤À¤±¤Ë¤·¤Æ¤ª¤¤¤Æ¤¯¤À¤µ¤¤¡¥
+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>.
-FIXNUM¤Ë´Ø¤·¤Æ¤ÏÊÑ´¹¥Þ¥¯¥í¤ò·Ðͳ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥C¤ÎÀ°¿ô
-¤«¤éVALUE¤ËÊÑ´¹¤¹¤ë¥Þ¥¯¥í¤Ï°Ê²¼¤Î¤â¤Î¤¬¤¢¤ê¤Þ¤¹¡¥É¬Íפ˱þ¤¸
-¤Æ»È¤¤Ê¬¤±¤Æ¤¯¤À¤µ¤¤¡¥
+To convert C numbers to Ruby value, use these macros.
- INT2FIX() ¤â¤È¤ÎÀ°¿ô¤¬31bit°ÊÆâ¤Ë¼ý¤Þ¤ë»þ
- INT2NUM() Ǥ°Õ¤ÎÀ°¿ô¤«¤éVALUE¤Ø
+ INT2FIX() for intergers within 31bits.
+ INT2NUM() for arbitrary sized integer.
-INT2NUM()¤ÏÀ°¿ô¤¬FIXNUM¤ÎÈϰϤ˼ý¤Þ¤é¤Ê¤¤¾ì¹ç¡¤Bignum¤ËÊÑ´¹
-¤·¤Æ¤¯¤ì¤Þ¤¹(¤¬¡¤¾¯¤·ÃÙ¤¤)¡¥
+INT2NUM() converts integers into Bignums, if it is out of FIXNUM
+range, but bit slower.
1.5 Manipulate Ruby data
@@ -190,23 +184,15 @@ interpreter. Useful functions are listed below (not all):
2. Extend Ruby with C
-¸¶ÍýŪ¤ËRuby¤Ç½ñ¤±¤ë¤³¤È¤ÏC¤Ç¤â½ñ¤±¤Þ¤¹¡¥Ruby¤½¤Î¤â¤Î¤¬C¤Çµ­
-½Ò¤µ¤ì¤Æ¤¤¤ë¤ó¤Ç¤¹¤«¤é¡¤ÅöÁ³¤È¤¤¤¨¤ÐÅöÁ³¤Ê¤ó¤Ç¤¹¤±¤É¡¥¤³¤³¤Ç
-¤ÏRuby¤Î³ÈÄ¥¤Ë»È¤¦¤³¤È¤¬Â¿¤¤¤À¤í¤¦¤Èͽ¬¤µ¤ì¤ëµ¡Ç½¤òÃæ¿´¤Ë¾Ò
-²ð¤·¤Þ¤¹¡¥
-
2.1 Add new features to Ruby
-Ruby¤ÇÄ󶡤µ¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤¨¤ÐRuby¥¤¥ó¥¿¥×¥ê¥¿¤Ë¿·¤·¤¤µ¡Ç½
-¤òÄɲ乤뤳¤È¤¬¤Ç¤­¤Þ¤¹¡¥Ruby¤Ç¤Ï°Ê²¼¤Îµ¡Ç½¤òÄɲ乤ë´Ø¿ô¤¬
-Ä󶡤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+You can add new features (classes, methods, etc.) to the Ruby
+interpreter. Ruby provides the API to define things below:
* Classes, Modules
* Methods, Singleton Methods
* Constants
-¤Ç¤Ï½ç¤Ë¾Ò²ð¤·¤Þ¤¹¡¥
-
2.1.1 Class/module definition
To define class or module, use functions below:
@@ -327,9 +313,9 @@ by the symbol mid.
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:
@@ -346,9 +332,7 @@ See 2.1.3 for defining new constant.
3. Informatin sharing between Ruby and C
-C¸À¸ì¤ÈRuby¤Î´Ö¤Ç¾ðÊó¤ò¶¦Í­¤¹¤ëÊýË¡¤Ë¤Ä¤¤¤Æ²òÀ⤷¤Þ¤¹¡¥
-
-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.
@@ -363,43 +347,35 @@ Ruby nil in C scope.
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)
-¤³¤Î´Ø¿ô¤ÏRuby¤ÈC¤È¤Ç¶¦Í­¤¹¤ëÂç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ¤¹¡¥ÊÑ¿ô̾¤¬
-`$'¤Ç»Ï¤Þ¤é¤Ê¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤Þ¤¹¡¥¤³¤ÎÊÑ¿ô¤ÎÃͤòÊÑ
-¹¹¤¹¤ë¤È¼«Æ°Åª¤ËRuby¤ÎÂбþ¤¹¤ëÊÑ¿ô¤ÎÃͤâÊѤï¤ê¤Þ¤¹¡¥
+This function defines the variable which is shared by the both world.
+The value of the global variable pointerd 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)
-¤³¤ì¤éÊÑ¿ô¤Î¾¤Ëhook¤ò¤Ä¤±¤¿Âç°èÊÑ¿ô¤òÄêµÁ¤Ç¤­¤Þ¤¹¡¥hookÉÕ¤­
-¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤òÍѤ¤¤ÆÄêµÁ¤·¤Þ¤¹¡¥hookÉÕ¤­Âç°èÊÑ¿ô¤Î
-Ãͤλ²¾È¤äÀßÄê¤Ïhook¤Ç¹Ô¤¦É¬Íפ¬¤¢¤ê¤Þ¤¹¡¥
+You can defined hooked variables. The accessor functions (getter and
+setter) are called on access to the hooked variables.
void rb_define_hooked_variable(char *name, VALUE *var,
VALUE (*getter)(), VALUE (*setter)())
-¤³¤Î´Ø¿ô¤ÏC¤Î´Ø¿ô¤Ë¤è¤Ã¤Æhook¤Î¤Ä¤±¤é¤ì¤¿Âç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ
-¤¹¡¥ÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï´Ø¿ôgetter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì
-¤¿»þ¤Ë¤Ï´Ø¿ôsetter¤¬¸Æ¤Ð¤ì¤ë¡¥hook¤ò»ØÄꤷ¤Ê¤¤¾ì¹ç¤Ïgetter¤ä
-setter¤Ë0¤ò»ØÄꤷ¤Þ¤¹¡¥
-
-# getter¤âsetter¤â0¤Ê¤é¤Ðrb_define_variable()¤ÈƱ¤¸¤Ë¤Ê¤ë¡¥
-
-¤½¤ì¤«¤é¡¤C¤Î´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ëRuby¤ÎÂç°èÊÑ¿ô¤òÄêµÁ¤¹¤ë
-´Ø¿ô¤¬¤¢¤ê¤Þ¤¹¡¥
+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().
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:
@@ -408,54 +384,44 @@ The prototypes of the getter and setter functions are as following:
3.3 Encapsulate C data into Ruby object
-C¤ÎÀ¤³¦¤ÇÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿(¹½Â¤ÂÎ)¤òRuby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ
-¼è¤ê°·¤¤¤¿¤¤¾ì¹ç¤¬¤¢¤ê¤¨¤Þ¤¹¡¥¤³¤Î¤è¤¦¤Ê¾ì¹ç¤Ë¤Ï¡¤Data¤È¤¤¤¦
-Ruby¥ª¥Ö¥¸¥§¥¯¥È¤ËC¤Î¹½Â¤ÂÎ(¤Ø¤Î¥Ý¥¤¥ó¥¿)¤ò¤¯¤ë¤à¤³¤È¤ÇRuby
-¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ¼è¤ê°·¤¨¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡¥
-
-Data¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Æ¹½Â¤ÂΤòRuby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¥«¥×¥»¥ë
-²½¤¹¤ë¤¿¤á¤Ë¤Ï¡¤°Ê²¼¤Î¥Þ¥¯¥í¤ò»È¤¤¤Þ¤¹¡¥
+To wrapping and objectify the C pointer as Ruby object (so called
+DATA), use Data_Wrap_Struct().
Data_Wrap_Struct(class,mark,free,ptr)
-¤³¤Î¥Þ¥¯¥í¤ÎÌá¤êÃͤÏÀ¸À®¤µ¤ì¤¿Data¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¹¡¥
-
-class¤Ï¤³¤ÎData¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¯¥é¥¹¤Ç¤¹¡¥ptr¤Ï¥«¥×¥»¥ë²½¤¹¤ë
-C¤Î¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤Ç¤¹¡¥mark¤Ï¤³¤Î¹½Â¤ÂΤ¬Ruby¤Î¥ª¥Ö¥¸¥§
-¥¯¥È¤Ø¤Î»²¾È¤¬¤¢¤ë»þ¤Ë»È¤¦´Ø¿ô¤Ç¤¹¡¥¤½¤Î¤è¤¦¤Ê»²¾È¤ò´Þ¤Þ¤Ê¤¤
-»þ¤Ë¤Ï0¤ò»ØÄꤷ¤Þ¤¹¡¥
+Data_Wrap_Struct() returns a created DATA object. The class 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.
-# ¤½¤Î¤è¤¦¤Ê»²¾È¤Ï´«¤á¤é¤ì¤Þ¤»¤ó¡¥
-
-free¤Ï¤³¤Î¹½Â¤ÂΤ¬¤â¤¦ÉÔÍפˤʤä¿»þ¤Ë¸Æ¤Ð¤ì¤ë´Ø¿ô¤Ç¤¹¡¥¤³¤Î
-´Ø¿ô¤¬¥¬¡¼¥Ù¡¼¥¸¥³¥ì¥¯¥¿¤«¤é¸Æ¤Ð¤ì¤Þ¤¹¡¥
-
-C¤Î¹½Â¤ÂΤγäÅö¤ÈData¥ª¥Ö¥¸¥§¥¯¥È¤ÎÀ¸À®¤òƱ»þ¤Ë¹Ô¤¦¥Þ¥¯¥í¤È
-¤·¤Æ°Ê²¼¤Î¤â¤Î¤¬Ä󶡤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+You can allocate and wrap the structure in one step.
Data_Make_Struct(class, type, mark, free, sval)
-¤³¤Î¥Þ¥¯¥í¤ÎÌá¤êÃͤÏÀ¸À®¤µ¤ì¤¿Data¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¹¡¥
+This macro returns an allocated Data object, wrapping the pointer to
+the structure, which is also allocated. This macro works like:
+
+ (sval = ALLOC(type), Data_Wrap_Struct(class, mark, free, sval))
-class, mark, free¤ÏData_Wrap_Struct¤ÈƱ¤¸Æ¯¤­¤ò¤·¤Þ¤¹¡¥type
-¤Ï³ä¤êÅö¤Æ¤ëC¹½Â¤ÂΤη¿¤Ç¤¹¡¥³ä¤êÅö¤Æ¤é¤ì¤¿¹½Â¤ÂΤÏÊÑ¿ôsval
-¤ËÂåÆþ¤µ¤ì¤Þ¤¹¡¥¤³¤ÎÊÑ¿ô¤Î·¿¤Ï (type*) ¤Ç¤¢¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥
+Arguments, class, mark, free, works like thier counterpart of
+Data_Wrap_Struct(). The pointer to allocated structure will be
+assigned to sval, which should be the pointer to the type specified.
-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
@@ -477,17 +443,17 @@ 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 prural source
+files, avoid chooing ``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 exapmle, ``Init_dbm()'' will be executed when loading
+the library.
+
+Here's the example of an initializing function.
--
Init_dbm()
@@ -509,11 +475,7 @@ Init_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 {
@@ -525,12 +487,10 @@ struct dbmdata {
obj = Data_Make_Struct(class,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) {\
@@ -539,14 +499,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
@@ -557,13 +514,11 @@ 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 arbtrary number of arguments receives
+arguments like this:
--
static VALUE
@@ -580,36 +535,28 @@ 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 exapmle "11" means, the method requires at least one
+argument, and at most receives two arguments.
-Ruby¤ÎÇÛÎó¤Ç°ú¿ô¤ò¼õ¤±¼è¤ë¤â¤Î¤Ïindexes¤¬¤¢¤ê¤Þ¤¹¡¥¼ÂÁõ¤Ï¤³
-¤¦¤Ç¤¹¡¥
+The methods with arbtrary 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
@@ -620,72 +567,82 @@ not exported to the Ruby world. You need to protect them by
(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.
-extconf.rb¤Ï¥â¥¸¥å¡¼¥ë¤Î¥³¥ó¥Ñ¥¤¥ë¤ËɬÍפʾò·ï¤Î¥Á¥§¥Ã¥¯¤Ê¤É
-¤ò¹Ô¤¦¤³¤È¤¬ÌÜŪ¤Ç¤¹¡¥extconf.rb¤ÎÃæ¤Ç¤Ï°Ê²¼¤ÎRuby´Ø¿ô¤ò»È¤¦
-¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥
+The extconf.rb is the file to check compilation condition etc. You
+need to put
- have_library(lib, func): ¥é¥¤¥Ö¥é¥ê¤Î¸ºß¥Á¥§¥Ã¥¯
- have_func(func): ´Ø¿ô¤Î¸ºß¥Á¥§¥Ã¥¯
- have_header(header): ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¥Á¥§¥Ã¥¯
- create_makefile(target): Makefile¤ÎÀ¸À®
+ require 'mkmf'
-°Ê²¼¤ÎÊÑ¿ô¤ò»È¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥
+at the top of the file. You can use the funcitons below to check the
+condition.
- $CFLAGS: ¥³¥ó¥Ñ¥¤¥ë»þ¤ËÄɲÃŪ¤Ë»ØÄꤹ¤ë¥Õ¥é¥°(-I¤Ê¤É)
- $LDFLAGS: ¥ê¥ó¥¯»þ¤ËÄɲÃŪ¤Ë»ØÄꤹ¤ë¥Õ¥é¥°(-L¤Ê¤É)
+ have_library(lib, func): check whether library containing function exists.
+ have_func(func): check whether function exists
+ have_header(header): check whether header file exists
+ create_makefile(target): generate Makefile
-¥â¥¸¥å¡¼¥ë¤ò¥³¥ó¥Ñ¥¤¥ë¤¹¤ë¾ò·ï¤¬Â·¤ï¤Ê¤º¡¤¤½¤Î¥â¥¸¥å¡¼¥ë¤Ï¥³
-¥ó¥Ñ¥¤¥ë¤·¤Ê¤¤»þ¤Ë¤Ïcreate_makefile¤ò¸Æ¤Ð¤Ê¤±¤ì¤ÐMakefile¤Ï
-À¸À®¤µ¤ì¤º¡¤¥³¥ó¥Ñ¥¤¥ë¤â¹Ô¤ï¤ì¤Þ¤»¤ó¡¥
+The value of variables below will affect Makefile.
+
+ $CFLAGS: included in CFLAGS make variable (such as -I)
+ $LDFLAGS: included in LDFLAGS make variable (such as -L)
+
+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
-¤Ê¤É¤Çºî¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤¢¤Ã¤Æ»¤Ï̵¤¤¤Ç¤·¤ç¤¦¡¥
+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) generate Makefile
+
+Try generate Makefile by:
+
+ 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
-(8) make
+Type
-Ruby¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Çmake¤ò¼Â¹Ô¤¹¤ë¤ÈMakefile¤òÀ¸À®¤«¤émake¡¤
-ɬÍפˤè¤Ã¤Æ¤Ï¤½¤Î¥â¥¸¥å¡¼¥ë¤ÎRuby¤Ø¤Î¥ê¥ó¥¯¤Þ¤Ç¼«Æ°Åª¤Ë¼Â¹Ô
-¤·¤Æ¤¯¤ì¤Þ¤¹¡¥extconf.rb¤ò½ñ¤­´¹¤¨¤ë¤Ê¤É¤·¤ÆMakefile¤ÎºÆÀ¸À®
-¤¬É¬Íפʻþ¤Ï¤Þ¤¿Ruby¥Ç¥£¥ì¥¯¥È¥ê¤Çmake¤·¤Æ¤¯¤À¤µ¤¤¡¥
+ make
+
+to compile your extension. You don't need this step neither, if you
+put extension library under ext directory of the ruby source tree.
(9) debug
-You may need to rb_debug the module. The modules can be linked
-statically by adding directory name in the ext/Setup file,
-so that you can inspect the module by the debugger.
+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.
(10) done, now you have the extension library
-¸å¤Ï¤³¤Ã¤½¤ê»È¤¦¤Ê¤ê¡¤¹­¤¯¸ø³«¤¹¤ë¤Ê¤ê¡¤Çä¤ë¤Ê¤ê¡¤¤´¼«Í³¤Ë¤ª
-»È¤¤¤¯¤À¤µ¤¤¡¥Ruby¤Îºî¼Ô¤Ï³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ë´Ø¤·¤Æ°ìÀڤθ¢Íø¤ò
-¼çÄ¥¤·¤Þ¤»¤ó¡¥
-
-Appendix A. 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.
-Ruby¤Î¥½¡¼¥¹¤Ï¤¤¤¯¤Ä¤«¤ËʬÎह¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤³¤Î¤¦¤Á¥¯¥é
-¥¹¥é¥¤¥Ö¥é¥ê¤ÎÉôʬ¤Ï´ðËÜŪ¤Ë³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ÈƱ¤¸ºî¤êÊý¤Ë¤Ê¤Ã
-¤Æ¤¤¤Þ¤¹¡¥¤³¤ì¤é¤Î¥½¡¼¥¹¤Ïº£¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤Û¤È¤ó¤ÉÍý²ò¤Ç¤­¤ë¤È
-»×¤¤¤Þ¤¹¡¥
+Appendix A. Ruby source files overview
ruby language core
@@ -737,18 +694,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
@@ -758,58 +712,58 @@ const: nil object
Qtrue
-const: Qtrue object(default true value)
+const: true object(default true value)
Qfalse
-const: Qfalse object
+const: false object
-** C¥Ç¡¼¥¿¤Î¥«¥×¥»¥ë²½
+** C pointer wrapping
Data_Wrap_Struct(VALUE class, 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)
-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)
-super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤Ruby¥¯¥é¥¹¤òÄêµÁ¤¹¤ë¡¥
+Defines new Ruby class as subclass of super.
VALUE rb_define_class_under(VALUE module, 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)
-¿·¤·¤¤Ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¡¥
+Defines new Ruby module.
VALUE rb_define_module_under(VALUE module, char *name, VALUE super)
-¿·¤·¤¤Ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤·¡¤module¤ÎÄê¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
+Defines new Ruby module, under the modules's namespace.
void rb_include_module(VALUE class, 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
@@ -871,115 +825,118 @@ Defines global contant. This is just work as
rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc)
-¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥argc¤Ïself¤ò½ü¤¯°ú¿ô¤Î¿ô¡¥argc¤¬-1¤Î»þ,
-´Ø¿ô¤Ë¤Ï°ú¿ô¤Î¿ô(self¤ò´Þ¤Þ¤Ê¤¤)¤òÂè1°ú¿ô, °ú¿ô¤ÎÇÛÎó¤òÂè2°ú
-¿ô¤È¤¹¤ë·Á¼°¤ÇÍ¿¤¨¤é¤ì¤ë(Âè3°ú¿ô¤Ïself)¡¥argc¤¬-2¤Î»þ, Âè1°ú
-¿ô¤¬self, Âè2°ú¿ô¤¬args(args¤Ï°ú¿ô¤ò´Þ¤àRuby¤ÎÇÛÎó)¤È¤¤¤¦·Á
-¼°¤ÇÍ¿¤¨¤é¤ì¤ë¡¥
+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)
-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_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, 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-optinal argument, 2 optinal
+aruguments. 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)
-ʸ»úÎó¤òRuby¤È¥¹¥¯¥ê¥×¥È¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¡¦¼Â¹Ô¤¹¤ë¡¥
+Compiles and executes the string as Ruby program.
ID rb_intern(char *name)
-ʸ»úÎó¤ËÂбþ¤¹¤ëID¤òÊÖ¤¹¡¥
+Returns ID corresponding the name.
char *rb_id2name(ID id)
-ID¤ËÂбþ¤¹¤ëʸ»úÎó¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥
+Returns the name corresponding ID.
char *rb_class2name(VALUE class)
-class¤Î̾Á°¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥class¤¬Ì¾Á°¤ò»ý¤¿¤Ê¤¤»þ¤Ë¤Ï,
-ÁÄÀè¤òÁ̤äÆ̾Á°¤ò»ý¤Ä¥¯¥é¥¹¤Î̾Á°¤òÊÖ¤¹¡¥
+Returns the name of the class.
-** ¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô
+** Instance Variables
VALUE rb_iv_get(VALUE obj, 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)
-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(char *fmt, ...)
-** Îã³°¡¦¥¨¥é¡¼
+Prints warning message according to the printf-like format.
void rb_warning(char *fmt, ...)
-rb_verbose»þ¤Ëɸ½à¥¨¥é¡¼½ÐÎϤ˷ٹð¾ðÊó¤òɽ¼¨¤¹¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
+Prints warning message according to the printf-like format, if
+$VERBOSE is true.
- void rb_raise(rb_eRuntimeError, char *fmt, ...)
+ void rb_raise(VALUE exception, char *fmt, ...)
-Îã³°¤òȯÀ¸¤µ¤»¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
+Raises an exception of class exception. The fmt is the format string
+just like printf().
void rb_fatal(char *fmt, ...)
-Ã×̿ŪÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥Ä̾ï¤ÎÎã³°½èÍý¤Ï¹Ô¤Ê¤ï¤ì¤º, ¥¤¥ó¥¿¡¼
-¥×¥ê¥¿¤¬½ªÎ»¤¹¤ë(¤¿¤À¤·ensure¤Ç»ØÄꤵ¤ì¤¿¥³¡¼¥É¤Ï½ªÎ»Á°¤Ë¼Â
-¹Ô¤µ¤ì¤ë)¡¥
+Raises fatal error, terminates the interpreter. No exception handling
+will be done for fatal error, but ensure blocks will be executed.
void rb_bug(char *fmt, ...)
-¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ê¤É¥×¥í¥°¥é¥à¤Î¥Ð¥°¤Ç¤·¤«È¯À¸¤¹¤ë¤Ï¤º¤Î¤Ê¤¤¾õ
-¶·¤Î»þ¸Æ¤Ö¡¥¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ï¥³¥¢¥À¥ó¥×¤·Ä¾¤Á¤Ë½ªÎ»¤¹¤ë¡¥Îã³°
-½èÍý¤Ï°ìÀڹԤʤï¤ì¤Ê¤¤¡¥
+Termintates 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
@@ -999,8 +956,7 @@ Specifies the name of the script ($0).
Appendix B. Functions Available in extconf.rb
-extconf.rb¤ÎÃæ¤Ç¤ÏÍøÍѲÄǽ¤Ê¥³¥ó¥Ñ¥¤¥ë¾ò·ï¥Á¥§¥Ã¥¯¤Î´Ø¿ô¤Ï°Ê
-²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥
+These functions are available in extconf.rb:
have_library(lib, func)
@@ -1024,6 +980,6 @@ this method, the compilation will not be done.
/*
* Local variables:
- * fill-column: 60
+ * fill-column: 70
* end:
*/
diff --git a/README.EXT.jp b/README.EXT.jp
new file mode 100644
index 0000000000..da3902b8cc
--- /dev/null
+++ b/README.EXT.jp
@@ -0,0 +1,1168 @@
+.\" README.EXT - -*- Text -*- created at: Mon Aug 7 16:45:54 JST 1995
+
+Ruby¤Î³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Îºî¤êÊý¤òÀâÌÀ¤·¤Þ¤¹¡¥
+
+1¡¥´ðÁÃÃμ±
+
+C¤ÎÊÑ¿ô¤Ë¤Ï·¿¤¬¤¢¤ê¡¤¥Ç¡¼¥¿¤Ë¤Ï·¿¤¬¤¢¤ê¤Þ¤»¤ó¡¥¤Ç¤¹¤«¤é¡¤¤¿
+¤È¤¨¤Ð¥Ý¥¤¥ó¥¿¤òint¤ÎÊÑ¿ô¤ËÂåÆþ¤¹¤ë¤È¡¤¤½¤ÎÃͤÏÀ°¿ô¤È¤·¤Æ¼è
+¤ê°·¤ï¤ì¤Þ¤¹¡¥µÕ¤ËRuby¤ÎÊÑ¿ô¤Ë¤Ï·¿¤¬¤Ê¤¯¡¤¥Ç¡¼¥¿¤Ë·¿¤¬¤¢¤ê¤Þ
+¤¹¡¥¤³¤Î°ã¤¤¤Î¤¿¤á¡¤C¤ÈRuby¤ÏÁê¸ß¤ËÊÑ´¹¤·¤Ê¤±¤ì¤Ð¡¤¤ª¸ß¤¤¤Î
+¥Ç¡¼¥¿¤ò¥¢¥¯¥»¥¹¤Ç¤­¤Þ¤»¤ó¡¥
+
+Ruby¤Î¥Ç¡¼¥¿¤ÏVALUE¤È¤¤¤¦C¤Î·¿¤Çɽ¸½¤µ¤ì¤Þ¤¹¡¥VALUE·¿¤Î¥Ç¡¼
+¥¿¤Ï¤½¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤ò¼«Ê¬¤ÇÃΤäƤ¤¤Þ¤¹¡¥¤³¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤È
+¤¤¤¦¤Î¤Ï¥Ç¡¼¥¿(¥ª¥Ö¥¸¥§¥¯¥È)¤Î¼ÂºÝ¤Î¹½Â¤¤ò°ÕÌ£¤·¤Æ¤¤¤Æ¡¤Ruby
+¤Î¥¯¥é¥¹¤È¤Ï¤Þ¤¿°ã¤Ã¤¿¤â¤Î¤Ç¤¹¡¥
+
+VALUE¤«¤éC¤Ë¤È¤Ã¤Æ°ÕÌ£¤Î¤¢¤ë¥Ç¡¼¥¿¤ò¼è¤ê½Ð¤¹¤¿¤á¤Ë¤Ï
+
+ (1) VALUE¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤òÃΤë
+ (2) VALUE¤òC¤Î¥Ç¡¼¥¿¤ËÊÑ´¹¤¹¤ë
+
+¤ÎξÊý¤¬É¬ÍפǤ¹¡¥(1)¤ò˺¤ì¤ë¤È´Ö°ã¤Ã¤¿¥Ç¡¼¥¿¤ÎÊÑ´¹¤¬¹Ô¤ï¤ì
+¤Æ¡¤ºÇ°­¥×¥í¥°¥é¥à¤¬core dump¤·¤Þ¤¹¡¥
+
+1.1 ¥Ç¡¼¥¿¥¿¥¤¥×
+
+Ruby¤Ë¤Ï¥æ¡¼¥¶¤¬»È¤¦²ÄǽÀ­¤Î¤¢¤ë°Ê²¼¤Î¥¿¥¤¥×¤¬¤¢¤ê¤Þ¤¹¡¥
+
+ T_NIL nil
+ T_OBJECT Ä̾ï¤Î¥ª¥Ö¥¸¥§¥¯¥È
+ T_CLASS ¥¯¥é¥¹
+ T_MODULE ¥â¥¸¥å¡¼¥ë
+ T_FLOAT ÉâÆ°¾®¿ôÅÀ¿ô
+ T_STRING ʸ»úÎó
+ T_REGEXP Àµµ¬É½¸½
+ T_ARRAY ÇÛÎó
+ T_FIXNUM Fixnum(31bitĹÀ°¿ô)
+ T_HASH Ï¢ÁÛÇÛÎó
+ T_STRUCT (Ruby¤Î)¹½Â¤ÂÎ
+ T_BIGNUM ¿ÇÜĹÀ°¿ô
+ T_FILE Æþ½ÐÎÏ
+ T_TRUE ¿¿
+ T_FALSE µ¶
+ T_DATA ¥Ç¡¼¥¿
+
+¤½¤Î¾¤ËÆâÉô¤ÇÍøÍѤµ¤ì¤Æ¤¤¤ë°Ê²¼¤Î¥¿¥¤¥×¤¬¤¢¤ê¤Þ¤¹¡¥
+
+ T_ICLASS
+ T_MATCH
+ T_VARMAP
+ T_SCOPE
+ T_NODE
+
+¤Û¤È¤ó¤É¤Î¥¿¥¤¥×¤ÏC¤Î¹½Â¤ÂΤǼÂÁõ¤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+
+1.2 VALUE¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤ò¥Á¥§¥Ã¥¯¤¹¤ë
+
+ruby.h¤Ç¤ÏTYPE()¤È¤¤¤¦¥Þ¥¯¥í¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Æ¡¤VALUE¤Î¥Ç¡¼¥¿
+¥¿¥¤¥×¤òÃΤ뤳¤È¤¬½ÐÍè¤Þ¤¹¡¥TYPE()¥Þ¥¯¥í¤Ï¾å¤Ç¾Ò²ð¤·¤¿T_XXXX
+¤Î·Á¼°¤ÎÄê¿ô¤òÊÖ¤·¤Þ¤¹¡¥VALUE¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤Ë±þ¤¸¤Æ½èÍý¤¹¤ë
+¾ì¹ç¤Ë¤Ï¡¤TYPE()¤ÎÃͤÇʬ´ô¤¹¤ë¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
+
+ switch (TYPE(obj)) {
+ case T_FIXNUM:
+ /* FIXNUM¤Î½èÍý */
+ break;
+ case T_STRING:
+ /* ʸ»úÎó¤Î½èÍý */
+ break;
+ case T_ARRAY:
+ /* ÇÛÎó¤Î½èÍý */
+ break;
+ default:
+ /* Îã³°¤òȯÀ¸¤µ¤»¤ë */
+ TypeError("not valid value");
+ break;
+ }
+
+¤½¤ì¤È¥Ç¡¼¥¿¥¿¥¤¥×¤ò¥Á¥§¥Ã¥¯¤·¤Æ¡¤Àµ¤·¤¯¤Ê¤±¤ì¤ÐÎã³°¤òȯÀ¸¤¹
+¤ë´Ø¿ô¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+
+ void Check_Type(VALUE value, int type)
+
+¤³¤Î´Ø¿ô¤Ïvalue¤¬type¤Ç̵¤±¤ì¤Ð¡¤Îã³°¤òȯÀ¸¤µ¤»¤Þ¤¹¡¥°ú¿ô¤È
+¤·¤ÆÍ¿¤¨¤é¤ì¤¿VALUE¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤¬Àµ¤·¤¤¤«¤É¤¦¤«¥Á¥§¥Ã¥¯¤¹
+¤ë¤¿¤á¤Ë¤Ï¡¤¤³¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+
+FIXNUM¤ÈNIL¤Ë´Ø¤·¤Æ¤Ï¤è¤ê¹â®¤ÊȽÊÌ¥Þ¥¯¥í¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+
+ FIXNUM_P(obj)
+ NIL_P(obj)
+
+1.3 VALUE¤òC¤Î¥Ç¡¼¥¿¤ËÊÑ´¹¤¹¤ë
+
+¥Ç¡¼¥¿¥¿¥¤¥×¤¬T_NIL, T_FALSE, T_TRUE¤Ç¤¢¤ë»þ¡¤¥Ç¡¼¥¿¤Ï¤½¤ì¤¾
+¤ìnil, false, true¤Ç¤¹¡¥¤³¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Ï¤Ò¤È
+¤Ä¤º¤Ä¤·¤«Â¸ºß¤·¤Þ¤»¤ó¡¥
+
+¥Ç¡¼¥¿¥¿¥¤¥×¤¬T_FIXNUM¤Î»þ¡¤¤³¤ì¤Ï31bit¤Î¥µ¥¤¥º¤ò»ý¤ÄÀ°¿ô¤Ç
+¤¹¡¥FIXNUM¤òC¤ÎÀ°¿ô¤ËÊÑ´¹¤¹¤ë¤¿¤á¤Ë¤Ï¥Þ¥¯¥í¡ÖFIX2INT()¡×¤ò»È
+¤¤¤Þ¤¹¡¥¤½¤ì¤«¤é¡¤FIXNUM¤Ë¸Â¤é¤ºRuby¤Î¥Ç¡¼¥¿¤òÀ°¿ô¤ËÊÑ´¹¤¹¤ë
+¡ÖNUM2INT()¡×¤È¤¤¤¦¥Þ¥¯¥í¤¬¤¢¤ê¤Þ¤¹¡¥¤³¤Î¥Þ¥¯¥í¤Ï¥Ç¡¼¥¿¥¿¥¤
+¥×¤Î¥Á¥§¥Ã¥¯Ìµ¤·¤Ç»È¤¨¤Þ¤¹(À°¿ô¤ËÊÑ´¹¤Ç¤­¤Ê¤¤¾ì¹ç¤Ë¤ÏÎã³°¤¬
+ȯÀ¸¤¹¤ë)¡¥
+
+ƱÍͤ˥Á¥§¥Ã¥¯Ìµ¤·¤Ç»È¤¨¤ëÊÑ´¹¥Þ¥¯¥í¤Ïdouble¤ò¼è¤ê½Ð¤¹
+¡ÖNUM2DBL()¡×¤Èchar*¤ò¼è¤ê½Ð¤¹¡ÖSTR2CSTR()¡×¤¬¤¢¤ê¤Þ¤¹¡¥
+
+¤½¤ì°Ê³°¤Î¥Ç¡¼¥¿¥¿¥¤¥×¤ÏÂбþ¤¹¤ëC¤Î¹½Â¤ÂΤ¬¤¢¤ê¤Þ¤¹¡¥Âбþ¤¹
+¤ë¹½Â¤ÂΤΤ¢¤ëVALUE¤Ï¤½¤Î¤Þ¤Þ¥­¥ã¥¹¥È(·¿ÊÑ´¹)¤¹¤ì¤Ð¹½Â¤ÂΤÎ
+¥Ý¥¤¥ó¥¿¤ËÊÑ´¹¤Ç¤­¤Þ¤¹¡¥
+
+¹½Â¤ÂΤϡÖstruct RXxxxx¡×¤È¤¤¤¦Ì¾Á°¤Çruby.h¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤Þ
+¤¹¡¥Î㤨¤Ðʸ»úÎó¤Ï¡Östruct RString¡×¤Ç¤¹¡¥¼ÂºÝ¤Ë»È¤¦²ÄǽÀ­¤¬
+¤¢¤ë¤Î¤Ïʸ»úÎó¤ÈÇÛÎ󤯤餤¤À¤È»×¤¤¤Þ¤¹¡¥
+
+ruby.h¤Ç¤Ï¹½Â¤ÂΤإ­¥ã¥¹¥È¤¹¤ë¥Þ¥¯¥í¤â¡ÖRXXXXX()¡×(Á´ÉôÂçʸ
+»ú¤Ë¤·¤¿¤â¤Î)¤È¤¤¤¦Ì¾Á°¤ÇÄ󶡤µ¤ì¤Æ¤¤¤Þ¤¹(Îã: RSTRING())¡¥
+
+Î㤨¤Ð¡¤Ê¸»úÎóstr¤ÎŤµ¤òÆÀ¤ë¤¿¤á¤Ë¤Ï¡ÖRSTRING(str)->len¡×¤È
+¤·¡¤Ê¸»úÎóstr¤òchar*¤È¤·¤ÆÆÀ¤ë¤¿¤á¤Ë¤Ï¡ÖRSTRING(str)->ptr¡×
+¤È¤·¤Þ¤¹¡¥ÇÛÎó¤Î¾ì¹ç¤Ë¤Ï¡¤¤½¤ì¤¾¤ì¡ÖRARRAY(ary)->len¡×¡¤
+¡ÖRARRAY(ary)->ptr¡×¤È¤Ê¤ê¤Þ¤¹¡¥
+
+Ruby¤Î¹½Â¤ÂΤòľÀÜ¥¢¥¯¥»¥¹¤¹¤ë»þ¤Ëµ¤¤ò¤Ä¤±¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¤³
+¤È¤Ï¡¤ÇÛÎó¤äʸ»úÎó¤Î¹½Â¤ÂΤÎÃæ¿È¤Ï»²¾È¤¹¤ë¤À¤±¤Ç¡¤Ä¾ÀÜÊѹ¹¤·
+¤Ê¤¤¤³¤È¤Ç¤¹¡¥Ä¾ÀÜÊѹ¹¤·¤¿¾ì¹ç¡¤¥ª¥Ö¥¸¥§¥¯¥È¤ÎÆâÍƤÎÀ°¹çÀ­¤¬
+¤È¤ì¤Ê¤¯¤Ê¤Ã¤Æ¡¤»×¤ï¤Ì¥Ð¥°¤Î¸¶°ø¤Ë¤Ê¤ê¤Þ¤¹¡¥
+
+1.4 C¤Î¥Ç¡¼¥¿¤òVALUE¤ËÊÑ´¹¤¹¤ë
+
+VALUE¤Î¼ÂºÝ¤Î¹½Â¤¤Ï
+
+ * FIXNUM¤Î¾ì¹ç
+
+ 1bitº¸¥·¥Õ¥È¤·¤Æ¡¤LSB¤òΩ¤Æ¤ë¡¥
+
+ * ¤½¤Î¾¤Î¥Ý¥¤¥ó¥¿¤Î¾ì¹ç
+
+ ¤½¤Î¤Þ¤ÞVALUE¤Ë¥­¥ã¥¹¥È¤¹¤ë¡¥
+
+¤È¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥¤è¤Ã¤Æ¡¤LSB¤ò¥Á¥§¥Ã¥¯¤¹¤ì¤ÐVALUE¤¬FIXNUM¤«¤É
+¤¦¤«¤ï¤«¤ë¤ï¤±¤Ç¤¹(¥Ý¥¤¥ó¥¿¤ÎLSB¤¬Î©¤Ã¤Æ¤¤¤Ê¤¤¤³¤È¤ò²¾Äꤷ¤Æ
+¤¤¤ë)¡¥
+
+¤Ç¤¹¤«¤é¡¤FIXNUM°Ê³°¤ÎRuby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤Î¹½Â¤ÂΤÏñ¤ËVALUE
+¤Ë¥­¥ã¥¹¥È¤¹¤ë¤À¤±¤ÇVALUE¤ËÊÑ´¹½ÐÍè¤Þ¤¹¡¥¤¿¤À¤·¡¤Ç¤°Õ¤Î¹½Â¤
+ÂΤ¬VALUE¤Ë¥­¥ã¥¹¥È½ÐÍè¤ë¤ï¤±¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó¡¥¥­¥ã¥¹¥È¤¹¤ë¤Î
+¤ÏRuby¤ÎÃΤäƤ¤¤ë¹½Â¤ÂÎ(ruby.h¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ëstruct RXxxx
+¤Î¤â¤Î)¤À¤±¤Ç¤¹¡¥
+
+FIXNUM¤Ë´Ø¤·¤Æ¤ÏÊÑ´¹¥Þ¥¯¥í¤ò·Ðͳ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥C¤ÎÀ°¿ô
+¤«¤éVALUE¤ËÊÑ´¹¤¹¤ë¥Þ¥¯¥í¤Ï°Ê²¼¤Î¤â¤Î¤¬¤¢¤ê¤Þ¤¹¡¥É¬Íפ˱þ¤¸
+¤Æ»È¤¤Ê¬¤±¤Æ¤¯¤À¤µ¤¤¡¥
+
+ INT2FIX() ¤â¤È¤ÎÀ°¿ô¤¬31bit°ÊÆâ¤Ë¼ý¤Þ¤ë¼«¿®¤¬¤¢¤ë»þ
+ INT2NUM() Ǥ°Õ¤ÎÀ°¿ô¤«¤éVALUE¤Ø
+
+INT2NUM()¤ÏÀ°¿ô¤¬FIXNUM¤ÎÈϰϤ˼ý¤Þ¤é¤Ê¤¤¾ì¹ç¡¤Bignum¤ËÊÑ´¹
+¤·¤Æ¤¯¤ì¤Þ¤¹(¤¬¡¤¾¯¤·ÃÙ¤¤)¡¥
+
+1.5 Ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë
+
+ÀèÄø¤â½Ò¤Ù¤¿Ä̤ꡤRuby¤Î¹½Â¤ÂΤò¥¢¥¯¥»¥¹¤¹¤ë»þ¤ËÆâÍƤι¹¿·¤ò
+¹Ô¤¦¤³¤È¤Ï´«¤á¤é¤ì¤Þ¤»¤ó¡¥¤Ç¡¤Ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë»þ¤Ë¤Ï
+Ruby¤¬ÍÑ°Õ¤·¤Æ¤¤¤ë´Ø¿ô¤òÍѤ¤¤Æ¤¯¤À¤µ¤¤¡¥
+
+¤³¤³¤Ç¤Ï¤â¤Ã¤È¤â»È¤ï¤ì¤ë¤Ç¤¢¤í¤¦Ê¸»úÎó¤ÈÇÛÎó¤ÎÀ¸À®/Áàºî¤ò¹Ô
+¤¤´Ø¿ô¤ò¤¢¤²¤Þ¤¹(Á´Éô¤Ç¤Ï¤Ê¤¤¤Ç¤¹)¡¥
+
+ ʸ»úÎó¤ËÂФ¹¤ë´Ø¿ô
+
+ rb_str_new(char *ptr, int len)
+
+ ¿·¤·¤¤Ruby¤Îʸ»úÎó¤òÀ¸À®¤¹¤ë¡¥
+
+ rb_str_new2(char *ptr)
+
+ C¤Îʸ»úÎ󤫤éRuby¤Îʸ»úÎó¤òÀ¸À®¤¹¤ë¡¥¤³¤Î´Ø¿ô¤Îµ¡Ç½¤Ï
+ rb_str_new(ptr, strlen(ptr))¤ÈƱÅù¤Ç¤¢¤ë¡¥
+
+ rb_str_cat(VALUE str, char *ptr, int len)
+
+ Ruby¤Îʸ»úÎóstr¤Ëlen¥Ð¥¤¥È¤Îʸ»úÎóptr¤òÄɲ乤롥
+
+ ÇÛÎó¤ËÂФ¹¤ë´Ø¿ô
+
+ rb_ary_new()
+
+ Í×ÁǤ¬0¤ÎÇÛÎó¤òÀ¸À®¤¹¤ë¡¥
+
+ rb_ary_new2(int len)
+
+ Í×ÁǤ¬0¤ÎÇÛÎó¤òÀ¸À®¤¹¤ë¡¥lenÍ×ÁÇʬ¤ÎÎΰè¤ò¤¢¤é¤«¤¸¤á³ä¤ê
+ Åö¤Æ¤Æ¤ª¤¯¡¥
+
+ rb_ary_new3(int n, ...)
+
+ °ú¿ô¤Ç»ØÄꤷ¤¿nÍ×ÁǤò´Þ¤àÇÛÎó¤òÀ¸À®¤¹¤ë¡¥
+
+ rb_ary_new4(int n, VALUE *elts)
+
+ ÇÛÎó¤ÇÍ¿¤¨¤¿nÍ×ÁǤÎÇÛÎó¤òÀ¸À®¤¹¤ë¡¥
+
+ rb_ary_push(VALUE ary, VALUE val)
+ rb_ary_pop(VALUE ary)
+ rb_ary_shift(VALUE ary)
+ rb_ary_unshift(VALUE ary, VALUE val)
+ rb_ary_entry(VALUE ary, int idx)
+
+ Array¤ÎƱ̾¤Î¥á¥½¥Ã¥É¤ÈƱ¤¸Æ¯¤­¤ò¤¹¤ë´Ø¿ô¡¥Âè1°ú¿ô¤Ïɬ¤º
+ ÇÛÎó¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤¡¥
+
+2¡¥Ruby¤Îµ¡Ç½¤ò»È¤¦
+
+¸¶ÍýŪ¤ËRuby¤Ç½ñ¤±¤ë¤³¤È¤ÏC¤Ç¤â½ñ¤±¤Þ¤¹¡¥Ruby¤½¤Î¤â¤Î¤¬C¤Çµ­
+½Ò¤µ¤ì¤Æ¤¤¤ë¤ó¤Ç¤¹¤«¤é¡¤ÅöÁ³¤È¤¤¤¨¤ÐÅöÁ³¤Ê¤ó¤Ç¤¹¤±¤É¡¥¤³¤³¤Ç
+¤ÏRuby¤Î³ÈÄ¥¤Ë»È¤¦¤³¤È¤¬Â¿¤¤¤À¤í¤¦¤Èͽ¬¤µ¤ì¤ëµ¡Ç½¤òÃæ¿´¤Ë¾Ò
+²ð¤·¤Þ¤¹¡¥
+
+2.1 Ruby¤Ëµ¡Ç½¤òÄɲ乤ë
+
+Ruby¤ÇÄ󶡤µ¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤¨¤ÐRuby¥¤¥ó¥¿¥×¥ê¥¿¤Ë¿·¤·¤¤µ¡Ç½
+¤òÄɲ乤뤳¤È¤¬¤Ç¤­¤Þ¤¹¡¥Ruby¤Ç¤Ï°Ê²¼¤Îµ¡Ç½¤òÄɲ乤ë´Ø¿ô¤¬
+Ä󶡤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+
+ * ¥¯¥é¥¹¡¤¥â¥¸¥å¡¼¥ë
+ * ¥á¥½¥Ã¥É¡¤Æðۥ᥽¥Ã¥É¤Ê¤É
+ * Äê¿ô
+
+¤Ç¤Ï½ç¤Ë¾Ò²ð¤·¤Þ¤¹¡¥
+
+2.1.1 ¥¯¥é¥¹/¥â¥¸¥å¡¼¥ëÄêµÁ
+
+¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¤¿¤á¤Ë¤Ï¡¤°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+
+ VALUE rb_define_class(char *name, VALUE super)
+ VALUE rb_define_module(char *name)
+
+¤³¤ì¤é¤Î´Ø¿ô¤Ï¿·¤·¤¯ÄêµÁ¤µ¤ì¤¿¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤òÊÖ¤·¤Þ¤¹¡¥
+¥á¥½¥Ã¥É¤äÄê¿ô¤ÎÄêµÁ¤Ë¤³¤ì¤é¤ÎÃͤ¬É¬ÍפʤΤǡ¤¤Û¤È¤ó¤É¤Î¾ì¹ç
+¤ÏÌá¤êÃͤòÊÑ¿ô¤Ë³ÊǼ¤·¤Æ¤ª¤¯É¬Íפ¬¤¢¤ë¤Ç¤·¤ç¤¦¡¥
+
+¥¯¥é¥¹¤ä¥â¥¸¥å¡¼¥ë¤ò¾¤Î¥¯¥é¥¹¤ÎÆâÉô¤Ë¥Í¥¹¥È¤·¤ÆÄêµÁ¤¹¤ë»þ¤Ë
+¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+
+ VALUE rb_define_class(VALUE outer, char *name, VALUE super)
+ VALUE rb_define_module(VALUE outer, char *name)
+
+2.1.2 ¥á¥½¥Ã¥É/Æðۥ᥽¥Ã¥ÉÄêµÁ
+
+¥á¥½¥Ã¥É¤äÆðۥ᥽¥Ã¥É¤òÄêµÁ¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+
+ void rb_define_method(VALUE class, char *name,
+ VALUE (*func)(), int argc)
+
+ void rb_define_singleton_method(VALUE object, char *name,
+ VALUE (*func)(), int argc)
+
+
+Ç°¤Î¤¿¤áÀâÌÀ¤¹¤ë¤È¡ÖÆðۥ᥽¥Ã¥É¡×¤È¤Ï¡¤¤½¤ÎÆÃÄê¤Î¥ª¥Ö¥¸¥§¥¯
+¥È¤ËÂФ·¤Æ¤À¤±Í­¸ú¤Ê¥á¥½¥Ã¥É¤Ç¤¹¡¥Ruby¤Ç¤Ï¤è¤¯Smalltalk¤Ë¤ª
+¤±¤ë¥¯¥é¥¹¥á¥½¥Ã¥É¤È¤·¤Æ¡¤¥¯¥é¥¹¤ËÂФ¹¤ëÆðۥ᥽¥Ã¥É¤¬»È¤ï¤ì
+¤Þ¤¹¡¥
+
+¤³¤ì¤é¤Î´Ø¿ô¤Î argc¤È¤¤¤¦°ú¿ô¤ÏC¤Î´Ø¿ô¤ØÅϤµ¤ì¤ë°ú¿ô¤Î¿ô(¤È
+·Á¼°)¤ò·è¤á¤Þ¤¹¡¥argc¤¬0°Ê¾å¤Î»þ¤Ï´Ø¿ô¤Ë°ú¤­ÅϤ¹°ú¿ô¤Î¿ô¤ò°Õ
+Ì£¤·¤Þ¤¹¡¥16¸Ä°Ê¾å¤Î°ú¿ô¤Ï»È¤¨¤Þ¤»¤ó(¤¬¡¤Íפê¤Þ¤»¤ó¤è¤Í¡¤¤½
+¤ó¤Ê¤Ë)¡¥¼ÂºÝ¤Î´Ø¿ô¤Ë¤ÏÀèƬ¤Î°ú¿ô¤È¤·¤Æself¤¬Í¿¤¨¤é¤ì¤Þ¤¹¤Î
+¤Ç¡¤»ØÄꤷ¤¿¿ô¤è¤ê1¿¤¤°ú¿ô¤ò»ý¤Ä¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
+
+argc¤¬Éé¤Î»þ¤Ï°ú¿ô¤Î¿ô¤Ç¤Ï¤Ê¤¯¡¤·Á¼°¤ò»ØÄꤷ¤¿¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
+argc¤¬-1¤Î»þ¤Ï°ú¿ô¤òÇÛÎó¤ËÆþ¤ì¤ÆÅϤµ¤ì¤Þ¤¹¡¥argc¤¬-2¤Î»þ¤Ï°ú
+¿ô¤ÏRuby¤ÎÇÛÎó¤È¤·¤ÆÅϤµ¤ì¤Þ¤¹¡¥
+
+¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ï¤â¤¦Æó¤Ä¤¢¤ê¤Þ¤¹¡¥¤Ò¤È¤Ä¤Ïprivate¥á
+¥½¥Ã¥É¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ç¡¤°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¤Ç¤¹¡¥
+
+ void rb_define_private_method(VALUE class, char *name,
+ VALUE (*func)(), int argc)
+
+private¥á¥½¥Ã¥É¤È¤Ï´Ø¿ô·Á¼°¤Ç¤·¤«¸Æ¤Ó½Ð¤¹¤³¤È¤Î½ÐÍè¤Ê¤¤¥á¥½¥Ã
+¥É¤Ç¤¹¡¥
+
+¤â¤¦¤Ò¤È¤Ä¤Ï¥â¥¸¥å¡¼¥ë´Ø¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¤Ç¤¹¡¥¥â¥¸¥å¡¼¥ë´Ø¿ô
+¤È¤Ï¥â¥¸¥å¡¼¥ë¤ÎÆðۥ᥽¥Ã¥É¤Ç¤¢¤ê¡¤Æ±»þ¤Ëprivate¥á¥½¥Ã¥É¤Ç
+¤â¤¢¤ë¤â¤Î¤Ç¤¹¡¥Îã¤ò¤¢¤²¤ë¤ÈMath¥â¥¸¥å¡¼¥ë¤Îsqrt()¤Ê¤É¤¬¤¢¤²
+¤é¤ì¤Þ¤¹¡¥¤³¤Î¥á¥½¥Ã¥É¤Ï
+
+ Math.sqrt(4)
+
+¤È¤¤¤¦·Á¼°¤Ç¤â
+
+ include Math
+ sqrt(4)
+
+¤È¤¤¤¦·Á¼°¤Ç¤â»È¤¨¤Þ¤¹¡¥¥â¥¸¥å¡¼¥ë´Ø¿ô¤òÄêµÁ¤¹¤ë´Ø¿ô¤Ï°Ê²¼¤Î
+Ä̤ê¤Ç¤¹¡¥
+
+ void rb_define_module_function(VALUE module, char *name,
+ VALUE (*func)(), int argc)
+
+´Ø¿ôŪ¥á¥½¥Ã¥É(Kernel¥â¥¸¥å¡¼¥ë¤Îprivate method)¤òÄêµÁ¤¹¤ë¤¿
+¤á¤Î´Ø¿ô¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¹¡¥
+
+ void rb_define_global_function(char *name, VALUE (*func)(), int argc)
+
+
+2.1.3 Äê¿ôÄêµÁ
+
+³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤¬É¬ÍפÊÄê¿ô¤Ï¤¢¤é¤«¤¸¤áÄêµÁ¤·¤Æ¤ª¤¤¤¿Êý¤¬Îɤ¤
+¤Ç¤·¤ç¤¦¡¥Äê¿ô¤òÄêµÁ¤¹¤ë´Ø¿ô¤ÏÆó¤Ä¤¢¤ê¤Þ¤¹¡¥
+
+ void rb_define_const(VALUE class, char *name, VALUE val)
+ void rb_define_global_const(char *name, VALUE val)
+
+Á°¼Ô¤ÏÆÃÄê¤Î¥¯¥é¥¹/¥â¥¸¥å¡¼¥ë¤Ë°¤¹¤ëÄê¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¡¤¸å
+¼Ô¤Ï¥°¥í¡¼¥Ð¥ë¤ÊÄê¿ô¤òÄêµÁ¤¹¤ë¤â¤Î¤Ç¤¹¡¥
+
+2.2 Ruby¤Îµ¡Ç½¤òC¤«¤é¸Æ¤Ó½Ð¤¹
+
+´û¤Ë¡Ø1.5 Ruby¤Î¥Ç¡¼¥¿¤òÁàºî¤¹¤ë¡Ù¤Ç°ìÉô¾Ò²ð¤·¤¿¤è¤¦¤Ê´Ø¿ô¤ò
+»È¤¨¤Ð¡¤Ruby¤Îµ¡Ç½¤ò¼Â¸½¤·¤Æ¤¤¤ë´Ø¿ô¤òľÀܸƤӽФ¹¤³¤È¤¬½ÐÍè
+¤Þ¤¹¡¥
+
+# ¤³¤Î¤è¤¦¤Ê´Ø¿ô¤Î°ìÍ÷ɽ¤Ï¤¤¤Þ¤Î¤È¤³¤í¤¢¤ê¤Þ¤»¤ó¡¥¥½¡¼¥¹¤ò¸«
+# ¤ë¤·¤«¤Ê¤¤¤Ç¤¹¤Í¡¥
+
+¤½¤ì°Ê³°¤Ë¤âRuby¤Îµ¡Ç½¤ò¸Æ¤Ó½Ð¤¹ÊýË¡¤Ï¤¤¤¯¤Ä¤«¤¢¤ê¤Þ¤¹¡¥
+
+2.2.1 Ruby¤Î¥×¥í¥°¥é¥à¤òeval¤¹¤ë
+
+C¤«¤éRuby¤Îµ¡Ç½¤ò¸Æ¤Ó½Ð¤¹¤â¤Ã¤È¤â´Êñ¤ÊÊýË¡¤È¤·¤Æ¡¤Ê¸»úÎó¤Ç
+Í¿¤¨¤é¤ì¤¿Ruby¤Î¥×¥í¥°¥é¥à¤òɾ²Á¤¹¤ë°Ê²¼¤Î´Ø¿ô¤¬¤¢¤ê¤Þ¤¹¡¥
+
+ VALUE rb_eval_string(char *str)
+
+¤³¤Îɾ²Á¤Ï¸½ºß¤Î´Ä¶­¤Ç¹Ô¤ï¤ì¤Þ¤¹¡¥¤Ä¤Þ¤ê¡¤¸½ºß¤Î¥í¡¼¥«¥ëÊÑ¿ô
+¤Ê¤É¤ò¼õ¤±·Ñ¤®¤Þ¤¹¡¥
+
+2.2.2 ID¤Þ¤¿¤Ï¥·¥ó¥Ü¥ë
+
+C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤ËRuby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤³¤È¤â¤Ç¤­¤Þ
+¤¹¡¥¤½¤ÎÁ°¤Ë¡¤Ruby¥¤¥ó¥¿¥×¥ê¥¿Æâ¤Ç¥á¥½¥Ã¥É¤äÊÑ¿ô̾¤ò»ØÄꤹ¤ë
+»þ¤Ë»È¤ï¤ì¤Æ¤¤¤ëID¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Æ¤ª¤­¤Þ¤·¤ç¤¦¡¥
+
+ID¤È¤ÏÊÑ¿ô̾¡¤¥á¥½¥Ã¥É̾¤òɽ¤¹À°¿ô¤Ç¤¹¡¥Ruby¤ÎÃæ¤Ç¤Ï
+
+ :¼±ÊÌ»Ò
+
+¤Ç¥¢¥¯¥»¥¹¤Ç¤­¤Þ¤¹¡¥C¤«¤é¤³¤ÎÀ°¿ô¤òÆÀ¤ë¤¿¤á¤Ë¤Ï´Ø¿ô
+
+ rb_intern(char *name)
+
+¤ò»È¤¤¤Þ¤¹¡¥¤Þ¤¿°ìʸ»ú¤Î±é»»»Ò¤Ï¤½¤Îʸ»ú¥³¡¼¥É¤¬¤½¤Î¤Þ¤Þ¥·¥ó
+¥Ü¥ë¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥Ruby¤«¤é°ú¿ô¤È¤·¤ÆÍ¿¤¨¤é¤ì¤¿¥·¥ó¥Ü¥ë(¤Þ
+¤¿¤Ïʸ»úÎó)¤òID¤ËÊÑ´¹¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+
+ rb_to_id(VALUE symbol)
+
+2.2.3 C¤«¤éRuby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹
+
+C¤«¤éʸ»úÎó¤ò·Ðͳ¤»¤º¤ËRuby¤Î¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð¤¹¤¿¤á¤Ë¤Ï°Ê²¼
+¤Î´Ø¿ô¤ò»È¤¤¤Þ¤¹¡¥
+
+ VALUE rb_funcall(VALUE recv, ID mid, int argc, ...)
+
+¤³¤Î´Ø¿ô¤Ï¥ª¥Ö¥¸¥§¥¯¥Èrecv¤Îmid¤Ç»ØÄꤵ¤ì¤ë¥á¥½¥Ã¥É¤ò¸Æ¤Ó½Ð
+¤·¤Þ¤¹¡¥¤½¤Î¾¤Ë°ú¿ô¤Î»ØÄê¤Î»ÅÊý¤¬°ã¤¦°Ê²¼¤Î´Ø¿ô¤â¤¢¤ê¤Þ¤¹¡¥
+
+ VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)
+ VALUE rb_apply(VALUE recv, ID mid, VALUE args)
+
+apply¤Ë¤Ï°ú¿ô¤È¤·¤ÆRuby¤ÎÇÛÎó¤òÍ¿¤¨¤Þ¤¹¡¥
+
+2.2.4 ÊÑ¿ô/Äê¿ô¤ò»²¾È/¹¹¿·¤¹¤ë
+
+C¤«¤é´Ø¿ô¤ò»È¤Ã¤Æ»²¾È¡¦¹¹¿·¤Ç¤­¤ë¤Î¤Ï¡¤Äê¿ô¡¤¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ
+¿ô¤Ç¤¹¡¥Âç°èÊÑ¿ô¤Ï°ìÉô¤Î¤â¤Î¤ÏC¤ÎÂç°èÊÑ¿ô¤È¤·¤Æ¥¢¥¯¥»¥¹¤Ç¤­
+¤Þ¤¹¡¥¥í¡¼¥«¥ëÊÑ¿ô¤ò»²¾È¤¹¤ëÊýË¡¤Ï¸ø³«¤·¤Æ¤¤¤Þ¤»¤ó¡¥
+
+¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ò»²¾È¡¦¹¹¿·¤¹¤ë´Ø¿ô¤Ï°Ê²¼¤ÎÄÌ
+¤ê¤Ç¤¹¡¥
+
+ VALUE rb_ivar_get(VALUE obj, ID id)
+ VALUE rb_ivar_set(VALUE obj, ID id, VALUE val)
+
+id¤Ïrb_intern()¤ÇÆÀ¤é¤ì¤ë¤â¤Î¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
+
+Äê¿ô¤ò»²¾È¤¹¤ë¤Ë¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
+
+ VALUE rb_const_get(VALUE obj, ID id)
+
+Äê¿ô¤ò¿·¤·¤¯ÄêµÁ¤¹¤ë¤¿¤á¤Ë¤Ï¡Ø2.1.3 Äê¿ôÄêµÁ¡Ù¤Ç¾Ò²ð¤µ
+¤ì¤Æ¤¤¤ë´Ø¿ô¤ò»È¤Ã¤Æ¤¯¤À¤µ¤¤¡¥
+
+3¡¥Ruby¤ÈC¤È¤Î¾ðÊó¶¦Í­
+
+C¸À¸ì¤ÈRuby¤Î´Ö¤Ç¾ðÊó¤ò¶¦Í­¤¹¤ëÊýË¡¤Ë¤Ä¤¤¤Æ²òÀ⤷¤Þ¤¹¡¥
+
+3.1 C¤«¤é»²¾È¤Ç¤­¤ëRuby¤ÎÄê¿ô
+
+°Ê²¼¤ÎRuby¤ÎÄê¿ô¤ÏC¤Î¥ì¥Ù¥ë¤«¤é»²¾È¤Ç¤­¤Þ¤¹¡¥
+
+ Qtrue
+ Qfalse
+
+ ¿¿µ¶ÃÍ¡¥Qfalse¤ÏC¸À¸ì¤Ç¤âµ¶¤È¤ß¤Ê¤µ¤ì¤Þ¤¹(¤Ä¤Þ¤ê0)¡¥
+
+ Qnil
+
+ C¸À¸ì¤«¤é¸«¤¿¡Önil¡×¡¥
+
+3.2 C¤ÈRuby¤Ç¶¦Í­¤µ¤ì¤ëÂç°èÊÑ¿ô
+
+C¤ÈRuby¤ÇÂç°èÊÑ¿ô¤ò»È¤Ã¤Æ¾ðÊó¤ò¶¦Í­¤Ç¤­¤Þ¤¹¡¥¶¦Í­¤Ç¤­¤ëÂç°è
+ÊÑ¿ô¤Ë¤Ï¤¤¤¯¤Ä¤«¤Î¼ïÎब¤¢¤ê¤Þ¤¹¡¥¤½¤Î¤Ê¤«¤Ç¤â¤Ã¤È¤âÎɤ¯»È¤ï
+¤ì¤ë¤È»×¤ï¤ì¤ë¤Î¤Ïrb_define_variable()¤Ç¤¹¡¥
+
+ void rb_define_variable(char *name, VALUE *var)
+
+¤³¤Î´Ø¿ô¤ÏRuby¤ÈC¤È¤Ç¶¦Í­¤¹¤ëÂç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ¤¹¡¥ÊÑ¿ô̾¤¬
+`$'¤Ç»Ï¤Þ¤é¤Ê¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤Þ¤¹¡¥¤³¤ÎÊÑ¿ô¤ÎÃͤòÊÑ
+¹¹¤¹¤ë¤È¼«Æ°Åª¤ËRuby¤ÎÂбþ¤¹¤ëÊÑ¿ô¤ÎÃͤâÊѤï¤ê¤Þ¤¹¡¥
+
+¤Þ¤¿Ruby¦¤«¤é¤Ï¹¹¿·¤Ç¤­¤Ê¤¤ÊÑ¿ô¤â¤¢¤ê¤Þ¤¹¡¥¤³¤Îread only¤Î
+ÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ÇÄêµÁ¤·¤Þ¤¹¡¥
+
+ void rb_define_readonly_variable(char *name, VALUE *var)
+
+¤³¤ì¤éÊÑ¿ô¤Î¾¤Ëhook¤ò¤Ä¤±¤¿Âç°èÊÑ¿ô¤òÄêµÁ¤Ç¤­¤Þ¤¹¡¥hookÉÕ¤­
+¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤òÍѤ¤¤ÆÄêµÁ¤·¤Þ¤¹¡¥hookÉÕ¤­Âç°èÊÑ¿ô¤Î
+Ãͤλ²¾È¤äÀßÄê¤Ïhook¤Ç¹Ô¤¦É¬Íפ¬¤¢¤ê¤Þ¤¹¡¥
+
+ void rb_define_hooked_variable(char *name, VALUE *var,
+ VALUE (*getter)(), VALUE (*setter)())
+
+¤³¤Î´Ø¿ô¤ÏC¤Î´Ø¿ô¤Ë¤è¤Ã¤Æhook¤Î¤Ä¤±¤é¤ì¤¿Âç°èÊÑ¿ô¤òÄêµÁ¤·¤Þ
+¤¹¡¥ÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï´Ø¿ôgetter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì
+¤¿»þ¤Ë¤Ï´Ø¿ôsetter¤¬¸Æ¤Ð¤ì¤ë¡¥hook¤ò»ØÄꤷ¤Ê¤¤¾ì¹ç¤Ïgetter¤ä
+setter¤Ë0¤ò»ØÄꤷ¤Þ¤¹¡¥
+
+# getter¤âsetter¤â0¤Ê¤é¤Ðrb_define_variable()¤ÈƱ¤¸¤Ë¤Ê¤ë¡¥
+
+¤½¤ì¤«¤é¡¤C¤Î´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ëRuby¤ÎÂç°èÊÑ¿ô¤òÄêµÁ¤¹¤ë
+´Ø¿ô¤¬¤¢¤ê¤Þ¤¹¡¥
+
+ void rb_define_virtual_variable(char *name,
+ VALUE (*getter)(), VALUE (*setter)())
+
+¤³¤Î´Ø¿ô¤Ë¤è¤Ã¤ÆÄêµÁ¤µ¤ì¤¿Ruby¤ÎÂç°èÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ï
+getter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì¤Þ¤¹¡¥
+
+getter¤Èsetter¤Î»ÅÍͤϰʲ¼¤ÎÄ̤ê¤Ç¤¹¡¥
+
+ (*getter)(ID id, void *data, struct global_entry* entry);
+ (*setter)(VALUE val, ID id, void *data, struct global_entry* entry);
+
+3.3 C¤Î¥Ç¡¼¥¿¤òRuby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¤¹¤ë
+
+C¤ÎÀ¤³¦¤ÇÄêµÁ¤µ¤ì¤¿¥Ç¡¼¥¿(¹½Â¤ÂÎ)¤òRuby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ
+¼è¤ê°·¤¤¤¿¤¤¾ì¹ç¤¬¤¢¤ê¤¨¤Þ¤¹¡¥¤³¤Î¤è¤¦¤Ê¾ì¹ç¤Ë¤Ï¡¤Data¤È¤¤¤¦
+Ruby¥ª¥Ö¥¸¥§¥¯¥È¤ËC¤Î¹½Â¤ÂÎ(¤Ø¤Î¥Ý¥¤¥ó¥¿)¤ò¤¯¤ë¤à¤³¤È¤ÇRuby
+¥ª¥Ö¥¸¥§¥¯¥È¤È¤·¤Æ¼è¤ê°·¤¨¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤¹¡¥
+
+Data¥ª¥Ö¥¸¥§¥¯¥È¤òÀ¸À®¤·¤Æ¹½Â¤ÂΤòRuby¥ª¥Ö¥¸¥§¥¯¥È¤Ë¥«¥×¥»¥ë
+²½¤¹¤ë¤¿¤á¤Ë¤Ï¡¤°Ê²¼¤Î¥Þ¥¯¥í¤ò»È¤¤¤Þ¤¹¡¥
+
+ Data_Wrap_Struct(class,mark,free,ptr)
+
+¤³¤Î¥Þ¥¯¥í¤ÎÌá¤êÃͤÏÀ¸À®¤µ¤ì¤¿Data¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¹¡¥
+
+class¤Ï¤³¤ÎData¥ª¥Ö¥¸¥§¥¯¥È¤Î¥¯¥é¥¹¤Ç¤¹¡¥ptr¤Ï¥«¥×¥»¥ë²½¤¹¤ë
+C¤Î¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤Ç¤¹¡¥mark¤Ï¤³¤Î¹½Â¤ÂΤ¬Ruby¤Î¥ª¥Ö¥¸¥§
+¥¯¥È¤Ø¤Î»²¾È¤¬¤¢¤ë»þ¤Ë»È¤¦´Ø¿ô¤Ç¤¹¡¥¤½¤Î¤è¤¦¤Ê»²¾È¤ò´Þ¤Þ¤Ê¤¤
+»þ¤Ë¤Ï0¤ò»ØÄꤷ¤Þ¤¹¡¥
+
+# ¤½¤Î¤è¤¦¤Ê»²¾È¤Ï´«¤á¤é¤ì¤Þ¤»¤ó¡¥
+
+free¤Ï¤³¤Î¹½Â¤ÂΤ¬¤â¤¦ÉÔÍפˤʤä¿»þ¤Ë¸Æ¤Ð¤ì¤ë´Ø¿ô¤Ç¤¹¡¥¤³¤Î
+´Ø¿ô¤¬¥¬¡¼¥Ù¡¼¥¸¥³¥ì¥¯¥¿¤«¤é¸Æ¤Ð¤ì¤Þ¤¹¡¥
+
+C¤Î¹½Â¤ÂΤγäÅö¤ÈData¥ª¥Ö¥¸¥§¥¯¥È¤ÎÀ¸À®¤òƱ»þ¤Ë¹Ô¤¦¥Þ¥¯¥í¤È
+¤·¤Æ°Ê²¼¤Î¤â¤Î¤¬Ä󶡤µ¤ì¤Æ¤¤¤Þ¤¹¡¥
+
+ Data_Make_Struct(class, type, mark, free, sval)
+
+¤³¤Î¥Þ¥¯¥í¤ÎÌá¤êÃͤÏÀ¸À®¤µ¤ì¤¿Data¥ª¥Ö¥¸¥§¥¯¥È¤Ç¤¹¡¥
+
+class, mark, free¤ÏData_Wrap_Struct¤ÈƱ¤¸Æ¯¤­¤ò¤·¤Þ¤¹¡¥type
+¤Ï³ä¤êÅö¤Æ¤ëC¹½Â¤ÂΤη¿¤Ç¤¹¡¥³ä¤êÅö¤Æ¤é¤ì¤¿¹½Â¤ÂΤÏÊÑ¿ôsval
+¤ËÂåÆþ¤µ¤ì¤Þ¤¹¡¥¤³¤ÎÊÑ¿ô¤Î·¿¤Ï (type*) ¤Ç¤¢¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥
+
+Data¥ª¥Ö¥¸¥§¥¯¥È¤«¤é¥Ý¥¤¥ó¥¿¤ò¼è¤ê½Ð¤¹¤Î¤Ï°Ê²¼¤Î¥Þ¥¯¥í¤òÍѤ¤
+¤Þ¤¹¡¥
+
+ Data_Get_Struct(obj, type, sval)
+
+C¤Î¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤ÏÊÑ¿ôsval¤ËÂåÆþ¤µ¤ì¤Þ¤¹¡¥
+
+¤³¤ì¤é¤ÎData¤Î»È¤¤Êý¤Ï¤Á¤ç¤Ã¤Èʬ¤«¤ê¤Ë¤¯¤¤¤Î¤Ç¡¤¸å¤ÇÀâÌÀ¤¹¤ë
+ÎãÂê¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+4¡¥ÎãÂê - dbm¥Ñ¥Ã¥±¡¼¥¸¤òºî¤ë
+
+¤³¤³¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤È¤ê¤¢¤¨¤º³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ïºî¤ì¤ë¤Ï¤º¤Ç¤¹¡¥
+Ruby¤Îext¥Ç¥£¥ì¥¯¥È¥ê¤Ë¤¹¤Ç¤Ë´Þ¤Þ¤ì¤Æ¤¤¤ëdbm¥é¥¤¥Ö¥é¥ê¤òÎã¤Ë
+¤·¤ÆÃʳ¬Åª¤ËÀâÌÀ¤·¤Þ¤¹¡¥
+
+(1) ¥Ç¥£¥ì¥¯¥È¥ê¤òºî¤ë
+
+ % mkdir ext/dbm
+
+Ruby 1.1¤«¤é¤ÏǤ°Õ¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ç¥À¥¤¥Ê¥ß¥Ã¥¯¥é¥¤¥Ö¥é¥ê¤òºî
+¤ë¤³¤È¤¬¤Ç¤­¤ë¤è¤¦¤Ë¤Ê¤ê¤Þ¤·¤¿¡¥Ruby¤ËÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë¾ì¹ç¤Ë
+¤ÏRuby¤òŸ³«¤·¤¿¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¡¤ext¥Ç¥£¥ì¥¯¥È¥ê¤ÎÃæ¤Ë³ÈÄ¥
+¥é¥¤¥Ö¥é¥êÍѤΥǥ£¥ì¥¯¥È¥ê¤òºî¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥Ì¾Á°¤ÏŬÅö¤Ë
+Áª¤ó¤Ç¹½¤¤¤Þ¤»¤ó¡¥
+
+(2) MANIFEST¥Õ¥¡¥¤¥ë¤òºî¤ë
+
+ % cd ext/dbm
+ % touch MANIFEST
+
+³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Î²¼¤Ë¤ÏMANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬
+ɬÍפʤΤǡ¤¤È¤ê¤¢¤¨¤º¶õ¤Î¥Õ¥¡¥¤¥ë¤òºî¤Ã¤Æ¤ª¤­¤Þ¤¹¡¥¸å¤Ç¤³¤Î
+¥Õ¥¡¥¤¥ë¤Ë¤ÏɬÍפʥե¡¥¤¥ë°ìÍ÷¤¬Æþ¤ë¤³¤È¤Ë¤Ê¤ê¤Þ¤¹¡¥
+
+MANIFEST¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤Ï¡¤ÀÅŪ¥ê¥ó¥¯¤Îmake¤Î»þ¤Ë¥Ç¥£¥ì¥¯¥È¥ê
+¤¬³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ò´Þ¤ó¤Ç¤¤¤ë¤«¤É¤¦¤«È½Äꤹ¤ë¤¿¤á¤Ë»È¤ï¤ì¤ì¤Æ
+¤¤¤Þ¤¹¡¥¥À¥¤¥Ê¥ß¥Ã¥¯¥é¥¤¥Ö¥é¥ê¤òºî¤ë¾ì¹ç¤Ë¤Ïɬ¤º¤·¤âɬÍפǤÏ
+¤¢¤ê¤Þ¤»¤ó¡¥
+
+(3) À߷פ¹¤ë
+
+¤Þ¤¢¡¤ÅöÁ³¤Ê¤ó¤Ç¤¹¤±¤É¡¤¤É¤¦¤¤¤¦µ¡Ç½¤ò¼Â¸½¤¹¤ë¤«¤É¤¦¤«¤Þ¤ºÀß
+·×¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥¤É¤ó¤Ê¥¯¥é¥¹¤ò¤Ä¤¯¤ë¤«¡¤¤½¤Î¥¯¥é¥¹¤Ë¤Ï
+¤É¤ó¤Ê¥á¥½¥Ã¥É¤¬¤¢¤ë¤«¡¤¥¯¥é¥¹¤¬Ä󶡤¹¤ëÄê¿ô¤Ê¤É¤Ë¤Ä¤¤¤ÆÀß·×
+¤·¤Þ¤¹¡¥dbm¥¯¥é¥¹¤Ë¤Ä¤¤¤Æ¤Ïext/dbm.doc¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+(4) C¥³¡¼¥É¤ò½ñ¤¯
+
+³ÈÄ¥¥é¥¤¥Ö¥é¥êËÜÂΤȤʤëC¸À¸ì¤Î¥½¡¼¥¹¤ò½ñ¤­¤Þ¤¹¡¥C¸À¸ì¤Î¥½¡¼
+¥¹¤¬¤Ò¤È¤Ä¤Î»þ¤Ë¤Ï¡Ö¥é¥¤¥Ö¥é¥ê̾.c¡×¤òÁª¤Ö¤ÈÎɤ¤¤Ç¤·¤ç¤¦¡¥C
+¸À¸ì¤Î¥½¡¼¥¹¤¬Ê£¿ô¤Î¾ì¹ç¤Ë¤ÏµÕ¤Ë¡Ö¥é¥¤¥Ö¥é¥ê̾.c¡×¤È¤¤¤¦¥Õ¥¡
+¥¤¥ë̾¤ÏÈò¤±¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡¥¥ª¥Ö¥¸¥§¥¯¥È¥Õ¥¡¥¤¥ë¤È¥â¥¸¥å¡¼
+¥ëÀ¸À®»þ¤ËÃæ´ÖŪ¤ËÀ¸À®¤µ¤ì¤ë¡Ö¥é¥¤¥Ö¥é¥ê̾.o¡×¤È¤¤¤¦¥Õ¥¡¥¤¥ë
+¤È¤¬¾×Æͤ¹¤ë¤«¤é¤Ç¤¹¡¥
+
+Ruby¤Ï³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ò¥í¡¼¥É¤¹¤ë»þ¤Ë¡ÖInit_¥é¥¤¥Ö¥é¥ê̾¡×¤È
+¤¤¤¦´Ø¿ô¤ò¼«Æ°Åª¤Ë¼Â¹Ô¤·¤Þ¤¹¡¥dbm¥é¥¤¥Ö¥é¥ê¤Î¾ì¹ç¡ÖInit_dbm¡×
+¤Ç¤¹¡¥¤³¤Î´Ø¿ô¤ÎÃæ¤Ç¥¯¥é¥¹¡¤¥â¥¸¥å¡¼¥ë¡¤¥á¥½¥Ã¥É¡¤Äê¿ô¤Ê¤É¤Î
+ÄêµÁ¤ò¹Ô¤¤¤Þ¤¹¡¥dbm.c¤«¤é°ìÉô°úÍѤ·¤Þ¤¹¡¥
+
+--
+Init_dbm()
+{
+ /* DBM¥¯¥é¥¹¤òÄêµÁ¤¹¤ë */
+ cDBM = rb_define_class("DBM", rb_cObject);
+ /* DBM¤ÏEnumerate¥â¥¸¥å¡¼¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë */
+ rb_include_module(cDBM, rb_mEnumerable);
+
+ /* DBM¥¯¥é¥¹¤Î¥¯¥é¥¹¥á¥½¥Ã¥Éopen(): °ú¿ô¤ÏC¤ÎÇÛÎó¤Ç¼õ¤±¤ë */
+ rb_define_singleton_method(cDBM, "open", fdbm_s_open, -1);
+
+ /* DBM¥¯¥é¥¹¤Î¥á¥½¥Ã¥Éclose(): °ú¿ô¤Ï¤Ê¤· */
+ rb_define_method(cDBM, "close", fdbm_close, 0);
+ /* DBM¥¯¥é¥¹¤Î¥á¥½¥Ã¥É[]: °ú¿ô¤Ï1¸Ä */
+ rb_define_method(cDBM, "[]", fdbm_fetch, 1);
+ :
+
+ /* DBM¥Ç¡¼¥¿¤ò³ÊǼ¤¹¤ë¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô̾¤Î¤¿¤á¤ÎID */
+ id_dbm = rb_intern("dbm");
+}
+--
+
+DBM¥é¥¤¥Ö¥é¥ê¤Ïdbm¤Î¥Ç¡¼¥¿¤ÈÂбþ¤¹¤ë¥ª¥Ö¥¸¥§¥¯¥È¤Ë¤Ê¤ë¤Ï¤º¤Ç
+¤¹¤«¤é¡¤C¤ÎÀ¤³¦¤Îdbm¤òRuby¤ÎÀ¤³¦¤Ë¼è¤ê¹þ¤àɬÍפ¬¤¢¤ê¤Þ¤¹¡¥
+
+
+dbm.c¤Ç¤ÏData_Make_Struct¤ò°Ê²¼¤Î¤è¤¦¤Ë»È¤Ã¤Æ¤¤¤Þ¤¹¡¥
+
+--
+struct dbmdata {
+ int di_size;
+ DBM *di_dbm;
+};
+
+
+obj = Data_Make_Struct(class,struct dbmdata,0,free_dbm,dbmp);
+--
+
+¤³¤³¤Ç¤Ïdbmstruct¹½Â¤ÂΤؤΥݥ¤¥ó¥¿¤òData¤Ë¥«¥×¥»¥ë²½¤·¤Æ¤¤
+¤Þ¤¹¡¥DBM*¤òľÀÜ¥«¥×¥»¥ë²½¤·¤Ê¤¤¤Î¤Ïclose()¤·¤¿»þ¤Î½èÍý¤ò¹Í
+¤¨¤Æ¤Î¤³¤È¤Ç¤¹¡¥
+
+Data¥ª¥Ö¥¸¥§¥¯¥È¤«¤édbmstruct¹½Â¤ÂΤΥݥ¤¥ó¥¿¤ò¼è¤ê½Ð¤¹¤¿¤á
+¤Ë°Ê²¼¤Î¥Þ¥¯¥í¤ò»È¤Ã¤Æ¤¤¤Þ¤¹¡¥
+
+--
+#define GetDBM(obj, dbmp) {\
+ Data_Get_Struct(obj, struct dbmdata, dbmp);\
+ if (dbmp->di_dbm == 0) closed_dbm();\
+}
+--
+
+¤Á¤ç¤Ã¤ÈÊ£»¨¤Ê¥Þ¥¯¥í¤Ç¤¹¤¬¡¤Íפ¹¤ë¤Ëdbmdata¹½Â¤ÂΤΥݥ¤¥ó¥¿
+¤Î¼è¤ê½Ð¤·¤È¡¤close¤µ¤ì¤Æ¤¤¤ë¤«¤É¤¦¤«¤Î¥Á¥§¥Ã¥¯¤ò¤Þ¤È¤á¤Æ¤¤
+¤ë¤À¤±¤Ç¤¹¡¥
+
+DBM¥¯¥é¥¹¤Ë¤Ï¤¿¤¯¤µ¤ó¥á¥½¥Ã¥É¤¬¤¢¤ê¤Þ¤¹¤¬¡¤Ê¬Îह¤ë¤È3¼ïÎà¤Î
+°ú¿ô¤Î¼õ¤±Êý¤¬¤¢¤ê¤Þ¤¹¡¥¤Ò¤È¤Ä¤Ï°ú¿ô¤Î¿ô¤¬¸ÇÄê¤Î¤â¤Î¤Ç¡¤Îã¤È
+¤·¤Æ¤Ïdelete¥á¥½¥Ã¥É¤¬¤¢¤ê¤Þ¤¹¡¥delete¥á¥½¥Ã¥É¤ò¼ÂÁõ¤·¤Æ¤¤¤ë
+fdbm_delete()¤Ï¤³¤Î¤è¤¦¤Ë¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
+
+--
+static VALUE
+fdbm_delete(obj, keystr)
+ VALUE obj, keystr;
+{
+ :
+}
+--
+
+°ú¿ô¤Î¿ô¤¬¸ÇÄê¤Î¥¿¥¤¥×¤ÏÂè1°ú¿ô¤¬self¡¤Âè2°ú¿ô°Ê¹ß¤¬¥á¥½¥Ã¥É
+¤Î°ú¿ô¤È¤Ê¤ê¤Þ¤¹¡¥
+
+°ú¿ô¤Î¿ô¤¬ÉÔÄê¤Î¤â¤Î¤ÏC¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î¤ÈRuby¤ÎÇÛÎó¤Ç¼õ¤±
+¤ë¤â¤Î¤È¤¬¤¢¤ê¤Þ¤¹¡¥dbm¥é¥¤¥Ö¥é¥ê¤ÎÃæ¤Ç¡¤C¤ÎÇÛÎó¤Ç¼õ¤±¤ë¤â¤Î
+¤ÏDBM¤Î¥¯¥é¥¹¥á¥½¥Ã¥É¤Ç¤¢¤ëopen()¤Ç¤¹¡¥¤³¤ì¤ò¼ÂÁõ¤·¤Æ¤¤¤ë´Ø
+¿ôfdbm_s_open()¤Ï¤³¤¦¤Ê¤Ã¤Æ¤¤¤Þ¤¹¡¥
+
+--
+static VALUE
+fdbm_s_open(argc, argv, class)
+ int argc;
+ VALUE *argv;
+ VALUE class;
+{
+ :
+ if (rb_scan_args(argc, argv, "11", &file, &vmode) == 1) {
+ mode = 0666; /* default value */
+ }
+ :
+}
+--
+
+¤³¤Î¥¿¥¤¥×¤Î´Ø¿ô¤ÏÂè1°ú¿ô¤¬Í¿¤¨¤é¤ì¤¿°ú¿ô¤Î¿ô¡¤Âè2°ú¿ô¤¬Í¿¤¨
+¤é¤ì¤¿°ú¿ô¤ÎÆþ¤Ã¤Æ¤¤¤ëÇÛÎó¤Ë¤Ê¤ê¤Þ¤¹¡¥self¤ÏÂè3°ú¿ô¤È¤·¤ÆÍ¿
+¤¨¤é¤ì¤Þ¤¹¡¥
+
+¤³¤ÎÇÛÎó¤ÇÍ¿¤¨¤é¤ì¤¿°ú¿ô¤ò²òÀϤ¹¤ë¤¿¤á¤Î´Ø¿ô¤¬open()¤Ç¤â»È¤ï
+¤ì¤Æ¤¤¤ërb_scan_args()¤Ç¤¹¡¥Âè3°ú¿ô¤Ë»ØÄꤷ¤¿¥Õ¥©¡¼¥Þ¥Ã¥È¤Ë
+½¾¤¤¡¤Âè4ÊÑ¿ô°Ê¹ß¤Ë»ØÄꤷ¤¿ÊÑ¿ô¤ËÃͤòÂåÆþ¤·¤Æ¤¯¤ì¤Þ¤¹¡¥¤³¤Î
+¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï¡¤Âè1ʸ»úÌܤ¬¾Êά¤Ç¤­¤Ê¤¤°ú¿ô¤Î¿ô¡¤Âè2ʸ»úÌܤ¬
+¾Êά¤Ç¤­¤ë°ú¿ô¤Î¿ô¡¤Âè3ʸ»úÌܤ¬Âбþ¤¹¤ëÁê¼ê¤¬Ìµ¤¤¤¢¤Þ¤ê¤Î°ú
+¿ô¤¬¤¢¤ë¤«¤É¤¦¤«¤ò¼¨¤¹"*"¤Ç¤¹¡¥2ʸ»úÌܤÈ3ʸ»úÌܤϾÊά¤Ç¤­¤Þ
+¤¹¡¥dbm.c¤ÎÎã¤Ç¤Ï¡¤¥Õ¥©¡¼¥Þ¥Ã¥È¤Ï"11"¤Ç¤¹¤«¤é¡¤°ú¿ô¤ÏºÇÄã1¤Ä
+¤Ç¡¤2¤Ä¤Þ¤Çµö¤µ¤ì¤ë¤È¤¤¤¦°ÕÌ£¤Ë¤Ê¤ê¤Þ¤¹¡¥¾Êά¤µ¤ì¤Æ¤¤¤ë»þ¤Î
+ÊÑ¿ô¤ÎÃͤÏnil(C¸À¸ì¤Î¥ì¥Ù¥ë¤Ç¤ÏQnil)¤Ë¤Ê¤ê¤Þ¤¹¡¥
+
+Ruby¤ÎÇÛÎó¤Ç°ú¿ô¤ò¼õ¤±¼è¤ë¤â¤Î¤Ïindexes¤¬¤¢¤ê¤Þ¤¹¡¥¼ÂÁõ¤Ï¤³
+¤¦¤Ç¤¹¡¥
+
+--
+static VALUE
+fdbm_indexes(obj, args)
+ VALUE obj, args;
+{
+ :
+}
+--
+
+Âè1°ú¿ô¤Ïself¡¤Âè2°ú¿ô¤ÏRuby¤ÎÇÛÎó¤Ç¤¹¡¥
+
+** Ãí°Õ»ö¹à
+
+Ruby¤È¶¦Í­¤Ï¤·¤Ê¤¤¤¬Ruby¤Î¥ª¥Ö¥¸¥§¥¯¥È¤ò³ÊǼ¤¹¤ë²ÄǽÀ­¤Î¤¢¤ë
+C¤ÎÂç°èÊÑ¿ô¤Ï°Ê²¼¤Î´Ø¿ô¤ò»È¤Ã¤ÆRuby¥¤¥ó¥¿¥×¥ê¥¿¤ËÊÑ¿ô¤Î¸ºß
+¤ò¶µ¤¨¤Æ¤¢¤²¤Æ¤¯¤À¤µ¤¤¡¥¤Ç¤Ê¤¤¤ÈGC¤Ç¥È¥é¥Ö¥ë¤òµ¯¤³¤·¤Þ¤¹¡¥
+
+ void rb_global_variable(VALUE *var)
+
+(5) extconf.rb¤òÍÑ°Õ¤¹¤ë
+
+Makefile¤òºî¤ë¾ì¹ç¤Î¿÷·¿¤Ë¤Ê¤ëextconf.rb¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤òºî¤ê
+¤Þ¤¹¡¥extconf.rb¤Ï¥é¥¤¥Ö¥é¥ê¤Î¥³¥ó¥Ñ¥¤¥ë¤ËɬÍפʾò·ï¤Î¥Á¥§¥Ã
+¥¯¤Ê¤É¤ò¹Ô¤¦¤³¤È¤¬ÌÜŪ¤Ç¤¹¡¥¤Þ¤º¡¤
+
+ require 'mkmf'
+
+¤òextconf.rb¤ÎÀèƬ¤ËÃÖ¤­¤Þ¤¹¡¥extconf.rb¤ÎÃæ¤Ç¤Ï°Ê²¼¤ÎRuby´Ø
+¿ô¤ò»È¤¦¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥
+
+ have_library(lib, func): ¥é¥¤¥Ö¥é¥ê¤Î¸ºß¥Á¥§¥Ã¥¯
+ have_func(func): ´Ø¿ô¤Î¸ºß¥Á¥§¥Ã¥¯
+ have_header(header): ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¥Á¥§¥Ã¥¯
+ create_makefile(target): Makefile¤ÎÀ¸À®
+
+°Ê²¼¤ÎÊÑ¿ô¤ò»È¤¦¤³¤È¤¬¤Ç¤­¤Þ¤¹¡¥
+
+ $CFLAGS: ¥³¥ó¥Ñ¥¤¥ë»þ¤ËÄɲÃŪ¤Ë»ØÄꤹ¤ë¥Õ¥é¥°(-I¤Ê¤É)
+ $LDFLAGS: ¥ê¥ó¥¯»þ¤ËÄɲÃŪ¤Ë»ØÄꤹ¤ë¥Õ¥é¥°(-L¤Ê¤É)
+
+¥é¥¤¥Ö¥é¥ê¤ò¥³¥ó¥Ñ¥¤¥ë¤¹¤ë¾ò·ï¤¬Â·¤ï¤º¡¤¤½¤Î¥é¥¤¥Ö¥é¥ê¤ò¥³¥ó
+¥Ñ¥¤¥ë¤·¤Ê¤¤»þ¤Ë¤Ïcreate_makefile¤ò¸Æ¤Ð¤Ê¤±¤ì¤ÐMakefile¤ÏÀ¸
+À®¤µ¤ì¤º¡¤¥³¥ó¥Ñ¥¤¥ë¤â¹Ô¤ï¤ì¤Þ¤»¤ó¡¥
+
+(6) depend¤òÍÑ°Õ¤¹¤ë
+
+¤â¤·¡¤¥Ç¥£¥ì¥¯¥È¥ê¤Ëdepend¤È¤¤¤¦¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹¤ì¤Ð¡¤
+Makefile¤¬°Í¸´Ø·¸¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤¯¤ì¤Þ¤¹¡¥
+
+ % gcc -MM *.c > depend
+
+¤Ê¤É¤Çºî¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤¢¤Ã¤Æ»¤Ï̵¤¤¤Ç¤·¤ç¤¦¡¥
+
+(7) MANIFEST¥Õ¥¡¥¤¥ë¤Ë¥Õ¥¡¥¤¥ë̾¤òÆþ¤ì¤ë
+
+ % find * -type f -print > MANIFEST
+ % vi MANIFEST
+
+*.o, *~¤Ê¤ÉÉÔɬÍפʥե¡¥¤¥ë°Ê³°¤ÏMANIFEST¤ËÄɲ䷤Ƥª¤­¤Þ¤¹¡¥
+make»þ¤Ë¤ÏMANIFEST¤ÎÆâÍƤϻ²¾È¤·¤Þ¤»¤ó¤Î¤Ç¡¤¶õ¤Î¤Þ¤Þ¤Ç¤âÌäÂê
+¤Ïµ¯¤­¤Þ¤»¤ó¤¬¡¤¥Ñ¥Ã¥±¡¼¥¸¥ó¥°¤Î»þ¤Ë»²¾È¤¹¤ë¤³¤È¤¬¤¢¤ë¤Î¤È¡¤
+ɬÍפʥե¡¥¤¥ë¤ò¶èÊ̤Ǥ­¤ë¤Î¤Ç¡¤ÍÑ°Õ¤·¤Æ¤ª¤¤¤¿Êý¤¬Îɤ¤¤Ç¤·¤ç
+¤¦¡¥
+
+(8) Makefile¤òÀ¸À®¤¹¤ë
+
+Makefile¤ò¼ÂºÝ¤ËÀ¸À®¤¹¤ë¤¿¤á¤Ë¤Ï
+
+ ruby extconf.rb
+
+¤È¤·¤Þ¤¹¡¥extconf.rb¤Ë require 'mkmf' ¤Î¹Ô¤¬¤Ê¤¤¾ì¹ç¤Ë¤Ï¥¨¥é¡¼
+¤Ë¤Ê¤ê¤Þ¤¹¤Î¤Ç¡¤°ú¿ô¤òÄɲä·¤Æ
+
+ ruby -r mkmf extconf.rb
+
+¤È¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+¥Ç¥£¥ì¥¯¥È¥ê¤òext°Ê²¼¤ËÍÑ°Õ¤·¤¿¾ì¹ç¤Ë¤ÏRubyÁ´ÂΤÎmake¤Î»þ¤Ë
+¼«Æ°Åª¤ËMakefile¤¬À¸À®¤µ¤ì¤Þ¤¹¤Î¤Ç¡¤¤³¤Î¥¹¥Æ¥Ã¥×¤ÏÉÔÍפǤ¹¡¥
+
+(9) make¤¹¤ë
+
+ưŪ¥ê¥ó¥¯¥é¥¤¥Ö¥é¥ê¤òÀ¸À®¤¹¤ë¾ì¹ç¤Ë¤Ï¤½¤Î¾ì¤Çmake¤·¤Æ¤¯¤À¤µ
+¤¤¡¥É¬ÍפǤ¢¤ì¤Ð make install ¤Ç¥¤¥ó¥¹¥È¡¼¥ë¤µ¤ì¤Þ¤¹¡¥
+
+ext°Ê²¼¤Ë¥Ç¥£¥ì¥¯¥È¥ê¤òÍÑ°Õ¤·¤¿¾ì¹ç¤Ï¡¤Ruby¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Ç
+make¤ò¼Â¹Ô¤¹¤ë¤ÈMakefile¤òÀ¸À®¤«¤émake¡¤É¬Íפˤè¤Ã¤Æ¤Ï¤½¤Î¥â
+¥¸¥å¡¼¥ë¤ÎRuby¤Ø¤Î¥ê¥ó¥¯¤Þ¤Ç¼«Æ°Åª¤Ë¼Â¹Ô¤·¤Æ¤¯¤ì¤Þ¤¹¡¥
+extconf.rb¤ò½ñ¤­´¹¤¨¤ë¤Ê¤É¤·¤ÆMakefile¤ÎºÆÀ¸À®¤¬É¬Íפʻþ¤Ï¤Þ
+¤¿Ruby¥Ç¥£¥ì¥¯¥È¥ê¤Çmake¤·¤Æ¤¯¤À¤µ¤¤¡¥
+
+³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ïmake install¤ÇRuby¥é¥¤¥Ö¥é¥ê¤Î¥Ç¥£¥ì¥¯¥È¥ê¤Î
+²¼¤Ë¥³¥Ô¡¼¤µ¤ì¤Þ¤¹¡¥¤â¤·³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤È¶¨Ä´¤·¤Æ»È¤¦Ruby¤Çµ­
+½Ò¤µ¤ì¤¿¥×¥í¥°¥é¥à¤¬¤¢¤ê¡¤Ruby¥é¥¤¥Ö¥é¥ê¤ËÃÖ¤­¤¿¤¤¾ì¹ç¤Ë¤Ï¡¤
+³ÈÄ¥¥é¥¤¥Ö¥é¥êÍѤΥǥ£¥ì¥¯¥È¥ê¤Î²¼¤Ë lib ¤È¤¤¤¦¥Ç¥£¥ì¥¯¥È¥ê
+¤òºî¤ê¡¤¤½¤³¤Ë ³ÈÄ¥»Ò .rb ¤Î¥Õ¥¡¥¤¥ë¤òÃÖ¤¤¤Æ¤ª¤±¤ÐƱ»þ¤Ë¥¤¥ó
+¥¹¥È¡¼¥ë¤µ¤ì¤Þ¤¹¡¥
+
+(10) ¥Ç¥Ð¥Ã¥°
+
+¤Þ¤¢¡¤¥Ç¥Ð¥Ã¥°¤·¤Ê¤¤¤ÈÆ°¤«¤Ê¤¤¤Ç¤·¤ç¤¦¤Í¡¥ext/Setup¤Ë¥Ç¥£¥ì
+¥¯¥È¥ê̾¤ò½ñ¤¯¤ÈÀÅŪ¤Ë¥ê¥ó¥¯¤¹¤ë¤Î¤Ç¥Ç¥Ð¥Ã¥¬¤¬»È¤¨¤ë¤è¤¦¤Ë¤Ê
+¤ê¤Þ¤¹¡¥¤½¤Îʬ¥³¥ó¥Ñ¥¤¥ë¤¬ÃÙ¤¯¤Ê¤ê¤Þ¤¹¤±¤É¡¥
+
+(11) ¤Ç¤­¤¢¤¬¤ê
+
+¸å¤Ï¤³¤Ã¤½¤ê»È¤¦¤Ê¤ê¡¤¹­¤¯¸ø³«¤¹¤ë¤Ê¤ê¡¤Çä¤ë¤Ê¤ê¡¤¤´¼«Í³¤Ë¤ª
+»È¤¤¤¯¤À¤µ¤¤¡¥Ruby¤Îºî¼Ô¤Ï³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ë´Ø¤·¤Æ°ìÀڤθ¢Íø¤ò
+¼çÄ¥¤·¤Þ¤»¤ó¡¥
+
+Appendix A. Ruby¤Î¥½¡¼¥¹¥³¡¼¥É¤ÎʬÎà
+
+Ruby¤Î¥½¡¼¥¹¤Ï¤¤¤¯¤Ä¤«¤ËʬÎह¤ë¤³¤È¤¬½ÐÍè¤Þ¤¹¡¥¤³¤Î¤¦¤Á¥¯¥é
+¥¹¥é¥¤¥Ö¥é¥ê¤ÎÉôʬ¤Ï´ðËÜŪ¤Ë³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤ÈƱ¤¸ºî¤êÊý¤Ë¤Ê¤Ã
+¤Æ¤¤¤Þ¤¹¡¥¤³¤ì¤é¤Î¥½¡¼¥¹¤Ïº£¤Þ¤Ç¤ÎÀâÌÀ¤Ç¤Û¤È¤ó¤ÉÍý²ò¤Ç¤­¤ë¤È
+»×¤¤¤Þ¤¹¡¥
+
+Ruby¸À¸ì¤Î¥³¥¢
+
+ class.c
+ error.c
+ eval.c
+ gc.c
+ object.c
+ parse.y
+ variable.c
+
+¥æ¡¼¥Æ¥£¥ê¥Æ¥£´Ø¿ô
+
+ dln.c
+ fnmatch.c
+ glob.c
+ regex.c
+ st.c
+ util.c
+
+Ruby¥³¥Þ¥ó¥É¤Î¼ÂÁõ
+
+ dmyext.c
+ inits.c
+ main.c
+ ruby.c
+ version.c
+
+¥¯¥é¥¹¥é¥¤¥Ö¥é¥ê
+
+ array.c
+ bignum.c
+ compar.c
+ dir.c
+ enum.c
+ file.c
+ hash.c
+ io.c
+ marshal.c
+ math.c
+ numeric.c
+ pack.c
+ process.c
+ random.c
+ range.c
+ re.c
+ signal.c
+ sprintf.c
+ string.c
+ struct.c
+ time.c
+
+Appendix B. ³ÈÄ¥ÍÑ´Ø¿ô¥ê¥Õ¥¡¥ì¥ó¥¹
+
+C¸À¸ì¤«¤éRuby¤Îµ¡Ç½¤òÍøÍѤ¹¤ëAPI¤Ï°Ê²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥
+
+** ·¿
+
+VALUE
+
+ Ruby¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¸½¤¹¤ë·¿¡¥É¬Íפ˱þ¤¸¤Æ¥­¥ã¥¹¥È¤·¤ÆÍѤ¤¤ë¡¥
+ ÁȤ߹þ¤ß·¿¤òɽ¸½¤¹¤ëC¤Î·¿¤Ïruby.h¤Ëµ­½Ò¤·¤Æ¤¢¤ëR¤Ç»Ï¤Þ¤ë¹½Â¤
+ ÂΤǤ¢¤ë¡¥VALUE·¿¤ò¤³¤ì¤é¤Ë¥­¥ã¥¹¥È¤¹¤ë¤¿¤á¤ËR¤Ç»Ï¤Þ¤ë¹½Â¤ÂÎ
+ ̾¤òÁ´¤ÆÂçʸ»ú¤Ë¤·¤¿Ì¾Á°¤Î¥Þ¥¯¥í¤¬ÍÑ°Õ¤µ¤ì¤Æ¤¤¤ë¡¥
+
+** ÊÑ¿ô¡¦Äê¿ô
+
+Qnil
+
+ Äê¿ô: nil¥ª¥Ö¥¸¥§¥¯¥È
+
+Qtrue
+
+ Äê¿ô: true¥ª¥Ö¥¸¥§¥¯¥È(¿¿¤Î¥Ç¥Õ¥©¥ë¥ÈÃÍ)
+
+Qfalse
+
+ Äê¿ô: false¥ª¥Ö¥¸¥§¥¯¥È
+
+** C¥Ç¡¼¥¿¤Î¥«¥×¥»¥ë²½
+
+Data_Wrap_Struct(VALUE class, void (*mark)(), void (*free)(), void *sval)
+
+ C¤ÎǤ°Õ¤Î¥Ý¥¤¥ó¥¿¤ò¥«¥×¥»¥ë²½¤·¤¿Ruby¥ª¥Ö¥¸¥§¥¯¥È¤òÊÖ¤¹¡¥¤³
+ ¤Î¥Ý¥¤¥ó¥¿¤¬Ruby¤«¤é¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¯¤Ê¤Ã¤¿»þ¡¤free¤Ç»ØÄꤷ¤¿
+ ´Ø¿ô¤¬¸Æ¤Ð¤ì¤ë¡¥¤Þ¤¿¡¤¤³¤Î¥Ý¥¤¥ó¥¿¤Î»Ø¤¹¥Ç¡¼¥¿¤¬Â¾¤ÎRuby¥ª¥Ö
+ ¥¸¥§¥¯¥È¤ò»Ø¤·¤Æ¤¤¤ë¾ì¹ç¡¤mark¤Ë»ØÄꤹ¤ë´Ø¿ô¤Ç¥Þ¡¼¥¯¤¹¤ëɬÍ×
+ ¤¬¤¢¤ë¡¥
+
+Data_Make_Struct(class, type, mark, free, sval)
+
+ type·¿¤Î¥á¥â¥ê¤òmalloc¤·¡¤ÊÑ¿ôsval¤ËÂåÆþ¤·¤¿¸å¡¤¤½¤ì¤ò¥«¥×¥»
+ ¥ë²½¤·¤¿¥Ç¡¼¥¿¤òÊÖ¤¹¥Þ¥¯¥í¡¥
+
+Data_Get_Struct(data, type, sval)
+
+ data¤«¤étype·¿¤Î¥Ý¥¤¥ó¥¿¤ò¼è¤ê½Ð¤·ÊÑ¿ôsval¤ËÂåÆþ¤¹¤ë¥Þ¥¯¥í¡¥
+
+** ·¿¥Á¥§¥Ã¥¯
+
+TYPE(value)
+FIXNUM_P(value)
+NIL_P(value)
+void Check_Type(VALUE value, int type)
+void Check_SafeStr(VALUE value)
+
+** ·¿ÊÑ´¹
+
+FIX2INT(value)
+INT2FIX(i)
+NUM2INT(value)
+INT2NUM(i)
+NUM2DBL(value)
+rb_float_new(f)
+STR2CSTR(value)
+rb_str_new2(s)
+
+** ¥¯¥é¥¹/¥â¥¸¥å¡¼¥ëÄêµÁ
+
+VALUE rb_define_class(char *name, VALUE super)
+
+ super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤Ruby¥¯¥é¥¹¤òÄêµÁ¤¹¤ë¡¥
+
+VALUE rb_define_class_under(VALUE module, char *name, VALUE super)
+
+ super¤Î¥µ¥Ö¥¯¥é¥¹¤È¤·¤Æ¿·¤·¤¤Ruby¥¯¥é¥¹¤òÄêµÁ¤·¡¤module¤Î
+ Äê¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
+
+VALUE rb_define_module(char *name)
+
+ ¿·¤·¤¤Ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤¹¤ë¡¥
+
+VALUE rb_define_module_under(VALUE module, char *name, VALUE super)
+
+ ¿·¤·¤¤Ruby¥â¥¸¥å¡¼¥ë¤òÄêµÁ¤·¡¤module¤ÎÄê¿ô¤È¤·¤ÆÄêµÁ¤¹¤ë¡¥
+
+void rb_include_module(VALUE class, VALUE module)
+
+ ¥â¥¸¥å¡¼¥ë¤ò¥¤¥ó¥¯¥ë¡¼¥É¤¹¤ë¡¥class¤¬¤¹¤Ç¤Ëmodule¤ò¥¤¥ó¥¯
+ ¥ë¡¼¥É¤·¤Æ¤¤¤ë»þ¤Ë¤Ï²¿¤â¤·¤Ê¤¤(¿½Å¥¤¥ó¥¯¥ë¡¼¥É¤Î¶Ø»ß)¡¥
+
+void rb_extend_object(VALUE object, VALUE module)
+
+ ¥ª¥Ö¥¸¥§¥¯¥È¤ò¥â¥¸¥å¡¼¥ë(¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥á¥½¥Ã¥É)¤Ç³ÈÄ¥¤¹¤ë¡¥
+
+** Âç°èÊÑ¿ôÄêµÁ
+
+void rb_define_variable(char *name, VALUE *var)
+
+ Ruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ë¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô̾¤¬`$'¤Ç
+ »Ï¤Þ¤é¤Ê¤¤»þ¤Ë¤Ï¼«Æ°Åª¤ËÄɲ䵤ì¤ë¡¥name¤È¤·¤ÆRuby¤Î¼±ÊÌ»Ò
+ ¤È¤·¤Æµö¤µ¤ì¤Ê¤¤Ê¸»ú(Î㤨¤Ð` ')¤ò´Þ¤à¾ì¹ç¤Ë¤ÏRuby¥×¥í¥°¥é
+ ¥à¤«¤é¤Ï¸«¤¨¤Ê¤¯¤Ê¤ë¡¥
+
+void rb_define_readonly_variable(char *name, VALUE *var)
+
+ Ruby¤ÈC¤È¤Ç¶¦Í­¤¹¤ëread only¤Î¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥
+ read only¤Ç¤¢¤ë¤³¤È°Ê³°¤Ïrb_define_variable()¤ÈƱ¤¸¡¥
+
+void rb_define_virtual_variable(char *name,
+ VALUE (*getter)(), VALUE (*setter)())
+
+ ´Ø¿ô¤Ë¤è¤Ã¤Æ¼Â¸½¤µ¤ì¤ëRubyÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô¤¬»²¾È¤µ¤ì¤¿
+ »þ¤Ë¤Ïgetter¤¬¡¤ÊÑ¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ïsetter¤¬¸Æ¤Ð¤ì
+ ¤ë¡¥
+
+void rb_define_hooked_variable(char *name, VALUE *var,
+ VALUE (*getter)(), VALUE (*setter)())
+
+ ´Ø¿ô¤Ë¤è¤Ã¤Æhook¤Î¤Ä¤±¤é¤ì¤¿¥°¥í¡¼¥Ð¥ëÊÑ¿ô¤òÄêµÁ¤¹¤ë¡¥ÊÑ¿ô
+ ¤¬»²¾È¤µ¤ì¤¿»þ¤Ë¤Ïgetter¤¬¡¤´Ø¿ô¤ËÃͤ¬¥»¥Ã¥È¤µ¤ì¤¿»þ¤Ë¤Ï
+ setter¤¬¸Æ¤Ð¤ì¤ë¡¥getter¤äsetter¤Ë0¤ò»ØÄꤷ¤¿»þ¤Ë¤Ïhook¤ò
+ »ØÄꤷ¤Ê¤¤¤Î¤ÈƱ¤¸»ö¤Ë¤Ê¤ë¡¥
+
+void rb_global_variable(VALUE *var)
+
+ GC¤Î¤¿¤á¡¤Ruby¥×¥í¥°¥é¥à¤«¤é¤Ï¥¢¥¯¥»¥¹¤µ¤ì¤Ê¤¤¤¬, Ruby¥ª¥Ö
+ ¥¸¥§¥¯¥È¤ò´Þ¤àÂç°èÊÑ¿ô¤ò¥Þ¡¼¥¯¤¹¤ë¡¥
+
+** Äê¿ô
+
+void rb_define_const(VALUE klass, char *name, VALUE val)
+
+ Äê¿ô¤òÄêµÁ¤¹¤ë¡¥
+
+void rb_define_global_const(char *name, VALUE val)
+
+ Âç°èÄê¿ô¤òÄêµÁ¤¹¤ë¡¥
+
+ rb_define_const(cKernal, name, val)
+
+ ¤ÈƱ¤¸°ÕÌ£¡¥
+
+** ¥á¥½¥Ã¥ÉÄêµÁ
+
+rb_define_method(VALUE class, char *name, VALUE (*func)(), int argc)
+
+ ¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥argc¤Ïself¤ò½ü¤¯°ú¿ô¤Î¿ô¡¥argc¤¬-1¤Î»þ,
+ ´Ø¿ô¤Ë¤Ï°ú¿ô¤Î¿ô(self¤ò´Þ¤Þ¤Ê¤¤)¤òÂè1°ú¿ô, °ú¿ô¤ÎÇÛÎó¤òÂè2
+ °ú¿ô¤È¤¹¤ë·Á¼°¤ÇÍ¿¤¨¤é¤ì¤ë(Âè3°ú¿ô¤Ïself)¡¥argc¤¬-2¤Î»þ,
+ Âè1°ú¿ô¤¬self, Âè2°ú¿ô¤¬args(args¤Ï°ú¿ô¤ò´Þ¤àRuby¤ÎÇÛÎó)¤È
+ ¤¤¤¦·Á¼°¤ÇÍ¿¤¨¤é¤ì¤ë¡¥
+
+rb_define_private_method(VALUE class, char *name, VALUE (*func)(), int argc)
+
+ private¥á¥½¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¡¥
+
+rb_define_singleton_method(VALUE class, char *name, VALUE (*func)(), int argc)
+
+ Æðۥ᥽¥Ã¥É¤òÄêµÁ¤¹¤ë¡¥°ú¿ô¤Ïrb_define_method()¤ÈƱ¤¸¡¥
+
+rb_scan_args(int argc, VALUE *argv, char *fmt, ...)
+
+ argc,argv·Á¼°¤ÇÍ¿¤¨¤é¤ì¤¿°ú¿ô¤òʬ²ò¤¹¤ë¡¥fmt¤Ïɬ¿Ü°ú¿ô¤Î¿ô,
+ Éղðú¿ô¤Î¿ô, »Ä¤ê¤Î°ú¿ô¤¬¤¢¤ë¤«¤ò»ØÄꤹ¤ëʸ»úÎó¤Ç, "¿ô»ú
+ ¿ô»ú*"¤È¤¤¤¦·Á¼°¤Ç¤¢¤ë¡¥ 2 ÈÖÌܤοô»ú¤È"*"¤Ï¤½¤ì¤¾¤ì¾Êά²Ä
+ ǽ¤Ç¤¢¤ë¡¥É¬¿Ü°ú¿ô¤¬°ì¤Ä¤â¤Ê¤¤¾ì¹ç¤Ï0¤ò»ØÄꤹ¤ë¡¥Âè3°ú¿ô°Ê
+ ¹ß¤ÏÊÑ¿ô¤Ø¤Î¥Ý¥¤¥ó¥¿¤Ç, ³ºÅö¤¹¤ëÍ×ÁǤ¬¤½¤ÎÊÑ¿ô¤Ë³ÊǼ¤µ¤ì¤ë¡¥
+ Éղðú¿ô¤ËÂбþ¤¹¤ë°ú¿ô¤¬Í¿¤¨¤é¤ì¤Æ¤¤¤Ê¤¤¾ì¹ç¤ÏÊÑ¿ô¤ËQnil¤¬
+ ÂåÆþ¤µ¤ì¤ë¡¥
+
+** Ruby¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·
+
+VALUE rb_funcall(VALUE recv, ID mid, int narg, ...)
+
+ ¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¡¥Ê¸»úÎ󤫤émid¤òÆÀ¤ë¤¿¤á¤Ë¤Ïrb_intern()¤ò
+ »È¤¦¡¥
+
+VALUE rb_funcall2(VALUE recv, ID mid, int argc, VALUE *argv)
+
+ ¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¡¥°ú¿ô¤òargc,argv·Á¼°¤ÇÅϤ¹¡¥
+
+VALUE rb_eval_string(char *str)
+
+ ʸ»úÎó¤òRuby¤È¥¹¥¯¥ê¥×¥È¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¡¦¼Â¹Ô¤¹¤ë¡¥
+
+ID rb_intern(char *name)
+
+ ʸ»úÎó¤ËÂбþ¤¹¤ëID¤òÊÖ¤¹¡¥
+
+char *rb_id2name(ID id)
+
+ ID¤ËÂбþ¤¹¤ëʸ»úÎó¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥
+
+char *rb_class2name(VALUE class)
+
+ class¤Î̾Á°¤òÊÖ¤¹(¥Ç¥Ð¥Ã¥°ÍÑ)¡¥class¤¬Ì¾Á°¤ò»ý¤¿¤Ê¤¤»þ¤Ë¤Ï,
+ ÁÄÀè¤òÁ̤äÆ̾Á°¤ò»ý¤Ä¥¯¥é¥¹¤Î̾Á°¤òÊÖ¤¹¡¥
+
+** ¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô
+
+VALUE rb_iv_get(VALUE obj, char *name)
+
+ obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤ÎÃͤòÆÀ¤ë¡¥`@'¤Ç»Ï¤Þ¤é¤Ê¤¤¥¤¥ó¥¹¥¿¥ó
+ ¥¹ÊÑ¿ô¤Ï Ruby¥×¥í¥°¥é¥à¤«¤é¥¢¥¯¥»¥¹¤Ç¤­¤Ê¤¤¡Ö±£¤ì¤¿¡×¥¤¥ó
+ ¥¹¥¿¥ó¥¹ÊÑ¿ô¤Ë¤Ê¤ë¡¥Äê¿ô¤ÏÂçʸ»ú¤Î̾Á°¤ò»ý¤Ä¥¯¥é¥¹(¤Þ¤¿¤Ï
+ ¥â¥¸¥å¡¼¥ë)¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤È¤·¤Æ¼ÂÁõ¤µ¤ì¤Æ¤¤¤ë¡¥
+
+VALUE rb_iv_set(VALUE obj, char *name, VALUE val)
+
+ obj¤Î¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô¤òval¤Ë¥»¥Ã¥È¤¹¤ë¡¥
+
+** À©¸æ¹½Â¤
+
+VALUE rb_iterate(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)
+
+ func2¤ò¥Ö¥í¥Ã¥¯¤È¤·¤ÆÀßÄꤷ, func1¤ò¥¤¥Æ¥ì¡¼¥¿¤È¤·¤Æ¸Æ¤Ö¡¥
+ func1¤Ë¤Ï arg1¤¬°ú¿ô¤È¤·¤ÆÅϤµ¤ì, func2¤Ë¤ÏÂè1°ú¿ô¤Ë¥¤¥Æ¥ì¡¼
+ ¥¿¤«¤éÍ¿¤¨¤é¤ì¤¿ÃÍ, Âè2°ú¿ô¤Ëarg2¤¬ÅϤµ¤ì¤ë¡¥
+
+VALUE rb_yield(VALUE val)
+
+ val¤òÃͤȤ·¤Æ¥¤¥Æ¥ì¡¼¥¿¥Ö¥í¥Ã¥¯¤ò¸Æ¤Ó½Ð¤¹¡¥
+
+VALUE rb_rescue(VALUE (*func1)(), void *arg1, VALUE (*func2)(), void *arg2)
+
+ ´Ø¿ôfunc1¤òarg1¤ò°ú¿ô¤Ë¸Æ¤Ó½Ð¤¹¡¥func1¤Î¼Â¹ÔÃæ¤ËÎã³°¤¬È¯À¸
+ ¤·¤¿»þ¤Ë¤Ï func2¤òarg2¤ò°ú¿ô¤È¤·¤Æ¸Æ¤Ö¡¥Ìá¤êÃͤÏÎã³°¤¬È¯À¸
+ ¤·¤Ê¤«¤Ã¤¿»þ¤Ïfunc1¤ÎÌá¤êÃÍ, Îã³°¤¬È¯À¸¤·¤¿»þ¤Ë¤Ïfunc2¤ÎÌá
+ ¤êÃͤǤ¢¤ë¡¥
+
+VALUE rb_ensure(VALUE (*func1)(), void *arg1, void (*func2)(), void *arg2)
+
+ ´Ø¿ôfunc1¤òarg1¤ò°ú¿ô¤È¤·¤Æ¼Â¹Ô¤·, ¼Â¹Ô½ªÎ»¸å(¤¿¤È¤¨Îã³°¤¬
+ ȯÀ¸¤·¤Æ¤â) func2¤òarg2¤ò°ú¿ô¤È¤·¤Æ¼Â¹Ô¤¹¤ë¡¥Ìá¤êÃͤÏfunc1
+ ¤ÎÌá¤êÃͤǤ¢¤ë(Îã³°¤¬È¯À¸¤·¤¿»þ¤ÏÌá¤é¤Ê¤¤)¡¥
+
+** Îã³°¡¦¥¨¥é¡¼
+
+void rb_warning(char *fmt, ...)
+
+ rb_verbose»þ¤Ëɸ½à¥¨¥é¡¼½ÐÎϤ˷ٹð¾ðÊó¤òɽ¼¨¤¹¤ë¡¥°ú¿ô¤Ï
+ printf()¤ÈƱ¤¸¡¥
+
+void rb_raise(rb_eRuntimeError, char *fmt, ...)
+
+ RuntimeErrorÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥°ú¿ô¤Ïprintf()¤ÈƱ¤¸¡¥
+
+void rb_raise(VALUE exception, char *fmt, ...)
+
+ exception¤Ç»ØÄꤷ¤¿Îã³°¤òȯÀ¸¤µ¤»¤ë¡¥fmt°Ê²¼¤Î°ú¿ô¤Ï
+ printf()¤ÈƱ¤¸¡¥
+
+void rb_fatal(char *fmt, ...)
+
+ Ã×̿ŪÎã³°¤òȯÀ¸¤µ¤»¤ë¡¥Ä̾ï¤ÎÎã³°½èÍý¤Ï¹Ô¤Ê¤ï¤ì¤º, ¥¤¥ó¥¿¡¼
+ ¥×¥ê¥¿¤¬½ªÎ»¤¹¤ë(¤¿¤À¤·ensure¤Ç»ØÄꤵ¤ì¤¿¥³¡¼¥É¤Ï½ªÎ»Á°¤Ë
+ ¼Â¹Ô¤µ¤ì¤ë)¡¥
+
+void rb_bug(char *fmt, ...)
+
+ ¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ê¤É¥×¥í¥°¥é¥à¤Î¥Ð¥°¤Ç¤·¤«È¯À¸¤¹¤ë¤Ï¤º¤Î¤Ê¤¤
+ ¾õ¶·¤Î»þ¸Æ¤Ö¡¥¥¤¥ó¥¿¡¼¥×¥ê¥¿¤Ï¥³¥¢¥À¥ó¥×¤·Ä¾¤Á¤Ë½ªÎ»¤¹¤ë¡¥
+ Îã³°½èÍý¤Ï°ìÀڹԤʤï¤ì¤Ê¤¤¡¥
+
+** Ruby¤Î½é´ü²½¡¦¼Â¹Ô
+
+Ruby¤ò¥¢¥×¥ê¥±¡¼¥·¥ç¥ó¤ËËä¤á¹þ¤à¾ì¹ç¤Ë¤Ï°Ê²¼¤Î¥¤¥ó¥¿¥Õ¥§¡¼¥¹
+¤ò»È¤¦¡¥Ä̾ï¤Î³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ë¤ÏɬÍפʤ¤¡¥
+
+void ruby_init(int argc, char **argv, char **envp)
+
+ Ruby¥¤¥ó¥¿¥×¥ê¥¿¤Î½é´ü²½¤ò¹Ô¤Ê¤¦¡¥
+
+void ruby_run()
+
+ Ruby¥¤¥ó¥¿¥×¥ê¥¿¤ò¼Â¹Ô¤¹¤ë¡¥
+
+void ruby_script(char *name)
+
+ Ruby¤Î¥¹¥¯¥ê¥×¥È̾($0)¤òÀßÄꤹ¤ë¡¥
+
+
+Appendix B. extconf.rb¤Ç»È¤¨¤ë´Ø¿ô¤¿¤Á
+
+extconf.rb¤ÎÃæ¤Ç¤ÏÍøÍѲÄǽ¤Ê¥³¥ó¥Ñ¥¤¥ë¾ò·ï¥Á¥§¥Ã¥¯¤Î´Ø¿ô¤Ï°Ê
+²¼¤ÎÄ̤ê¤Ç¤¢¤ë¡¥
+
+have_library(lib, func)
+
+ ´Ø¿ôfunc¤òÄêµÁ¤·¤Æ¤¤¤ë¥é¥¤¥Ö¥é¥êlib¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥
+ ¥é¥¤¥Ö¥é¥ê¤¬Â¸ºß¤¹¤ë»þ¡¤true¤òÊÖ¤¹¡¥
+
+find_library(lib, func, path...)
+
+ ´Ø¿ôfunc¤òÄêµÁ¤·¤Æ¤¤¤ë¥é¥¤¥Ö¥é¥êlib¤Î¸ºß¤ò -Lpath ¤òÄɲÃ
+ ¤·¤Ê¤¬¤é¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥é¥¤¥Ö¥é¥ê¤¬¸«ÉÕ¤«¤Ã¤¿»þ¡¤true¤òÊÖ¤¹¡¥
+ ·ë²Ì¤ò¥­¥ã¥Ã¥·¥å¤·¤Ê¤¤¡¥
+
+have_func(func)
+
+ ´Ø¿ôfunc¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥func¤¬É¸½à¤Ç¤Ï¥ê¥ó¥¯¤µ¤ì¤Ê¤¤
+ ¥é¥¤¥Ö¥é¥êÆâ¤Î¤â¤Î¤Ç¤¢¤ë»þ¤Ë¤ÏÀè¤Ëhave_library¤Ç¤½¤Î¥é¥¤¥Ö
+ ¥é¥ê¤ò¥Á¥§¥Ã¥¯¤·¤Æ¤ª¤¯»ö¡¥´Ø¿ô¤¬Â¸ºß¤¹¤ë»þtrue¤òÊÖ¤¹¡¥
+
+have_header(header)
+
+ ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¤ò¥Á¥§¥Ã¥¯¤¹¤ë¡¥¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤¹
+ ¤ë»þtrue¤òÊÖ¤¹¡¥
+
+find_header(header)
+
+ ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤Î¸ºß¤ò -Ipath ¤òÄɲ䷤ʤ¬¤é¥Á¥§¥Ã¥¯¤¹¤ë¡¥
+ ¥Ø¥Ã¥À¥Õ¥¡¥¤¥ë¤¬¸«ÉÕ¤«¤Ã¤¿»þtrue¤òÊÖ¤¹¡¥·ë²Ì¤ò¥­¥ã¥Ã¥·¥å¤·
+ ¤Ê¤¤¡¥
+
+create_makefile(target)
+
+ ³ÈÄ¥¥é¥¤¥Ö¥é¥êÍѤÎMakefile¤òÀ¸À®¤¹¤ë¡¥¤³¤Î´Ø¿ô¤ò¸Æ¤Ð¤Ê¤±¤ì
+ ¤Ð¤½¤Î¥é¥¤¥Ö¥é¥ê¤Ï¥³¥ó¥Ñ¥¤¥ë¤µ¤ì¤Ê¤¤¡¥target¤Ï¥â¥¸¥å¡¼¥ë̾
+ ¤òɽ¤¹¡¥
+
+with_config(withval[, default=nil])
+
+ --with-<withval>¤Ç»ØÄꤵ¤ì¤¿¥ª¥×¥·¥ç¥óÃͤòÆÀ¤ë¡¥
+
+dir_config(target)
+
+ --with-<target>-dir, --with-<target>-include, --with-<target>-lib
+ ¤Î¤¤¤º¤ì¤«¤Ç»ØÄꤵ¤ì¤ë¥Ç¥£¥ì¥¯¥È¥ê¤ò $CFLAGS ¤ä $LDFLAGS
+ ¤ËÄɲ乤롥
+
+/*
+ * Local variables:
+ * fill-column: 60
+ * end:
+ */
diff --git a/README.jp b/README.jp
index d137a435d8..8115dc45a0 100644
--- a/README.jp
+++ b/README.jp
@@ -32,24 +32,45 @@ Ruby¤Ï¥Æ¥­¥¹¥È½èÍý´Ø·¸¤ÎǽÎϤʤɤËÍ¥¤ì¡¤Perl¤ÈƱ¤¸¤¯¤é¤¤¶¯ÎÏ
ftp://ftp.netlab.co.jp/pub/lang/ruby/
+** CVS¤Ç
+
+ $ cvs -d :pserver:anonymous@cvs.netlab.co.jp:/home/cvs login
+ (Logging in to anonymous@cvs.netlab.co.jp)
+ CVS password: guest
+ $ cvs -d :pserver:anonymous@cvs.netlab.co.jp:/home/cvs checkout ruby
* ¥Û¡¼¥à¥Ú¡¼¥¸
- Ruby¤Î¥Û¡¼¥à¥Ú¡¼¥¸¤ÎURL¤Ï
+Ruby¤Î¥Û¡¼¥à¥Ú¡¼¥¸¤ÎURL¤Ï
http://www.netlab.co.jp/ruby/jp/
- ¤Ç¤¹¡¥
+¤Ç¤¹¡¥
* ¥á¡¼¥ê¥ó¥°¥ê¥¹¥È
- Ruby¤Ë´Ø¤ï¤ëÏÃÂê¤Î¤¿¤á¤Î¥á¡¼¥ê¥ó¥°¥ê¥¹¥È¤ò³«Àߤ·¤Þ¤·¤¿¡¥¥¢
- ¥É¥ì¥¹¤Ï
+Ruby¤Î¥á¡¼¥ê¥ó¥°¥ê¥¹¥È¤¬¤¢¤ê¤Þ¤¹¡£»²²Ã´õ˾¤ÎÊý¤Ï
+
+ ruby-list-ctl@netlab.co.jp
+
+¤Þ¤ÇËÜʸ¤Ë
+
+ subscribe YourFirstName YourFamilyName
+
+¤È½ñ¤¤¤ÆÁ÷¤Ã¤Æ²¼¤µ¤¤¡£
+
+Ruby³«È¯¼Ô¸þ¤±¥á¡¼¥ê¥ó¥°¥ê¥¹¥È¤â¤¢¤ê¤Þ¤¹¡£¤³¤Á¤é¤Ç¤Ïruby¤Î¥Ð
+¥°¡¢¾­Íè¤Î»ÅÍͳÈÄ¥¤Ê¤É¼ÂÁõ¾å¤ÎÌäÂê¤Ë¤Ä¤¤¤ÆµÄÏÀ¤µ¤ì¤Æ¤¤¤Þ¤¹¡£
+»²²Ã´õ˾¤ÎÊý¤Ï
+
+ ruby-dev-ctl@netlab.co.jp
- ruby-list@netlab.co.jp
+¤Þ¤Çruby-list¤ÈƱÍͤÎÊýË¡¤Ç¥á¡¼¥ë¤·¤Æ¤¯¤À¤µ¤¤¡£
- ¤Ç¤¹¡¥¤³¤Î¥¢¥É¥ì¥¹¤Ë¥á¡¼¥ë¤òÁ÷¤ì¤Ð¡¤¼«Æ°Åª¤ËÅÐÏ¿¤µ¤ì¤Þ¤¹¡¥
+Ruby³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë¤Ä¤¤¤ÆÏ䷹礦ruby-ext¥á¡¼¥ê¥ó¥°¥ê¥¹¥È¤È
+±Ñ¸ì¤ÇÏ䷹礦ruby-talk¥á¡¼¥ê¥ó¥°¥ê¥¹¥È¤â¤¢¤ê¤Þ¤¹¡£»²²ÃÊýË¡
+¤Ï¤É¤ì¤âƱ¤¸¤Ç¤¹¡£
* ¥³¥ó¥Ñ¥¤¥ë¡¦¥¤¥ó¥¹¥È¡¼¥ë
@@ -142,22 +163,21 @@ Licence)¤Þ¤¿¤Ï°Ê²¼¤Ë¼¨¤¹¾ò·ï¤ÇRuby¤òºÆÇÛÉۤǤ­¤Þ¤¹¡¥GPL¤Ë¤Ä
(b) µ¡³£²ÄÆɤʥ½¡¼¥¹¥³¡¼¥É¤òźÉÕ¤¹¤ë¡¥
- (c) Êѹ¹¤ò¹Ô¤Ã¤¿¥Ð¥¤¥Ê¥ê¤Ï̾Á°¤òÊѹ¹¤·¤¿¤¦¤¨¡¤¥½¡¼¥¹¤Î
- Æþ¼êË¡¤òÌÀ¼¨¤¹¤ë¡¥
+ (c) Êѹ¹¤ò¹Ô¤Ã¤¿¥Ð¥¤¥Ê¥ê¤Ï̾Á°¤òÊѹ¹¤·¤¿¤¦¤¨¡¤¥ª¥ê¥¸¥Ê
+ ¥ë¤Î¥½¡¼¥¹¥³¡¼¥É¤ÎÆþ¼êË¡¤òÌÀ¼¨¤¹¤ë¡¥
(d) ¤½¤Î¾¤ÎÇÛÉÛ¾ò·ï¤òºî¼Ô¤È¹ç°Õ¤¹¤ë¡¥
4. ¾¤Î¥×¥í¥°¥é¥à¤Ø¤Î°úÍѤϤ¤¤«¤Ê¤ëÌÜŪ¤Ç¤¢¤ì¼«Í³¤Ç¤¹¡¥¤¿
¤À¤·¡¤Ruby¤Ë´Þ¤Þ¤ì¤ë¾¤Îºî¼Ô¤Ë¤è¤ë¥³¡¼¥É¤Ï¡¤¤½¤ì¤¾¤ì¤Î
ºî¼Ô¤Î°Õ¸þ¤Ë¤è¤ëÀ©¸Â¤¬²Ã¤¨¤é¤ì¤Þ¤¹¡¥¶ñÂÎŪ¤Ë¤Ïgc.c(°ìÉô)¡¤
- util.c(°ìÉô)¡¤st.[ch]¡¤regex.[ch], fnmatch.[ch], glob.c
- ¤ª¤è¤Ó./missing¥Ç¥£¥ì¥¯¥È¥ê²¼¤Î¥Õ¥¡¥¤¥ë·²¤¬³ºÅö¤·¤Þ¤¹¡¥
- ¤½¤ì¤¾¤ì¤ÎÇÛÉÛ¾ò·ï¤Ê¤É¤ËÉÕ¤¤¤Æ¤Ï³Æ¥Õ¥¡¥¤¥ë¤ò»²¾È¤·¤Æ¤¯
- ¤À¤µ¤¤¡¥
+ util.c(°ìÉô)¡¤st.[ch]¡¤regex.[ch] ¤ª¤è¤Ó. /missing¥Ç¥£
+ ¥ì¥¯¥È¥ê²¼¤Î¥Õ¥¡¥¤¥ë·²¤¬³ºÅö¤·¤Þ¤¹¡¥¤½¤ì¤¾¤ì¤ÎÇÛÉÛ¾ò·ï
+ ¤Ê¤É¤ËÉÕ¤¤¤Æ¤Ï³Æ¥Õ¥¡¥¤¥ë¤ò»²¾È¤·¤Æ¤¯¤À¤µ¤¤¡¥
5. Ruby¤Ø¤ÎÆþÎϤȤʤ륹¥¯¥ê¥×¥È¤ª¤è¤Ó¡¤Ruby¤«¤é¤Î½ÐÎϤθ¢
Íø¤ÏRuby¤Îºî¼Ô¤Ç¤Ï¤Ê¤¯¡¤¤½¤ì¤¾¤ì¤ÎÆþ½ÐÎϤòÀ¸À®¤·¤¿¿Í¤Ë
- °¤·¤Þ¤¹¡¥¤Þ¤¿¡¤Ruby¤ËÁȤ߹þ¤à¤¿¤á¤Î³ÈÄ¥¥â¥¸¥å¡¼¥ë¤Ë¤Ä
+ °¤·¤Þ¤¹¡¥¤Þ¤¿¡¤Ruby¤ËÁȤ߹þ¤à¤¿¤á¤Î³ÈÄ¥¥é¥¤¥Ö¥é¥ê¤Ë¤Ä
¤¤¤Æ¤âƱÍͤǤ¹¡¥
6. Ruby¤Ï̵ÊݾڤǤ¹¡¥ºî¼Ô¤ÏRuby¤ò¥µ¥Ý¡¼¥È¤¹¤ë°Õ»Ö¤Ï¤¢¤ê¤Þ
diff --git a/ToDo b/ToDo
index 3bc7887489..1ecd529b3e 100644
--- a/ToDo
+++ b/ToDo
@@ -1,8 +1,17 @@
Language Spec.
+* compile time string concatenation, "hello" "world" => "helloworld"
+* ../... outside condition invokes operator method too.
+* %w(a\ b\ c abc) => ["a b c", "abc"]
* package or access control for global variables
-* named arguments like foo(nation:="german").
-* multiple return values, yield values. maybe imcompatible
+* class variable (prefix?)
+* named arguments like foo(nation:="german") or foo(nation: "german").
+* method to retrieve argument information (need 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 ??
Hacking Interpreter
@@ -12,17 +21,28 @@ Hacking Interpreter
* remove rb_eval() recursions
* syntax tree -> bytecode ???
* scrambled script, or script filter
-* regular expression bug /(?:\s+\d+){2}/ URGENT!!
+* setuid ruby
+
+Standard Libraries
+
+* Struct::new([name,]member,...) ??
+* String#scanf(?)
+* Object#fmt(?)
+* Time::strptime
+* Integer[num], Float[num]; Fixnum[num]?
+* method to detect 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()
Extension Libraries
-* mod_ruby, FastCGI ruby
-* InterBase module
+* FastCGI ruby
* ptk.rb pTk wrapper that is compatible to tk.rb
Ruby Libraries
-* CGI.rb
+* net/pop.rb net/smtp.rb
* httplib.rb, urllib.rb, nttplib.rb, etc.
* format like perl's
@@ -33,5 +53,4 @@ Tools
Misc
-* translate README.EXT fully into English
* publish Ruby books
diff --git a/array.c b/array.c
index 8f6c0c223f..9cc0ac1815 100644
--- a/array.c
+++ b/array.c
@@ -6,7 +6,7 @@
$Date$
created at: Fri Aug 6 09:46:12 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -49,7 +49,7 @@ rb_ary_modify(ary)
rb_raise(rb_eTypeError, "can't modify frozen array");
if (FL_TEST(ary, ARY_TMPLOCK))
rb_raise(rb_eTypeError, "can't modify array during sort");
- if (rb_safe_level() >= 4 && !FL_TEST(ary, FL_TAINT))
+ if (!FL_TEST(ary, FL_TAINT) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify array");
}
@@ -72,7 +72,7 @@ rb_ary_frozen_p(ary)
VALUE
rb_ary_new2(len)
- size_t len;
+ long len;
{
NEWOBJ(ary, struct RArray);
OBJSETUP(ary, rb_cArray, T_ARRAY);
@@ -86,6 +86,7 @@ rb_ary_new2(len)
ary->len = 0;
ary->capa = len;
ary->ptr = 0;
+ if (len == 0) len++;
ary->ptr = ALLOC_N(VALUE, len);
return (VALUE)ary;
@@ -107,16 +108,16 @@ rb_ary_new()
VALUE
#ifdef HAVE_STDARG_PROTOTYPES
-rb_ary_new3(size_t n, ...)
+rb_ary_new3(long n, ...)
#else
rb_ary_new3(n, va_alist)
- size_t n;
+ long n;
va_dcl
#endif
{
va_list ar;
VALUE ary;
- size_t i;
+ long i;
if (n < 0) {
rb_raise(rb_eIndexError, "negative number of items(%d)", n);
@@ -135,7 +136,7 @@ rb_ary_new3(n, va_alist)
VALUE
rb_ary_new4(n, elts)
- size_t n;
+ long n;
VALUE *elts;
{
VALUE ary;
@@ -169,7 +170,7 @@ rb_ary_s_new(argc, argv, klass)
VALUE *argv;
VALUE klass;
{
- size_t len = 0;
+ long len = 0;
VALUE size, val;
NEWOBJ(ary, struct RArray);
OBJSETUP(ary, klass, T_ARRAY);
@@ -180,7 +181,7 @@ rb_ary_s_new(argc, argv, klass)
ary->capa = ARY_DEFAULT_SIZE;
}
else {
- size_t capa = NUM2UINT(size);
+ long capa = NUM2LONG(size);
if (capa < 0) {
rb_raise(rb_eArgError, "negative array size");
@@ -194,7 +195,6 @@ rb_ary_s_new(argc, argv, klass)
ary->ptr = ALLOC_N(VALUE, ary->capa);
memfill(ary->ptr, len, val);
ary->len = len;
- rb_obj_call_init((VALUE)ary);
return (VALUE)ary;
}
@@ -208,8 +208,7 @@ rb_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;
}
@@ -217,6 +216,7 @@ rb_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;
}
@@ -224,19 +224,24 @@ rb_ary_s_create(argc, argv, klass)
void
rb_ary_store(ary, idx, val)
VALUE ary;
- size_t idx;
+ long idx;
VALUE val;
{
rb_ary_modify(ary);
if (idx < 0) {
- idx = RARRAY(ary)->len + idx;
+ idx += RARRAY(ary)->len;
if (idx < 0) {
- rb_raise(rb_eIndexError, "negative index of array");
+ 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) {
@@ -310,7 +315,11 @@ rb_ary_unshift(ary, item)
{
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);
}
@@ -326,7 +335,7 @@ rb_ary_unshift(ary, item)
VALUE
rb_ary_entry(ary, offset)
VALUE ary;
- size_t offset;
+ long offset;
{
if (RARRAY(ary)->len == 0) return Qnil;
@@ -341,25 +350,25 @@ rb_ary_entry(ary, offset)
}
static VALUE
-rb_ary_subseq(ary, beg, len)
+rb_ary_subary(ary, beg, len)
VALUE ary;
- size_t beg, len;
+ long beg, len;
{
VALUE ary2;
- if (len <= 0) {
- return rb_ary_new2(0);
- }
+ if (beg > RARRAY(ary)->len) return Qnil;
if (beg < 0) {
len += beg;
beg = 0;
}
+ if (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 = rb_ary_new2(len);
MEMCPY(RARRAY(ary2)->ptr, RARRAY(ary)->ptr+beg, VALUE, len);
@@ -368,39 +377,6 @@ rb_ary_subseq(ary, beg, len)
return ary2;
}
-static VALUE
-beg_len(range, begp, lenp, len)
- VALUE range;
- size_t *begp, *lenp;
- size_t len;
-{
- size_t beg, end;
- size_t b, e;
-
- if (!rb_range_beg_end(range, &beg, &end)) return Qfalse;
- b = beg; e = end;
-
- if (beg < 0) {
- beg = len + beg;
- }
- if (end < 0) {
- end = len + end;
- }
- if (beg > end) {
- rb_raise(rb_eIndexError, "end smaller than beg [%d..%d]", b, e);
- }
-
- *begp = beg;
- if (beg > len) {
- *lenp = 0;
- }
- else {
- len = end - beg +1;
- *lenp = len;
- }
- return Qtrue;
-}
-
VALUE
rb_ary_aref(argc, argv, ary)
int argc;
@@ -408,29 +384,36 @@ rb_ary_aref(argc, argv, ary)
VALUE ary;
{
VALUE arg1, arg2;
- size_t beg, len;
+ long beg, len;
if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) {
- beg = NUM2UINT(arg1);
- len = NUM2UINT(arg2);
+ beg = NUM2LONG(arg1);
+ len = NUM2LONG(arg2);
if (beg < 0) {
beg = RARRAY(ary)->len + beg;
}
- return rb_ary_subseq(ary, beg, len);
+ return rb_ary_subary(ary, beg, len);
}
/* special case - speeding up */
if (FIXNUM_P(arg1)) {
- return rb_ary_entry(ary, FIX2UINT(arg1));
+ return rb_ary_entry(ary, FIX2LONG(arg1));
}
else if (TYPE(arg1) == T_BIGNUM) {
rb_raise(rb_eIndexError, "index too big");
}
- else if (beg_len(arg1, &beg, &len, RARRAY(ary)->len)) {
+ else {
/* check if idx is Range */
- return rb_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_subary(ary, beg, len);
+ }
}
- return rb_ary_entry(ary, NUM2UINT(arg1));
+ return rb_ary_entry(ary, NUM2LONG(arg1));
}
static VALUE
@@ -438,11 +421,11 @@ rb_ary_index(ary, val)
VALUE ary;
VALUE val;
{
- size_t 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;
}
@@ -452,11 +435,11 @@ rb_ary_rindex(ary, val)
VALUE ary;
VALUE val;
{
- size_t i = RARRAY(ary)->len;
+ long i = RARRAY(ary)->len;
while (i--) {
if (rb_equal(RARRAY(ary)->ptr[i], val))
- return INT2FIX(i);
+ return INT2NUM(i);
}
return Qnil;
}
@@ -468,11 +451,11 @@ rb_ary_indexes(argc, argv, ary)
VALUE ary;
{
VALUE new_ary;
- size_t i;
+ long i;
new_ary = rb_ary_new2(argc);
for (i=0; i<argc; i++) {
- rb_ary_store(new_ary, i, rb_ary_entry(ary, NUM2UINT(argv[i])));
+ rb_ary_push(new_ary, rb_ary_aref(1, argv+i, ary));
}
return new_ary;
@@ -481,24 +464,24 @@ rb_ary_indexes(argc, argv, ary)
static void
rb_ary_replace(ary, beg, len, rpl)
VALUE ary, rpl;
- size_t beg, len;
+ long beg, len;
{
- if (len < 0) {
- rb_raise(rb_eIndexError, "negative length %d", len);
+ 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;
+ rb_raise(rb_eIndexError, "index %d out of array", beg);
+ }
+ if (beg + len > RARRAY(ary)->len) {
+ len = RARRAY(ary)->len - beg;
}
if (TYPE(rpl) != T_ARRAY) {
rpl = rb_Array(rpl);
}
- if (beg + len < 0 || (beg < 0 && beg <= -len)) {
- rb_raise(rb_eIndexError, "index %d out of range", beg);
- }
- if (beg < 0) {
- len += beg;
- beg = 0;
- }
-
rb_ary_modify(ary);
if (beg >= RARRAY(ary)->len) {
len = beg + RARRAY(rpl)->len;
@@ -511,7 +494,7 @@ rb_ary_replace(ary, beg, len, rpl)
RARRAY(ary)->len = len;
}
else {
- size_t alen;
+ long alen;
if (beg + len > RARRAY(ary)->len) {
len = RARRAY(ary)->len - beg;
@@ -539,24 +522,17 @@ rb_ary_aset(argc, argv, ary)
VALUE ary;
{
VALUE arg1, arg2, arg3;
- size_t offset;
- size_t beg, len;
+ long offset, beg, len;
if (rb_scan_args(argc, argv, "21", &arg1, &arg2, &arg3) == 3) {
- beg = NUM2UINT(arg1);
- len = NUM2UINT(arg2);
-
- if (beg < 0) {
- beg = RARRAY(ary)->len + beg;
- }
- rb_ary_replace(ary, beg, len, arg3);
+ rb_ary_replace(ary, NUM2LONG(arg1), NUM2LONG(arg2), arg3);
return arg3;
}
else if (FIXNUM_P(arg1)) {
- offset = FIX2UINT(arg1);
+ offset = FIX2LONG(arg1);
goto fixnum;
}
- else if (beg_len(arg1, &beg, &len, RARRAY(ary)->len)) {
+ else if (rb_range_beg_len(arg1, &beg, &len, RARRAY(ary)->len, 1)) {
/* check if idx is Range */
rb_ary_replace(ary, beg, len, arg2);
return arg2;
@@ -565,7 +541,7 @@ rb_ary_aset(argc, argv, ary)
rb_raise(rb_eIndexError, "index too big");
}
- offset = NUM2UINT(arg1);
+ offset = NUM2LONG(arg1);
fixnum:
rb_ary_store(ary, offset, arg2);
return arg2;
@@ -575,43 +551,43 @@ VALUE
rb_ary_each(ary)
VALUE ary;
{
- size_t i;
+ long i;
for (i=0; i<RARRAY(ary)->len; i++) {
rb_yield(RARRAY(ary)->ptr[i]);
}
- return Qnil;
+ return ary;
}
static VALUE
rb_ary_each_index(ary)
VALUE ary;
{
- size_t 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
rb_ary_reverse_each(ary)
VALUE ary;
{
- size_t len = RARRAY(ary)->len;
+ long len = RARRAY(ary)->len;
while (len--) {
rb_yield(RARRAY(ary)->ptr[len]);
}
- return Qnil;
+ return ary;
}
static VALUE
rb_ary_length(ary)
VALUE ary;
{
- return INT2FIX(RARRAY(ary)->len);
+ return INT2NUM(RARRAY(ary)->len);
}
static VALUE
@@ -639,7 +615,7 @@ static VALUE
rb_ary_dup(ary)
VALUE ary;
{
- return rb_ary_new4(RARRAY(ary)->len, RARRAY(ary)->ptr);
+ return rb_ary_s_create(RARRAY(ary)->len, RARRAY(ary)->ptr, CLASS_OF(ary));
}
static VALUE
@@ -663,7 +639,7 @@ VALUE
rb_ary_join(ary, sep)
VALUE ary, sep;
{
- size_t i;
+ long i;
VALUE result, tmp;
if (RARRAY(ary)->len == 0) return rb_str_new(0, 0);
@@ -742,11 +718,7 @@ rb_ary_to_s(ary)
return str;
}
-#ifdef USE_THREAD
static ID inspect_key;
-#else
-static VALUE inspect_tbl;
-#endif
struct inspect_arg {
VALUE (*func)();
@@ -764,11 +736,9 @@ static VALUE
inspect_ensure(obj)
VALUE obj;
{
-#ifdef USE_THREAD
VALUE inspect_tbl;
inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key);
-#endif
rb_ary_pop(inspect_tbl);
return 0;
}
@@ -780,7 +750,6 @@ rb_protect_inspect(func, obj, arg)
{
struct inspect_arg iarg;
-#ifdef USE_THREAD
VALUE inspect_tbl;
if (!inspect_key) {
@@ -791,12 +760,6 @@ rb_protect_inspect(func, obj, arg)
inspect_tbl = rb_ary_new();
rb_thread_local_aset(rb_thread_current(), inspect_key, inspect_tbl);
}
-#else
- if (!inspect_tbl) {
- inspect_tbl = rb_ary_new();
- rb_global_variable(&inspect_tbl);
- }
-#endif
rb_ary_push(inspect_tbl, obj);
iarg.func = func;
iarg.arg1 = obj;
@@ -808,15 +771,11 @@ VALUE
rb_inspecting_p(obj)
VALUE obj;
{
-#ifdef USE_THREAD
VALUE inspect_tbl;
if (!inspect_key) return Qfalse;
inspect_tbl = rb_thread_local_aref(rb_thread_current(), inspect_key);
if (NIL_P(inspect_tbl)) return Qfalse;
-#else
- if (!inspect_tbl) return Qnil;
-#endif
return rb_ary_includes(inspect_tbl, obj);
}
@@ -824,7 +783,7 @@ static VALUE
inspect_ary(ary)
VALUE ary;
{
- size_t i = 0;
+ long i = 0;
VALUE s, str;
str = rb_str_new2("[");
@@ -953,7 +912,7 @@ rb_ary_delete(ary, item)
VALUE ary;
VALUE item;
{
- size_t i1, i2;
+ long i1, i2;
rb_ary_modify(ary);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
@@ -981,11 +940,11 @@ rb_ary_delete_at(ary, at)
VALUE ary;
VALUE at;
{
- size_t i1, i2, pos;
+ long i1, i2, pos;
VALUE del = Qnil;
rb_ary_modify(ary);
- pos = NUM2UINT(at);
+ pos = NUM2LONG(at);
for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) {
if (i1 == pos) {
del = RARRAY(ary)->ptr[i1];
@@ -1005,11 +964,11 @@ static VALUE
rb_ary_delete_if(ary)
VALUE ary;
{
- size_t i1, i2;
+ long i1, i2;
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];
}
@@ -1024,7 +983,7 @@ static VALUE
rb_ary_filter(ary)
VALUE ary;
{
- size_t i;
+ long i;
rb_ary_modify(ary);
for (i = 0; i < RARRAY(ary)->len; i++) {
@@ -1038,7 +997,7 @@ rb_ary_replace_method(ary, ary2)
VALUE ary, ary2;
{
ary2 = to_ary(ary2);
- rb_ary_replace(ary, 0, RARRAY(ary2)->len, ary2);
+ rb_ary_replace(ary, 0, RARRAY(ary)->len, ary2);
return ary;
}
@@ -1061,20 +1020,28 @@ rb_ary_fill(argc, argv, ary)
VALUE ary;
{
VALUE item, arg1, arg2;
- size_t beg, len, end;
+ long beg, end, len;
VALUE *p, *pend;
- if (rb_scan_args(argc, argv, "12", &item, &arg1, &arg2) == 2 &&
- beg_len(arg1, &beg, &len, RARRAY(ary)->len)) {
- /* beg and len set already */
- }
- else {
- beg = NIL_P(arg1)?0:NUM2UINT(arg1);
+ rb_scan_args(argc, argv, "12", &item, &arg1, &arg2);
+ 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;
}
- len = NIL_P(arg2)?RARRAY(ary)->len - beg:NUM2UINT(arg2);
+ len = NIL_P(arg2)?RARRAY(ary)->len - beg:NUM2LONG(arg2);
+ break;
}
rb_ary_modify(ary);
end = beg + len;
@@ -1138,13 +1105,13 @@ rb_ary_times(ary, times)
VALUE times;
{
VALUE ary2;
- size_t i, len;
+ long i, len;
if (TYPE(times) == T_STRING) {
return rb_ary_join(ary, times);
}
- len = NUM2UINT(times);
+ len = NUM2LONG(times);
if (len < 0) {
rb_raise(rb_eArgError, "negative argument");
}
@@ -1200,7 +1167,7 @@ static VALUE
rb_ary_equal(ary1, ary2)
VALUE ary1, ary2;
{
- size_t i;
+ long i;
if (TYPE(ary2) != T_ARRAY) return Qfalse;
if (RARRAY(ary1)->len != RARRAY(ary2)->len) return Qfalse;
@@ -1215,7 +1182,7 @@ static VALUE
rb_ary_eql(ary1, ary2)
VALUE ary1, ary2;
{
- size_t i;
+ long i;
if (TYPE(ary2) != T_ARRAY) return Qfalse;
if (RARRAY(ary1)->len != RARRAY(ary2)->len)
@@ -1231,7 +1198,7 @@ static VALUE
rb_ary_hash(ary)
VALUE ary;
{
- size_t i;
+ long i;
int h;
h = RARRAY(ary)->len;
@@ -1247,7 +1214,7 @@ rb_ary_includes(ary, item)
VALUE ary;
VALUE item;
{
- size_t i;
+ long i;
for (i=0; i<RARRAY(ary)->len; i++) {
if (rb_equal(RARRAY(ary)->ptr[i], item)) {
return Qtrue;
@@ -1261,7 +1228,7 @@ rb_ary_cmp(ary, ary2)
VALUE ary;
VALUE ary2;
{
- size_t i, len;
+ long i, len;
ary2 = to_ary(ary2);
len = RARRAY(ary)->len;
@@ -1285,7 +1252,7 @@ rb_ary_diff(ary1, ary2)
VALUE ary1, ary2;
{
VALUE ary3;
- size_t i;
+ long i;
ary2 = to_ary(ary2);
ary3 = rb_ary_new();
@@ -1302,7 +1269,7 @@ rb_ary_and(ary1, ary2)
VALUE ary1, ary2;
{
VALUE ary3;
- size_t i;
+ long i;
ary2 = to_ary(ary2);
ary3 = rb_ary_new();
@@ -1320,7 +1287,7 @@ rb_ary_or(ary1, ary2)
VALUE ary1, ary2;
{
VALUE ary3;
- size_t i;
+ long i;
if (TYPE(ary2) != T_ARRAY) {
if (rb_ary_includes(ary1, ary2)) return ary1;
@@ -1414,7 +1381,7 @@ static VALUE
rb_ary_nitems(ary)
VALUE ary;
{
- size_t n = 0;
+ long n = 0;
VALUE *p, *pend;
p = RARRAY(ary)->ptr;
@@ -1423,14 +1390,14 @@ rb_ary_nitems(ary)
if (!NIL_P(*p)) n++;
p++;
}
- return INT2FIX(n);
+ return INT2NUM(n);
}
static VALUE
rb_ary_flatten_bang(ary)
VALUE ary;
{
- size_t i;
+ long i;
int mod = 0;
rb_ary_modify(ary);
@@ -1504,6 +1471,7 @@ Init_Array()
rb_define_method(rb_cArray, "delete", rb_ary_delete, 1);
rb_define_method(rb_cArray, "delete_at", rb_ary_delete_at, 1);
rb_define_method(rb_cArray, "delete_if", rb_ary_delete_if, 0);
+ rb_define_method(rb_cArray, "reject!", rb_ary_delete_if, 0);
rb_define_method(rb_cArray, "filter", rb_ary_filter, 0);
rb_define_method(rb_cArray, "replace", rb_ary_replace_method, 1);
rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);
diff --git a/bignum.c b/bignum.c
index 770e86ad80..36a46af3fd 100644
--- a/bignum.c
+++ b/bignum.c
@@ -26,7 +26,7 @@ typedef unsigned short USHORT;
static VALUE
bignew_1(klass, len, sign)
VALUE klass;
- size_t len;
+ long len;
char sign;
{
NEWOBJ(big, struct RBignum);
@@ -54,7 +54,7 @@ void
rb_big_2comp(x) /* get 2's complement */
VALUE x;
{
- int i = RBIGNUM(x)->len;
+ long i = RBIGNUM(x)->len;
USHORT *ds = BDIGITS(x);
long num;
@@ -79,7 +79,7 @@ static VALUE
bignorm(x)
VALUE x;
{
- size_t len = RBIGNUM(x)->len;
+ long len = RBIGNUM(x)->len;
USHORT *ds = BDIGITS(x);
while (len-- && !ds[len]) ;
@@ -165,13 +165,13 @@ rb_int2inum(n)
VALUE
rb_str2inum(str, base)
- char *str;
+ const char *str;
int base;
{
char sign = 1, c;
unsigned long num;
- size_t len, blen = 1;
- int i;
+ long len, blen = 1;
+ long i;
VALUE z;
USHORT *zds;
@@ -191,6 +191,10 @@ rb_str2inum(str, base)
str++;
base = 16;
}
+ else if (*str == 'b' || *str == 'B') {
+ str++;
+ base = 2;
+ }
else {
base = 8;
}
@@ -204,16 +208,19 @@ rb_str2inum(str, base)
while (str[0] == '0') 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;
}
+ if (base == 2 && str[0] == '0' && (str[1] == 'b'||str[1] == 'B')) {
+ str += 2;
+ }
while (str[0] == '0') str++;
len = 4*strlen(str)*sizeof(char);
}
if (len <= (sizeof(VALUE)*CHAR_BIT)) {
- unsigned int val = strtoul((char*)str, 0, base);
+ unsigned long val = strtoul((char*)str, 0, base);
if (POSFIXABLE(val)) {
if (sign) return INT2FIX(val);
@@ -278,7 +285,7 @@ rb_big2str(x, base)
{
VALUE t;
USHORT *ds;
- unsigned int i, j, hbase;
+ unsigned long i, j, hbase;
VALUE ss;
char *s, c;
@@ -316,7 +323,7 @@ rb_big2str(x, base)
s[0] = RBIGNUM(x)->sign ? '+' : '-';
while (i && j) {
- int k = i;
+ long k = i;
unsigned long num = 0;
while (k--) {
num = BIGUP(num) + ds[k];
@@ -352,7 +359,7 @@ rb_big2ulong(x)
VALUE x;
{
unsigned long num;
- size_t len = RBIGNUM(x)->len;
+ long len = RBIGNUM(x)->len;
USHORT *ds;
if (len > sizeof(long)/sizeof(USHORT))
@@ -390,13 +397,20 @@ VALUE
rb_dbl2big(d)
double d;
{
- unsigned int i = 0;
+ unsigned long i = 0;
long c;
USHORT *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++;
}
@@ -417,7 +431,7 @@ rb_big2dbl(x)
VALUE x;
{
double d = 0.0;
- size_t i = RBIGNUM(x)->len;
+ long i = RBIGNUM(x)->len;
USHORT *ds = BDIGITS(x);
while (i--) {
@@ -438,7 +452,7 @@ static VALUE
rb_big_cmp(x, y)
VALUE x, y;
{
- size_t xlen = RBIGNUM(x)->len;
+ long xlen = RBIGNUM(x)->len;
switch (TYPE(y)) {
case T_FIXNUM:
@@ -490,7 +504,7 @@ rb_big_neg(x)
VALUE x;
{
VALUE z = rb_big_clone(x);
- size_t i = RBIGNUM(x)->len;
+ long i = RBIGNUM(x)->len;
USHORT *ds = BDIGITS(z);
if (!RBIGNUM(x)->sign) rb_big_2comp(z);
@@ -508,7 +522,7 @@ bigsub(x, y)
VALUE z = 0;
USHORT *zds;
long num;
- size_t i;
+ long i;
i = RBIGNUM(x)->len;
/* if x is larger than y, swap */
@@ -556,7 +570,7 @@ bigadd(x, y, sign)
{
VALUE z;
long num;
- size_t i, len;
+ long i, len;
sign = (sign == RBIGNUM(y)->sign);
if (RBIGNUM(x)->sign != sign) {
@@ -636,7 +650,7 @@ VALUE
rb_big_mul(x, y)
VALUE x, y;
{
- size_t i, j;
+ long i, j;
unsigned long n = 0;
VALUE z;
USHORT *zds;
@@ -685,11 +699,11 @@ bigdivmod(x, y, div, mod, modulo)
VALUE *div, *mod;
int modulo;
{
- size_t nx = RBIGNUM(x)->len, ny = RBIGNUM(y)->len;
- int i, j;
+ long nx = RBIGNUM(x)->len, ny = RBIGNUM(y)->len;
+ long i, j;
VALUE yy, z;
USHORT *xds, *yds, *zds, *tds;
- size_t t2;
+ unsigned long t2;
long num;
USHORT dd, q;
@@ -711,10 +725,11 @@ bigdivmod(x, y, div, mod, modulo)
zds[i] = (USHORT)(t2 / dd);
t2 %= dd;
}
+ RBIGNUM(z)->sign = RBIGNUM(x)->sign==RBIGNUM(y)->sign;
if (div) *div = bignorm(z);
if (mod) {
if (!RBIGNUM(y)->sign) t2 = -(long)t2;
- *mod = INT2FIX(t2);
+ *mod = INT2NUM(t2);
}
return;
}
@@ -798,7 +813,7 @@ bigdivmod(x, y, div, mod, modulo)
RBIGNUM(*mod)->len = ny;
RBIGNUM(*mod)->sign = RBIGNUM(x)->sign;
if (modulo && RBIGNUM(x)->sign != RBIGNUM(y)->sign) {
- size_t len = ny;
+ long len = ny;
zds = BDIGITS(*mod);
while (len-- && !zds[len]);
if (len > 0) {
@@ -936,6 +951,7 @@ rb_big_pow(x, y)
}
z = rb_big_mul(z, x);
}
+ if (!FIXNUM_P(z)) z = bignorm(z);
return z;
}
d = (double)yy;
@@ -953,7 +969,7 @@ rb_big_and(x, y)
{
VALUE z;
USHORT *ds1, *ds2, *zds;
- size_t i, l1, l2;
+ long i, l1, l2;
char sign;
if (FIXNUM_P(y)) {
@@ -985,7 +1001,7 @@ rb_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++) {
@@ -1004,7 +1020,7 @@ rb_big_or(x, y)
{
VALUE z;
USHORT *ds1, *ds2, *zds;
- unsigned int i, l1, l2;
+ unsigned long i, l1, l2;
char sign;
if (FIXNUM_P(y)) {
@@ -1036,7 +1052,7 @@ rb_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++) {
@@ -1112,11 +1128,11 @@ rb_big_lshift(x, y)
{
USHORT *xds, *zds;
int shift = NUM2INT(y);
- size_t s1 = shift/BITSPERDIG;
- size_t s2 = shift%BITSPERDIG;
+ int s1 = shift/BITSPERDIG;
+ int s2 = shift%BITSPERDIG;
VALUE z;
unsigned long num = 0;
- size_t len, i;
+ long len, i;
if (shift < 0) return rb_big_rshift(x, INT2FIX(-shift));
xds = BDIGITS(x);
@@ -1141,12 +1157,12 @@ rb_big_rshift(x, y)
{
USHORT *xds, *zds;
int shift = NUM2INT(y);
- size_t s1 = shift/BITSPERDIG;
- size_t s2 = shift%BITSPERDIG;
+ int s1 = shift/BITSPERDIG;
+ int s2 = shift%BITSPERDIG;
VALUE z;
unsigned long num = 0;
- size_t i = RBIGNUM(x)->len;
- size_t j;
+ long i = RBIGNUM(x)->len;
+ long j;
if (shift < 0) return rb_big_lshift(x, INT2FIX(-shift));
if (s1 > RBIGNUM(x)->len) {
@@ -1173,7 +1189,7 @@ rb_big_aref(x, y)
{
USHORT *xds;
int shift = NUM2INT(y);
- size_t s1, s2;
+ int s1, s2;
if (shift < 0) return INT2FIX(0);
s1 = shift/BITSPERDIG;
@@ -1197,7 +1213,7 @@ static VALUE
rb_big_hash(x)
VALUE x;
{
- size_t i, len;
+ long i, len;
int key;
USHORT *digits;
@@ -1216,7 +1232,7 @@ rb_big_coerce(x, y)
return rb_assoc_new(rb_int2big(FIX2LONG(y)), x);
}
else {
- rb_raise(rb_eTypeError, "can't coerce %s to Bignum",
+ rb_raise(rb_eTypeError, "Can't coerce %s to Bignum",
rb_class2name(CLASS_OF(y)));
}
/* not reached */
@@ -1243,7 +1259,7 @@ rb_big_rand(max)
VALUE max;
{
struct RBignum *v;
- size_t len;
+ long len;
len = RBIGNUM(max)->len;
v = RBIGNUM(bignew(len,1));
diff --git a/class.c b/class.c
index 86ac8c5ae7..32dc0e1372 100644
--- a/class.c
+++ b/class.c
@@ -6,7 +6,7 @@
$Date$
created at: Tue Aug 10 15:05:44 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -105,7 +105,7 @@ rb_define_class_id(id, super)
VALUE
rb_define_class(name, super)
- char *name;
+ const char *name;
VALUE super;
{
VALUE klass;
@@ -122,7 +122,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;
@@ -164,7 +164,7 @@ rb_define_module_id(id)
VALUE
rb_define_module(name)
- char *name;
+ const char *name;
{
VALUE module;
ID id;
@@ -179,7 +179,7 @@ rb_define_module(name)
VALUE
rb_define_module_under(outer, name)
VALUE outer;
- char *name;
+ const char *name;
{
VALUE module;
ID id;
@@ -199,8 +199,11 @@ include_class_new(module, super)
NEWOBJ(klass, struct RClass);
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;
@@ -365,6 +368,8 @@ method_list(mod, option, func)
VALUE klass;
VALUE *p, *q, *pend;
+ if (!FL_TEST(mod, FL_TAINT) && rb_safe_level() >= 4)
+ rb_raise(rb_eSecurityError, "Insecure: can't get metainfo");
ary = rb_ary_new();
for (klass = mod; klass; klass = RCLASS(klass)->super) {
st_foreach(RCLASS(klass)->m_tbl, func, ary);
@@ -426,6 +431,8 @@ rb_obj_singleton_methods(obj)
VALUE klass;
VALUE *p, *q, *pend;
+ if (rb_safe_level() >= 4 && !FL_TEST(obj, FL_TAINT))
+ rb_raise(rb_eSecurityError, "Insecure: can't get metainfo");
ary = rb_ary_new();
klass = CLASS_OF(obj);
while (klass && FL_TEST(klass, FL_SINGLETON)) {
@@ -458,7 +465,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;
{
@@ -472,7 +479,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;
{
@@ -483,7 +490,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;
{
@@ -494,7 +501,7 @@ 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);
}
@@ -504,7 +511,7 @@ rb_singleton_class(obj)
VALUE obj;
{
if (rb_special_const_p(obj)) {
- rb_raise(rb_eTypeError, "cannot define singleton");
+ rb_raise(rb_eTypeError, "can't define singleton");
}
if (FL_TEST(RBASIC(obj)->klass, FL_SINGLETON)) {
return RBASIC(obj)->klass;
@@ -517,7 +524,7 @@ rb_singleton_class(obj)
void
rb_define_singleton_method(obj, name, func, argc)
VALUE obj;
- char *name;
+ const char *name;
VALUE (*func)();
int argc;
{
@@ -527,7 +534,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;
{
@@ -537,7 +544,7 @@ rb_define_module_function(module, name, func, argc)
void
rb_define_global_function(name, func, argc)
- char *name;
+ const char *name;
VALUE (*func)();
int argc;
{
@@ -547,7 +554,7 @@ rb_define_global_function(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));
}
@@ -555,7 +562,7 @@ 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, Qfalse);
@@ -571,17 +578,17 @@ rb_define_attr(klass, name, read, write)
int
#ifdef HAVE_STDARG_PROTOTYPES
-rb_scan_args(int argc, VALUE *argv, char *fmt, ...)
+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;
+ const char *p = fmt;
VALUE *var;
va_list vargs;
@@ -596,10 +603,10 @@ rb_scan_args(argc, argv, fmt, va_alist)
if (ISDIGIT(*p)) {
n = *p - '0';
if (n > argc)
- rb_raise(rb_eArgError, "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++;
}
@@ -612,10 +619,10 @@ rb_scan_args(argc, argv, fmt, va_alist)
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++;
@@ -624,15 +631,15 @@ rb_scan_args(argc, argv, fmt, va_alist)
if(*p == '*') {
var = va_arg(vargs, VALUE*);
if (argc > i) {
- *var = rb_ary_new4(argc-i, argv+i);
+ if (var) *var = rb_ary_new4(argc-i, argv+i);
}
else {
- *var = rb_ary_new();
+ if (var) *var = rb_ary_new();
}
}
else if (*p == '\0') {
if (argc > i) {
- rb_raise(rb_eArgError, "Wrong # of arguments(%d for %d)", argc, i);
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for %d)", argc, i);
}
}
else {
diff --git a/compar.c b/compar.c
index a6212a86bb..50e4fa3a87 100644
--- a/compar.c
+++ b/compar.c
@@ -6,7 +6,7 @@
$Date$
created at: Thu Aug 26 14:39:48 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
diff --git a/config.guess b/config.guess
index 042d209871..7e23afe37b 100644
--- a/config.guess
+++ b/config.guess
@@ -62,6 +62,9 @@ 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}'`
@@ -379,7 +382,7 @@ EOF
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
- 9000/6?? | 9000/7?? | 9000/80[24] | 9000/8?[13679] | 9000/892 )
+ 9000/[678]?? )
sed 's/^ //' << EOF >dummy.c
#include <stdlib.h>
#include <unistd.h>
@@ -621,11 +624,11 @@ EOF
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-gnu${LIBC} ; exit 0
+ echo ${UNAME_MACHINE}-unknown-linux${LIBC} ; exit 0
elif test "${UNAME_MACHINE}" = "mips" ; then
cat >dummy.c <<EOF
main(argc, argv)
diff --git a/config.sub b/config.sub
index 858aba7aa5..aa2241272b 100644
--- a/config.sub
+++ b/config.sub
@@ -151,7 +151,7 @@ case $basic_machine in
# 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 | hppa2.0 \
+ | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w \
| alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \
| i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \
| mips64 | mipsel | mips64el | mips64orion | mips64orionel \
@@ -178,7 +178,7 @@ case $basic_machine in
| m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \
| mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \
| power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \
- | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* \
+ | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \
| alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \
| ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \
| sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \
@@ -705,6 +705,8 @@ case $os in
-gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
+ -os2_emx)
+ ;;
# First accept the basic system types.
# The portable systems comes first.
# Each alternative MUST END IN A *, to match a version number.
@@ -721,7 +723,7 @@ case $os in
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux* | -uxpv* | -beos*)
+ | -mingw32* | -linux* | -uxpv* | -beos* | -rhapsody* )
# Remember, each alternative MUST END IN *, to match a version number.
;;
-sunos5*)
diff --git a/config_h.dj b/config_h.dj
new file mode 100644
index 0000000000..36b80537fd
--- /dev/null
+++ b/config_h.dj
@@ -0,0 +1,71 @@
+#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 "/usr/local/lib/ruby/1.4"
+#define RUBY_SITE_LIB "/usr/local/lib/ruby/1.4/site_ruby"
+#define RUBY_PLATFORM "i386-djgpp"
+#define RUBY_ARCHLIB "/usr/local/lib/ruby/1.4/i386-djgpp"
+#define RUBY_SITE_ARCHLIB "/usr/local/lib/ruby/1.4/site_ruby/i386-djgpp"
diff --git a/config_s.dj b/config_s.dj
new file mode 100644
index 0000000000..7ba18e4376
--- /dev/null
+++ b/config_s.dj
@@ -0,0 +1,56 @@
+s%@CFLAGS@%-O2%g
+s%@CPPFLAGS@%%g
+s%@CXXFLAGS@%%g
+s%@DEFS@% -DUSE_THREAD=1 -DSIZEOF_INT=4 -DSIZEOF_LONG=4 -DSIZEOF_VOIDP=4 -DHAVE_PROTOTYPES=1 -DHAVE_STDARG_PROTOTYPES=1 -DHAVE_ATTR_NORETURN=1 -DHAVE_DIRENT_H=1 -DSTDC_HEADERS=1 -DHAVE_STDLIB_H=1 -DHAVE_UNISTD_H=1 -DHAVE_LIMITS_H=1 -DHAVE_SYS_FILE_H=1 -DHAVE_SYS_IOCTL_H=1 -DHAVE_PWD_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_TIMES_H=1 -DHAVE_SYS_PARAM_H=1 -DHAVE_SYS_WAIT_H=1 -DHAVE_STRING_H=1 -DHAVE_UTIME_H=1 -DHAVE_MEMORY_H=1 -DHAVE_DIRECT_H=1 -DHAVE_ST_BLKSIZE=1 -DHAVE_ST_RDEV=1 -DGETGROUPS_T=gid_t -DRETSIGTYPE=void -DHAVE_ALLOCA=1 -Dvfork=fork -DHAVE_DUP2=1 -DHAVE_SETENV=1 -DHAVE_MEMMOVE=1 -DHAVE_MKDIR=1 -DHAVE_STRCASECMP=1 -DHAVE_STRERROR=1 -DHAVE_STRFTIME=1 -DHAVE_STRCHR=1 -DHAVE_STRSTR=1 -DHAVE_STRTOUL=1 -DHAVE_STRDUP=1 -DHAVE_FMOD=1 -DHAVE_RANDOM=1 -DHAVE_WAITPID=1 -DHAVE_GETCWD=1 -DHAVE_TRUNCATE=1 -DHAVE_CHSIZE=1 -DHAVE_TIMES=1 -DHAVE_UTIMES=1 -DHAVE_FCNTL=1 -DHAVE_SETITIMER=1 -DHAVE_GETGROUPS=1 -DHAVE_SIGPROCMASK=1 -DHAVE_SIGACTION=1 -DHAVE_SETSID=1 -DPOSIX_SIGNAL=1 -DBSD_SETPGRP=setpgrp -DRSHIFT=\(x,y\)\ \(\(x\)\>\>y\) -DFILE_COUNT=_cnt -DDLEXT=\".so\" -DRUBY_LIB=\"/usr/local/lib/ruby\" -DRUBY_SITE_LIB=\"/usr/local/lib/ruby/site_ruby\" -DRUBY_ARCHLIB=\"/usr/local/lib/ruby/i386-djgpp\" -DRUBY_SITE_ARCHLIB=\"/usr/local/lib/ruby/site_ruby/i386-djgpp\" -DRUBY_PLATFORM=\"i386-djgpp\" %g
+s%@LDFLAGS@%%g
+s%@LIBS@%-lm %g
+s%@exec_prefix@%${prefix}%g
+s%@prefix@%/usr/local%g
+s%@program_transform_name@%s,x,x,%g
+s%@bindir@%${exec_prefix}/bin%g
+s%@sbindir@%${exec_prefix}/sbin%g
+s%@libexecdir@%${exec_prefix}/libexec%g
+s%@datadir@%${prefix}/share%g
+s%@sysconfdir@%${prefix}/etc%g
+s%@sharedstatedir@%${prefix}/com%g
+s%@localstatedir@%${prefix}/var%g
+s%@libdir@%${exec_prefix}/lib%g
+s%@includedir@%${prefix}/include%g
+s%@oldincludedir@%/usr/include%g
+s%@infodir@%${prefix}/info%g
+s%@mandir@%${prefix}/man%g
+s%@host@%i386-pc-djgpp%g
+s%@host_alias@%i386-djgpp%g
+s%@host_cpu@%i386%g
+s%@host_vendor@%pc%g
+s%@host_os@%djgpp%g
+s%@CC@%gcc%g
+s%@CPP@%gcc -E%g
+s%@YACC@%bison -y%g
+s%@RANLIB@%ranlib%g
+s%@AR@%ar%g
+s%@INSTALL_PROGRAM@%${INSTALL}%g
+s%@INSTALL_DATA@%${INSTALL} -m 644%g
+s%@SET_MAKE@%%g
+s%@LIBOBJS@% crypt.o flock.o fnmatch.o snprintf.o%g
+s%@ALLOCA@%%g
+s%@DEFAULT_KCODE@%%g
+s%@EXEEXT@%.exe%g
+s%@OBJEXT@%o%g
+s%@DLDFLAGS@%%g
+s%@STATIC@%%g
+s%@CCDLFLAGS@%%g
+s%@LDSHARED@%ld%g
+s%@DLEXT@%o%g
+s%@STRIP@%strip%g
+s%@EXTSTATIC@%%g
+s%@binsuffix@%.exe%g
+s%@setup@%Setup%g
+s%@LIBRUBY@%libruby.a%g
+s%@LIBRUBY_A@%libruby.a%g
+s%@LIBRUBYARG@%libruby.a%g
+s%@LIBRUBY_SO@%%g
+s%@SOLIBS@%%g
+s%@srcdir%.%g
+s%@arch@%i386-djgpp%g
+ac_given_srcdir=.
diff --git a/configure b/configure
index 31a40f05e8..700b05c496 100644
--- a/configure
+++ b/configure
@@ -1,7 +1,7 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated automatically using autoconf version 2.12.2
+# Generated automatically using autoconf version 2.13
# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc.
#
# This configure script is free software; the Free Software Foundation
@@ -14,13 +14,17 @@ ac_default_prefix=/usr/local
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/Apple Multi Architecture Binary. "
ac_help="$ac_help
+--with-default-kcode=CODE specify default value for \$KCODE (utf8|euc|sjis|none)"
+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"
+ac_help="$ac_help
+--enable-shared build a shared library for Ruby. "
+ac_help="$ac_help
+--with-search-path specify the additional search path"
# Initialize some variables set by options.
# The variables have the same names as the options, with
@@ -343,7 +347,7 @@ EOF
verbose=yes ;;
-version | --version | --versio | --versi | --vers)
- echo "configure generated by autoconf version 2.12.2"
+ echo "configure generated by autoconf version 2.13"
exit 0 ;;
-with-* | --with-*)
@@ -532,6 +536,13 @@ fi
+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]*\)"'`
+
+
+
# Check whether --with-gcc or --without-gcc was given.
if test "${with_gcc+set}" = set; then
withval="$with_gcc"
@@ -554,22 +565,6 @@ then
(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 USE_THREAD 1
-EOF
-
-fi
-
ac_aux_dir=
for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do
if test -f $ac_dir/install-sh; then
@@ -596,7 +591,7 @@ 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:600: checking host system type" >&5
+echo "configure:595: checking host system type" >&5
host_alias=$host
case "$host_alias" in
@@ -621,30 +616,22 @@ 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
+ fat_binary=$enableval
fi
if test "$fat_binary" = yes ; then
- echo $ac_n "checking target architecture ""... $ac_c" 1>&6
-echo "configure:631: checking target architecture " >&5
+ echo $ac_n "checking target architecture""... $ac_c" 1>&6
+echo "configure:626: checking target architecture" >&5
case "$host_os" in
rhapsody*)
echo -n "MacOS X Server: "
- if test "$TARGET_ARCHS" = "" ; then
- TARGET_ARCHS="ppc i386"
- fi
+ if test "$TARGET_ARCHS" = "" ; then
+ TARGET_ARCHS="ppc i386"
+ fi
;;
nextstep*|openstep*)
- echo -n "NeXTSTEP/OPENSTEP: "
-
- if test "$host_os" = "rhapsody" ; then
- echo -n "Rhapsody: "
- if test "$TARGET_ARCHS" = "" ; then
- TARGET_ARCHS="ppc i486"
- fi
- else
echo -n "NeXTSTEP/OPENSTEP: "
if test "$TARGET_ARCHS" = "" ; then
if test `/usr/bin/arch` = "m68k" ; then
@@ -653,7 +640,6 @@ echo "configure:631: checking target architecture " >&5
TARGET_ARCHS="m68k `/usr/bin/arch`"
fi
fi
- fi
;;
esac
# /usr/lib/arch_tool -archify_list $TARGET_ARCHS
@@ -663,7 +649,7 @@ echo "configure:631: checking target architecture " >&5
echo -n " $archs"
done
cat >> confdefs.h <<\EOF
-#define NEXT_FAT_BINARY 1
+#define NEXT_FAT_BINARY 1
EOF
echo "."
@@ -692,7 +678,7 @@ 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:696: checking for $ac_word" >&5
+echo "configure:682: 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
@@ -722,7 +708,7 @@ 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:726: checking for $ac_word" >&5
+echo "configure:712: 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
@@ -773,7 +759,7 @@ fi
# Extract the first word of "cl", so it can be a program name with args.
set dummy cl; ac_word=$2
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
-echo "configure:777: checking for $ac_word" >&5
+echo "configure:763: 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
@@ -805,7 +791,7 @@ fi
fi
echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6
-echo "configure:809: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5
+echo "configure:795: 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.
@@ -816,12 +802,12 @@ cross_compiling=$ac_cv_prog_cc_cross
cat > conftest.$ac_ext << EOF
-#line 820 "configure"
+#line 806 "configure"
#include "confdefs.h"
main(){return(0);}
EOF
-if { (eval echo configure:825: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:811: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
ac_cv_prog_cc_works=yes
# If we can't run a trivial program, we are probably using a cross compiler.
if (./conftest; exit) 2>/dev/null; then
@@ -847,12 +833,12 @@ 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:851: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5
+echo "configure:837: 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:856: checking whether we are using GNU C" >&5
+echo "configure:842: 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
@@ -861,7 +847,7 @@ else
yes;
#endif
EOF
-if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:865: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
+if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:851: \"$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
@@ -880,7 +866,7 @@ ac_test_CFLAGS="${CFLAGS+set}"
ac_save_CFLAGS="$CFLAGS"
CFLAGS=
echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
-echo "configure:884: checking whether ${CC-cc} accepts -g" >&5
+echo "configure:870: 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
@@ -912,7 +898,7 @@ else
fi
echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6
-echo "configure:916: checking how to run the C preprocessor" >&5
+echo "configure:902: checking how to run the C preprocessor" >&5
# On Suns, sometimes $CPP names a directory.
if test -n "$CPP" && test -d "$CPP"; then
CPP=
@@ -927,13 +913,13 @@ else
# On the NeXT, cc -E runs the code through the compiler's parser,
# not just through cpp.
cat > conftest.$ac_ext <<EOF
-#line 931 "configure"
+#line 917 "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:937: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:923: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -944,13 +930,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -E -traditional-cpp"
cat > conftest.$ac_ext <<EOF
-#line 948 "configure"
+#line 934 "configure"
#include "confdefs.h"
#include <assert.h>
Syntax Error
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:954: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:940: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -961,13 +947,13 @@ else
rm -rf conftest*
CPP="${CC-cc} -nologo -E"
cat > conftest.$ac_ext <<EOF
-#line 965 "configure"
+#line 951 "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:971: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:957: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
:
@@ -993,13 +979,13 @@ echo "$ac_t""$CPP" 1>&6
if test $ac_cv_prog_gcc = yes; then
echo $ac_n "checking whether ${CC-cc} needs -traditional""... $ac_c" 1>&6
-echo "configure:997: checking whether ${CC-cc} needs -traditional" >&5
+echo "configure:983: 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 1003 "configure"
+#line 989 "configure"
#include "confdefs.h"
#include <sgtty.h>
Autoconf TIOCGETP
@@ -1017,7 +1003,7 @@ rm -f conftest*
if test $ac_cv_prog_gcc_traditional = no; then
cat > conftest.$ac_ext <<EOF
-#line 1021 "configure"
+#line 1007 "configure"
#include "confdefs.h"
#include <termio.h>
Autoconf TCGETA
@@ -1043,7 +1029,7 @@ 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:1047: checking for $ac_word" >&5
+echo "configure:1033: 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
@@ -1076,7 +1062,7 @@ 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:1080: checking for $ac_word" >&5
+echo "configure:1066: 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
@@ -1109,7 +1095,7 @@ 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:1113: checking for $ac_word" >&5
+echo "configure:1099: 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
@@ -1139,72 +1125,30 @@ 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
-# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
-# AFS /usr/afsws/bin/install, which mishandles nonexistent args
-# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
-# ./install, which can be erroneously created by make from ./install.sh.
-echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
-echo "configure:1155: checking for a BSD compatible install" >&5
-if test -z "$INSTALL"; then
-if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
+
+echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6
+echo "configure:1131: checking whether ln -s works" >&5
+if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
- IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS=":"
- for ac_dir in $PATH; do
- # Account for people who put trailing slashes in PATH elements.
- case "$ac_dir/" in
- /|./|.//|/etc/*|/usr/sbin/*|/usr/etc/*|/sbin/*|/usr/afsws/bin/*|/usr/ucb/*) ;;
- *)
- # OSF1 and SCO ODT 3.0 have their own names for install.
- # Don't use installbsd from OSF since it installs stuff as root
- # by default.
- for ac_prog in ginstall scoinst install; do
- if test -f $ac_dir/$ac_prog; then
- if test $ac_prog = install &&
- grep dspmsg $ac_dir/$ac_prog >/dev/null 2>&1; then
- # AIX install. It has an incompatible calling convention.
- :
- else
- ac_cv_path_install="$ac_dir/$ac_prog -c"
- break 2
- fi
- fi
- done
- ;;
- esac
- done
- IFS="$ac_save_IFS"
-
+ rm -f conftestdata
+if ln -s X conftestdata 2>/dev/null
+then
+ rm -f conftestdata
+ ac_cv_prog_LN_S="ln -s"
+else
+ ac_cv_prog_LN_S=ln
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_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}'
-
-test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+LN_S="$ac_cv_prog_LN_S"
+if test "$ac_cv_prog_LN_S" = "ln -s"; then
+ echo "$ac_t""yes" 1>&6
+else
+ echo "$ac_t""no" 1>&6
+fi
echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6
-echo "configure:1208: checking whether ${MAKE-make} sets \${MAKE}" >&5
+echo "configure:1152: 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
@@ -1231,20 +1175,140 @@ else
fi
+echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6
+echo "configure:1180: checking for Cygwin environment" >&5
+if eval "test \"`echo '$''{'ac_cv_cygwin'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1185 "configure"
+#include "confdefs.h"
+
+int main() {
+
+#ifndef __CYGWIN__
+#define __CYGWIN__ __CYGWIN32__
+#endif
+return __CYGWIN__;
+; return 0; }
+EOF
+if { (eval echo configure:1196: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_cygwin=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_cygwin=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_cygwin" 1>&6
+CYGWIN=
+test "$ac_cv_cygwin" = yes && CYGWIN=yes
+echo $ac_n "checking for mingw32 environment""... $ac_c" 1>&6
+echo "configure:1213: checking for mingw32 environment" >&5
+if eval "test \"`echo '$''{'ac_cv_mingw32'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1218 "configure"
+#include "confdefs.h"
+
+int main() {
+return __MINGW32__;
+; return 0; }
+EOF
+if { (eval echo configure:1225: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_mingw32=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_mingw32=no
+fi
+rm -f conftest*
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_mingw32" 1>&6
+MINGW32=
+test "$ac_cv_mingw32" = yes && MINGW32=yes
+
+
+echo $ac_n "checking for executable suffix""... $ac_c" 1>&6
+echo "configure:1244: checking for executable suffix" >&5
+if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$CYGWIN" = yes || test "$MINGW32" = yes; then
+ ac_cv_exeext=.exe
+else
+ rm -f conftest*
+ echo 'int main () { return 0; }' > conftest.$ac_ext
+ ac_cv_exeext=
+ if { (eval echo configure:1254: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then
+ for file in conftest.*; do
+ case $file in
+ *.c | *.o | *.obj) ;;
+ *) ac_cv_exeext=`echo $file | sed -e s/conftest//` ;;
+ esac
+ done
+ else
+ { echo "configure: error: installation or configuration problem: compiler cannot create executables." 1>&2; exit 1; }
+ fi
+ rm -f conftest*
+ test x"${ac_cv_exeext}" = x && ac_cv_exeext=no
+fi
+fi
+
+EXEEXT=""
+test x"${ac_cv_exeext}" != xno && EXEEXT=${ac_cv_exeext}
+echo "$ac_t""${ac_cv_exeext}" 1>&6
+ac_exeext=$EXEEXT
+
+echo $ac_n "checking for object suffix""... $ac_c" 1>&6
+echo "configure:1275: checking for object suffix" >&5
+if eval "test \"`echo '$''{'ac_cv_objext'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ rm -f conftest*
+echo 'int i = 1;' > conftest.$ac_ext
+if { (eval echo configure:1281: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ for ac_file in conftest.*; do
+ case $ac_file in
+ *.c) ;;
+ *) ac_cv_objext=`echo $ac_file | sed -e s/conftest.//` ;;
+ esac
+ done
+else
+ { echo "configure: error: installation or configuration problem; compiler does not work" 1>&2; exit 1; }
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_objext" 1>&6
+OBJEXT=$ac_cv_objext
+ac_objext=$ac_cv_objext
+
+
# 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:1238: checking for minix/config.h" >&5
+echo "configure:1302: 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 1243 "configure"
+#line 1307 "configure"
#include "confdefs.h"
#include <minix/config.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1248: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:1312: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1283,7 +1347,7 @@ fi
echo $ac_n "checking size of int""... $ac_c" 1>&6
-echo "configure:1287: checking size of int" >&5
+echo "configure:1351: 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
@@ -1291,7 +1355,7 @@ else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 1295 "configure"
+#line 1359 "configure"
#include "confdefs.h"
#include <stdio.h>
main()
@@ -1302,7 +1366,7 @@ main()
exit(0);
}
EOF
-if { (eval echo configure:1306: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1370: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_sizeof_int=`cat conftestval`
else
@@ -1321,8 +1385,47 @@ cat >> confdefs.h <<EOF
EOF
+echo $ac_n "checking size of short""... $ac_c" 1>&6
+echo "configure:1390: 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 1398 "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:1409: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./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 long""... $ac_c" 1>&6
-echo "configure:1326: checking size of long" >&5
+echo "configure:1429: 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
@@ -1330,7 +1433,7 @@ else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 1334 "configure"
+#line 1437 "configure"
#include "confdefs.h"
#include <stdio.h>
main()
@@ -1341,7 +1444,7 @@ main()
exit(0);
}
EOF
-if { (eval echo configure:1345: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1448: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_sizeof_long=`cat conftestval`
else
@@ -1361,7 +1464,7 @@ EOF
echo $ac_n "checking size of void*""... $ac_c" 1>&6
-echo "configure:1365: checking size of void*" >&5
+echo "configure:1468: 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
@@ -1369,7 +1472,7 @@ else
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 1373 "configure"
+#line 1476 "configure"
#include "confdefs.h"
#include <stdio.h>
main()
@@ -1380,7 +1483,7 @@ main()
exit(0);
}
EOF
-if { (eval echo configure:1384: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:1487: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_sizeof_voidp=`cat conftestval`
else
@@ -1399,21 +1502,99 @@ cat >> confdefs.h <<EOF
EOF
+echo $ac_n "checking size of float""... $ac_c" 1>&6
+echo "configure:1507: checking size of float" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_float'+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 1515 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(float));
+ exit(0);
+}
+EOF
+if { (eval echo configure:1526: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_float=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_float=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_float" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_FLOAT $ac_cv_sizeof_float
+EOF
+
+
+echo $ac_n "checking size of double""... $ac_c" 1>&6
+echo "configure:1546: checking size of double" >&5
+if eval "test \"`echo '$''{'ac_cv_sizeof_double'+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 1554 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof(double));
+ exit(0);
+}
+EOF
+if { (eval echo configure:1565: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_sizeof_double=`cat conftestval`
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_sizeof_double=0
+fi
+rm -fr conftest*
+fi
+
+fi
+echo "$ac_t""$ac_cv_sizeof_double" 1>&6
+cat >> confdefs.h <<EOF
+#define SIZEOF_DOUBLE $ac_cv_sizeof_double
+EOF
+
+
echo $ac_n "checking for prototypes""... $ac_c" 1>&6
-echo "configure:1405: checking for prototypes" >&5
+echo "configure:1586: checking for prototypes" >&5
if eval "test \"`echo '$''{'rb_cv_have_prototypes'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1410 "configure"
+#line 1591 "configure"
#include "confdefs.h"
int foo(int x) { return 0; }
int main() {
return foo(10);
; return 0; }
EOF
-if { (eval echo configure:1417: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1598: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_have_prototypes=yes
else
@@ -1433,13 +1614,51 @@ EOF
fi
+echo $ac_n "checking token paste string""... $ac_c" 1>&6
+echo "configure:1619: checking token paste string" >&5
+if eval "test \"`echo '$''{'rb_cv_tokenpaste'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 1624 "configure"
+#include "confdefs.h"
+#define paste(a,b) a##b
+int main() {
+int xy = 1; return paste(x,y);
+; return 0; }
+EOF
+if { (eval echo configure:1631: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ rb_cv_tokenpaste=ansi
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ rb_cv_tokenpaste=knr
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$rb_cv_tokenpaste" 1>&6
+if test "$rb_cv_tokenpaste" = ansi; then
+ cat >> confdefs.h <<\EOF
+#define TOKEN_PASTE(x,y) x##y
+EOF
+
+else
+ cat >> confdefs.h <<\EOF
+#define TOKEN_PASTE(x,y) x/**/y
+EOF
+
+fi
+
echo $ac_n "checking for variable length prototypes and stdarg.h""... $ac_c" 1>&6
-echo "configure:1438: checking for variable length prototypes and stdarg.h" >&5
+echo "configure:1657: checking for variable length prototypes and stdarg.h" >&5
if eval "test \"`echo '$''{'rb_cv_stdarg'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1443 "configure"
+#line 1662 "configure"
#include "confdefs.h"
#include <stdarg.h>
@@ -1456,7 +1675,7 @@ int main() {
return foo(10, "", 3.14);
; return 0; }
EOF
-if { (eval echo configure:1460: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1679: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_stdarg=yes
else
@@ -1477,19 +1696,19 @@ EOF
fi
echo $ac_n "checking for gcc attribute noreturn""... $ac_c" 1>&6
-echo "configure:1481: checking for gcc attribute noreturn" >&5
+echo "configure:1700: checking for gcc attribute noreturn" >&5
if eval "test \"`echo '$''{'rb_cv_have_attr_noreturn'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
cat > conftest.$ac_ext <<EOF
-#line 1486 "configure"
+#line 1705 "configure"
#include "confdefs.h"
void exit(int x) __attribute__ ((noreturn));
int main() {
; return 0; }
EOF
-if { (eval echo configure:1493: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1712: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_have_attr_noreturn=yes
else
@@ -1515,10 +1734,11 @@ openstep*) ;;
rhapsody*) ;;
human*) ;;
beos*) ;;
+cygwin*) ;;
*) LIBS="-lm $LIBS";;
esac
echo $ac_n "checking for crypt in -lcrypt""... $ac_c" 1>&6
-echo "configure:1522: checking for crypt in -lcrypt" >&5
+echo "configure:1742: 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
@@ -1526,7 +1746,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lcrypt $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1530 "configure"
+#line 1750 "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
@@ -1537,7 +1757,7 @@ int main() {
crypt()
; return 0; }
EOF
-if { (eval echo configure:1541: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1761: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1565,7 +1785,7 @@ else
fi
echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6
-echo "configure:1569: checking for dlopen in -ldl" >&5
+echo "configure:1789: 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
@@ -1573,7 +1793,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ldl $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1577 "configure"
+#line 1797 "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
@@ -1584,7 +1804,7 @@ int main() {
dlopen()
; return 0; }
EOF
-if { (eval echo configure:1588: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1808: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1612,7 +1832,7 @@ else
fi
# Dynamic linking for SunOS/Solaris and SYSV
echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6
-echo "configure:1616: checking for shl_load in -ldld" >&5
+echo "configure:1836: 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
@@ -1620,7 +1840,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ldld $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1624 "configure"
+#line 1844 "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
@@ -1631,7 +1851,7 @@ int main() {
shl_load()
; return 0; }
EOF
-if { (eval echo configure:1635: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1855: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1659,7 +1879,7 @@ else
fi
# Dynamic linking for HP-UX
echo $ac_n "checking for setlocale in -lxpg4""... $ac_c" 1>&6
-echo "configure:1663: checking for setlocale in -lxpg4" >&5
+echo "configure:1883: checking for setlocale in -lxpg4" >&5
ac_lib_var=`echo xpg4'_'setlocale | sed 'y%./+-%__p_%'`
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
@@ -1667,7 +1887,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lxpg4 $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1671 "configure"
+#line 1891 "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
@@ -1678,7 +1898,7 @@ int main() {
setlocale()
; return 0; }
EOF
-if { (eval echo configure:1682: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1902: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1711,12 +1931,12 @@ 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:1715: checking for $ac_hdr that defines DIR" >&5
+echo "configure:1935: 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 1720 "configure"
+#line 1940 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_hdr>
@@ -1724,7 +1944,7 @@ int main() {
DIR *dirp = 0;
; return 0; }
EOF
-if { (eval echo configure:1728: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:1948: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
eval "ac_cv_header_dirent_$ac_safe=yes"
else
@@ -1749,7 +1969,7 @@ done
# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix.
if test $ac_header_dirent = dirent.h; then
echo $ac_n "checking for opendir in -ldir""... $ac_c" 1>&6
-echo "configure:1753: checking for opendir in -ldir" >&5
+echo "configure:1973: 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
@@ -1757,7 +1977,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-ldir $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1761 "configure"
+#line 1981 "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
@@ -1768,7 +1988,7 @@ int main() {
opendir()
; return 0; }
EOF
-if { (eval echo configure:1772: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:1992: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1790,7 +2010,7 @@ fi
else
echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6
-echo "configure:1794: checking for opendir in -lx" >&5
+echo "configure:2014: 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
@@ -1798,7 +2018,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lx $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 1802 "configure"
+#line 2022 "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
@@ -1809,7 +2029,7 @@ int main() {
opendir()
; return 0; }
EOF
-if { (eval echo configure:1813: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2033: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -1832,12 +2052,12 @@ fi
fi
echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6
-echo "configure:1836: checking for ANSI C header files" >&5
+echo "configure:2056: 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 1841 "configure"
+#line 2061 "configure"
#include "confdefs.h"
#include <stdlib.h>
#include <stdarg.h>
@@ -1845,7 +2065,7 @@ else
#include <float.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1849: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2069: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1862,7 +2082,7 @@ rm -f conftest*
if test $ac_cv_header_stdc = yes; then
# SunOS 4.x string.h does not declare mem*, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1866 "configure"
+#line 2086 "configure"
#include "confdefs.h"
#include <string.h>
EOF
@@ -1880,7 +2100,7 @@ fi
if test $ac_cv_header_stdc = yes; then
# ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
cat > conftest.$ac_ext <<EOF
-#line 1884 "configure"
+#line 2104 "configure"
#include "confdefs.h"
#include <stdlib.h>
EOF
@@ -1901,7 +2121,7 @@ if test "$cross_compiling" = yes; then
:
else
cat > conftest.$ac_ext <<EOF
-#line 1905 "configure"
+#line 2125 "configure"
#include "confdefs.h"
#include <ctype.h>
#define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
@@ -1912,7 +2132,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2);
exit (0); }
EOF
-if { (eval echo configure:1916: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2136: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
:
else
@@ -1935,23 +2155,65 @@ 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 direct.h
+echo $ac_n "checking for sys/wait.h that is POSIX.1 compatible""... $ac_c" 1>&6
+echo "configure:2160: checking for sys/wait.h that is POSIX.1 compatible" >&5
+if eval "test \"`echo '$''{'ac_cv_header_sys_wait_h'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 2165 "configure"
+#include "confdefs.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
+#endif
+#ifndef WIFEXITED
+#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
+#endif
+int main() {
+int s;
+wait (&s);
+s = WIFEXITED (s) ? WEXITSTATUS (s) : 1;
+; return 0; }
+EOF
+if { (eval echo configure:2181: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_header_sys_wait_h=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_header_sys_wait_h" 1>&6
+if test $ac_cv_header_sys_wait_h = yes; then
+ cat >> confdefs.h <<\EOF
+#define HAVE_SYS_WAIT_H 1
+EOF
+
+fi
+
+for ac_hdr in 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 fnmatch.h
do
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
-echo "configure:1945: checking for $ac_hdr" >&5
+echo "configure:2207: 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 1950 "configure"
+#line 2212 "configure"
#include "confdefs.h"
#include <$ac_hdr>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:1955: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2217: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -1979,12 +2241,12 @@ done
echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6
-echo "configure:1983: checking for uid_t in sys/types.h" >&5
+echo "configure:2245: 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 1988 "configure"
+#line 2250 "configure"
#include "confdefs.h"
#include <sys/types.h>
EOF
@@ -2013,12 +2275,12 @@ EOF
fi
echo $ac_n "checking for size_t""... $ac_c" 1>&6
-echo "configure:2017: checking for size_t" >&5
+echo "configure:2279: 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 2022 "configure"
+#line 2284 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -2046,12 +2308,12 @@ EOF
fi
echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6
-echo "configure:2050: checking for st_blksize in struct stat" >&5
+echo "configure:2312: 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 2055 "configure"
+#line 2317 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -2059,7 +2321,7 @@ int main() {
struct stat s; s.st_blksize;
; return 0; }
EOF
-if { (eval echo configure:2063: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2325: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_struct_st_blksize=yes
else
@@ -2081,12 +2343,12 @@ fi
save_LIBOJBS="$LIBOBJS"
echo $ac_n "checking for st_blocks in struct stat""... $ac_c" 1>&6
-echo "configure:2085: checking for st_blocks in struct stat" >&5
+echo "configure:2347: 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 2090 "configure"
+#line 2352 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -2094,7 +2356,7 @@ int main() {
struct stat s; s.st_blocks;
; return 0; }
EOF
-if { (eval echo configure:2098: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2360: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_struct_st_blocks=yes
else
@@ -2118,12 +2380,12 @@ fi
LIBOBJS="$save_LIBOBJS"
echo $ac_n "checking for st_rdev in struct stat""... $ac_c" 1>&6
-echo "configure:2122: checking for st_rdev in struct stat" >&5
+echo "configure:2384: 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 2127 "configure"
+#line 2389 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/stat.h>
@@ -2131,7 +2393,7 @@ int main() {
struct stat s; s.st_rdev;
; return 0; }
EOF
-if { (eval echo configure:2135: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2397: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_struct_st_rdev=yes
else
@@ -2153,7 +2415,7 @@ fi
echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6
-echo "configure:2157: checking type of array argument to getgroups" >&5
+echo "configure:2419: 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
@@ -2161,7 +2423,7 @@ else
ac_cv_type_getgroups=cross
else
cat > conftest.$ac_ext <<EOF
-#line 2165 "configure"
+#line 2427 "configure"
#include "confdefs.h"
/* Thanks to Mike Rendell for this test. */
@@ -2186,7 +2448,7 @@ main()
}
EOF
-if { (eval echo configure:2190: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2452: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_type_getgroups=gid_t
else
@@ -2200,7 +2462,7 @@ fi
if test $ac_cv_type_getgroups = cross; then
cat > conftest.$ac_ext <<EOF
-#line 2204 "configure"
+#line 2466 "configure"
#include "confdefs.h"
#include <unistd.h>
EOF
@@ -2224,12 +2486,12 @@ EOF
echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6
-echo "configure:2228: checking return type of signal handlers" >&5
+echo "configure:2490: 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 2233 "configure"
+#line 2495 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <signal.h>
@@ -2246,7 +2508,7 @@ int main() {
int i;
; return 0; }
EOF
-if { (eval echo configure:2250: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:2512: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_type_signal=void
else
@@ -2267,19 +2529,19 @@ EOF
# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
# for constant arguments. Useless!
echo $ac_n "checking for working alloca.h""... $ac_c" 1>&6
-echo "configure:2271: checking for working alloca.h" >&5
+echo "configure:2533: 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 2276 "configure"
+#line 2538 "configure"
#include "confdefs.h"
#include <alloca.h>
int main() {
char *p = alloca(2 * sizeof(int));
; return 0; }
EOF
-if { (eval echo configure:2283: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2545: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_header_alloca_h=yes
else
@@ -2300,12 +2562,12 @@ EOF
fi
echo $ac_n "checking for alloca""... $ac_c" 1>&6
-echo "configure:2304: checking for alloca" >&5
+echo "configure:2566: 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 2309 "configure"
+#line 2571 "configure"
#include "confdefs.h"
#ifdef __GNUC__
@@ -2333,7 +2595,7 @@ int main() {
char *p = (char *) alloca(1);
; return 0; }
EOF
-if { (eval echo configure:2337: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2599: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_func_alloca_works=yes
else
@@ -2365,12 +2627,12 @@ EOF
echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6
-echo "configure:2369: checking whether alloca needs Cray hooks" >&5
+echo "configure:2631: 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 2374 "configure"
+#line 2636 "configure"
#include "confdefs.h"
#if defined(CRAY) && ! defined(CRAY2)
webecray
@@ -2395,12 +2657,12 @@ echo "$ac_t""$ac_cv_os_cray" 1>&6
if test $ac_cv_os_cray = yes; then
for ac_func in _getb67 GETB67 getb67; do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2399: checking for $ac_func" >&5
+echo "configure:2661: 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 2404 "configure"
+#line 2666 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2423,7 +2685,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2427: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2689: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2450,7 +2712,7 @@ done
fi
echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6
-echo "configure:2454: checking stack direction for C alloca" >&5
+echo "configure:2716: 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
@@ -2458,7 +2720,7 @@ else
ac_cv_c_stack_direction=0
else
cat > conftest.$ac_ext <<EOF
-#line 2462 "configure"
+#line 2724 "configure"
#include "confdefs.h"
find_stack_direction ()
{
@@ -2477,7 +2739,7 @@ main ()
exit (find_stack_direction() < 0);
}
EOF
-if { (eval echo configure:2481: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2743: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_stack_direction=1
else
@@ -2499,12 +2761,12 @@ EOF
fi
echo $ac_n "checking for pid_t""... $ac_c" 1>&6
-echo "configure:2503: checking for pid_t" >&5
+echo "configure:2765: 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 2508 "configure"
+#line 2770 "configure"
#include "confdefs.h"
#include <sys/types.h>
#if STDC_HEADERS
@@ -2533,17 +2795,17 @@ fi
ac_safe=`echo "vfork.h" | sed 'y%./+-%__p_%'`
echo $ac_n "checking for vfork.h""... $ac_c" 1>&6
-echo "configure:2537: checking for vfork.h" >&5
+echo "configure:2799: 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 2542 "configure"
+#line 2804 "configure"
#include "confdefs.h"
#include <vfork.h>
EOF
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
-{ (eval echo configure:2547: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+{ (eval echo configure:2809: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
if test -z "$ac_err"; then
rm -rf conftest*
@@ -2568,18 +2830,18 @@ else
fi
echo $ac_n "checking for working vfork""... $ac_c" 1>&6
-echo "configure:2572: checking for working vfork" >&5
+echo "configure:2834: 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:2578: checking for vfork" >&5
+echo "configure:2840: 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 2583 "configure"
+#line 2845 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char vfork(); below. */
@@ -2602,7 +2864,7 @@ vfork();
; return 0; }
EOF
-if { (eval echo configure:2606: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:2868: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_vfork=yes"
else
@@ -2624,7 +2886,7 @@ fi
ac_cv_func_vfork_works=$ac_cv_func_vfork
else
cat > conftest.$ac_ext <<EOF
-#line 2628 "configure"
+#line 2890 "configure"
#include "confdefs.h"
/* Thanks to Paul Eggert for this test. */
#include <stdio.h>
@@ -2719,7 +2981,7 @@ main() {
}
}
EOF
-if { (eval echo configure:2723: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:2985: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_func_vfork_works=yes
else
@@ -2742,7 +3004,7 @@ EOF
fi
echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6
-echo "configure:2746: checking for 8-bit clean memcmp" >&5
+echo "configure:3008: 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
@@ -2750,7 +3012,7 @@ else
ac_cv_func_memcmp_clean=no
else
cat > conftest.$ac_ext <<EOF
-#line 2754 "configure"
+#line 3016 "configure"
#include "confdefs.h"
main()
@@ -2760,7 +3022,7 @@ main()
}
EOF
-if { (eval echo configure:2764: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3026: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_func_memcmp_clean=yes
else
@@ -2777,16 +3039,17 @@ fi
echo "$ac_t""$ac_cv_func_memcmp_clean" 1>&6
test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}"
-for ac_func in dup2 memmove mkdir strcasecmp strerror strftime\
- strchr strstr strtoul strdup crypt flock vsnprintf
+for ac_func in dup2 memmove mkdir strcasecmp strncasecmp strerror strftime\
+ strchr strstr strtoul strdup crypt flock vsnprintf\
+ fnmatch isinf isnan finite
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2785: checking for $ac_func" >&5
+echo "configure:3048: 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 2790 "configure"
+#line 3053 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2809,7 +3072,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2813: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3076: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2838,16 +3101,16 @@ done
for ac_func in fmod killpg drand48 random wait4 waitpid syscall getcwd\
truncate chsize times utimes fcntl lockf setitimer\
setruid seteuid setreuid setrgid setegid setregid\
- setpgrp2 getpgid setpgid getgroups getpriority\
- dlopen sigprocmask sigaction _setjmp setpgrp setsid
+ getpgrp setpgrp getpgid setpgid getgroups getpriority\
+ dlopen sigprocmask sigaction _setjmp setsid
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:2846: checking for $ac_func" >&5
+echo "configure:3109: 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 2851 "configure"
+#line 3114 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -2870,7 +3133,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:2874: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3137: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -2894,14 +3157,13 @@ else
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:2900: checking whether struct tm is in sys/time.h or time.h" >&5
+echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6
+echo "configure:3162: 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 2905 "configure"
+#line 3167 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <time.h>
@@ -2909,7 +3171,7 @@ int main() {
struct tm *tp; tp->tm_sec;
; return 0; }
EOF
-if { (eval echo configure:2913: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3175: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_struct_tm=time.h
else
@@ -2930,12 +3192,12 @@ EOF
fi
echo $ac_n "checking for tm_zone in struct tm""... $ac_c" 1>&6
-echo "configure:2934: checking for tm_zone in struct tm" >&5
+echo "configure:3196: 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 2939 "configure"
+#line 3201 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <$ac_cv_struct_tm>
@@ -2943,7 +3205,7 @@ int main() {
struct tm tm; tm.tm_zone;
; return 0; }
EOF
-if { (eval echo configure:2947: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3209: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_struct_tm_zone=yes
else
@@ -2963,12 +3225,12 @@ EOF
else
echo $ac_n "checking for tzname""... $ac_c" 1>&6
-echo "configure:2967: checking for tzname" >&5
+echo "configure:3229: 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 2972 "configure"
+#line 3234 "configure"
#include "confdefs.h"
#include <time.h>
#ifndef tzname /* For SGI. */
@@ -2978,7 +3240,7 @@ int main() {
atoi(*tzname);
; return 0; }
EOF
-if { (eval echo configure:2982: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3244: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
ac_cv_var_tzname=yes
else
@@ -2999,15 +3261,16 @@ EOF
fi
fi
+if test "$ac_cv_func_strftime" = no; then
cat > conftest.$ac_ext <<EOF
-#line 3004 "configure"
+#line 3267 "configure"
#include "confdefs.h"
int main() {
extern int daylight; int i = daylight;
; return 0; }
EOF
-if { (eval echo configure:3011: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:3274: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
cat >> confdefs.h <<\EOF
#define HAVE_DAYLIGHT 1
@@ -3027,15 +3290,15 @@ EOF
else
echo $ac_n "checking for BSD signal semantics""... $ac_c" 1>&6
-echo "configure:3031: checking for BSD signal semantics" >&5
- if eval "test \"`echo '$''{'rb_cv_bsd_signal'+set}'`\" = set"; then
+echo "configure:3294: 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; }
+ rb_cv_bsd_signal=no
else
cat > conftest.$ac_ext <<EOF
-#line 3039 "configure"
+#line 3302 "configure"
#include "confdefs.h"
#include <stdio.h>
@@ -3057,7 +3320,7 @@ main()
}
EOF
-if { (eval echo configure:3061: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3324: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
rb_cv_bsd_signal=yes
else
@@ -3071,7 +3334,7 @@ fi
fi
- echo "$ac_t""$rb_cv_bsd_signal" 1>&6
+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
@@ -3080,92 +3343,211 @@ EOF
fi
fi
-if test "$ac_cv_func_setpgrp2" = yes; then
- cat >> confdefs.h <<\EOF
-#define BSD_GETPGRP getpgrp2
+echo $ac_n "checking whether getpgrp takes no argument""... $ac_c" 1>&6
+echo "configure:3348: checking whether getpgrp takes no argument" >&5
+if eval "test \"`echo '$''{'ac_cv_func_getpgrp_void'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: cannot check getpgrp if cross compiling" 1>&2; exit 1; }
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3356 "configure"
+#include "confdefs.h"
+
+/*
+ * If this system has a BSD-style getpgrp(),
+ * which takes a pid argument, exit unsuccessfully.
+ *
+ * Snarfed from Chet Ramey's bash pgrp.c test program
+ */
+#include <stdio.h>
+#include <sys/types.h>
+
+int pid;
+int pg1, pg2, pg3, pg4;
+int ng, np, s, child;
+
+main()
+{
+ pid = getpid();
+ pg1 = getpgrp(0);
+ pg2 = getpgrp();
+ pg3 = getpgrp(pid);
+ pg4 = getpgrp(1);
+
+ /*
+ * If all of these values are the same, it's pretty sure that
+ * we're on a system that ignores getpgrp's first argument.
+ */
+ if (pg2 == pg4 && pg1 == pg3 && pg2 == pg3)
+ exit(0);
+
+ child = fork();
+ if (child < 0)
+ exit(1);
+ else if (child == 0) {
+ np = getpid();
+ /*
+ * If this is Sys V, this will not work; pgrp will be
+ * set to np because setpgrp just changes a pgrp to be
+ * the same as the pid.
+ */
+ setpgrp(np, pg1);
+ ng = getpgrp(0); /* Same result for Sys V and BSD */
+ if (ng == pg1) {
+ exit(1);
+ } else {
+ exit(0);
+ }
+ } else {
+ wait(&s);
+ exit(s>>8);
+ }
+}
+
EOF
+if { (eval echo configure:3411: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_getpgrp_void=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -fr conftest*
+ ac_cv_func_getpgrp_void=no
+fi
+rm -fr conftest*
+fi
+
+fi
+
+echo "$ac_t""$ac_cv_func_getpgrp_void" 1>&6
+if test $ac_cv_func_getpgrp_void = yes; then
cat >> confdefs.h <<\EOF
-#define BSD_SETPGRP setpgrp2
+#define GETPGRP_VOID 1
EOF
-else
- echo $ac_n "checking whether getpgrp() has arg""... $ac_c" 1>&6
-echo "configure:3095: checking whether getpgrp() has arg" >&5
- if eval "test \"`echo '$''{'rb_cv_bsdgetpgrp'+set}'`\" = set"; then
+fi
+
+echo $ac_n "checking whether setpgrp takes no argument""... $ac_c" 1>&6
+echo "configure:3435: checking whether setpgrp takes no argument" >&5
+if eval "test \"`echo '$''{'ac_cv_func_setpgrp_void'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
+ if test "$cross_compiling" = yes; then
+ { echo "configure: error: cannot check setpgrp if cross compiling" 1>&2; exit 1; }
+else
cat > conftest.$ac_ext <<EOF
-#line 3100 "configure"
+#line 3443 "configure"
#include "confdefs.h"
+
+#ifdef HAVE_UNISTD_H
#include <unistd.h>
-int main() {
-getpgrp(0);
-; return 0; }
+#endif
+
+/*
+ * If this system has a BSD-style setpgrp, which takes arguments, exit
+ * successfully.
+ */
+main()
+{
+ if (setpgrp(1,1) == -1)
+ exit(0);
+ else
+ exit(1);
+}
+
EOF
-if { (eval echo configure:3107: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- rb_cv_bsdgetpgrp=yes
+if { (eval echo configure:3463: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ ac_cv_func_setpgrp_void=no
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
- rb_cv_bsdgetpgrp=no
+ rm -fr conftest*
+ ac_cv_func_setpgrp_void=yes
fi
-rm -f conftest*
+rm -fr 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
+
+fi
+
+echo "$ac_t""$ac_cv_func_setpgrp_void" 1>&6
+if test $ac_cv_func_setpgrp_void = yes; then
+ cat >> confdefs.h <<\EOF
+#define SETPGRP_VOID 1
EOF
- fi
+fi
+
- echo $ac_n "checking whether setpgrp() has args""... $ac_c" 1>&6
-echo "configure:3128: checking whether setpgrp() has args" >&5
- if eval "test \"`echo '$''{'rb_cv_bsdsetpgrp'+set}'`\" = set"; then
+echo $ac_n "checking for working strtod""... $ac_c" 1>&6
+echo "configure:3488: checking for working strtod" >&5
+if eval "test \"`echo '$''{'rb_cv_func_strtod'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
+ if test "$cross_compiling" = yes; then
+ rb_cv_func_strtod=no
+else
cat > conftest.$ac_ext <<EOF
-#line 3133 "configure"
+#line 3496 "configure"
#include "confdefs.h"
-#include <unistd.h>
-int main() {
-setpgrp(1, 1);
-; return 0; }
+
+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);
+}
+
EOF
-if { (eval echo configure:3140: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
- rm -rf conftest*
- rb_cv_bsdsetpgrp=yes
+if { (eval echo configure:3526: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+then
+ rb_cv_func_strtod=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
- rm -rf conftest*
- rb_cv_bsdsetpgrp=no
+ rm -fr conftest*
+ rb_cv_func_strtod=no
fi
-rm -f conftest*
+rm -fr 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_t""$rb_cv_func_strtod" 1>&6
+test $rb_cv_func_strtod = no && LIBOBJS="$LIBOBJS strtod.o"
+
echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6
-echo "configure:3162: checking whether byte ordering is bigendian" >&5
+echo "configure:3544: 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 3169 "configure"
+#line 3551 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
@@ -3176,11 +3558,11 @@ int main() {
#endif
; return 0; }
EOF
-if { (eval echo configure:3180: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3562: \"$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 3184 "configure"
+#line 3566 "configure"
#include "confdefs.h"
#include <sys/types.h>
#include <sys/param.h>
@@ -3191,7 +3573,7 @@ int main() {
#endif
; return 0; }
EOF
-if { (eval echo configure:3195: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3577: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
ac_cv_c_bigendian=yes
else
@@ -3211,7 +3593,7 @@ if test "$cross_compiling" = yes; then
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 3215 "configure"
+#line 3597 "configure"
#include "confdefs.h"
main () {
/* Are we little or big endian? From Harbison&Steele. */
@@ -3224,7 +3606,7 @@ main () {
exit (u.c[sizeof (long) - 1] == 1);
}
EOF
-if { (eval echo configure:3228: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3610: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_bigendian=no
else
@@ -3247,15 +3629,90 @@ EOF
fi
+echo $ac_n "checking for working const""... $ac_c" 1>&6
+echo "configure:3634: checking for working const" >&5
+if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then
+ echo $ac_n "(cached) $ac_c" 1>&6
+else
+ cat > conftest.$ac_ext <<EOF
+#line 3639 "configure"
+#include "confdefs.h"
+
+int main() {
+
+/* Ultrix mips cc rejects this. */
+typedef int charset[2]; const charset x;
+/* SunOS 4.1.1 cc rejects this. */
+char const *const *ccp;
+char **p;
+/* NEC SVR4.0.2 mips cc rejects this. */
+struct point {int x, y;};
+static struct point const zero = {0,0};
+/* AIX XL C 1.02.0.0 rejects this.
+ It does not let you subtract one const X* pointer from another in an arm
+ of an if-expression whose if-part is not a constant expression */
+const char *g = "string";
+ccp = &g + (g ? g-g : 0);
+/* HPUX 7.0 cc rejects these. */
+++ccp;
+p = (char**) ccp;
+ccp = (char const *const *) p;
+{ /* SCO 3.2v4 cc rejects this. */
+ char *t;
+ char const *s = 0 ? (char *) 0 : (char const *) 0;
+
+ *t++ = 0;
+}
+{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */
+ int x[] = {25, 17};
+ const int *foo = &x[0];
+ ++foo;
+}
+{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
+ typedef const int *iptr;
+ iptr p = 0;
+ ++p;
+}
+{ /* AIX XL C 1.02.0.0 rejects this saying
+ "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
+ struct s { int j; const int *ap[3]; };
+ struct s *b; b->j = 5;
+}
+{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
+ const int foo = 10;
+}
+
+; return 0; }
+EOF
+if { (eval echo configure:3688: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ ac_cv_c_const=yes
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ rm -rf conftest*
+ ac_cv_c_const=no
+fi
+rm -f conftest*
+fi
+
+echo "$ac_t""$ac_cv_c_const" 1>&6
+if test $ac_cv_c_const = no; then
+ cat >> confdefs.h <<\EOF
+#define const
+EOF
+
+fi
+
echo $ac_n "checking whether char is unsigned""... $ac_c" 1>&6
-echo "configure:3252: checking whether char is unsigned" >&5
+echo "configure:3709: 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 3259 "configure"
+#line 3716 "configure"
#include "confdefs.h"
#ifdef __CHAR_UNSIGNED__
yes
@@ -3277,7 +3734,7 @@ if test "$cross_compiling" = yes; then
{ echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
else
cat > conftest.$ac_ext <<EOF
-#line 3281 "configure"
+#line 3738 "configure"
#include "confdefs.h"
/* volatile prevents gcc2 from optimizing the test away on sparcs. */
#if !defined(__STDC__) || __STDC__ != 1
@@ -3287,7 +3744,7 @@ main() {
volatile char c = 255; exit(c < 0);
}
EOF
-if { (eval echo configure:3291: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3748: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
ac_cv_c_char_unsigned=yes
else
@@ -3312,15 +3769,15 @@ fi
echo $ac_n "checking whether right shift preserve sign bit""... $ac_c" 1>&6
-echo "configure:3316: checking whether right shift preserve sign bit" >&5
+echo "configure:3773: checking whether right shift preserve sign bit" >&5
if eval "test \"`echo '$''{'rb_cv_rshift_sign'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test "$cross_compiling" = yes; then
- { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; }
+ rb_cv_rshift_sign=yes
else
cat > conftest.$ac_ext <<EOF
-#line 3324 "configure"
+#line 3781 "configure"
#include "confdefs.h"
int
@@ -3332,7 +3789,7 @@ main()
}
EOF
-if { (eval echo configure:3336: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3793: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
rb_cv_rshift_sign=yes
else
@@ -3346,7 +3803,7 @@ fi
fi
- echo "$ac_t""$rb_cv_rshift_sign" 1>&6
+echo "$ac_t""$rb_cv_rshift_sign" 1>&6
if test "$rb_cv_rshift_sign" = yes; then
cat >> confdefs.h <<\EOF
#define RSHIFT(x,y) ((x)>>y)
@@ -3360,19 +3817,19 @@ EOF
fi
echo $ac_n "checking count field in FILE structures""... $ac_c" 1>&6
-echo "configure:3364: checking count field in FILE structures" >&5
+echo "configure:3821: 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 3369 "configure"
+#line 3826 "configure"
#include "confdefs.h"
#include <stdio.h>
int main() {
FILE *f = stdin; f->_cnt = 0;
; return 0; }
EOF
-if { (eval echo configure:3376: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3833: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_fcnt="_cnt"
else
@@ -3382,14 +3839,14 @@ fi
rm -f conftest*
if test "$rb_cv_fcnt" = ""; then
cat > conftest.$ac_ext <<EOF
-#line 3386 "configure"
+#line 3843 "configure"
#include "confdefs.h"
#include <stdio.h>
int main() {
FILE *f = stdin; f->__cnt = 0;
; return 0; }
EOF
-if { (eval echo configure:3393: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3850: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_fcnt="__cnt"
else
@@ -3400,14 +3857,14 @@ rm -f conftest*
fi
if test "$rb_cv_fcnt" = ""; then
cat > conftest.$ac_ext <<EOF
-#line 3404 "configure"
+#line 3861 "configure"
#include "confdefs.h"
#include <stdio.h>
int main() {
FILE *f = stdin; f->_r = 0;
; return 0; }
EOF
-if { (eval echo configure:3411: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3868: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_fcnt="_r"
else
@@ -3418,19 +3875,37 @@ rm -f conftest*
fi
if test "$rb_cv_fcnt" = ""; then
cat > conftest.$ac_ext <<EOF
-#line 3422 "configure"
+#line 3879 "configure"
#include "confdefs.h"
#include <stdio.h>
int main() {
FILE *f = stdin; f->readCount = 0;
; return 0; }
EOF
-if { (eval echo configure:3429: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:3886: \"$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
+fi
+rm -f conftest*
+fi
+if test "$rb_cv_fcnt" = ""; then
+ cat > conftest.$ac_ext <<EOF
+#line 3897 "configure"
+#include "confdefs.h"
+#include <stdio.h>
+int main() {
+FILE *f = stdin; f->_rcount = 0;
+; return 0; }
+EOF
+if { (eval echo configure:3904: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+ rm -rf conftest*
+ rb_cv_fcnt="_rcount"
+else
+ echo "configure: failed program was:" >&5
+ cat conftest.$ac_ext >&5
rm -rf conftest*
rb_cv_fcnt="not found"
fi
@@ -3448,6 +3923,32 @@ EOF
fi
+
+# Check whether --with-default-kcode or --without-default-kcode was given.
+if test "${with_default_kcode+set}" = set; then
+ withval="$with_default_kcode"
+ case $withval in
+ utf8) cat >> confdefs.h <<\EOF
+#define DEFAULT_KCODE KCODE_UTF8
+EOF
+;;
+ euc) cat >> confdefs.h <<\EOF
+#define DEFAULT_KCODE KCODE_EUC
+EOF
+;;
+ sjis) cat >> confdefs.h <<\EOF
+#define DEFAULT_KCODE KCODE_SJIS
+EOF
+;;
+ none) cat >> confdefs.h <<\EOF
+#define DEFAULT_KCODE KCODE_NONE
+EOF
+;;
+ *) echo "configure: warning: $withval is not valid kcode; ignored" 1>&2;;
+ esac
+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"
@@ -3461,18 +3962,19 @@ else
fi
+
case "$host_os" in
linux*)
echo $ac_n "checking whether ELF binaries are produced""... $ac_c" 1>&6
-echo "configure:3468: checking whether ELF binaries are produced" >&5
- if eval "test \"`echo '$''{'rb_cv_linux_elf'+set}'`\" = set"; then
+echo "configure:3970: checking whether ELF binaries are produced" >&5
+if eval "test \"`echo '$''{'rb_cv_binary_elf'+set}'`\" = set"; then
echo $ac_n "(cached) $ac_c" 1>&6
else
if test "$cross_compiling" = yes; then
- :
+ rb_cv_binary_elf=yes
else
cat > conftest.$ac_ext <<EOF
-#line 3476 "configure"
+#line 3978 "configure"
#include "confdefs.h"
/* Test for whether ELF binaries are produced */
@@ -3492,24 +3994,24 @@ main() {
}
EOF
-if { (eval echo configure:3496: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:3998: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
- rb_cv_linux_elf=yes
+ rb_cv_binary_elf=yes
else
echo "configure: failed program was:" >&5
cat conftest.$ac_ext >&5
rm -fr conftest*
- rb_cv_linux_elf=no
+ rb_cv_binary_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
+echo "$ac_t""$rb_cv_binary_elf" 1>&6
+ if test "$rb_cv_binary_elf" = no; then
with_dln_a_out=yes
- host_os=linux-a.out
+ host_os=${host_os}-a_out
else
LDFLAGS="-rdynamic"
fi;;
@@ -3522,22 +4024,28 @@ 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:3526: checking whether OS depend dynamic link works" >&5
+echo "configure:4028: checking whether OS depend dynamic link works" >&5
if test "$GCC" = yes; then
case "$host_os" in
nextstep*) ;;
openstep*) ;;
rhapsody*) ;;
human*) ;;
- cygwin*) CCDLFLAGS=-DDLLIMPORT;;
- *) CCDLFLAGS=-fpic;;
+ bsdi3*) ;;
+ cygwin*) ;;
+ netbsd*) CCDLFLAGS=-fpic
+ case "$host_cpu" in
+ mips*) CCDLFLAGS=-fPIC ;;
+ *) ;;
+ esac ;;
+ *) CCDLFLAGS=-fPIC;;
esac
else
case "$host_os" in
hpux*) CCDLFLAGS='+z';;
- solaris*|irix*) CCDLFLAGS='-K pic' ;;
- sunos*) CCDLFLAGS='-pic' ;;
- esix*|uxpds*) CCDLFLAGS='-Kpic' ;;
+ solaris*|irix*) CCDLFLAGS='-K PIC' ;;
+ sunos*) CCDLFLAGS='-PIC' ;;
+ esix*|uxpds*) CCDLFLAGS='-KPIC' ;;
*) CCDLFLAGS='' ;;
esac
fi
@@ -3547,7 +4055,12 @@ echo "configure:3526: checking whether OS depend dynamic link works" >&5
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;;
@@ -3557,19 +4070,29 @@ echo "configure:3526: checking whether OS depend dynamic link works" >&5
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 ;;
- freebsd3*) LDSHARED="ld -Bshareable"
- LDFLAGS="-rdynamic"
+ linux*) LDSHARED="$CC -shared"
rb_cv_dlopen=yes ;;
- freebsd*) LDSHARED="ld -Bshareable"
+ freebsd*) LDSHARED="$CC -shared"
+ if test -x /usr/bin/objformat && \
+ test `/usr/bin/objformat` = "elf" ; then
+ LDFLAGS="-rdynamic"
+ DLDFLAGS='-Wl,-soname,$(.TARGET)'
+ rb_cv_freebsd_elf=yes
+ 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"
rb_cv_dlopen=yes ;;
openbsd*) LDSHARED="ld -Bforcearchive -Bshareable"
- CCDLFLAGS=-fPIC
rb_cv_dlopen=yes ;;
- nextstep*) LDSHARED='cc -r'
+ bsdi3*) case "$CC" in
+ *shlicc*) LDSHARED="$CC -r"
+ rb_cv_dlopen=yes ;;
+ esac ;;
+ nextstep*) LDSHARED='cc -r -nostdlib'
LDFLAGS="-u libsys_s"
DLDFLAGS="$ARCH_FLAG"
rb_cv_dlopen=yes ;;
@@ -3581,22 +4104,30 @@ echo "configure:3526: checking whether OS depend dynamic link works" >&5
LDFLAGS=""
DLDFLAGS="$ARCH_FLAG"
rb_cv_dlopen=yes ;;
- aix*) LDSHARED='../../miniruby ../aix_ld.rb $(TARGET)'
+ aix*) LDSHARED='/usr/ccs/bin/ld'
+ XLDFLAGS='-Wl,-bE:ruby.imp'
+ DLDFLAGS='-eInit_$(TARGET) -bI:$(topdir)/ruby.imp -bM:SRE -T512 -H512 -lc'
rb_cv_dlopen=yes ;;
+
human*) DLDFLAGS=''
LDSHARED=''
- LDFLAGS='' ;;
- beos*) LDSHARED="ld -xms"
- case "$host_cpu" in
+ LDFLAGS=''
+ rb_cv_dlopen=yes ;;
+ beos*) case "$host_cpu" in
powerpc*)
+ LDSHARED="ld -xms"
DLDFLAGS="-f ruby.exp -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o"
;;
+ i586*)
+ LDSHARED="ld -shared"
+ DLDFLAGS="-L/boot/develop/lib/x86 -lbe -lroot"
+ ;;
*)
DLDFLAGS="ruby.def -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o"
- ;;
esac
rb_cv_dlopen=yes ;;
- cygwin*) LDSHARED='../../miniruby ../cygwin32_ld.rb' ;;
+ cygwin*) LDSHARED='dllwrap --export-all -s'
+ rb_cv_dlopen=yes ;;
*) LDSHARED='ld' ;;
esac
echo "$ac_t""$rb_cv_dlopen" 1>&6
@@ -3605,14 +4136,14 @@ 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:3610: checking whether matz's dln works" >&5
cat confdefs.h > config.h
- if eval "test \"`echo '$''{'rb_cv_dln_a_out'+set}'`\" = set"; then
+ echo $ac_n "checking whether matz's dln works""... $ac_c" 1>&6
+echo "configure:4142: checking whether matz's dln works" >&5
+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 3616 "configure"
+#line 4147 "configure"
#include "confdefs.h"
#define USE_DLN_A_OUT
@@ -3622,7 +4153,7 @@ int main() {
; return 0; }
EOF
-if { (eval echo configure:3626: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
+if { (eval echo configure:4157: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then
rm -rf conftest*
rb_cv_dln_a_out=yes
else
@@ -3634,7 +4165,7 @@ fi
rm -f conftest*
fi
- echo "$ac_t""$rb_cv_dln_a_out" 1>&6
+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
@@ -3651,9 +4182,9 @@ if test "$dln_a_out_works" = yes; then
else
STATIC=-Bstatic
fi
- DLEXT=o
+ DLEXT=so
cat >> confdefs.h <<\EOF
-#define DLEXT ".o"
+#define DLEXT ".so"
EOF
CCDLFLAGS=
@@ -3664,9 +4195,9 @@ else
#define DLEXT ".sl"
EOF
;;
- nextstep*) DLEXT=o
+ nextstep*) DLEXT=bundle
cat >> confdefs.h <<\EOF
-#define DLEXT ".o"
+#define DLEXT ".bundle"
EOF
;;
openstep*) DLEXT=bundle
@@ -3684,6 +4215,11 @@ EOF
#define DLEXT ".dll"
EOF
;;
+ os2_emx) DLEXT=o
+ cat >> confdefs.h <<\EOF
+#define DLEXT ".so"
+EOF
+;;
*) DLEXT=so
cat >> confdefs.h <<\EOF
#define DLEXT ".so"
@@ -3724,7 +4260,7 @@ fi
case "$host_os" in
human*)
echo $ac_n "checking for _harderr in -lsignal""... $ac_c" 1>&6
-echo "configure:3728: checking for _harderr in -lsignal" >&5
+echo "configure:4264: 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
@@ -3732,7 +4268,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lsignal $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 3736 "configure"
+#line 4272 "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
@@ -3743,7 +4279,7 @@ int main() {
_harderr()
; return 0; }
EOF
-if { (eval echo configure:3747: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4283: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -3771,7 +4307,7 @@ else
fi
echo $ac_n "checking for hmemset in -lhmem""... $ac_c" 1>&6
-echo "configure:3775: checking for hmemset in -lhmem" >&5
+echo "configure:4311: 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
@@ -3779,7 +4315,7 @@ else
ac_save_LIBS="$LIBS"
LIBS="-lhmem $LIBS"
cat > conftest.$ac_ext <<EOF
-#line 3783 "configure"
+#line 4319 "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
@@ -3790,7 +4326,7 @@ int main() {
hmemset()
; return 0; }
EOF
-if { (eval echo configure:3794: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4330: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_lib_$ac_lib_var=yes"
else
@@ -3820,12 +4356,12 @@ fi
for ac_func in select
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
-echo "configure:3824: checking for $ac_func" >&5
+echo "configure:4360: 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 3829 "configure"
+#line 4365 "configure"
#include "confdefs.h"
/* System header to define __stub macros and hopefully few prototypes,
which can conflict with char $ac_func(); below. */
@@ -3848,7 +4384,7 @@ $ac_func();
; return 0; }
EOF
-if { (eval echo configure:3852: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
+if { (eval echo configure:4388: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
rm -rf conftest*
eval "ac_cv_func_$ac_func=yes"
else
@@ -3873,15 +4409,15 @@ fi
done
echo $ac_n "checking whether PD libc _dtos18 fail to convert big number""... $ac_c" 1>&6
-echo "configure:3877: checking whether PD libc _dtos18 fail to convert big number" >&5
- if eval "test \"`echo '$''{'rb_cv_missing__dtos18'+set}'`\" = set"; then
+echo "configure:4413: 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; }
+ rb_cv_missing__dtos18=no
else
cat > conftest.$ac_ext <<EOF
-#line 3885 "configure"
+#line 4421 "configure"
#include "confdefs.h"
#include <stdio.h>
@@ -3893,7 +4429,7 @@ main ()
}
EOF
-if { (eval echo configure:3897: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4433: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
rb_cv_missing__dtos18=yes
else
@@ -3907,7 +4443,7 @@ fi
fi
- echo "$ac_t""$rb_cv_missing__dtos18" 1>&6
+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
@@ -3915,15 +4451,15 @@ EOF
fi
echo $ac_n "checking whether PD libc fconvert fail to round""... $ac_c" 1>&6
-echo "configure:3919: checking whether PD libc fconvert fail to round" >&5
- if eval "test \"`echo '$''{'rb_cv_missing_fconvert'+set}'`\" = set"; then
+echo "configure:4455: 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; }
+ rb_cv_missing_fconvert=no
else
cat > conftest.$ac_ext <<EOF
-#line 3927 "configure"
+#line 4463 "configure"
#include "confdefs.h"
#include <stdio.h>
@@ -3936,7 +4472,7 @@ main ()
}
EOF
-if { (eval echo configure:3940: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
+if { (eval echo configure:4476: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null
then
rb_cv_missing_fconvert=yes
else
@@ -3950,7 +4486,7 @@ fi
fi
- echo "$ac_t""$rb_cv_missing_fconvert" 1>&6
+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
@@ -3959,24 +4495,24 @@ EOF
fi
LIBOBJS="$LIBOBJS x68.o"
CFLAGS="$CFLAGS -fansi-only -cc1-stack=196608 -cpp-stack=2694144"
- binsuffix=.x
+ EXEEXT=.x
+ OBJEXT=o
setup=Setup.x68
;;
+ os2_emx)
+ LIBOBJS="$LIBOBJS os2.o"
+ setup=Setup.emx
+ ;;
cygwin*)
- binsuffix=.exe
setup=Setup
;;
*)
- binsuffix=
setup=Setup
;;
esac
-
-
-
if test "$prefix" = NONE; then
prefix=$ac_default_prefix
fi
@@ -3985,18 +4521,22 @@ if test "$fat_binary" = yes ; then
CFLAGS="$CFLAGS $ARCH_FLAG"
fi
-LIBRUBY='libruby.a'
-LIBRUBYARG='libruby.a'
+LIBRUBY_A='lib$(RUBY_INSTALL_NAME).a'
+LIBRUBY='$(LIBRUBY_A)'
+LIBRUBYARG='$(LIBRUBY_A)'
SOLIBS=
if test "$host_os" = "beos"; then
- CFLAGS="$CFLAGS -relax_pointers"
- LIBRUBY='libruby.so'
- LIBRUBYARG='-lruby'
+ LIBRUBY='$(LIBRUBY_SO)'
+ LIBRUBYARG='-l$(RUBY_INSTALL_NAME)'
SOLIBS='-lnet'
echo creating ruby.def
case "$host_cpu" in
powerpc*)
cp beos/ruby.def.in ruby.exp
+ CFLAGS="$CFLAGS -relax_pointers"
+ ;;
+ i586*)
+ LDFLAGS="$LDFLAGS -L."
;;
*)
echo EXPORTS > ruby.def
@@ -4005,9 +4545,75 @@ if test "$host_os" = "beos"; then
esac
fi
+FIRSTMAKEFILE=""
+LIBRUBY_LDSHARED=$LDSHARED
+LIBRUBY_DLDFLAGS=$DLDFLAGS
+LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR).$(TEENY)'
+LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so'
+# Check whether --enable-enable-shared or --disable-enable-shared was given.
+if test "${enable_enable_shared+set}" = set; then
+ enableval="$enable_enable_shared"
+ enable_shared=$enableval
+fi
+
if test "$enable_shared" = 'yes'; then
- LIBRUBY='libruby.so'
- LIBRUBYARG='-L./ -lruby'
+ LIBRUBY='$(LIBRUBY_SO)'
+ LIBRUBYARG='-L. -l$(RUBY_INSTALL_NAME)'
+ CFLAGS="$CFLAGS $CCDLFLAGS"
+ case "$host_os" in
+ sunos4*)
+ LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).so'
+ ;;
+ linux*)
+ XLDFLAGS='-Wl,-rpath,${prefix}/lib':/usr/lib:/lib
+ LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).so'
+ ;;
+ freebsd*)
+ LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR)$(MINOR)'
+ if test "$rb_cv_freebsd_elf" != "yes" ; then
+ LIBRUBY_SO="$LIBRUBY_SO.\$(TEENY)"
+ LIBRUBY_ALIASES=''
+ fi
+ ;;
+ netbsd*)
+ LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR)'
+ case "$host_cpu" in
+ alpha|mipsel|mipseb|powerpc|sparc64) # ELF platforms
+ LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR) lib$(RUBY_INSTALL_NAME).so' ;;
+ *) LIBRUBY_ALIASES= ;; # a.out platforms
+ esac
+ ;;
+ 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'
+ ;;
+ cygwin*)
+ LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).a'
+ LIBRUBY_ALIASES=''
+ LIBRUBY_A='lib$(RUBY_INSTALL_NAME)s.a'
+ LIBRUBYARG='-L. -l$(RUBY_INSTALL_NAME)'
+ FIRSTMAKEFILE=GNUmakefile:cygwin/GNUmakefile.in
+ LIBOBJS="$LIBOBJS strftime.o"
+ CCDLFLAGS=-DUSEIMPORTLIB
+ ;;
+ *)
+ ;;
+ esac
fi
case "$host_os" in
@@ -4029,6 +4635,11 @@ esac
+
+
+
+
+
ri_prefix=
test "$program_prefix" != NONE &&
ri_prefix=$program_prefix
@@ -4038,52 +4649,60 @@ test "$program_suffix" != NONE &&
ri_suffix=$program_suffix
RUBY_INSTALL_NAME="${ri_prefix}ruby${ri_suffix}"
+RUBY_LIB_PATH="${prefix}/lib/ruby/${MAJOR}.${MINOR}"
cat >> confdefs.h <<EOF
-#define RUBY_LIB "${prefix}/lib/${RUBY_INSTALL_NAME}"
+#define RUBY_LIB "${RUBY_LIB_PATH}"
EOF
+RUBY_SITE_LIB_PATH="${RUBY_LIB_PATH}/site_ruby"
cat >> confdefs.h <<EOF
-#define RUBY_SITE_LIB "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby"
+#define RUBY_SITE_LIB "${RUBY_SITE_LIB_PATH}"
EOF
+configure_args=$ac_configure_args
+
if test "$fat_binary" = yes ; then
arch="fat-${host_os}"
cat >> confdefs.h <<EOF
-#define RUBY_THIN_ARCHLIB "${prefix}/lib/${RUBY_INSTALL_NAME}/" __ARCHITECTURE__ "-${host_os}"
+#define RUBY_THIN_ARCHLIB "${RUBY_LIB_PATH}/" __ARCHITECTURE__ "-${host_os}"
EOF
cat >> confdefs.h <<EOF
-#define RUBY_SITE_THIN_ARCHLIB "${prefix}/lib/${RUBY_INSTALL_NAME}/" __ARCHITECTURE__ "-${host_os}"
+#define RUBY_SITE_THIN_ARCHLIB "${RUBY_SITE_LIB_PATH}/" __ARCHITECTURE__ "-${host_os}"
EOF
-
cat >> confdefs.h <<EOF
-#define RUBY_ARCHLIB "${prefix}/lib/${RUBY_INSTALL_NAME}/${arch}"
+#define RUBY_PLATFORM __ARCHITECTURE__ "-${host_os}"
EOF
+else
+ arch="${host_cpu}-${host_os}"
cat >> confdefs.h <<EOF
-#define RUBY_SITE_ARCHLIB "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby/${arch}"
+#define RUBY_PLATFORM "${arch}"
EOF
- cat >> confdefs.h <<EOF
-#define RUBY_PLATFORM __ARCHITECTURE__ "-${host_os}"
+fi
+cat >> confdefs.h <<EOF
+#define RUBY_ARCHLIB "${RUBY_LIB_PATH}/${arch}"
EOF
-else
- arch="${host_cpu}-${host_os}"
- cat >> confdefs.h <<EOF
-#define RUBY_ARCHLIB "${prefix}/lib/${RUBY_INSTALL_NAME}/${arch}"
+cat >> confdefs.h <<EOF
+#define RUBY_SITE_ARCHLIB "${RUBY_SITE_LIB_PATH}/${arch}"
EOF
- cat >> confdefs.h <<EOF
-#define RUBY_SITE_ARCHLIB "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby/${arch}"
-EOF
+# Check whether --with-search-path or --without-search-path was given.
+if test "${with_search_path+set}" = set; then
+ withval="$with_search_path"
+ search_path=$withval
+fi
+
+if test "$search_path" != ""; then
cat >> confdefs.h <<EOF
-#define RUBY_PLATFORM "${arch}"
+#define RUBY_SEARCH_PATH "$search_path"
EOF
fi
@@ -4193,7 +4812,7 @@ do
echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion"
exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;;
-version | --version | --versio | --versi | --vers | --ver | --ve | --v)
- echo "$CONFIG_STATUS generated by autoconf version 2.12.2"
+ echo "$CONFIG_STATUS generated by autoconf version 2.13"
exit 0 ;;
-help | --help | --hel | --he | --h)
echo "\$ac_cs_usage"; exit 0 ;;
@@ -4202,9 +4821,8 @@ do
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
+trap 'rm -fr `echo "$FIRSTMAKEFILE Makefile ext/extmk.rb" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15
EOF
cat >> $CONFIG_STATUS <<EOF
@@ -4236,6 +4854,9 @@ s%@includedir@%$includedir%g
s%@oldincludedir@%$oldincludedir%g
s%@infodir@%$infodir%g
s%@mandir@%$mandir%g
+s%@MAJOR@%$MAJOR%g
+s%@MINOR@%$MINOR%g
+s%@TEENY@%$TEENY%g
s%@host@%$host%g
s%@host_alias@%$host_alias%g
s%@host_cpu@%$host_cpu%g
@@ -4246,12 +4867,14 @@ s%@CPP@%$CPP%g
s%@YACC@%$YACC%g
s%@RANLIB@%$RANLIB%g
s%@AR@%$AR%g
-s%@INSTALL_PROGRAM@%$INSTALL_PROGRAM%g
-s%@INSTALL_SCRIPT@%$INSTALL_SCRIPT%g
-s%@INSTALL_DATA@%$INSTALL_DATA%g
+s%@LN_S@%$LN_S%g
s%@SET_MAKE@%$SET_MAKE%g
+s%@EXEEXT@%$EXEEXT%g
+s%@OBJEXT@%$OBJEXT%g
s%@LIBOBJS@%$LIBOBJS%g
s%@ALLOCA@%$ALLOCA%g
+s%@DEFAULT_KCODE@%$DEFAULT_KCODE%g
+s%@XLDFLAGS@%$XLDFLAGS%g
s%@DLDFLAGS@%$DLDFLAGS%g
s%@STATIC@%$STATIC%g
s%@CCDLFLAGS@%$CCDLFLAGS%g
@@ -4259,12 +4882,18 @@ 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%@LIBRUBY_LDSHARED@%$LIBRUBY_LDSHARED%g
+s%@LIBRUBY_DLDFLAGS@%$LIBRUBY_DLDFLAGS%g
+s%@RUBY_INSTALL_NAME@%$RUBY_INSTALL_NAME%g
+s%@LIBRUBY_A@%$LIBRUBY_A%g
+s%@LIBRUBY_SO@%$LIBRUBY_SO%g
+s%@LIBRUBY_ALIASES@%$LIBRUBY_ALIASES%g
s%@LIBRUBY@%$LIBRUBY%g
s%@LIBRUBYARG@%$LIBRUBYARG%g
s%@SOLIBS@%$SOLIBS%g
s%@arch@%$arch%g
+s%@configure_args@%$configure_args%g
CEOF
EOF
@@ -4306,7 +4935,7 @@ EOF
cat >> $CONFIG_STATUS <<EOF
-CONFIG_FILES=\${CONFIG_FILES-"Makefile ext/extmk.rb"}
+CONFIG_FILES=\${CONFIG_FILES-"$FIRSTMAKEFILE Makefile ext/extmk.rb"}
EOF
cat >> $CONFIG_STATUS <<\EOF
for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
@@ -4341,10 +4970,6 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
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"
@@ -4360,7 +4985,6 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then
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*
diff --git a/configure.bat b/configure.bat
index 093d43549d..ce0aa8bd9f 100644
--- a/configure.bat
+++ b/configure.bat
@@ -1,6 +1,24 @@
@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
+grep -qs MAJOR top.sed
+if errorlevel 1 goto seen
+if errorlevel 0 goto not_seen
+:seen
+ sed -n "/VERSION /s/[^0-9.]//gp" < version.h > version.out
+ cut -d. -f1 version.out > major.out
+ cut -d. -f2 version.out > minor.out
+ cut -d. -f3 version.out > teeny.out
+ sed "s/^/s,@MAJOR@,/;s/$/,/g" major.out >> top.sed
+ sed "s/^/s,@MINOR@,/;s/$/,/g" minor.out >> top.sed
+ sed "s/^/s,@TEENY@,/;s/$/,/g" teeny.out >> top.sed
+ rm version.out major.out minor.out teeny.out
+:not_seen
+sed -f top.sed < Makefile.in > Makefile
+sed -f top.sed < ext\extmk.rb.in > ext\extmk.rb
copy config_h.dj config.h
-copy config_s.dj config.status
+if not (%OS%) == (Windows_NT) goto LFN
+ copy missing\vsnprintf.c missing\vsnprint.c
+ copy config_s.dj config.sta
+goto end
+:LFN
+ copy config_s.dj config.status
+:end
diff --git a/configure.in b/configure.in
index 0477ade03e..8e86e42e4e 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,42 +25,25 @@ 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(USE_THREAD)
-fi
-
AC_CANONICAL_HOST
dnl checks for fat-binary
fat_binary=no
-AC_ARG_ENABLE( fat-binary,
+AC_ARG_ENABLE(fat-binary,
[--enable-fat-binary build a NeXT/Apple Multi Architecture Binary. ],
- [ fat_binary=$enableval ] )
+ [fat_binary=$enableval])
if test "$fat_binary" = yes ; then
- AC_MSG_CHECKING( target architecture )
+ AC_MSG_CHECKING(target architecture)
case "$host_os" in
rhapsody*)
echo -n "MacOS X Server: "
- if test "$TARGET_ARCHS" = "" ; then
- TARGET_ARCHS="ppc i386"
- fi
+ if test "$TARGET_ARCHS" = "" ; then
+ TARGET_ARCHS="ppc i386"
+ fi
;;
nextstep*|openstep*)
- echo -n "NeXTSTEP/OPENSTEP: "
-
- if test "$host_os" = "rhapsody" ; then
- echo -n "Rhapsody: "
- if test "$TARGET_ARCHS" = "" ; then
- TARGET_ARCHS="ppc i486"
- fi
- else
echo -n "NeXTSTEP/OPENSTEP: "
if test "$TARGET_ARCHS" = "" ; then
if test `/usr/bin/arch` = "m68k" ; then
@@ -62,7 +52,6 @@ AC_ARG_ENABLE( fat-binary,
TARGET_ARCHS="m68k `/usr/bin/arch`"
fi
fi
- fi
;;
esac
# /usr/lib/arch_tool -archify_list $TARGET_ARCHS
@@ -71,7 +60,7 @@ AC_ARG_ENABLE( fat-binary,
ARCH_FLAG="$ARCH_FLAG -arch $archs "
echo -n " $archs"
done
- AC_DEFINE( NEXT_FAT_BINARY )
+ AC_DEFINE(NEXT_FAT_BINARY)
echo "."
fi
@@ -84,28 +73,43 @@ AC_PROG_YACC
AC_PROG_RANLIB
AC_SUBST(AR)
AC_CHECK_PROGS(AR, ar aal, ar)
-AC_PROG_INSTALL
+
+AC_PROG_LN_S
AC_PROG_MAKE_SET
+AC_EXEEXT
+AC_OBJEXT
+
# checks for UNIX variants that set C preprocessor variables
AC_MINIX
AC_CHECK_SIZEOF(int)
+AC_CHECK_SIZEOF(short)
AC_CHECK_SIZEOF(long)
AC_CHECK_SIZEOF(void*)
+AC_CHECK_SIZEOF(float)
+AC_CHECK_SIZEOF(double)
-AC_MSG_CHECKING(for prototypes)
-AC_CACHE_VAL(rb_cv_have_prototypes,
+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)])
-AC_MSG_RESULT($rb_cv_have_prototypes)
if test "$rb_cv_have_prototypes" = yes; then
AC_DEFINE(HAVE_PROTOTYPES)
fi
-AC_MSG_CHECKING(for variable length prototypes and stdarg.h)
-AC_CACHE_VAL(rb_cv_stdarg,
+AC_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, ...) {
@@ -119,17 +123,14 @@ int foo(int x, ...) {
], [return foo(10, "", 3.14);],
rb_cv_stdarg=yes,
rb_cv_stdarg=no)])
-AC_MSG_RESULT($rb_cv_stdarg)
if test "$rb_cv_stdarg" = yes; then
AC_DEFINE(HAVE_STDARG_PROTOTYPES)
fi
-AC_MSG_CHECKING(for gcc attribute noreturn)
-AC_CACHE_VAL(rb_cv_have_attr_noreturn,
+AC_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)])
-AC_MSG_RESULT($rb_cv_have_attr_noreturn)
if test "$rb_cv_have_attr_noreturn" = yes; then
AC_DEFINE(HAVE_ATTR_NORETURN)
fi
@@ -141,6 +142,7 @@ openstep*) ;;
rhapsody*) ;;
human*) ;;
beos*) ;;
+cygwin*) ;;
*) LIBS="-lm $LIBS";;
esac
AC_CHECK_LIB(crypt, crypt)
@@ -151,9 +153,10 @@ AC_CHECK_LIB(xpg4, setlocale) # FreeBSD needs this
dnl Checks for header files.
AC_HEADER_DIRENT
AC_HEADER_STDC
-AC_CHECK_HEADERS(stdlib.h unistd.h limits.h sys/file.h sys/ioctl.h pwd.h \
- sys/select.h sys/time.h sys/times.h sys/param.h sys/wait.h\
- syscall.h a.out.h string.h utime.h memory.h direct.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 fnmatch.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_UID_T
@@ -170,15 +173,16 @@ AC_TYPE_SIGNAL
AC_FUNC_ALLOCA
AC_FUNC_VFORK
AC_FUNC_MEMCMP
-AC_REPLACE_FUNCS(dup2 memmove mkdir strcasecmp strerror strftime\
- strchr strstr strtoul strdup crypt flock vsnprintf)
+AC_REPLACE_FUNCS(dup2 memmove mkdir strcasecmp strncasecmp strerror strftime\
+ strchr strstr strtoul strdup crypt flock vsnprintf\
+ fnmatch isinf isnan finite)
AC_CHECK_FUNCS(fmod killpg drand48 random wait4 waitpid syscall getcwd\
truncate chsize times utimes fcntl lockf setitimer\
setruid seteuid setreuid setrgid setegid setregid\
- setpgrp2 getpgid setpgid getgroups getpriority\
- dlopen sigprocmask sigaction _setjmp setpgrp setsid)
+ getpgrp setpgrp getpgid setpgid getgroups getpriority\
+ dlopen sigprocmask sigaction _setjmp setsid)
+AC_STRUCT_TIMEZONE
if test "$ac_cv_func_strftime" = no; then
- AC_STRUCT_TIMEZONE
AC_TRY_LINK([],
[extern int daylight; int i = daylight;], AC_DEFINE(HAVE_DAYLIGHT))
fi
@@ -186,8 +190,7 @@ 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>
@@ -208,43 +211,51 @@ 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_C_CONST
AC_CHAR_UNSIGNED
-AC_MSG_CHECKING(whether right shift preserve sign bit)
-AC_CACHE_VAL(rb_cv_rshift_sign,
+AC_CACHE_CHECK(whether right shift preserve sign bit, rb_cv_rshift_sign,
[AC_TRY_RUN([
int
main()
@@ -255,15 +266,15 @@ main()
}
],
rb_cv_rshift_sign=yes,
- rb_cv_rshift_sign=no)])
- AC_MSG_RESULT($rb_cv_rshift_sign)
+ rb_cv_rshift_sign=no,
+ rb_cv_rshift_sign=yes)])
if test "$rb_cv_rshift_sign" = yes; then
AC_DEFINE(RSHIFT(x,y), ((x)>>y))
else
AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>y) : (x)>>y))
fi
-AC_MSG_CHECKING([count field in FILE structures])
+AC_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", )
@@ -278,7 +289,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)])
@@ -287,17 +304,31 @@ else
AC_DEFINE_UNQUOTED(FILE_COUNT, $rb_cv_fcnt)
fi
+dnl default value for $KANJI
+AC_SUBST(DEFAULT_KCODE)
+AC_ARG_WITH(default-kcode,
+ [--with-default-kcode=CODE specify default value for \$KCODE (utf8|euc|sjis|none)],
+ [case $withval in
+ utf8) AC_DEFINE(DEFAULT_KCODE, KCODE_UTF8);;
+ euc) AC_DEFINE(DEFAULT_KCODE, KCODE_EUC);;
+ sjis) AC_DEFINE(DEFAULT_KCODE, KCODE_SJIS);;
+ none) AC_DEFINE(DEFAULT_KCODE, KCODE_NONE);;
+ *) AC_MSG_WARN($withval is not valid kcode; ignored);;
+ esac])
+
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(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])
+AC_SUBST(XLDFLAGS)dnl
+
case "$host_os" in
linux*)
- AC_MSG_CHECKING(whether ELF binaries are produced)
- AC_CACHE_VAL(rb_cv_linux_elf,
+ 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>
@@ -315,13 +346,12 @@ 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" = no; then
with_dln_a_out=yes
- host_os=linux-a.out
+ host_os=${host_os}-a_out
else
LDFLAGS="-rdynamic"
fi;;
@@ -345,15 +375,21 @@ if test "$with_dln_a_out" != yes; then
openstep*) ;;
rhapsody*) ;;
human*) ;;
- cygwin*) CCDLFLAGS=-DDLLIMPORT;;
- *) CCDLFLAGS=-fpic;;
+ bsdi3*) ;;
+ cygwin*) ;;
+ netbsd*) CCDLFLAGS=-fpic
+ case "$host_cpu" in
+ mips*) CCDLFLAGS=-fPIC ;;
+ *) ;;
+ esac ;;
+ *) CCDLFLAGS=-fPIC;;
esac
else
case "$host_os" in
hpux*) CCDLFLAGS='+z';;
- solaris*|irix*) CCDLFLAGS='-K pic' ;;
- sunos*) CCDLFLAGS='-pic' ;;
- esix*|uxpds*) CCDLFLAGS='-Kpic' ;;
+ solaris*|irix*) CCDLFLAGS='-K PIC' ;;
+ sunos*) CCDLFLAGS='-PIC' ;;
+ esix*|uxpds*) CCDLFLAGS='-KPIC' ;;
*) CCDLFLAGS='' ;;
esac
fi
@@ -363,7 +399,12 @@ if test "$with_dln_a_out" != yes; then
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;;
@@ -373,19 +414,29 @@ if test "$with_dln_a_out" != yes; then
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 ;;
- freebsd3*) LDSHARED="ld -Bshareable"
- LDFLAGS="-rdynamic"
+ linux*) LDSHARED="$CC -shared"
rb_cv_dlopen=yes ;;
- freebsd*) LDSHARED="ld -Bshareable"
+ freebsd*) LDSHARED="$CC -shared"
+ if test -x /usr/bin/objformat && \
+ test `/usr/bin/objformat` = "elf" ; then
+ LDFLAGS="-rdynamic"
+ DLDFLAGS='-Wl,-soname,$(.TARGET)'
+ rb_cv_freebsd_elf=yes
+ 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"
rb_cv_dlopen=yes ;;
openbsd*) LDSHARED="ld -Bforcearchive -Bshareable"
- CCDLFLAGS=-fPIC
rb_cv_dlopen=yes ;;
- nextstep*) LDSHARED='cc -r'
+ bsdi3*) case "$CC" in
+ *shlicc*) LDSHARED="$CC -r"
+ rb_cv_dlopen=yes ;;
+ esac ;;
+ nextstep*) LDSHARED='cc -r -nostdlib'
LDFLAGS="-u libsys_s"
DLDFLAGS="$ARCH_FLAG"
rb_cv_dlopen=yes ;;
@@ -397,22 +448,30 @@ if test "$with_dln_a_out" != yes; then
LDFLAGS=""
DLDFLAGS="$ARCH_FLAG"
rb_cv_dlopen=yes ;;
- aix*) LDSHARED='../../miniruby ../aix_ld.rb $(TARGET)'
+ aix*) LDSHARED='/usr/ccs/bin/ld'
+ XLDFLAGS='-Wl,-bE:ruby.imp'
+ DLDFLAGS='-eInit_$(TARGET) -bI:$(topdir)/ruby.imp -bM:SRE -T512 -H512 -lc'
rb_cv_dlopen=yes ;;
+
human*) DLDFLAGS=''
LDSHARED=''
- LDFLAGS='' ;;
- beos*) LDSHARED="ld -xms"
- case "$host_cpu" in
+ LDFLAGS=''
+ rb_cv_dlopen=yes ;;
+ beos*) case "$host_cpu" in
powerpc*)
+ LDSHARED="ld -xms"
DLDFLAGS="-f ruby.exp -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o"
;;
+ i586*)
+ LDSHARED="ld -shared"
+ DLDFLAGS="-L/boot/develop/lib/x86 -lbe -lroot"
+ ;;
*)
DLDFLAGS="ruby.def -lbe -lroot glue-noinit.a init_term_dyn.o start_dyn.o"
- ;;
esac
rb_cv_dlopen=yes ;;
- cygwin*) LDSHARED='../../miniruby ../cygwin32_ld.rb' ;;
+ cygwin*) LDSHARED='dllwrap --export-all -s'
+ rb_cv_dlopen=yes ;;
*) LDSHARED='ld' ;;
esac
AC_MSG_RESULT($rb_cv_dlopen)
@@ -421,9 +480,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"
@@ -431,7 +489,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)
@@ -445,21 +502,23 @@ 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
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");;
cygwin*) DLEXT=dll
AC_DEFINE(DLEXT, ".dll");;
+ os2_emx) DLEXT=o
+ AC_DEFINE(DLEXT, ".so");;
*) DLEXT=so
AC_DEFINE(DLEXT, ".so");;
esac
@@ -498,8 +557,8 @@ case "$host_os" in
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_CACHE_CHECK(whether PD libc _dtos18 fail to convert big number,
+ rb_cv_missing__dtos18,
[AC_TRY_RUN(
changequote(<<, >>)dnl
<<
@@ -512,13 +571,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
<<
@@ -532,29 +590,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
+ EXEEXT=.x
+ OBJEXT=o
setup=Setup.x68
;;
+ dnl OS/2 environment w/ Autoconf 2.1x for EMX
+ os2_emx)
+ LIBOBJS="$LIBOBJS os2.o"
+ setup=Setup.emx
+ ;;
cygwin*)
- binsuffix=.exe
setup=Setup
;;
*)
- binsuffix=
setup=Setup
;;
esac
-
-
-AC_SUBST(binsuffix)
AC_SUBST(setup)
if test "$prefix" = NONE; then
@@ -565,18 +623,22 @@ if test "$fat_binary" = yes ; then
CFLAGS="$CFLAGS $ARCH_FLAG"
fi
-LIBRUBY='libruby.a'
-LIBRUBYARG='libruby.a'
+LIBRUBY_A='lib$(RUBY_INSTALL_NAME).a'
+LIBRUBY='$(LIBRUBY_A)'
+LIBRUBYARG='$(LIBRUBY_A)'
SOLIBS=
if test "$host_os" = "beos"; then
- CFLAGS="$CFLAGS -relax_pointers"
- LIBRUBY='libruby.so'
- LIBRUBYARG='-lruby'
+ LIBRUBY='$(LIBRUBY_SO)'
+ LIBRUBYARG='-l$(RUBY_INSTALL_NAME)'
SOLIBS='-lnet'
echo creating ruby.def
case "$host_cpu" in
powerpc*)
cp beos/ruby.def.in ruby.exp
+ CFLAGS="$CFLAGS -relax_pointers"
+ ;;
+ i586*)
+ LDFLAGS="$LDFLAGS -L."
;;
*)
echo EXPORTS > ruby.def
@@ -585,9 +647,72 @@ if test "$host_os" = "beos"; then
esac
fi
+FIRSTMAKEFILE=""
+LIBRUBY_LDSHARED=$LDSHARED
+LIBRUBY_DLDFLAGS=$DLDFLAGS
+LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR).$(TEENY)'
+LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so'
+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./ -lruby'
+ LIBRUBY='$(LIBRUBY_SO)'
+ LIBRUBYARG='-L. -l$(RUBY_INSTALL_NAME)'
+ CFLAGS="$CFLAGS $CCDLFLAGS"
+ case "$host_os" in
+ sunos4*)
+ LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).so'
+ ;;
+ linux*)
+ XLDFLAGS='-Wl,-rpath,${prefix}/lib':/usr/lib:/lib
+ LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).so'
+ ;;
+ freebsd*)
+ LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR)$(MINOR)'
+ if test "$rb_cv_freebsd_elf" != "yes" ; then
+ LIBRUBY_SO="$LIBRUBY_SO.\$(TEENY)"
+ LIBRUBY_ALIASES=''
+ fi
+ ;;
+ netbsd*)
+ LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR)'
+ case "$host_cpu" in
+ alpha|mipsel|mipseb|powerpc|sparc64) # ELF platforms
+ LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR) lib$(RUBY_INSTALL_NAME).so' ;;
+ *) LIBRUBY_ALIASES= ;; # a.out platforms
+ esac
+ ;;
+ 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'
+ ;;
+ cygwin*)
+ LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).a'
+ LIBRUBY_ALIASES=''
+ LIBRUBY_A='lib$(RUBY_INSTALL_NAME)s.a'
+ LIBRUBYARG='-L. -l$(RUBY_INSTALL_NAME)'
+ FIRSTMAKEFILE=GNUmakefile:cygwin/GNUmakefile.in
+ LIBOBJS="$LIBOBJS strftime.o"
+ CCDLFLAGS=-DUSEIMPORTLIB
+ ;;
+ *)
+ ;;
+ esac
fi
case "$host_os" in
@@ -604,7 +729,12 @@ case "$host_os" in
;;
esac
-
+AC_SUBST(LIBRUBY_LDSHARED)
+AC_SUBST(LIBRUBY_DLDFLAGS)
+AC_SUBST(RUBY_INSTALL_NAME)
+AC_SUBST(LIBRUBY_A)
+AC_SUBST(LIBRUBY_SO)
+AC_SUBST(LIBRUBY_ALIASES)
AC_SUBST(LIBRUBY)
AC_SUBST(LIBRUBYARG)
AC_SUBST(SOLIBS)
@@ -618,30 +748,39 @@ test "$program_suffix" != NONE &&
ri_suffix=$program_suffix
RUBY_INSTALL_NAME="${ri_prefix}ruby${ri_suffix}"
-AC_DEFINE_UNQUOTED(RUBY_LIB, "${prefix}/lib/${RUBY_INSTALL_NAME}")
-AC_DEFINE_UNQUOTED(RUBY_SITE_LIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby")
+RUBY_LIB_PATH="${prefix}/lib/ruby/${MAJOR}.${MINOR}"
+AC_DEFINE_UNQUOTED(RUBY_LIB, "${RUBY_LIB_PATH}")
+RUBY_SITE_LIB_PATH="${RUBY_LIB_PATH}/site_ruby"
+AC_DEFINE_UNQUOTED(RUBY_SITE_LIB, "${RUBY_SITE_LIB_PATH}")
AC_SUBST(arch)dnl
+configure_args=$ac_configure_args
+AC_SUBST(configure_args)dnl
+
if test "$fat_binary" = yes ; then
arch="fat-${host_os}"
AC_DEFINE_UNQUOTED(RUBY_THIN_ARCHLIB,
- "${prefix}/lib/${RUBY_INSTALL_NAME}/" __ARCHITECTURE__ "-${host_os}" )
+ "${RUBY_LIB_PATH}/" __ARCHITECTURE__ "-${host_os}")
AC_DEFINE_UNQUOTED(RUBY_SITE_THIN_ARCHLIB,
- "${prefix}/lib/${RUBY_INSTALL_NAME}/" __ARCHITECTURE__ "-${host_os}" )
-
- AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/${arch}")
- AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby/${arch}")
- AC_DEFINE_UNQUOTED(RUBY_PLATFORM, __ARCHITECTURE__ "-${host_os}" )
+ "${RUBY_SITE_LIB_PATH}/" __ARCHITECTURE__ "-${host_os}")
+ AC_DEFINE_UNQUOTED(RUBY_PLATFORM, __ARCHITECTURE__ "-${host_os}")
else
arch="${host_cpu}-${host_os}"
- AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/${arch}")
- AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${prefix}/lib/${RUBY_INSTALL_NAME}/site_ruby/${arch}")
AC_DEFINE_UNQUOTED(RUBY_PLATFORM, "${arch}")
fi
+AC_DEFINE_UNQUOTED(RUBY_ARCHLIB, "${RUBY_LIB_PATH}/${arch}")
+AC_DEFINE_UNQUOTED(RUBY_SITE_ARCHLIB, "${RUBY_SITE_LIB_PATH}/${arch}")
+
+AC_ARG_WITH(search-path,
+ [--with-search-path 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
-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..970e90e24a
--- /dev/null
+++ b/cygwin/GNUmakefile.in
@@ -0,0 +1,9 @@
+include Makefile
+
+RUBYCWDLL=rubycw.dll
+
+miniruby$(EXEEXT): $(RUBYCWDLL)
+
+$(RUBYCWDLL): $(OBJS) dmyext.o
+ dllwrap -o $(RUBYCWDLL) --export-all --output-lib=$(LIBRUBY_SO) --dllname=$(RUBYCWDLL) -Wl,-e,__cygwin_noncygwin_dll_entry@12 --add-stdcall-alias -s $(OBJS) dmyext.o
+ nm --extern-only $(OBJS) dmyext.o | sed -n '/^........ [CD] _\(.*\)$$/s//#define \1 (*__imp_\1)/p' >import.h
diff --git a/defines.h b/defines.h
index fb10d628b4..8e6eb83ca7 100644
--- a/defines.h
+++ b/defines.h
@@ -13,12 +13,12 @@
#define RUBY
/* define RUBY_USE_EUC/SJIS for default kanji-code */
-#if defined(MSDOS) || defined(__CYGWIN32__) || defined(__human68k__) || defined(__MACOS__)
-#undef RUBY_USE_EUC
-#define RUBY_USE_SJIS
+#ifndef DEFAULT_KCODE
+#if defined(MSDOS) || defined(__CYGWIN32__) || defined(__human68k__) || defined(__MACOS__) || defined(__EMX__) || defined(OS2)
+#define DEFAULT_KCODE KCODE_SJIS
#else
-#define RUBY_USE_EUC
-#undef RUBY_USE_SJIS
+#define DEFAULT_KCODE KCODE_EUC
+#endif
#endif
#ifdef NeXT
@@ -31,7 +31,7 @@
#endif /* NeXT */
#ifdef NT
-#include "missing/nt.h"
+#include "win32/win32.h"
#endif
#ifndef EXTERN
@@ -44,11 +44,16 @@
#define FLUSH_REGISTER_WINDOWS /* empty */
#endif
-#if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__MACOS__)
-#define RUBY_PATH_SEP ";"
+#if defined(MSDOS) || defined(_WIN32) || defined(__human68k__) || defined(__EMX__)
+#define DOSISH 1
+#endif
+
+#if defined(MSDOS) || defined(NT) || defined(__human68k__)
+#define PATH_SEP ";"
#else
-#define RUBY_PATH_SEP ":"
+#define PATH_SEP ":"
#endif
+#define PATH_SEP_CHAR PATH_SEP[0]
#if defined(__human68k__) || defined(__CYGWIN32__)
#undef HAVE_RANDOM
diff --git a/dir.c b/dir.c
index 51d7f9e344..31116a9fff 100644
--- a/dir.c
+++ b/dir.c
@@ -6,7 +6,7 @@
$Date$
created at: Wed Jan 5 09:51:01 JST 1994
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -47,14 +47,23 @@
# endif
#endif
+#ifdef HAVE_FNMATCH_H
+#include <fnmatch.h>
+#else
+#include "missing/fnmatch.h"
+#endif
+
#include <errno.h>
+#ifdef USE_CWGUSI
+# include <sys/errno.h>
+#endif
-#ifndef NT
+#ifndef HAVE_STDLIB_H
char *getenv();
#endif
-#ifdef USE_CWGUSI
-# include <sys/errno.h>
+#ifndef HAVE_STRING_H
+char *strchr _((char*,char));
#endif
VALUE rb_cDir;
@@ -149,10 +158,10 @@ static VALUE
dir_tell(dir)
VALUE dir;
{
+#if !defined(__CYGWIN32__) && !defined(__BEOS__)
DIR *dirp;
- int pos;
+ long pos;
-#if !defined(__CYGWIN32__) && !defined(__BEOS__)
GetDIR(dir, dirp);
pos = telldir(dirp);
return rb_int2inum(pos);
@@ -248,7 +257,7 @@ static VALUE
dir_s_chroot(dir, path)
VALUE dir, path;
{
-#if !defined(DJGPP) && !defined(NT) && !defined(__human68k__) && !defined(USE_CWGUSI) && !defined(__BEOS__)
+#if !defined(DJGPP) && !defined(NT) && !defined(__human68k__) && !defined(USE_CWGUSI) && !defined(__BEOS__) && !defined(__EMX__)
rb_secure(2);
Check_SafeStr(path);
@@ -303,29 +312,169 @@ dir_s_rmdir(obj, dir)
return Qtrue;
}
-#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;
+ }
+
+ 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 > 0 && pend[-1] == '/') {
+ 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
+
+static void
+glob(path, func, arg)
+ char *path;
+ void (*func)();
+ VALUE arg;
+{
+ struct stat st;
+ char *p, *m;
+
+ if (!has_magic(path, 0)) {
+ if (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;
+ DIR *dirp;
+ struct dirent *dp;
+
+ struct d_link {
+ char *path;
+ struct d_link *next;
+ } *tmp, *link = 0;
+
+ base = extract_path(path, p);
+ if (path == p) dir = ".";
+ else dir = base;
+
+ dirp = opendir(dir);
+ if (dirp == NULL) {
+ free(base);
+ break;
+ }
+ magic = extract_elem(p);
+ for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
+ if (fnmatch(magic, dp->d_name, FNM_PERIOD|FNM_PATHNAME) == 0) {
+ char *fix = ALLOC_N(char, strlen(base)+NAMLEN(dp)+2);
+
+ sprintf(fix, "%s%s%s", base, (*base)?"/":"", dp->d_name);
+ if (!m) {
+ (*func)(fix, arg);
+ free(fix);
+ continue;
+ }
+ tmp = ALLOC(struct d_link);
+ tmp->path = fix;
+ 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);
+ glob(t, func, arg);
+ free(t);
+ }
+ tmp = link;
+ link = link->next;
+ free(tmp->path);
+ free(tmp);
+ }
+ }
+ p = m;
+ }
+}
-char **glob_filename();
-extern char *glob_error_return;
+static void
+push_pattern(path, ary)
+ char *path;
+ VALUE ary;
+{
+ rb_ary_push(ary, rb_tainted_str_new2(path));
+}
static void
push_globs(ary, s)
VALUE ary;
char *s;
{
- char **fnames, **ff;
-
- fnames = glob_filename(s);
- if (fnames == (char**)-1) rb_sys_fail(s);
- ff = fnames;
- while (*ff) {
- rb_ary_push(ary, rb_tainted_str_new2(*ff));
- free(*ff);
- ff++;
- }
- if (fnames != &glob_error_return) {
- free(fnames);
- }
+ glob(s, push_pattern, ary);
}
static void
@@ -333,9 +482,10 @@ 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;
@@ -347,7 +497,8 @@ push_braces(ary, s)
p++;
}
while (*p) {
- if (*p == '}' && lbrace) {
+ if (*p == '{') nest++;
+ if (*p == '}' && --nest == 0) {
rbrace = p;
break;
}
@@ -355,6 +506,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;
@@ -368,46 +522,44 @@ 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, str)
VALUE dir, str;
{
char *p, *pend;
- char buf[MAXPATHLEN];
- char *t, *t0;
+ char buffer[MAXPATHLEN], *buf = buffer;
+ char *t;
int nest;
VALUE ary;
Check_SafeStr(str);
- if (RSTRING(str)->len > MAXPATHLEN) {
- rb_raise(rb_eArgError, "pathname too long (%d bytes)",
- RSTRING(str)->len);
- }
ary = rb_ary_new();
+ if (RSTRING(str)->len >= MAXPATHLEN)
+ buf = xmalloc(RSTRING(str)->len + 1);
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);
}
@@ -416,6 +568,8 @@ dir_s_glob(dir, str)
}
/* else unmatched braces */
}
+ if (buf != buffer)
+ free(buf);
return ary;
}
diff --git a/dln.c b/dln.c
index 858291d5b7..e6c7adde70 100644
--- a/dln.c
+++ b/dln.c
@@ -6,7 +6,7 @@
$Date$
created at: Tue Jan 18 17:05:06 JST 1994
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -30,9 +30,11 @@ char *dln_argv0;
# include <strings.h>
#endif
+#ifndef xmalloc
void *xmalloc();
void *xcalloc();
void *xrealloc();
+#endif
#include <stdio.h>
#ifndef NT
@@ -56,7 +58,6 @@ void *xrealloc();
#endif
#ifndef NT
-char *strdup();
char *getenv();
#endif
@@ -64,6 +65,7 @@ char *getenv();
# include <TextUtils.h>
# include <CodeFragments.h>
# include <Aliases.h>
+# include "macruby_private.h"
#endif
#ifdef __BEOS__
@@ -78,7 +80,7 @@ int eaccess();
#endif
#ifndef FUNCNAME_PATTERN
-# if defined(__hp9000s300) || defined(__NetBSD__) || defined(__BORLANDC__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) || defined(NeXT) || defined(__WATCOMC__)
+# if defined(__hp9000s300) || (defined(__NetBSD__) && (!defined(__alpha__) && !defined(__mips__))) || defined(__BORLANDC__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) || defined(NeXT) || defined(__WATCOMC__) || defined(__APPLE__)
# define FUNCNAME_PATTERN "_Init_%.200s"
# else
# define FUNCNAME_PATTERN "Init_%.200s"
@@ -87,7 +89,8 @@ int eaccess();
static void
init_funcname(buf, file)
- char *buf, *file;
+ char *buf;
+ char *file;
{
char *p, *slash;
@@ -100,7 +103,7 @@ init_funcname(buf, file)
#endif
sprintf(buf, FUNCNAME_PATTERN, slash + 1);
- for (p = buf; *p; p++) { /* Delete suffix it it exists */
+ for (p = buf; *p; p++) { /* Delete suffix if it exists */
if (*p == '.') {
*p = '\0'; break;
}
@@ -315,7 +318,7 @@ sym_hash(hdrp, syms)
static int
dln_init(prog)
- char *prog;
+ const char *prog;
{
char *file;
int fd;
@@ -423,7 +426,7 @@ load_text_data(fd, hdrp, bss, disp)
}
static int
-underb_f_print(key, value)
+undef_print(key, value)
char *key, *value;
{
fprintf(stderr, " %s\n", key);
@@ -434,7 +437,7 @@ static void
dln_print_undef()
{
fprintf(stderr, " Undefined symbols:\n");
- st_foreach(undef_tbl, underb_f_print, NULL);
+ st_foreach(undef_tbl, undef_print, NULL);
}
static void
@@ -462,7 +465,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;
{
@@ -492,7 +495,7 @@ link_undef(name, base, reloc)
}
struct reloc_arg {
- char *name;
+ const char *name;
long value;
};
@@ -562,7 +565,7 @@ reloc_undef(no, undef, arg)
static void
unlink_undef(name, value)
- char *name;
+ const char *name;
long value;
{
struct reloc_arg arg;
@@ -595,7 +598,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;
@@ -873,7 +876,7 @@ 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;
{
@@ -893,7 +896,7 @@ 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];
@@ -1030,7 +1033,7 @@ load_lib(lib)
static int
load(file)
- char *file;
+ const char *file;
{
int fd;
int result;
@@ -1056,7 +1059,7 @@ load(file)
void*
dln_sym(name)
- char *name;
+ const char *name;
{
struct nlist *sym;
@@ -1076,7 +1079,7 @@ dln_sym(name)
# endif
#endif
-#ifdef hpux
+#ifdef __hpux
#include <errno.h>
#include "dl.h"
#endif
@@ -1094,12 +1097,16 @@ dln_sym(name)
#include <mach-o/dyld.h>
#endif
#endif
+#ifdef __APPLE__
+#include <mach-o/dyld.h>
+#endif
+
#ifdef _WIN32
#include <windows.h>
#endif
-static char *
+static const char *
dln_strerror()
{
#ifdef USE_DLN_A_OUT
@@ -1152,7 +1159,7 @@ dln_strerror()
#if defined(_AIX)
static void
-aix_loaderror(char *pathname)
+aix_loaderror(const char *pathname)
{
char *message[8], errbuf[1024];
int i,j;
@@ -1184,11 +1191,11 @@ aix_loaderror(char *pathname)
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");
}
@@ -1200,7 +1207,7 @@ aix_loaderror(char *pathname)
void
dln_load(file)
- char *file;
+ const char *file;
{
#ifdef _WIN32
HINSTANCE handle;
@@ -1277,7 +1284,7 @@ dln_load(file)
}
#endif /* USE_DLN_DLOPEN */
-#ifdef hpux
+#ifdef __hpux
#define DLN_DEFINED
{
shl_t lib = NULL;
@@ -1308,16 +1315,19 @@ dln_load(file)
{
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;
}
#endif /* _AIX */
-#ifdef NeXT
+#if defined(NeXT) || defined(__APPLE__)
#define DLN_DEFINED
/*----------------------------------------------------
By SHIROYAMA Takayuki Psi@fortune.nest.or.jp
@@ -1327,7 +1337,8 @@ dln_load(file)
Mi hisho@tasihara.nest.or.jp,
and... Miss ARAI Akino(^^;)
----------------------------------------------------*/
-#if NS_TARGET_MAJOR < 4 /* NeXTSTEP rld functions */
+#if defined(NeXT) && (NS_TARGET_MAJOR < 4)/* NeXTSTEP rld functions */
+
{
unsigned long init_address;
char *object_files[2] = {NULL, NULL};
@@ -1351,19 +1362,19 @@ dln_load(file)
init_fct = (void(*)())init_address;
(*init_fct)();
- return ;
+ return;
}
#else/* OPENSTEP dyld functions */
{
- int dyld_result ;
- NSObjectFileImage obj_file ; /* handle, but not use it */
+ 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 );
+ dyld_result = NSCreateObjectFileImageFromFile(file, &obj_file);
if (dyld_result != NSObjectFileImageSuccess) {
rb_loaderror("Failed to load %.200s", file);
@@ -1373,15 +1384,15 @@ dln_load(file)
/* lookup the initial function */
/*NSIsSymbolNameDefined require function name without "_" */
- if( NSIsSymbolNameDefined( buf + 1 ) ) {
+ 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 = NSAddressOfSymbol(NSLookupAndBindSymbol(buf));
(*init_fct)();
- return ;
+ return;
}
#endif /* rld or dyld */
#endif
@@ -1406,14 +1417,14 @@ dln_load(file)
/* strcat(init_fct_symname, "__Fv"); */ /* parameter nothing. */
/* "__Fv" dont need! The Be Book Bug ? */
err_stat = get_image_symbol(img_id, buf,
- B_SYMBOL_TYPE_TEXT, &init_fct);
+ B_SYMBOL_TYPE_TEXT, (void **)&init_fct);
if (err_stat != B_NO_ERROR) {
char real_name[1024];
strcpy(real_name, buf);
strcat(real_name, "__Fv");
err_stat = get_image_symbol(img_id, real_name,
- B_SYMBOL_TYPE_TEXT, &init_fct);
+ B_SYMBOL_TYPE_TEXT, (void **)&init_fct);
}
if ((B_BAD_IMAGE_ID == err_stat) || (B_BAD_INDEX == err_stat)) {
@@ -1453,8 +1464,8 @@ dln_load(file)
c2pstr(fullpath);
(void)FSMakeFSSpec(0, 0, fullpath, &libspec);
err = ResolveAliasFile(&libspec, 1, &isfolder, &didsomething);
- if ( err ) {
- rb_loaderror("Unresolved Alias - %s", file);
+ if (err) {
+ rb_loaderror("Unresolved Alias - %s", file);
}
/* Load the fragment (or return the connID if it is already loaded */
@@ -1462,16 +1473,16 @@ dln_load(file)
err = GetDiskFragment(&libspec, 0, 0, fragname,
kLoadCFrag, &connID, &mainAddr,
errMessage);
- if ( err ) {
- p2cstr(errMessage);
- rb_loaderror("%s - %s",errMessage , file);
+ 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);
+ if (err) {
+ rb_loaderror("Unresolved symbols - %s" , file);
}
init_fct = (void (*)())symAddr;
@@ -1496,8 +1507,8 @@ 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__)
@@ -1519,18 +1530,24 @@ dln_find_exe(fname, path)
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;
@@ -1545,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
@@ -1561,26 +1581,23 @@ 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
-#ifndef __MACOS__
+
if (fname[0] == '/') return fname;
if (strncmp("./", fname, 2) == 0 || strncmp("../", fname, 3) == 0)
return fname;
if (exe_flag && strchr(fname, '/')) return fname;
-#if defined(MSDOS) || defined(NT) || defined(__human68k__)
+#if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__EMX__)
if (fname[0] == '\\') return fname;
if (strlen(fname) > 2 && fname[1] == ':') return fname;
if (strncmp(".\\", fname, 2) == 0 || strncmp("..\\", fname, 3) == 0)
return fname;
if (exe_flag && strchr(fname, '\\')) return fname;
#endif
-#endif /* __MACOS__ */
for (dp = path;; dp = ++ep) {
register int l;
@@ -1588,7 +1605,7 @@ dln_find_1(fname, path, exe_flag)
int fspace;
/* extract a component */
- ep = strchr(dp, RUBY_PATH_SEP[0]);
+ ep = strchr(dp, PATH_SEP[0]);
if (ep == NULL)
ep = dp+strlen(dp);
@@ -1606,7 +1623,7 @@ dln_find_1(fname, path, exe_flag)
*/
if (*dp == '~' && (l == 1 ||
-#if defined(MSDOS) || defined(NT) || defined(__human68k__)
+#if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__EMX__)
dp[1] == '\\' ||
#endif
dp[1] == '/')) {
@@ -1632,11 +1649,7 @@ dln_find_1(fname, path, exe_flag)
/* add a "/" between directory and filename */
if (ep[-1] != '/')
-#ifdef __MACOS__
- *bp++ = ':';
-#else
*bp++ = '/';
-#endif
}
/* now append the file name */
@@ -1651,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)
@@ -1664,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
};
@@ -1679,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..6e4f606212 100644
--- a/dln.h
+++ b/dln.h
@@ -3,7 +3,6 @@
dln.h -
$Author$
- $Revision$
$Date$
created at: Wed Jan 19 16:53:09 JST 1994
@@ -14,17 +13,18 @@
#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/enum.c b/enum.c
index 2b4b904018..dc7e2112a4 100644
--- a/enum.c
+++ b/enum.c
@@ -6,7 +6,7 @@
$Date$
created at: Fri Oct 1 15:15:19 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -56,6 +56,7 @@ enum_grep(obj, pat)
arg[0] = pat; arg[1] = tmp = rb_ary_new();
rb_iterate(rb_each, obj, grep_i, (VALUE)arg);
+ if (RARRAY(tmp)->len == 0) return Qnil;
return tmp;
}
}
@@ -122,6 +123,28 @@ enum_find_all(obj)
}
static VALUE
+reject_i(i, tmp)
+ VALUE i, tmp;
+{
+ if (!RTEST(rb_yield(i))) {
+ rb_ary_push(tmp, i);
+ }
+ return Qnil;
+}
+
+static VALUE
+enum_reject(obj)
+ VALUE obj;
+{
+ VALUE tmp;
+
+ tmp = rb_ary_new();
+ rb_iterate(rb_each, obj, reject_i, tmp);
+
+ return tmp;
+}
+
+static VALUE
collect_i(i, tmp)
VALUE i, tmp;
{
@@ -373,7 +396,10 @@ Init_Enumerable()
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,"min", enum_min, 0);
rb_define_method(rb_mEnumerable,"max", enum_max, 0);
diff --git a/env.h b/env.h
index 79fdfc2bef..6c38d4cbb1 100644
--- a/env.h
+++ b/env.h
@@ -3,7 +3,6 @@
env.h -
$Author$
- $Revision$
$Date$
created at: Mon Jul 11 11:53:03 JST 1994
@@ -19,6 +18,7 @@ extern struct FRAME {
VALUE last_class;
VALUE cbase;
struct FRAME *prev;
+ struct FRAME *tmp;
char *file;
int line;
int iter;
@@ -37,7 +37,7 @@ extern struct SCOPE {
#define SCOPE_MALLOC 1
#define SCOPE_NOSTACK 2
-extern int rb_in_eval;
+extern int ruby_in_eval;
extern VALUE ruby_class;
diff --git a/error.c b/error.c
index 44ca067472..300c09fed0 100644
--- a/error.c
+++ b/error.c
@@ -6,7 +6,7 @@
$Date$
created at: Mon Aug 9 16:11:34 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -45,10 +45,10 @@ err_snprintf(buf, len, fmt, args)
}
}
-static void err_append _((char*));
+static void err_append _((const char*));
static void
err_print(fmt, args)
- char *fmt;
+ const char *fmt;
va_list args;
{
char buf[BUFSIZ];
@@ -59,10 +59,10 @@ err_print(fmt, args)
void
#ifdef HAVE_STDARG_PROTOTYPES
-rb_compile_error(char *fmt, ...)
+rb_compile_error(const char *fmt, ...)
#else
rb_compile_error(fmt, va_alist)
- char *fmt;
+ const char *fmt;
va_dcl
#endif
{
@@ -76,10 +76,10 @@ rb_compile_error(fmt, va_alist)
void
#ifdef HAVE_STDARG_PROTOTYPES
-rb_compile_error_append(char *fmt, ...)
+rb_compile_error_append(const char *fmt, ...)
#else
rb_compile_error_append(fmt, va_alist)
- char *fmt;
+ const char *fmt;
va_dcl
#endif
{
@@ -94,10 +94,10 @@ rb_compile_error_append(fmt, va_alist)
void
#ifdef HAVE_STDARG_PROTOTYPES
-rb_warn(char *fmt, ...)
+rb_warn(const char *fmt, ...)
#else
rb_warn(fmt, va_alist)
- char *fmt;
+ const char *fmt;
va_dcl
#endif
{
@@ -114,17 +114,17 @@ rb_warn(fmt, va_alist)
/* rb_warning() reports only in verbose mode */
void
#ifdef HAVE_STDARG_PROTOTYPES
-rb_warning(char *fmt, ...)
+rb_warning(const char *fmt, ...)
#else
rb_warning(fmt, va_alist)
- char *fmt;
+ const char *fmt;
va_dcl
#endif
{
char buf[BUFSIZ];
va_list args;
- if (!RTEST(rb_verbose)) return;
+ if (!RTEST(ruby_verbose)) return;
snprintf(buf, BUFSIZ, "warning: %s", fmt);
@@ -135,10 +135,10 @@ rb_warning(fmt, va_alist)
void
#ifdef HAVE_STDARG_PROTOTYPES
-rb_bug(char *fmt, ...)
+rb_bug(const char *fmt, ...)
#else
rb_bug(fmt, va_alist)
- char *fmt;
+ const char *fmt;
va_dcl
#endif
{
@@ -146,7 +146,7 @@ rb_bug(fmt, va_alist)
va_list args;
snprintf(buf, BUFSIZ, "[BUG] %s", fmt);
- rb_in_eval = 0;
+ ruby_in_eval = 0;
va_init_list(args, fmt);
err_print(buf, args);
@@ -156,7 +156,7 @@ rb_bug(fmt, va_alist)
static struct types {
int type;
- char *name;
+ const char *name;
} builtin_types[] = {
T_NIL, "nil",
T_OBJECT, "Object",
@@ -220,7 +220,10 @@ rb_check_type(x, t)
#include <errno.h>
VALUE rb_eException;
-VALUE rb_eSystemExit, rb_eInterrupt, rb_eFatal;
+VALUE rb_eSystemExit;
+VALUE rb_eInterrupt;
+VALUE rb_eSignal;
+VALUE rb_eFatal;
VALUE rb_eStandardError;
VALUE rb_eRuntimeError;
VALUE rb_eSyntaxError;
@@ -238,8 +241,8 @@ VALUE rb_mErrno;
VALUE
rb_exc_new(etype, ptr, len)
VALUE etype;
- char *ptr;
- int len;
+ const char *ptr;
+ long len;
{
VALUE exc = rb_obj_alloc(etype);
@@ -250,7 +253,7 @@ rb_exc_new(etype, ptr, len)
VALUE
rb_exc_new2(etype, s)
VALUE etype;
- char *s;
+ const char *s;
{
return rb_exc_new(etype, s, strlen(s));
}
@@ -283,20 +286,21 @@ exc_initialize(argc, argv, exc)
}
static VALUE
-exc_new(argc, argv, self)
+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;
}
exc = rb_obj_alloc(etype);
- rb_obj_call_init(exc);
+ rb_obj_call_init(exc, argc, argv);
return exc;
}
@@ -337,7 +341,10 @@ static VALUE
exc_backtrace(exc)
VALUE exc;
{
- return rb_iv_get(exc, "bt");
+ ID bt = rb_intern("bt");
+
+ if (!rb_ivar_defined(exc, bt)) return Qnil;
+ return rb_ivar_get(exc, bt);
}
static VALUE
@@ -370,54 +377,15 @@ exc_set_backtrace(exc, bt)
return rb_iv_set(exc, "bt", check_backtrace(bt));
}
-static VALUE
-exception(argc, argv)
- int argc;
- VALUE *argv;
-{
- VALUE v = Qnil;
- VALUE etype = rb_eStandardError;
- int i;
- ID id;
-
- if (argc == 0) {
- rb_raise(rb_eArgError, "wrong # of arguments");
- }
- rb_warn("Exception() is now obsolete");
- if (TYPE(argv[argc-1]) == T_CLASS) {
- etype = argv[argc-1];
- argc--;
- if (!rb_funcall(etype, '<', 1, rb_eException)) {
- rb_raise(rb_eTypeError, "exception should be subclass of Exception");
- }
- }
- for (i=0; i<argc; i++) { /* argument check */
- id = rb_to_id(argv[i]);
- if (!rb_id2name(id)) {
- rb_raise(rb_eArgError, "argument needs to be symbol or string");
- }
- if (!rb_is_const_id(id)) {
- rb_raise(rb_eArgError, "identifier `%s' needs to be constant",
- rb_id2name(id));
- }
- }
- for (i=0; i<argc; i++) {
- v = rb_define_class_under(ruby_class,
- rb_id2name(rb_to_id(argv[i])),
- rb_eStandardError);
- }
- return v;
-}
-
#ifdef __BEOS__
typedef struct {
VALUE *list;
- size_t n;
+ int n;
} syserr_list_entry;
typedef struct {
int ix;
- size_t n;
+ int n;
} syserr_index_entry;
static VALUE syserr_list_b_general[16+1];
@@ -471,7 +439,7 @@ extern int sys_nerr;
static VALUE
set_syserr(i, name)
int i;
- char *name;
+ const char *name;
{
#ifdef __BEOS__
VALUE *list;
@@ -533,7 +501,8 @@ void
Init_Exception()
{
rb_eException = rb_define_class("Exception", rb_cObject);
- rb_define_method(rb_eException, "new", exc_new, -1);
+ 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);
@@ -543,8 +512,9 @@ Init_Exception()
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_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_eSyntaxError = rb_define_class("SyntaxError", rb_eStandardError);
@@ -559,17 +529,15 @@ Init_Exception()
rb_eNotImpError = rb_define_class("NotImplementError", rb_eException);
init_syserr();
-
- rb_define_global_function("Exception", exception, -1);
}
void
#ifdef HAVE_STDARG_PROTOTYPES
-rb_raise(VALUE exc, char *fmt, ...)
+rb_raise(VALUE exc, const char *fmt, ...)
#else
rb_raise(exc, fmt, va_alist)
VALUE exc;
- char *fmt;
+ const char *fmt;
va_dcl
#endif
{
@@ -584,10 +552,10 @@ rb_raise(exc, fmt, va_alist)
void
#ifdef HAVE_STDARG_PROTOTYPES
-rb_loaderror(char *fmt, ...)
+rb_loaderror(const char *fmt, ...)
#else
rb_loaderror(fmt, va_alist)
- char *fmt;
+ const char *fmt;
va_dcl
#endif
{
@@ -610,10 +578,10 @@ rb_notimplement()
void
#ifdef HAVE_STDARG_PROTOTYPES
-rb_fatal(char *fmt, ...)
+rb_fatal(const char *fmt, ...)
#else
rb_fatal(fmt, va_alist)
- char *fmt;
+ const char *fmt;
va_dcl
#endif
{
@@ -624,13 +592,13 @@ rb_fatal(fmt, va_alist)
vsnprintf(buf, BUFSIZ, fmt, args);
va_end(args);
- rb_in_eval = 0;
+ 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();
@@ -1079,20 +1047,20 @@ init_syserr()
static void
err_append(s)
- char *s;
+ const char *s;
{
- extern VALUE rb_errinfo;
+ extern VALUE ruby_errinfo;
- if (rb_in_eval) {
- if (NIL_P(rb_errinfo)) {
- rb_errinfo = rb_exc_new2(rb_eSyntaxError, s);
+ if (ruby_in_eval) {
+ if (NIL_P(ruby_errinfo)) {
+ ruby_errinfo = rb_exc_new2(rb_eSyntaxError, s);
}
else {
- VALUE str = rb_str_to_str(rb_errinfo);
+ VALUE str = rb_str_to_str(ruby_errinfo);
rb_str_cat(str, "\n", 1);
rb_str_cat(str, s, strlen(s));
- rb_errinfo = rb_exc_new3(rb_eSyntaxError, str);
+ ruby_errinfo = rb_exc_new3(rb_eSyntaxError, str);
}
}
else {
diff --git a/eval.c b/eval.c
index a7da313fbe..4f8f9f7c9e 100644
--- a/eval.c
+++ b/eval.c
@@ -6,7 +6,7 @@
$Date$
created at: Thu Jun 10 14:22:17 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -21,7 +21,7 @@
#include "dln.h"
#ifndef HAVE_STRING_H
-char *strrchr _((char*,char));
+char *strrchr _((const char*,const char));
#endif
#ifdef HAVE_UNISTD_H
@@ -38,6 +38,10 @@ char *strrchr _((char*,char));
#include <compat.h>
#endif
+#ifdef __MACOS__
+#include "macruby_private.h"
+#endif
+
#ifndef setjmp
#ifdef HAVE__SETJMP
#define setjmp(env) _setjmp(env)
@@ -64,6 +68,19 @@ static int scope_vmode;
#define SCOPE_SET(f) do {scope_vmode=(f);} while(0)
#define SCOPE_TEST(f) (scope_vmode&(f))
+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)
@@ -198,14 +215,13 @@ rb_alias(klass, name, def)
}
}
if (!orig || !orig->nd_body) {
- rb_raise(rb_eNameError, "undefined method `%s' for `%s'",
- rb_id2name(def), rb_class2name(klass));
+ print_undef(klass, def);
}
body = orig->nd_body;
if (nd_type(body) == NODE_FBODY) { /* was alias */
- body = body->nd_head;
def = body->nd_mid;
origin = body->nd_orig;
+ body = body->nd_head;
}
st_insert(RCLASS(klass)->m_tbl, name,
@@ -232,7 +248,7 @@ remove_method(klass, mid)
void
rb_remove_method(klass, name)
VALUE klass;
- char *name;
+ const char *name;
{
remove_method(klass, rb_intern(name));
}
@@ -240,7 +256,7 @@ rb_remove_method(klass, name)
void
rb_disable_super(klass, name)
VALUE klass;
- char *name;
+ const char *name;
{
VALUE origin;
NODE *body;
@@ -248,8 +264,7 @@ rb_disable_super(klass, name)
body = search_method(klass, mid, &origin);
if (!body || !body->nd_body) {
- rb_raise(rb_eNameError, "undefined method `%s' for `%s'",
- rb_id2name(mid), rb_class2name(klass));
+ print_undef(klass, mid);
}
if (origin == klass) {
body->nd_noex |= NOEX_UNDEF;
@@ -263,7 +278,7 @@ rb_disable_super(klass, name)
void
rb_enable_super(klass, name)
VALUE klass;
- char *name;
+ const char *name;
{
VALUE origin;
NODE *body;
@@ -271,8 +286,7 @@ rb_enable_super(klass, name)
body = search_method(klass, mid, &origin);
if (!body || !body->nd_body || origin != klass) {
- rb_raise(rb_eNameError, "undefined method `%s' for `%s'",
- rb_id2name(mid), rb_class2name(klass));
+ print_undef(klass, mid);
}
body->nd_noex &= ~NOEX_UNDEF;
}
@@ -294,8 +308,7 @@ rb_export_method(klass, name, noex)
body = search_method(rb_cObject, name, &origin);
}
if (!body) {
- rb_raise(rb_eNameError, "undefined method `%s' for `%s'",
- rb_id2name(name), rb_class2name(klass));
+ print_undef(klass, name);
}
if (body->nd_noex != noex) {
if (klass == origin) {
@@ -317,7 +330,7 @@ rb_method_boundp(klass, id, ex)
int noex;
if (rb_get_method_body(&klass, &id, &noex)) {
- if (ex && noex & NOEX_PRIVATE)
+ if (ex && (noex & NOEX_PRIVATE))
return Qfalse;
return Qtrue;
}
@@ -330,7 +343,7 @@ rb_attr(klass, id, read, write, ex)
ID id;
int read, write, ex;
{
- char *name;
+ const char *name;
char *buf;
ID attriv;
int noex;
@@ -366,8 +379,8 @@ rb_attr(klass, id, read, write, ex)
}
}
-static ID init, eqq, each, aref, aset, match;
-VALUE rb_errinfo = Qnil;
+static ID init, eqq, each, aref, aset, match, missing;
+VALUE ruby_errinfo = Qnil;
extern NODE *ruby_eval_tree_begin;
extern NODE *ruby_eval_tree;
extern int ruby_nerrs;
@@ -385,11 +398,13 @@ static struct SCOPE *top_scope;
#define PUSH_FRAME() { \
struct FRAME _frame; \
_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; \
ruby_frame = &_frame; \
#define POP_FRAME() \
@@ -407,14 +422,16 @@ struct BLOCK {
struct tag *tag;
int iter;
int vmode;
+ int flags;
struct RVarmap *d_vars;
-#ifdef USE_THREAD
VALUE orig_thread;
-#endif
struct BLOCK *prev;
};
+
+#define BLOCK_D_SCOPE 1
+#define BLOCK_DYNAMIC 2
+
static struct BLOCK *ruby_block;
-static struct BLOCK *ruby_calling_block;
#define PUSH_BLOCK(v,b) { \
struct BLOCK _block; \
@@ -427,10 +444,11 @@ static struct BLOCK *ruby_calling_block;
_block.frame.file = ruby_sourcefile;\
_block.frame.line = ruby_sourceline;\
_block.scope = ruby_scope; \
- _block.d_vars = ruby_dyna_vars; \
_block.prev = ruby_block; \
_block.iter = ruby_iter->iter; \
_block.vmode = scope_vmode; \
+ _block.flags = BLOCK_D_SCOPE; \
+ _block.d_vars = ruby_dyna_vars; \
ruby_block = &_block;
#define POP_BLOCK() \
@@ -439,37 +457,34 @@ static struct BLOCK *ruby_calling_block;
#define PUSH_BLOCK2(b) { \
struct BLOCK * volatile _old; \
- struct BLOCK * volatile _old_call; \
_old = ruby_block; \
- _old_call = ruby_calling_block; \
- ruby_calling_block = b; \
ruby_block = b;
#define POP_BLOCK2() \
- ruby_calling_block = _old_call; \
ruby_block = _old; \
}
struct RVarmap *ruby_dyna_vars;
#define PUSH_VARS() { \
- struct RVarmap * volatile _oldvmap; \
- _oldvmap = ruby_dyna_vars; \
+ struct RVarmap * volatile _old; \
+ _old = ruby_dyna_vars; \
ruby_dyna_vars = 0;
#define POP_VARS() \
- ruby_dyna_vars = _oldvmap; \
+ ruby_dyna_vars = _old; \
}
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;
- vars->next = ruby_dyna_vars;
+ vars->next = prev;
return vars;
}
@@ -507,17 +522,19 @@ rb_dvar_push(id, value)
ID id;
VALUE value;
{
- ruby_dyna_vars = new_dvar(id, value);
+ ruby_dyna_vars = new_dvar(id, value, ruby_dyna_vars);
}
-void
-rb_dvar_asgn(id, value)
+static void
+dvar_asgn(id, value, push)
ID id;
VALUE value;
+ int push;
{
struct RVarmap *vars = ruby_dyna_vars;
while (vars) {
+ if (push && vars->id == 0) break;
if (vars->id == id) {
vars->val = value;
return;
@@ -525,7 +542,14 @@ rb_dvar_asgn(id, value)
vars = vars->next;
}
rb_dvar_push(id, value);
- return;
+}
+
+void
+rb_dvar_asgn(id, value)
+ ID id;
+ VALUE value;
+{
+ dvar_asgn(id, value, 0);
}
static void
@@ -533,9 +557,16 @@ dvar_asgn_push(id, value)
ID id;
VALUE value;
{
- rb_dvar_asgn(id, value);
- if (ruby_calling_block) {
- ruby_calling_block->d_vars = ruby_dyna_vars;
+ struct RVarmap* vars = 0;
+
+ if (ruby_dyna_vars && ruby_dyna_vars->id == 0) {
+ vars = ruby_dyna_vars;
+ ruby_dyna_vars = ruby_dyna_vars->next;
+ }
+ dvar_asgn(id, value, 1);
+ if (vars) {
+ vars->next = ruby_dyna_vars;
+ ruby_dyna_vars = vars;
}
}
@@ -565,6 +596,7 @@ struct tag {
struct iter *iter;
ID tag;
VALUE retval;
+ struct SCOPE *scope;
int dst;
struct tag *prev;
};
@@ -577,6 +609,7 @@ static struct tag *prot_tag;
_tag.iter = ruby_iter; \
_tag.prev = prot_tag; \
_tag.retval = Qnil; \
+ _tag.scope = ruby_scope; \
_tag.tag = ptag; \
_tag.dst = 0; \
prot_tag = &_tag;
@@ -612,8 +645,8 @@ static struct tag *prot_tag;
VALUE ruby_class;
static VALUE ruby_wrapper; /* security wrapper */
-#define PUSH_CLASS() { \
- VALUE _class = ruby_class; \
+#define PUSH_CLASS() { \
+ VALUE _class = ruby_class; \
#define POP_CLASS() ruby_class = _class; }
@@ -630,39 +663,35 @@ static VALUE ruby_wrapper; /* security wrapper */
scope_vmode = SCOPE_PUBLIC;
#define SCOPE_DONT_RECYCLE FL_USER2
-
-static void scope_dup(struct SCOPE *);
-
-#define POP_SCOPE() \
- if (ruby_scope->flag == SCOPE_ALLOCA) {\
- if (FL_TEST(ruby_scope, SCOPE_DONT_RECYCLE)) {\
- scope_dup(ruby_scope);\
- FL_SET(_old, SCOPE_DONT_RECYCLE);\
- }\
- else {\
- ruby_scope->local_vars = 0;\
- ruby_scope->local_tbl = 0;\
+#define POP_SCOPE() \
+ if (FL_TEST(ruby_scope, SCOPE_DONT_RECYCLE)) {\
+ FL_SET(_old, SCOPE_DONT_RECYCLE);\
+ } \
+ else { \
+ if (ruby_scope->flag == SCOPE_ALLOCA) {\
+ ruby_scope->local_vars = 0; \
+ ruby_scope->local_tbl = 0; \
if (ruby_scope != top_scope)\
rb_gc_force_recycle((VALUE)ruby_scope);\
- }\
- }\
- else {\
- ruby_scope->flag |= SCOPE_NOSTACK;\
- }\
- ruby_scope = _old;\
- scope_vmode = _vmode;\
+ } \
+ else { \
+ 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 VALUE rb_yield_0 _((VALUE, VALUE, VALUE));
+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 VALUE massign _((VALUE,NODE*,VALUE,int));
+static void assign _((VALUE,NODE*,VALUE,int));
static int safe_level = 0;
/* safe-level:
@@ -770,12 +799,19 @@ error_print()
{
VALUE errat;
VALUE eclass;
- VALUE einfo;
- volatile int safe = safe_level;
+ char *einfo;
+ int elen;
- if (NIL_P(rb_errinfo)) return;
+ if (NIL_P(ruby_errinfo)) return;
- errat = get_backtrace(rb_errinfo);
+ PUSH_TAG(PROT_NONE);
+ if (EXEC_TAG() == 0) {
+ errat = get_backtrace(ruby_errinfo);
+ }
+ else {
+ errat = Qnil;
+ }
+ POP_TAG();
if (!NIL_P(errat)) {
VALUE mesg = RARRAY(errat)->ptr[0];
@@ -785,38 +821,46 @@ error_print()
}
}
- eclass = CLASS_OF(rb_errinfo);
- einfo = rb_obj_as_string(rb_errinfo);
- if (eclass == rb_eRuntimeError && RSTRING(einfo)->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(einfo)->len == 0) {
+ if (elen == 0) {
fprintf(stderr, ": ");
fwrite(RSTRING(epath)->ptr, 1, RSTRING(epath)->len, stderr);
putc('\n', stderr);
}
else {
char *tail = 0;
- int len = RSTRING(einfo)->len;
+ int len = elen;
if (RSTRING(epath)->ptr[0] == '#') epath = 0;
- if (tail = strchr(RSTRING(einfo)->ptr, '\n')) {
- len = tail - RSTRING(einfo)->ptr;
+ if (tail = strchr(einfo, '\n')) {
+ len = tail - einfo;
tail++; /* skip newline */
}
fprintf(stderr, ": ");
- fwrite(RSTRING(einfo)->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(einfo)->len-len-1, stderr);
+ fwrite(tail, 1, elen-len-1, stderr);
putc('\n', stderr);
}
}
@@ -836,13 +880,12 @@ error_print()
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;
}
}
}
- safe_level = safe;
}
#if !defined(NT) && !defined(__MACOS__)
@@ -851,17 +894,22 @@ extern char **environ;
char **rb_origenviron;
void rb_call_inits _((void));
-void Init_stack _((void));
+void Init_stack _((void*));
void Init_heap _((void));
void Init_ext _((void));
void
ruby_init()
{
+ static int initialized = 0;
static struct FRAME frame;
static struct iter iter;
int state;
+ if (initialized)
+ return;
+ initialized = 1;
+
ruby_frame = top_frame = &frame;
ruby_iter = &iter;
@@ -871,6 +919,7 @@ ruby_init()
rb_origenviron = environ;
#endif
+ Init_stack(0);
Init_heap();
PUSH_SCOPE();
ruby_scope->local_vars = 0;
@@ -879,13 +928,16 @@ ruby_init()
/* 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();
ruby_class = rb_cObject;
ruby_frame->self = ruby_top_self;
ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,rb_cObject,0,0);
rb_define_global_const("TOPLEVEL_BINDING", rb_f_binding(ruby_top_self));
+#ifdef __MACOS__
+ _macruby_init();
+#endif
ruby_prog_init();
}
POP_TAG();
@@ -905,13 +957,8 @@ 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 = ruby_eval_tree;
- ruby_require_modules();
- ruby_eval_tree = save;
}
POP_TAG();
if (state) {
@@ -925,49 +972,54 @@ static VALUE
eval_node(self)
VALUE self;
{
- VALUE result = Qnil;
- NODE *tree;
+ NODE *beg_tree, *tree;
- if (ruby_eval_tree_begin) {
- tree = ruby_eval_tree_begin;
+ beg_tree = ruby_eval_tree_begin;
+ tree = ruby_eval_tree;
+ if (beg_tree) {
ruby_eval_tree_begin = 0;
- rb_eval(self, tree);
+ rb_eval(self, beg_tree);
}
- if (!ruby_eval_tree) return Qnil;
-
- tree = ruby_eval_tree;
+ if (!tree) return Qnil;
ruby_eval_tree = 0;
- result = rb_eval(self, tree);
- return result;
+ return rb_eval(self, tree);
}
-int rb_in_eval;
+int ruby_in_eval;
-#ifdef USE_THREAD
static void rb_thread_cleanup _((void));
static void rb_thread_wait_other_threads _((void));
-#endif
static int exit_status;
-static void exec_end_proc _((void));
+static void
+call_required_libraries()
+{
+ NODE *save;
+
+ ruby_sourcefile = 0;
+ if (!ext_init) Init_ext();
+ save = ruby_eval_tree;
+ ruby_require_libraries();
+ ruby_eval_tree = save;
+}
void
ruby_run()
{
int state;
static int ex;
+ volatile NODE *tmp;
if (ruby_nerrs > 0) exit(ruby_nerrs);
- Init_stack();
-
+ Init_stack(&tmp);
PUSH_TAG(PROT_NONE);
PUSH_ITER(ITER_NOT);
if ((state = EXEC_TAG()) == 0) {
- if (!ext_init) Init_ext();
+ call_required_libraries();
eval_node(ruby_top_self);
}
POP_ITER();
@@ -978,10 +1030,8 @@ ruby_run()
PUSH_ITER(ITER_NOT);
if ((state = EXEC_TAG()) == 0) {
rb_trap_exit();
-#ifdef USE_THREAD
rb_thread_cleanup();
rb_thread_wait_other_threads();
-#endif
}
else {
ex = state;
@@ -1021,30 +1071,32 @@ ruby_run()
break;
case TAG_RAISE:
case TAG_FATAL:
- if (rb_obj_is_kind_of(rb_errinfo, rb_eSystemExit)) {
- exit(exit_status);
+ if (rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) {
+ ex = exit_status;
+ }
+ else {
+ error_print();
+ ex = 1;
}
- error_print();
- ex = 1;
break;
default:
rb_bug("Unknown longjmp status %d", ex);
break;
}
- exec_end_proc();
+ rb_exec_end_proc();
rb_gc_call_finalizer_at_exit();
exit(ex);
}
static void
compile_error(at)
- char *at;
+ const char *at;
{
VALUE str;
char *mesg;
int len;
- mesg = str2cstr(rb_errinfo, &len);
+ mesg = str2cstr(ruby_errinfo, &len);
ruby_nerrs = 0;
str = rb_str_new2("compile error");
if (at) {
@@ -1058,7 +1110,7 @@ compile_error(at)
VALUE
rb_eval_string(str)
- char *str;
+ const char *str;
{
VALUE v;
char *oldsrc = ruby_sourcefile;
@@ -1072,7 +1124,7 @@ rb_eval_string(str)
VALUE
rb_eval_string_protect(str, state)
- char *str;
+ const char *str;
int *state;
{
VALUE result; /* OK */
@@ -1094,6 +1146,33 @@ rb_eval_string_protect(str, state)
}
VALUE
+rb_eval_string_wrap(str, state)
+ const char *str;
+ int *state;
+{
+ int status;
+ VALUE self = ruby_top_self;
+ VALUE val;
+
+ 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;
+
+ POP_CLASS();
+ if (state) {
+ *state = status;
+ if (status) {
+ JUMP_TAG(status);
+ }
+ }
+ return val;
+}
+
+VALUE
rb_eval_cmd(cmd, arg)
VALUE cmd, arg;
{
@@ -1121,6 +1200,8 @@ rb_eval_cmd(cmd, arg)
val = eval(ruby_top_self, cmd, Qnil, 0, 0);
}
+ if (FL_TEST(ruby_scope, SCOPE_DONT_RECYCLE))
+ FL_SET(saved_scope, SCOPE_DONT_RECYCLE);
ruby_scope = saved_scope;
safe_level = safe;
POP_TAG();
@@ -1151,7 +1232,7 @@ rb_eval_cmd(cmd, arg)
return val;
}
-VALUE
+static VALUE
rb_trap_eval(cmd, sig)
VALUE cmd;
int sig;
@@ -1304,11 +1385,11 @@ rb_mod_alias_method(mod, newname, oldname)
}
#ifdef C_ALLOCA
-# define TMP_PROTECT NODE * volatile __protect_tmp=0
-# define TMP_ALLOC(n) \
- (__protect_tmp = rb_node_newnode(NODE_ALLOCA, \
- ALLOC_N(VALUE,n),__protect_tmp,n), \
- (void*)__protect_tmp->nd_head)
+# 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(n) ALLOCA_N(VALUE,n)
@@ -1411,7 +1492,7 @@ is_defined(self, node, buf)
case NODE_ZSUPER:
if (ruby_frame->last_func == 0) return 0;
else if (rb_method_boundp(RCLASS(ruby_frame->last_class)->super,
- ruby_frame->last_func, 1)) {
+ ruby_frame->last_func, 0)) {
if (nd_type(node) == NODE_SUPER) {
return arg_defined(self, node->nd_args, buf, "super");
}
@@ -1602,9 +1683,7 @@ call_trace_func(event, file, line, self, id, klass)
trace = trace_func;
trace_func = 0;
-#ifdef USE_THREAD
rb_thread_critical++;
-#endif
prev = ruby_frame;
PUSH_FRAME();
@@ -1632,9 +1711,7 @@ call_trace_func(event, file, line, self, id, klass)
POP_TAG();
POP_FRAME();
-#ifdef USE_THREAD
rb_thread_critical--;
-#endif
if (!trace_func) trace_func = trace;
ruby_sourceline = line_save;
ruby_sourcefile = file_save;
@@ -1651,10 +1728,6 @@ rb_eval(self, node)
{
int state;
volatile VALUE result = Qnil;
-#ifdef NOBLOCK_RECUR
- NODE * volatile next = 0;
- NODE * volatile nstack = 0;
-#endif
#define RETURN(v) { result = (v); goto finish; }
@@ -1663,24 +1736,13 @@ rb_eval(self, node)
switch (nd_type(node)) {
case NODE_BLOCK:
-#ifndef NOBLOCK_RECUR
- if (!node->nd_next) {
- node = node->nd_head;
- goto again;
- }
- while (node) {
- result = rb_eval(self, node->nd_head);
+ while (node->nd_next) {
+ rb_eval(self, node->nd_head);
node = node->nd_next;
}
- break;
-#else
- if (next) {
- nstack = rb_node_newnode(NODE_CREF,next,0,nstack);
- }
- next = node->nd_next;
node = node->nd_head;
goto again;
-#endif
+
case NODE_POSTEXE:
rb_f_END();
nd_set_type(node, NODE_NIL); /* exec just once */
@@ -1738,11 +1800,7 @@ rb_eval(self, node)
case NODE_IF:
ruby_sourceline = nd_line(node);
-#ifdef NOBLOCK_RECUR
- if (RTEST(result)){
-#else
if (RTEST(rb_eval(self, node->nd_cond))) {
-#endif
node = node->nd_body;
}
else {
@@ -1754,11 +1812,7 @@ rb_eval(self, node)
{
VALUE val;
-#ifdef NOBLOCK_RECUR
- val = result;
-#else
val = rb_eval(self, node->nd_head);
-#endif
node = node->nd_body;
while (node) {
NODE *tag;
@@ -1883,6 +1937,7 @@ rb_eval(self, node)
char *file = ruby_sourcefile;
int line = ruby_sourceline;
+ _block.flags &= ~BLOCK_D_SCOPE;
recv = rb_eval(self, node->nd_iter);
PUSH_ITER(ITER_PRE);
ruby_sourcefile = file;
@@ -1953,13 +2008,13 @@ rb_eval(self, node)
else {
result = Qnil;
}
- result = rb_yield_0(result, 0, 0);
+ result = rb_yield_0(result, 0, 0, Qfalse);
break;
case NODE_RESCUE:
retry_entry:
{
- volatile VALUE e_info = rb_errinfo;
+ volatile VALUE e_info = ruby_errinfo;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
@@ -1978,7 +2033,7 @@ rb_eval(self, node)
}
POP_TAG();
if (state == 0) {
- rb_errinfo = e_info;
+ ruby_errinfo = e_info;
}
else if (state == TAG_RETRY) {
state = 0;
@@ -2030,11 +2085,9 @@ rb_eval(self, node)
case NODE_DOT2:
case NODE_DOT3:
- result = rb_range_new(rb_eval(self, node->nd_beg), rb_eval(self, node->nd_end));
-#if 0
- break;
-#else
- result = rb_range_new(rb_eval(self, node->nd_beg), rb_eval(self, node->nd_end));
+ 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))
@@ -2045,7 +2098,6 @@ rb_eval(self, node)
else {
node->nd_state = 1;
}
-#endif
break;
case NODE_FLIP2: /* like AWK */
@@ -2106,13 +2158,7 @@ rb_eval(self, node)
TMP_PROTECT;
BEGIN_CALLARGS;
-#ifdef NOBLOCK_RECUR_incomplete
- printf("mid %s recv: ", rb_id2name(node->nd_mid));
- rb_p(result);
- recv = result;
-#else
recv = rb_eval(self, node->nd_recv);
-#endif
SETUP_ARGS(node->nd_args);
END_CALLARGS;
@@ -2167,7 +2213,11 @@ rb_eval(self, node)
case NODE_SCOPE:
{
- VALUE save = ruby_frame->cbase;
+ struct FRAME frame;
+
+ frame = *ruby_frame;
+ frame.tmp = ruby_frame;
+ ruby_frame = &frame;
PUSH_SCOPE();
PUSH_TAG(PROT_NONE);
@@ -2188,7 +2238,7 @@ rb_eval(self, node)
}
POP_TAG();
POP_SCOPE();
- ruby_frame->cbase = save;
+ ruby_frame = frame.tmp;
if (state) JUMP_TAG(state);
}
break;
@@ -2204,15 +2254,16 @@ 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);
- if (node->nd_mid == 0) { /* OR */
- if (RTEST(val)) break;
+ switch (node->nd_mid) {
+ case 0: /* OR */
+ if (RTEST(val)) RETURN(val);
val = rb_eval(self, rval);
- }
- else if (node->nd_mid == 1) { /* AND */
- if (!RTEST(val)) break;
+ break;
+ case 1: /* AND */
+ if (!RTEST(val)) RETURN(val);
val = rb_eval(self, rval);
- }
- else {
+ break;
+ default:
val = rb_funcall(val, node->nd_mid, 1, rb_eval(self, rval));
}
argv[argc-1] = val;
@@ -2228,15 +2279,16 @@ rb_eval(self, node)
recv = rb_eval(self, node->nd_recv);
val = rb_funcall(recv, id, 0);
- if (node->nd_next->nd_mid == 0) { /* OR */
- if (RTEST(val)) break;
+ switch (node->nd_next->nd_mid) {
+ case 0: /* OR */
+ if (RTEST(val)) RETURN(val);
val = rb_eval(self, node->nd_value);
- }
- else if (node->nd_next->nd_mid == 1) { /* AND */
- if (!RTEST(val)) break;
+ break;
+ case 1: /* AND */
+ if (!RTEST(val)) RETURN(val);
val = rb_eval(self, node->nd_value);
- }
- else {
+ break;
+ default:
val = rb_funcall(val, node->nd_next->nd_mid, 1,
rb_eval(self, node->nd_value));
}
@@ -2261,7 +2313,7 @@ rb_eval(self, node)
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:
@@ -2297,9 +2349,9 @@ rb_eval(self, node)
}
result = rb_eval(self, node->nd_value);
/* check for static scope constants */
- if (RTEST(rb_verbose) &&
+ if (RTEST(ruby_verbose) &&
ev_const_defined((NODE*)ruby_frame->cbase, node->nd_vid)) {
- if (RTEST(rb_verbose)) {
+ if (RTEST(ruby_verbose)) {
rb_warning("already initialized constant %s",
rb_id2name(node->nd_vid));
}
@@ -2445,10 +2497,13 @@ rb_eval(self, node)
str2 = list->nd_head->nd_lit;
break;
case NODE_EVSTR:
- rb_in_eval++;
- list->nd_head = compile(list->nd_head->nd_lit,0);
+ 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;
- rb_in_eval--;
+ ruby_in_eval--;
if (ruby_nerrs > 0) {
compile_error("string expansion");
}
@@ -2494,7 +2549,7 @@ rb_eval(self, node)
case NODE_ATTRSET:
if (ruby_frame->argc != 1)
- rb_raise(rb_eArgError, "Wrong # of arguments(%d for 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;
@@ -2514,10 +2569,10 @@ rb_eval(self, node)
body = search_method(ruby_class, node->nd_mid, &origin);
if (body) {
if (origin == ruby_class) {
- if (safe_level >= 3) {
+ if (safe_level >= 4) {
rb_raise(rb_eSecurityError, "re-defining method prohibited");
}
- if (RTEST(rb_verbose)) {
+ if (RTEST(ruby_verbose)) {
rb_warning("discarding old %s", rb_id2name(node->nd_mid));
}
}
@@ -2562,18 +2617,11 @@ rb_eval(self, node)
VALUE klass;
NODE *body = 0;
- if (FIXNUM_P(recv)) {
- rb_raise(rb_eTypeError, "Can't define method \"%s\" for Fixnum",
- rb_id2name(node->nd_mid));
- }
- if (NIL_P(recv)) {
- rb_raise(rb_eTypeError, "Can't define method \"%s\" for nil",
- rb_id2name(node->nd_mid));
- }
if (rb_special_const_p(recv)) {
rb_raise(rb_eTypeError,
- "Can't define method \"%s\" for special constants",
- rb_id2name(node->nd_mid));
+ "can't define method \"%s\" for %s",
+ rb_id2name(node->nd_mid),
+ rb_class2name(CLASS_OF(recv)));
}
if (rb_safe_level() >= 4 && !FL_TEST(recv, FL_TAINT)) {
@@ -2581,10 +2629,10 @@ rb_eval(self, node)
}
klass = rb_singleton_class(recv);
if (st_lookup(RCLASS(klass)->m_tbl, node->nd_mid, &body)) {
- if (safe_level >= 3) {
+ if (safe_level >= 4) {
rb_raise(rb_eSecurityError, "re-defining method prohibited");
}
- if (RTEST(rb_verbose)) {
+ if (RTEST(ruby_verbose)) {
rb_warning("redefine %s", rb_id2name(node->nd_mid));
}
}
@@ -2622,6 +2670,9 @@ rb_eval(self, node)
s0 = "";
}
}
+ else if (TYPE(klass) == T_MODULE) {
+ s0 = " module";
+ }
rb_raise(rb_eNameError, "undefined method `%s' for%s `%s'",
rb_id2name(node->nd_mid),s0,rb_class2name(klass));
}
@@ -2686,7 +2737,7 @@ rb_eval(self, node)
rb_id2name(node->nd_cname));
}
}
- if (safe_level >= 3) {
+ if (safe_level >= 4) {
rb_raise(rb_eSecurityError, "extending class prohibited");
}
rb_clear_cache();
@@ -2696,7 +2747,6 @@ rb_eval(self, node)
klass = rb_define_class_id(node->nd_cname, super);
rb_const_set(ruby_class, node->nd_cname, klass);
rb_set_class_path(klass,ruby_class,rb_id2name(node->nd_cname));
- rb_obj_call_init(klass);
}
if (ruby_wrapper) {
rb_extend_object(klass, ruby_wrapper);
@@ -2728,7 +2778,7 @@ rb_eval(self, node)
rb_raise(rb_eTypeError, "%s is not a module",
rb_id2name(node->nd_cname));
}
- if (safe_level >= 3) {
+ if (safe_level >= 4) {
rb_raise(rb_eSecurityError, "extending module prohibited");
}
}
@@ -2736,7 +2786,6 @@ rb_eval(self, node)
module = rb_define_module_id(node->nd_cname);
rb_const_set(ruby_class, node->nd_cname, module);
rb_set_class_path(module,ruby_class,rb_id2name(node->nd_cname));
- rb_obj_call_init(module);
}
if (ruby_wrapper) {
rb_extend_object(module, ruby_wrapper);
@@ -2752,14 +2801,9 @@ rb_eval(self, node)
VALUE klass;
klass = rb_eval(self, node->nd_recv);
- if (FIXNUM_P(klass)) {
- rb_raise(rb_eTypeError, "No virtual class for Fixnums");
- }
- if (NIL_P(klass)) {
- rb_raise(rb_eTypeError, "No virtual class for nil");
- }
if (rb_special_const_p(klass)) {
- rb_raise(rb_eTypeError, "No virtual class for special constants");
+ rb_raise(rb_eTypeError, "no virtual class for %s",
+ rb_class2name(CLASS_OF(klass)));
}
if (FL_TEST(CLASS_OF(klass), FL_SINGLETON)) {
rb_clear_cache();
@@ -2780,7 +2824,7 @@ rb_eval(self, node)
char *desc = is_defined(self, node->nd_head, buf);
if (desc) result = rb_str_new2(desc);
- else result = Qfalse;
+ else result = Qnil;
}
break;
@@ -2799,18 +2843,6 @@ rb_eval(self, node)
}
finish:
CHECK_INTS;
-#ifdef NOBLOCK_RECUR
- if (next) {
- node = next;
- next = 0;
- goto again;
- }
- if (nstack) {
- node = nstack->nd_head;
- nstack = nstack->nd_next;
- goto again;
- }
-#endif
return result;
}
@@ -2820,12 +2852,16 @@ module_setup(module, node)
NODE * volatile node;
{
int state;
- VALUE save = ruby_frame->cbase;
+ struct FRAME frame;
VALUE result; /* OK */
char *file = ruby_sourcefile;
int line = ruby_sourceline;
TMP_PROTECT;
+ frame = *ruby_frame;
+ frame.tmp = ruby_frame;
+ ruby_frame = &frame;
+
/* fill c-ref */
node->nd_clss = module;
node = node->nd_body;
@@ -2833,6 +2869,7 @@ module_setup(module, node)
PUSH_CLASS();
ruby_class = module;
PUSH_SCOPE();
+ PUSH_VARS();
if (node->nd_rval) ruby_frame->cbase = node->nd_rval;
if (node->nd_tbl) {
@@ -2856,10 +2893,11 @@ module_setup(module, node)
result = rb_eval(ruby_class, node->nd_next);
}
POP_TAG();
+ POP_VARS();
POP_SCOPE();
POP_CLASS();
- ruby_frame->cbase = save;
+ ruby_frame = frame.tmp;
if (trace_func) {
call_trace_func("end", file, line, 0, ruby_frame->last_func, 0);
}
@@ -2914,6 +2952,8 @@ rb_exit(status)
exit_status = status;
rb_exc_raise(rb_exc_new(rb_eSystemExit, 0, 0));
}
+ rb_exec_end_proc();
+ rb_gc_call_finalizer_at_exit();
exit(status);
}
@@ -2924,22 +2964,23 @@ rb_f_exit(argc, argv, obj)
VALUE obj;
{
VALUE status;
+ int istatus;
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);
+ rb_exit(istatus);
return Qnil; /* not reached */
}
static void
rb_abort()
{
- if (rb_errinfo) {
+ if (ruby_errinfo) {
error_print();
}
rb_exit(1);
@@ -2969,7 +3010,7 @@ rb_longjmp(tag, mesg)
{
VALUE at;
- if (NIL_P(mesg)) mesg = rb_errinfo;
+ if (NIL_P(mesg)) mesg = ruby_errinfo;
if (NIL_P(mesg)) {
mesg = rb_exc_new(rb_eRuntimeError, 0, 0);
}
@@ -2982,13 +3023,13 @@ rb_longjmp(tag, mesg)
}
}
if (!NIL_P(mesg)) {
- rb_errinfo = mesg;
+ ruby_errinfo = mesg;
}
- if (RTEST(rb_debug) && !NIL_P(rb_errinfo)
- && !rb_obj_is_kind_of(rb_errinfo, rb_eSystemExit)) {
+ if (RTEST(ruby_debug) && !NIL_P(ruby_errinfo)
+ && !rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) {
fprintf(stderr, "Exception `%s' at %s:%d\n",
- rb_class2name(CLASS_OF(rb_errinfo)),
+ rb_class2name(CLASS_OF(ruby_errinfo)),
ruby_sourcefile, ruby_sourceline);
}
@@ -3028,32 +3069,33 @@ rb_f_raise(argc, argv)
int argc;
VALUE *argv;
{
- VALUE arg1, arg2, arg3;
VALUE mesg;
- int n;
mesg = Qnil;
- switch (n = rb_scan_args(argc, argv, "03", &arg1, &arg2, &arg3)) {
+ switch (argc) {
+ case 0:
+ mesg = Qnil;
+ break;
case 1:
- mesg = arg1;
+ if (NIL_P(argv[0])) break;
+ if (TYPE(argv[0]) == T_STRING) {
+ mesg = rb_exc_new3(rb_eRuntimeError, argv[0]);
+ break;
+ }
+ mesg = rb_funcall(argv[0], rb_intern("exception"), 0, 0);
break;
case 3:
case 2:
- mesg = arg2;
+ mesg = rb_funcall(argv[0], rb_intern("exception"), 1, argv[1]);
+ break;
+ default:
+ rb_raise(rb_eArgError, "wrong # of arguments");
break;
}
-
if (!NIL_P(mesg)) {
- if (n == 1 && TYPE(mesg) == T_STRING) {
- mesg = rb_exc_new3(rb_eRuntimeError, mesg);
- }
- else {
- mesg = rb_funcall(arg1, rb_intern("new"), 1, mesg);
- }
- if (!rb_obj_is_kind_of(mesg, rb_eException)) {
+ if (!rb_obj_is_kind_of(mesg, rb_eException))
rb_raise(rb_eTypeError, "exception object expected");
- }
- set_backtrace(mesg, arg3);
+ set_backtrace(mesg, (argc>2)?argv[2]:Qnil);
}
PUSH_FRAME(); /* fake frame */
@@ -3086,8 +3128,9 @@ rb_f_iterator_p()
}
static VALUE
-rb_yield_0(val, self, klass)
+rb_yield_0(val, self, klass, acheck)
VALUE val, self, klass; /* OK */
+ int acheck;
{
NODE *node;
volatile VALUE result = Qnil;
@@ -3110,15 +3153,27 @@ rb_yield_0(val, self, klass)
old_scope = ruby_scope;
ruby_scope = block->scope;
ruby_block = block->prev;
- ruby_dyna_vars = block->d_vars;
+ if (block->flags & BLOCK_D_SCOPE) {
+ /* put place holder for dynamic (in-block) local variables */
+ ruby_dyna_vars = new_dvar(0, 0, block->d_vars);
+ }
+ else {
+ /* FOR does not introduce new scope */
+ ruby_dyna_vars = block->d_vars;
+ }
ruby_class = klass?klass:block->klass;
if (!self) 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 (nd_type(block->var) == NODE_MASGN)
+ massign(self, block->var, val, acheck);
+ else
+ assign(self, block->var, val, acheck);
+ }
+ POP_TAG();
+ if (state) goto pop_state;
}
PUSH_ITER(block->iter);
PUSH_TAG(PROT_NONE);
@@ -3154,6 +3209,7 @@ rb_yield_0(val, self, klass)
}
}
POP_TAG();
+ pop_state:
POP_ITER();
POP_CLASS();
POP_VARS();
@@ -3170,23 +3226,24 @@ VALUE
rb_yield(val)
VALUE val;
{
- return rb_yield_0(val, 0, 0);
+ return rb_yield_0(val, 0, 0, Qfalse);
}
static VALUE
rb_f_loop()
{
- for (;;) { rb_yield_0(Qnil, 0, 0); }
+ for (;;) { rb_yield_0(Qnil, 0, 0, Qfalse); }
}
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;
list = node->nd_head;
@@ -3196,33 +3253,49 @@ massign(self, node, val)
}
len = RARRAY(val)->len;
for (i=0; list && i<len; i++) {
- assign(self, list->nd_head, RARRAY(val)->ptr[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 (!list && i<len) {
- assign(self, node->nd_args, rb_ary_new4(len-i, RARRAY(val)->ptr+i));
+ if (node->nd_args == (NODE*)-1) {
+ /* ignore rest args */
+ }
+ else if (!list && i<len) {
+ assign(self, node->nd_args, rb_ary_new4(len-i, RARRAY(val)->ptr+i), check);
}
else {
- assign(self, node->nd_args, rb_ary_new2(0));
+ assign(self, node->nd_args, rb_ary_new2(0), check);
}
}
+ else if (check && i<len) goto arg_error;
}
- else if (node->nd_args) {
- assign(self, node->nd_args, Qnil);
+ else if (node->nd_args && node->nd_args != (NODE*)-1) {
+ assign(self, node->nd_args, Qnil, check);
}
+
+ if (check && list) 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;
{
switch (nd_type(lhs)) {
case NODE_GASGN:
@@ -3252,14 +3325,14 @@ assign(self, lhs, val)
break;
case NODE_MASGN:
- massign(self, lhs, val);
+ 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_call(CLASS_OF(recv), recv, lhs->nd_mid, 1, &val, 0);
}
@@ -3268,7 +3341,7 @@ assign(self, lhs, val)
VALUE args;
args = rb_eval(self, lhs->nd_args);
- RARRAY(args)->ptr[RARRAY(args)->len-1] = val;
+ rb_ary_push(args, val);
rb_call(CLASS_OF(recv), recv, lhs->nd_mid,
RARRAY(args)->len, RARRAY(args)->ptr, 0);
}
@@ -3339,7 +3412,7 @@ handle_rescue(self, node)
TMP_PROTECT;
if (!node->nd_args) {
- return rb_obj_is_kind_of(rb_errinfo, rb_eStandardError);
+ return rb_obj_is_kind_of(ruby_errinfo, rb_eStandardError);
}
BEGIN_CALLARGS;
@@ -3350,7 +3423,7 @@ handle_rescue(self, node)
if (!rb_obj_is_kind_of(argv[0], rb_cModule)) {
rb_raise(rb_eTypeError, "class or module required for rescue clause");
}
- if (rb_obj_is_kind_of(rb_errinfo, argv[0])) return 1;
+ if (rb_obj_is_kind_of(ruby_errinfo, argv[0])) return 1;
argv++;
}
return 0;
@@ -3363,18 +3436,18 @@ rb_rescue(b_proc, data1, r_proc, data2)
{
int state;
volatile VALUE result;
- volatile VALUE e_info = rb_errinfo;
+ volatile VALUE e_info = ruby_errinfo;
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
retry_entry:
result = (*b_proc)(data1);
}
- else if (state == TAG_RAISE && rb_obj_is_kind_of(rb_errinfo, rb_eStandardError)) {
+ else if (state == TAG_RAISE && rb_obj_is_kind_of(ruby_errinfo, rb_eStandardError)) {
if (r_proc) {
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
- result = (*r_proc)(data2, rb_errinfo);
+ result = (*r_proc)(data2, ruby_errinfo);
}
POP_TAG();
if (state == TAG_RETRY) {
@@ -3387,7 +3460,7 @@ rb_rescue(b_proc, data1, r_proc, data2)
state = 0;
}
if (state == 0) {
- rb_errinfo = e_info;
+ ruby_errinfo = e_info;
}
}
POP_TAG();
@@ -3443,6 +3516,26 @@ rb_ensure(b_proc, data1, e_proc, data2)
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;
+}
+
static int last_call_status;
#define CSTAT_PRIV 1
@@ -3456,8 +3549,9 @@ rb_f_missing(argc, argv, obj)
VALUE obj;
{
ID id;
- VALUE desc = 0;
+ volatile VALUE d = 0;
char *format = 0;
+ char *desc = "";
char *file = ruby_sourcefile;
int line = ruby_sourceline;
@@ -3469,41 +3563,39 @@ rb_f_missing(argc, argv, obj)
format = "undefined method `%s' for nil";
break;
case T_TRUE:
- format = "undefined method `%s' for Qtrue";
+ format = "undefined method `%s' for true";
break;
case T_FALSE:
- format = "undefined method `%s' for Qfalse";
+ format = "undefined method `%s' for false";
break;
case T_OBJECT:
- desc = rb_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 (rb_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 = rb_any_to_s(obj);
+ if (RSTRING(d)->len > 65) {
+ d = rb_any_to_s(obj);
}
+ desc = RSTRING(d)->ptr;
}
ruby_sourcefile = file;
@@ -3511,9 +3603,9 @@ rb_f_missing(argc, argv, obj)
PUSH_FRAME(); /* fake frame */
*ruby_frame = *_frame.prev->prev;
- rb_raise(rb_eNameError, 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 */
@@ -3535,7 +3627,7 @@ rb_undefined(obj, id, argc, argv, call_status)
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
@@ -3570,7 +3662,7 @@ call_cfunc(func, recv, len, argc, argv)
VALUE *argv;
{
if (len >= 0 && argc != len) {
- rb_raise(rb_eArgError, "Wrong # of arguments(%d for %d)",
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for %d)",
argc, len);
}
@@ -3681,7 +3773,6 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper)
rb_raise(rb_eSysStackError, "stack level too deep");
}
}
-
PUSH_ITER(itr);
PUSH_FRAME();
@@ -3775,21 +3866,23 @@ rb_call0(klass, recv, id, argc, argv, body, nosuper)
i = node->nd_cnt;
if (i > argc) {
- rb_raise(rb_eArgError, "Wrong # of arguments(%d for %d)",
+ 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) {
- rb_raise(rb_eArgError, "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) {
@@ -3802,7 +3895,7 @@ 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;
}
@@ -3896,13 +3989,20 @@ rb_call(klass, recv, mid, argc, argv, scope)
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) && !rb_obj_is_kind_of(ruby_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);
}
@@ -3991,6 +4091,16 @@ 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);
+}
+
static VALUE
backtrace(lev)
int lev;
@@ -3998,9 +4108,7 @@ backtrace(lev)
struct FRAME *frame = ruby_frame;
char buf[BUFSIZ];
VALUE ary;
- int slev = safe_level;
- safe_level = 0;
ary = rb_ary_new();
if (lev < 0) {
if (frame->last_func) {
@@ -4016,7 +4124,10 @@ backtrace(lev)
else {
while (lev-- > 0) {
frame = frame->prev;
- if (!frame) return Qnil;
+ if (!frame) {
+ ary = Qnil;
+ break;
+ }
}
}
while (frame && frame->file) {
@@ -4031,7 +4142,7 @@ backtrace(lev)
rb_ary_push(ary, rb_str_new2(buf));
frame = frame->prev;
}
- safe_level = slev;
+
return ary;
}
@@ -4081,15 +4192,15 @@ rb_frame_last_func()
}
static NODE*
-compile(src, place)
+compile(src, file, line)
VALUE src;
- char *place;
+ char *file;
+ int line;
{
NODE *node;
Check_Type(src, T_STRING);
- if (place == 0) place = ruby_sourcefile;
- node = rb_compile_string(place, src);
+ node = rb_compile_string(file, src, line);
if (ruby_nerrs == 0) return node;
return 0;
@@ -4105,7 +4216,6 @@ eval(self, src, scope, file, line)
volatile VALUE result = Qnil;
struct SCOPE * volatile old_scope;
struct BLOCK * volatile old_block;
- struct BLOCK * volatile old_call_block;
struct RVarmap * volatile old_d_vars;
int volatile old_vmode;
struct FRAME frame;
@@ -4128,12 +4238,10 @@ eval(self, src, scope, file, line)
/* PUSH BLOCK from data */
frame = data->frame;
- frame.prev = ruby_frame;
+ frame.tmp = ruby_frame; /* gc protection */
ruby_frame = &(frame);
old_scope = ruby_scope;
ruby_scope = data->scope;
- old_call_block = ruby_calling_block;
- ruby_calling_block = data;
old_block = ruby_block;
ruby_block = data->prev;
old_d_vars = ruby_dyna_vars;
@@ -4152,15 +4260,13 @@ eval(self, src, scope, file, line)
PUSH_CLASS();
ruby_class = ((NODE*)ruby_frame->cbase)->nd_clss;
- rb_in_eval++;
+ ruby_in_eval++;
if (TYPE(ruby_class) == T_ICLASS) {
ruby_class = RBASIC(ruby_class)->klass;
}
PUSH_TAG(PROT_NONE);
if ((state = EXEC_TAG()) == 0) {
- ruby_sourcefile = file;
- ruby_sourceline = line;
- compile(src, file);
+ compile(src, file, line);
if (ruby_nerrs > 0) {
compile_error(0);
}
@@ -4168,15 +4274,13 @@ eval(self, src, scope, file, line)
}
POP_TAG();
POP_CLASS();
- rb_in_eval--;
+ ruby_in_eval--;
if (!NIL_P(scope)) {
- ruby_frame = ruby_frame->prev;
+ ruby_frame = frame.tmp;
if (FL_TEST(ruby_scope, SCOPE_DONT_RECYCLE))
FL_SET(old_scope, SCOPE_DONT_RECYCLE);
ruby_scope = old_scope;
ruby_block = old_block;
- ruby_calling_block = old_call_block;
- data->d_vars = ruby_dyna_vars;
ruby_dyna_vars = old_d_vars;
data->vmode = scope_vmode; /* write back visibility mode */
scope_vmode = old_vmode;
@@ -4191,20 +4295,20 @@ eval(self, src, scope, file, line)
VALUE err;
VALUE errat;
- errat = get_backtrace(rb_errinfo);
+ errat = get_backtrace(ruby_errinfo);
if (strcmp(file, "(eval)") == 0) {
if (ruby_sourceline > 1) {
err = RARRAY(errat)->ptr[0];
rb_str_cat(err, ": ", 2);
- rb_str_concat(err, rb_errinfo);
+ rb_str_concat(err, ruby_errinfo);
}
else {
- err = rb_str_dup(rb_errinfo);
+ err = rb_str_dup(ruby_errinfo);
}
errat = Qnil;
- rb_exc_raise(rb_exc_new3(CLASS_OF(rb_errinfo), err));
+ rb_exc_raise(rb_exc_new3(CLASS_OF(ruby_errinfo), err));
}
- rb_exc_raise(rb_errinfo);
+ rb_exc_raise(ruby_errinfo);
}
JUMP_TAG(state);
}
@@ -4220,7 +4324,7 @@ rb_f_eval(argc, argv, 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 (argc >= 3) {
@@ -4235,6 +4339,7 @@ rb_f_eval(argc, argv, self)
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)();
@@ -4276,10 +4381,11 @@ eval_under_i(args)
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, file, line)
VALUE under, self, src;
- char *file;
+ const char *file;
int line;
{
VALUE args[4];
@@ -4296,50 +4402,70 @@ static VALUE
yield_under_i(self)
VALUE self;
{
- return rb_yield_0(self, self, ruby_class);
+ if (ruby_block->flags & BLOCK_DYNAMIC) {
+ struct BLOCK * volatile old_block = ruby_block;
+ struct BLOCK block;
+ volatile VALUE cbase = ruby_block->frame.cbase;
+ /* 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, Qfalse);
+ }
+ 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, Qfalse);
}
+/* block eval under the class/module context */
static VALUE
yield_under(under, self)
VALUE under, self;
{
- rb_secure(4);
+ if (rb_safe_level() >= 4 && !FL_TEST(self, FL_TAINT))
+ rb_raise(rb_eSecurityError, "Insecure: can't eval");
return exec_under(yield_under_i, under, self);
}
-VALUE
-rb_obj_instance_eval(argc, argv, self)
+static VALUE
+specific_eval(argc, argv, klass, self)
int argc;
VALUE *argv;
- VALUE self;
+ VALUE klass, self;
{
char *file = 0;
- int line = 0;
- VALUE klass;
+ int line = 1;
+ int iter = rb_iterator_p();
- if (argc == 0) {
- if (!rb_iterator_p()) {
- rb_raise(rb_eArgError, "block not supplied");
- }
- }
- else if (argc < 4) {
+ if (argc > 0) {
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]);
}
- else {
- rb_raise(rb_eArgError, "Wrong # of arguments: %s(src) or %s{..}",
- rb_id2name(ruby_frame->last_func),
- rb_id2name(ruby_frame->last_func));
+ else if (!iter) {
+ rb_raise(rb_eArgError, "block not supplied");
}
- if (rb_special_const_p(self)) {
- klass = Qnil;
- }
- else {
- klass = rb_singleton_class(self);
- }
- if (argc == 0) {
+ if (iter) {
return yield_under(klass, self);
}
else {
@@ -4347,53 +4473,57 @@ rb_obj_instance_eval(argc, argv, self)
}
}
-static VALUE
-rb_mod_module_eval(argc, argv, mod)
+VALUE
+rb_obj_instance_eval(argc, argv, self)
int argc;
VALUE *argv;
- VALUE mod;
+ VALUE self;
{
- char *file = 0;
- int line = 0;
+ VALUE klass;
- if (argc == 0) {
- if (!rb_iterator_p()) {
- rb_raise(rb_eArgError, "block not supplied");
- }
- }
- else if (argc < 4) {
- Check_SafeStr(argv[0]);
- if (argc > 1) file = STR2CSTR(argv[1]);
- if (argc > 2) line = NUM2INT(argv[2]);
+ if (rb_special_const_p(self)) {
+ klass = Qnil;
}
else {
- rb_raise(rb_eArgError, "Wrong # of arguments: %s(src) or %s{..}",
- rb_id2name(ruby_frame->last_func),
- rb_id2name(ruby_frame->last_func));
+ klass = rb_singleton_class(self);
}
- if (argc == 0) {
- return yield_under(mod, mod);
- }
- else {
- return eval_under(mod, mod, argv[0], file, line);
- }
+ return specific_eval(argc, argv, klass, self);
+}
+
+static VALUE
+rb_mod_module_eval(argc, argv, mod)
+ int argc;
+ VALUE *argv;
+ VALUE mod;
+{
+ return specific_eval(argc, argv, mod, mod);
}
VALUE rb_load_path;
static int
is_absolute_path(path)
- char *path;
+ const char *path;
{
if (path[0] == '/') return 1;
-# if defined(MSDOS) || defined(NT) || defined(__human68k__)
+# if defined(MSDOS) || defined(NT) || defined(__human68k__) || defined(__EMX__)
if (path[0] == '\\') return 1;
if (strlen(path) > 2 && path[1] == ':') return 1;
# endif
return 0;
}
+#ifdef __MACOS__
+static int
+is_macos_native_path(path)
+ const char *path;
+{
+ if (strchr(path, ':')) return 1;
+ return 0;
+}
+#endif
+
static char*
find_file(file)
char *file;
@@ -4402,6 +4532,16 @@ find_file(file)
volatile VALUE vpath;
char *path;
+#ifdef __MACOS__
+ if (is_macos_native_path(file)) {
+ FILE *f = fopen(file, "r");
+
+ if (f == NULL) return 0;
+ fclose(f);
+ return file;
+ }
+#endif
+
if (is_absolute_path(file)) {
FILE *f = fopen(file, "r");
@@ -4410,14 +4550,25 @@ find_file(file)
return file;
}
+ if (file[0] == '~') {
+ VALUE argv[1];
+ argv[0] = rb_str_new2(file);
+ file = STR2CSTR(rb_file_s_expand_path(1, argv));
+ }
+
if (rb_load_path) {
int i;
Check_Type(rb_load_path, T_ARRAY);
+ vpath = rb_ary_new();
for (i=0;i<RARRAY(rb_load_path)->len;i++) {
- Check_SafeStr(RARRAY(rb_load_path)->ptr[i]);
+ VALUE str = RARRAY(rb_load_path)->ptr[i];
+ Check_SafeStr(str);
+ if (RSTRING(str)->len > 0) {
+ rb_ary_push(vpath, str);
+ }
}
- vpath = rb_ary_join(rb_load_path, rb_str_new2(RUBY_PATH_SEP));
+ vpath = rb_ary_join(vpath, rb_str_new2(PATH_SEP));
path = STR2CSTR(vpath);
if (safe_level >= 2 && !rb_path_check(path)) {
rb_raise(rb_eSecurityError, "loading from unsefe path %s", path);
@@ -4447,18 +4598,12 @@ rb_load(fname, wrap)
else {
Check_SafeStr(fname);
}
-#ifndef __MACOS__
- if (RSTRING(fname)->ptr[0] == '~') {
- fname = rb_file_s_expand_path(1, &fname);
- }
-#endif
file = find_file(RSTRING(fname)->ptr);
if (!file) {
rb_raise(rb_eLoadError, "No such file to load -- %s", RSTRING(fname)->ptr);
}
PUSH_VARS();
- PUSH_TAG(PROT_NONE);
PUSH_CLASS();
if (!wrap) {
rb_secure(4); /* should alter global state */
@@ -4481,19 +4626,20 @@ rb_load(fname, wrap)
VALUE *vars = TMP_ALLOC(len);
*vars++ = 0;
MEMCPY(tbl, top_scope->local_tbl, ID, len);
- MEMCPY(vars, top_scope->local_vars, ID, len-1);
+ 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 = ruby_frame->last_func;
if (state == 0) {
- rb_in_eval++;
+ ruby_in_eval++;
rb_load_file(file);
- rb_in_eval--;
+ ruby_in_eval--;
if (ruby_nerrs == 0) {
eval_node(self);
}
@@ -4503,14 +4649,15 @@ rb_load(fname, wrap)
if (ruby_scope->local_tbl) /* toplevel was empty */
free(ruby_scope->local_tbl);
}
+ POP_TAG();
POP_SCOPE();
POP_FRAME();
POP_CLASS();
- POP_TAG();
POP_VARS();
ruby_wrapper = 0;
if (ruby_nerrs > 0) {
- rb_exc_raise(rb_errinfo);
+ ruby_nerrs = 0;
+ rb_exc_raise(ruby_errinfo);
}
if (state) JUMP_TAG(state);
}
@@ -4547,7 +4694,7 @@ static VALUE rb_features;
static int
rb_provided(feature)
- char *feature;
+ const char *feature;
{
VALUE *p, *pend;
char *f;
@@ -4568,14 +4715,12 @@ rb_provided(feature)
return Qfalse;
}
-#ifdef USE_THREAD
-static int rb_thread_loading _((char*));
-static void rb_thread_loading_done _((void));
-#endif
+static int rb_thread_loading _((const char*));
+static void rb_thread_loading_done _((const char*));
void
rb_provide(feature)
- char *feature;
+ const char *feature;
{
char *buf, *ext;
@@ -4598,6 +4743,7 @@ rb_f_require(obj, fname)
{
char *ext, *file, *feature, *buf; /* OK */
volatile VALUE load;
+ int state;
rb_secure(4);
Check_SafeStr(fname);
@@ -4609,7 +4755,7 @@ rb_f_require(obj, fname)
if (strcmp(".rb", ext) == 0) {
feature = file = RSTRING(fname)->ptr;
file = find_file(file);
- if (file) goto rb_load;
+ if (file) goto load_rb;
}
else if (strcmp(".so", ext) == 0 || strcmp(".o", ext) == 0) {
file = feature = RSTRING(fname)->ptr;
@@ -4621,12 +4767,12 @@ rb_f_require(obj, fname)
file = feature = buf;
}
file = find_file(file);
- if (file) goto dyna_load;
+ if (file) goto load_dyna;
}
else if (strcmp(DLEXT, ext) == 0) {
feature = RSTRING(fname)->ptr;
file = find_file(feature);
- if (file) goto dyna_load;
+ if (file) goto load_dyna;
}
}
buf = ALLOCA_N(char, strlen(RSTRING(fname)->ptr) + 5);
@@ -4636,59 +4782,56 @@ rb_f_require(obj, fname)
if (file) {
fname = rb_str_new2(file);
feature = buf;
- goto rb_load;
+ goto load_rb;
}
strcpy(buf, RSTRING(fname)->ptr);
strcat(buf, DLEXT);
file = find_file(buf);
if (file) {
feature = buf;
- goto dyna_load;
+ goto load_dyna;
}
rb_raise(rb_eLoadError, "No such file to load -- %s",
RSTRING(fname)->ptr);
- dyna_load:
-#ifdef USE_THREAD
+ load_dyna:
if (rb_thread_loading(feature)) return Qfalse;
- else {
- int state;
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
-#endif
- load = rb_str_new2(file);
- file = RSTRING(load)->ptr;
- dln_load(file);
- rb_provide(feature);
-#ifdef USE_THREAD
- }
- POP_TAG();
- rb_thread_loading_done();
- if (state) JUMP_TAG(state);
+
+ rb_provide(feature);
+ PUSH_TAG(PROT_NONE);
+ if ((state = EXEC_TAG()) == 0) {
+ load = rb_str_new2(file);
+ file = RSTRING(load)->ptr;
+ dln_load(file);
}
-#endif
+ POP_TAG();
+ rb_thread_loading_done(feature);
+ if (state) JUMP_TAG(state);
+
return Qtrue;
- rb_load:
-#ifdef USE_THREAD
+ load_rb:
if (rb_thread_loading(feature)) return Qfalse;
- else {
- int state;
- PUSH_TAG(PROT_NONE);
- if ((state = EXEC_TAG()) == 0) {
-#endif
- rb_load(fname, 0);
- rb_provide(feature);
-#ifdef USE_THREAD
- }
- POP_TAG();
- rb_thread_loading_done();
- if (state) JUMP_TAG(state);
+ rb_provide(feature);
+
+ PUSH_TAG(PROT_NONE);
+ if ((state = EXEC_TAG()) == 0) {
+ rb_load(fname, 0);
}
-#endif
+ POP_TAG();
+ rb_thread_loading_done(feature);
+ 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
set_method_visibility(self, argc, argv, ex)
VALUE self;
@@ -4804,8 +4947,7 @@ rb_mod_modfunc(argc, argv, module)
id = rb_to_id(argv[i]);
body = search_method(module, id, 0);
if (body == 0 || body->nd_body == 0) {
- rb_raise(rb_eNameError, "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);
@@ -4846,11 +4988,13 @@ rb_mod_include(argc, argv, module)
}
void
-rb_obj_call_init(obj)
+rb_obj_call_init(obj, argc, argv)
VALUE obj;
+ int argc;
+ VALUE *argv;
{
PUSH_ITER(rb_iterator_p()?ITER_PRE:ITER_NOT);
- rb_funcall2(obj, init, ruby_frame->argc, ruby_frame->argv);
+ rb_funcall2(obj, init, argc, argv);
POP_ITER();
}
@@ -4866,7 +5010,7 @@ rb_class_new_instance(argc, argv, klass)
rb_raise(rb_eTypeError, "can't create instance of virtual class");
}
obj = rb_obj_alloc(klass);
- rb_obj_call_init(obj);
+ rb_obj_call_init(obj, argc, argv);
return obj;
}
@@ -4919,7 +5063,7 @@ errinfo_setter(val, id, var)
ID id;
VALUE *var;
{
- if (!rb_obj_is_kind_of(val, rb_eException)) {
+ if (!NIL_P(val) && !rb_obj_is_kind_of(val, rb_eException)) {
rb_raise(rb_eTypeError, "assigning non-exception to $!");
}
*var = val;
@@ -4929,7 +5073,7 @@ static VALUE
errat_getter(id)
ID id;
{
- return get_backtrace(rb_errinfo);
+ return get_backtrace(ruby_errinfo);
}
static void
@@ -4938,10 +5082,10 @@ errat_setter(val, id, var)
ID id;
VALUE *var;
{
- if (NIL_P(rb_errinfo)) {
+ if (NIL_P(ruby_errinfo)) {
rb_raise(rb_eArgError, "$! not set");
}
- set_backtrace(rb_errinfo, val);
+ set_backtrace(ruby_errinfo, val);
}
VALUE rb_f_global_variables();
@@ -5026,15 +5170,20 @@ rb_f_at_exit()
return proc;
}
-static void
-exec_end_proc()
+void
+rb_exec_end_proc()
{
struct end_proc_data *link = end_proc_data;
+ struct end_proc_data *tmp;
+ int status;
while (link) {
- (*link->func)(link->data);
- link = link->next;
+ rb_protect((VALUE(*)())link->func, link->data, &status);
+ tmp = link->next;
+ free(link);
+ link = tmp;
}
+ end_proc_data = 0;
}
void
@@ -5047,6 +5196,7 @@ Init_eval()
aref = rb_intern("[]");
aset = rb_intern("[]=");
match = rb_intern("=~");
+ missing = rb_intern("method_missing");
rb_global_variable((VALUE*)&top_scope);
rb_global_variable((VALUE*)&ruby_eval_tree_begin);
@@ -5055,7 +5205,7 @@ Init_eval()
rb_global_variable((VALUE*)&ruby_dyna_vars);
rb_define_virtual_variable("$@", errat_getter, errat_setter);
- rb_define_hooked_variable("$!", &rb_errinfo, 0, errinfo_setter);
+ rb_define_hooked_variable("$!", &ruby_errinfo, 0, errinfo_setter);
rb_define_global_function("eval", rb_f_eval, -1);
rb_define_global_function("iterator?", rb_f_iterator_p, 0);
@@ -5178,10 +5328,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)
+ 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);
@@ -5197,13 +5357,37 @@ blk_copy_prev(block)
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->frame.argv, VALUE, tmp->frame.argc);
+ }
+ scope_dup(tmp->scope);
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->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)
@@ -5213,10 +5397,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);
@@ -5239,15 +5423,12 @@ rb_f_binding(self)
bind = Data_Make_Struct(rb_cBinding,struct BLOCK,blk_mark,blk_free,data);
*data = *ruby_block;
-#ifdef USE_THREAD
data->orig_thread = rb_thread_current();
-#endif
data->iter = rb_f_iterator_p();
+ frame_dup(&data->frame);
if (ruby_frame->prev) {
data->frame.last_func = ruby_frame->prev->last_func;
}
- data->frame.argv = ALLOC_N(VALUE, data->frame.argc);
- MEMCPY(data->frame.argv, ruby_block->frame.argv, VALUE, data->frame.argc);
if (data->iter) {
blk_copy_prev(data);
@@ -5319,22 +5500,19 @@ proc_s_new(klass)
proc = Data_Make_Struct(klass, struct BLOCK, blk_mark, blk_free, data);
*data = *ruby_block;
-#ifdef USE_THREAD
data->orig_thread = rb_thread_current();
-#endif
data->iter = data->prev?Qtrue:Qfalse;
- data->frame.argv = ALLOC_N(VALUE, data->frame.argc);
- MEMCPY(data->frame.argv, ruby_block->frame.argv, VALUE, data->frame.argc);
+ frame_dup(&data->frame);
if (data->iter) {
blk_copy_prev(data);
}
else {
data->prev = 0;
}
+ data->flags |= BLOCK_DYNAMIC;
scope_dup(data->scope);
proc_save_safe_level(proc);
- rb_obj_call_init(proc);
return proc;
}
@@ -5353,11 +5531,9 @@ blk_orphan(data)
(data->scope->flag & SCOPE_NOSTACK)) {
return 1;
}
-#ifdef USE_THREAD
if (data->orig_thread != rb_thread_current()) {
return 1;
}
-#endif
return 0;
}
@@ -5372,6 +5548,15 @@ proc_call(proc, args)
volatile int orphan;
volatile int safe = safe_level;
+ Data_Get_Struct(proc, struct BLOCK, data);
+ orphan = blk_orphan(data);
+
+ /* PUSH BLOCK from data */
+ old_block = ruby_block;
+ ruby_block = data;
+ PUSH_ITER(ITER_CUR);
+ ruby_frame->iter = ITER_CUR;
+
if (TYPE(args) == T_ARRAY) {
switch (RARRAY(args)->len) {
case 0:
@@ -5383,15 +5568,6 @@ proc_call(proc, args)
}
}
- Data_Get_Struct(proc, struct BLOCK, data);
- orphan = blk_orphan(data);
-
- /* PUSH BLOCK from data */
- old_block = ruby_block;
- ruby_block = data;
- PUSH_ITER(ITER_CUR);
- ruby_frame->iter = ITER_CUR;
-
if (orphan) {/* orphan procedure */
if (rb_iterator_p()) {
ruby_block->frame.iter = ITER_CUR;
@@ -5405,7 +5581,7 @@ proc_call(proc, args)
state = EXEC_TAG();
if (state == 0) {
proc_set_safe_level(proc);
- result = rb_yield_0(args, 0, 0);
+ result = rb_yield_0(args, 0, 0, Qtrue);
}
POP_TAG();
@@ -5436,6 +5612,31 @@ proc_call(proc, args)
}
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 FIX2INT(-1);
+ switch (nd_type(data->var)) {
+ default:
+ return INT2FIX(-2);
+ 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
block_pass(self, node)
VALUE self;
NODE *node;
@@ -5587,12 +5788,44 @@ method_call(argc, argv, 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_rest) 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 = rb_str_new2("#<");
@@ -5651,6 +5884,7 @@ Init_Proc()
rb_define_singleton_method(rb_cProc, "new", proc_s_new, 0);
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_global_function("proc", rb_f_lambda, 0);
rb_define_global_function("lambda", rb_f_lambda, 0);
@@ -5663,14 +5897,13 @@ Init_Proc()
rb_undef_method(CLASS_OF(rb_cMethod), "new");
rb_define_method(rb_cMethod, "call", method_call, -1);
rb_define_method(rb_cMethod, "[]", method_call, -1);
+ rb_define_method(rb_cMethod, "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_mKernel, "method", rb_obj_method, 1);
}
-#ifdef USE_THREAD
-
static VALUE rb_eThreadError;
int rb_thread_pending = 0;
@@ -5728,19 +5961,18 @@ struct thread {
struct SCOPE *scope;
struct RVarmap *dyna_vars;
struct BLOCK *block;
- struct BLOCK *cblock;
struct iter *iter;
struct tag *tag;
VALUE klass;
VALUE wrapper;
VALUE trace;
- int misc; /* misc. states (vmode/rb_trap_immediate) */
+ int flags; /* misc. states (vmode/rb_trap_immediate/raised) */
char *file;
int line;
- VALUE rb_errinfo;
+ VALUE errinfo;
VALUE last_status;
VALUE last_line;
VALUE last_match;
@@ -5760,10 +5992,12 @@ struct thread {
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
+
+static thread_t curr_thread = 0;
+static int num_waiting_on_fd = 0;
+static int num_waiting_on_timer = 0;
+static int num_waiting_on_join = 0;
#define FOREACH_THREAD_FROM(f,x) x = f; do { x = x->next;
#define END_FOREACH_FROM(f,x) } while (x != f)
@@ -5801,9 +6035,10 @@ thread_mark(th)
rb_gc_mark(th->scope);
rb_gc_mark(th->dyna_vars);
- rb_gc_mark(th->rb_errinfo);
+ 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->status == THREAD_KILLED) return;
@@ -5817,20 +6052,24 @@ thread_mark(th)
frame = th->frame;
while (frame && frame != top_frame) {
frame = ADJ(frame);
- if (frame->argv && !STACK(frame->argv)) {
- rb_gc_mark_frame(frame);
+ rb_gc_mark_frame(frame);
+ if (frame->tmp) {
+ struct FRAME *tmp = ADJ(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)) {
- rb_gc_mark_frame(&block->frame);
- }
+ rb_gc_mark_frame(&block->frame);
block = block->prev;
}
- rb_mark_tbl(th->locals);
}
void
@@ -5889,11 +6128,10 @@ rb_thread_save_context(th)
th->wrapper = ruby_wrapper;
th->dyna_vars = ruby_dyna_vars;
th->block = ruby_block;
- th->cblock = ruby_calling_block;
- th->misc = scope_vmode | (rb_trap_immediate<<8);
+ th->flags = scope_vmode | (rb_trap_immediate<<8);
th->iter = ruby_iter;
th->tag = prot_tag;
- th->rb_errinfo = rb_errinfo;
+ th->errinfo = ruby_errinfo;
th->last_status = rb_last_status;
th->last_line = rb_lastline_get();
th->last_match = rb_backref_get();
@@ -5902,8 +6140,6 @@ rb_thread_save_context(th)
th->trace = trace_func;
th->file = ruby_sourcefile;
th->line = ruby_sourceline;
-
- th->locals = 0;
}
static void rb_thread_restore_context _((thread_t,int));
@@ -5925,6 +6161,14 @@ 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 0
+#define RESTORE_FATAL 1
+#define RESTORE_INTERRUPT 2
+#define RESTORE_TRAP 3
+#define RESTORE_RAISE 4
+#define RESTORE_SIGNAL 5
static void
rb_thread_restore_context(th, exit)
@@ -5952,12 +6196,11 @@ rb_thread_restore_context(th, exit)
ruby_wrapper = th->wrapper;
ruby_dyna_vars = th->dyna_vars;
ruby_block = th->block;
- ruby_calling_block = th->cblock;
- scope_vmode = th->misc&SCOPE_MASK;
- rb_trap_immediate = th->misc>>8;
+ scope_vmode = th->flags&SCOPE_MASK;
+ rb_trap_immediate = (th->flags&0x100)?1:0;
ruby_iter = th->iter;
prot_tag = th->tag;
- rb_errinfo = th->rb_errinfo;
+ ruby_errinfo = th->errinfo;
rb_last_status = th->last_status;
safe_level = th->safe;
@@ -5974,26 +6217,31 @@ rb_thread_restore_context(th, exit)
rb_backref_set(tmp->last_match);
switch (ex) {
- case 1:
+ case RESTORE_FATAL:
JUMP_TAG(TAG_FATAL);
break;
- case 2:
+ case RESTORE_INTERRUPT:
rb_interrupt();
break;
- case 3:
+ case RESTORE_TRAP:
rb_trap_eval(th_cmd, th_sig);
errno = EINTR;
break;
- case 4:
+ case RESTORE_SIGNAL:
+ rb_raise(rb_eSignal, "SIG%s", th_signm);
+ 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_NORMAL:
default:
longjmp(tmp->context, 1);
}
@@ -6033,15 +6281,46 @@ rb_thread_dead(th)
return th->status == THREAD_KILLED;
}
+void
+rb_thread_fd_close(fd)
+ int fd;
+{
+ thread_t th;
+
+ FOREACH_THREAD(th) {
+ if ((th->wait_for & WAIT_FD) && th->fd == fd) {
+ th_raise_argc = 1;
+ th_raise_argv[0] = rb_exc_new2(rb_eIOError, "stream closed");
+ th_raise_file = ruby_sourcefile;
+ th_raise_line = ruby_sourceline;
+ curr_thread = th;
+ rb_thread_ready(th);
+ rb_thread_restore_context(curr_thread, RESTORE_RAISE);
+ }
+ }
+ END_FOREACH(th);
+}
+
static void
rb_thread_deadlock()
{
+#if 1
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);
+#else
+ static int invoked = 0;
+
+ if (invoked) return;
+ invoked = 1;
+ rb_prohibit_interrupt = 1;
+ ruby_errinfo = rb_exc_new2(rb_eFatal, "Thread: deadlock");
+ set_backtrace(ruby_errinfo, make_backtrace());
rb_abort();
+#endif
}
void
@@ -6053,7 +6332,9 @@ rb_thread_schedule()
select_err:
rb_thread_pending = 0;
- if (curr_thread == curr_thread->next) return;
+ if (curr_thread == curr_thread->next
+ && curr_thread->status == THREAD_RUNNABLE)
+ return;
next = 0;
curr = curr_thread; /* starting thread */
@@ -6143,7 +6424,14 @@ rb_thread_schedule()
n = select(max+1, &readfds, 0, 0, delay_ptr);
if (n < 0) {
if (rb_trap_pending) rb_trap_exec();
- goto select_err;
+ switch (errno) {
+ case EBADF:
+ case ENOMEM:
+ n = 0;
+ break;
+ default:
+ goto select_err;
+ }
}
if (n > 0) {
/* Some descriptors are ready.
@@ -6172,13 +6460,18 @@ rb_thread_schedule()
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",
+ fprintf(stderr, "%s:%d:deadlock 0x%lx: %d:%d %s\n",
th->file, th->line, th->thread, th->status,
th->wait_for, th==main_thread?"(main)":"");
+ if (th->status == THREAD_STOPPED) {
+ next = th;
+ }
}
END_FOREACH_FROM(curr, th);
/* raise fatal error to main thread */
rb_thread_deadlock();
+ rb_thread_ready(next);
+ next->status = THREAD_TO_KILL;
}
if (next->status == THREAD_RUNNABLE && next == curr_thread) {
return;
@@ -6195,9 +6488,9 @@ rb_thread_schedule()
curr_thread = next;
if (next->status == THREAD_TO_KILL) {
/* execute ensure-clause if any */
- rb_thread_restore_context(next, 1);
+ rb_thread_restore_context(next, RESTORE_FATAL);
}
- rb_thread_restore_context(next, 0);
+ rb_thread_restore_context(next, RESTORE_NORMAL);
}
void
@@ -6213,20 +6506,20 @@ rb_thread_wait_fd(fd)
rb_thread_schedule();
}
-void
+int
rb_thread_fd_writable(fd)
int fd;
{
struct timeval zero;
fd_set fds;
- if (curr_thread == curr_thread->next) return;
+ if (curr_thread == curr_thread->next) return 1;
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;
+ if (select(fd+1, 0, &fds, 0, &zero) == 1) return 0;
rb_thread_schedule();
}
}
@@ -6373,14 +6666,28 @@ rb_thread_join(thread)
{
thread_t th = rb_thread_check(thread);
- if (rb_thread_dead(th)) return thread;
- if ((th->wait_for & WAIT_JOIN) && th->join == curr_thread)
- rb_raise(rb_eThreadError, "Thread#join: deadlock");
- curr_thread->status = THREAD_STOPPED;
- curr_thread->join = th;
- num_waiting_on_join++;
- curr_thread->wait_for |= WAIT_JOIN;
- rb_thread_schedule();
+ if (!rb_thread_dead(th)) {
+ if (th == curr_thread)
+ rb_raise(rb_eThreadError, "recursive join");
+ if ((th->wait_for & WAIT_JOIN) && th->join == curr_thread)
+ rb_raise(rb_eThreadError, "Thread#join: deadlock - mutual join");
+ curr_thread->status = THREAD_STOPPED;
+ curr_thread->join = th;
+ num_waiting_on_join++;
+ curr_thread->wait_for |= WAIT_JOIN;
+ rb_thread_schedule();
+ }
+
+ 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;
}
@@ -6406,7 +6713,7 @@ rb_thread_main()
return main_thread->thread;
}
-static VALUE
+VALUE
rb_thread_wakeup(thread)
VALUE thread;
{
@@ -6419,7 +6726,7 @@ rb_thread_wakeup(thread)
return thread;
}
-static VALUE
+VALUE
rb_thread_run(thread)
VALUE thread;
{
@@ -6465,14 +6772,14 @@ rb_thread_pass()
return Qnil;
}
-static VALUE
+VALUE
rb_thread_stop()
{
rb_thread_critical = 0;
- curr_thread->status = THREAD_STOPPED;
if (curr_thread == curr_thread->next) {
rb_raise(rb_eThreadError, "stopping only thread");
}
+ curr_thread->status = THREAD_STOPPED;
rb_thread_schedule();
return Qnil;
@@ -6510,19 +6817,19 @@ rb_thread_sleep_forever()
rb_thread_schedule();
}
-static int rb_thread_abort;
+static int thread_abort;
static VALUE
rb_thread_s_abort_exc()
{
- return rb_thread_abort?Qtrue:Qfalse;
+ return thread_abort?Qtrue:Qfalse;
}
static VALUE
rb_thread_s_abort_exc_set(self, val)
VALUE self, val;
{
- rb_thread_abort = RTEST(val);
+ thread_abort = RTEST(val);
return val;
}
@@ -6545,41 +6852,44 @@ rb_thread_abort_exc_set(thread, val)
return val;
}
+#define THREAD_ALLOC(th) do {\
+ th = ALLOC(struct thread);\
+\
+ th->status = 0;\
+ th->result = 0;\
+ th->errinfo = Qnil;\
+\
+ th->stk_ptr = 0;\
+ th->stk_len = 0;\
+ th->stk_max = 0;\
+ th->wait_for = 0;\
+ th->fd = 0;\
+ th->delay = 0.0;\
+ th->join = 0;\
+\
+ th->frame = 0;\
+ th->scope = 0;\
+ th->klass = 0;\
+ th->wrapper = 0;\
+ th->dyna_vars = 0;\
+ th->block = 0;\
+ th->iter = 0;\
+ th->tag = 0;\
+ th->errinfo = 0;\
+ th->last_status = 0;\
+ th->last_line = 0;\
+ th->last_match = 0;\
+ th->abort = 0;\
+ th->locals = 0;\
+} while(0)
+
static thread_t
rb_thread_alloc(klass)
VALUE klass;
{
thread_t th;
- th = ALLOC(struct thread);
- th->status = THREAD_RUNNABLE;
-
- th->status = 0;
- th->result = 0;
- th->rb_errinfo = Qnil;
-
- th->stk_ptr = 0;
- th->stk_len = 0;
- th->stk_max = 0;
- th->wait_for = 0;
- th->fd = 0;
- th->delay = 0.0;
- th->join = 0;
-
- th->frame = 0;
- th->scope = 0;
- th->klass = 0;
- th->wrapper = 0;
- th->dyna_vars = 0;
- th->block = 0;
- th->iter = 0;
- th->tag = 0;
- th->rb_errinfo = 0;
- th->last_status = 0;
- th->last_line = 0;
- th->last_match = 0;
- th->abort = 0;
-
+ THREAD_ALLOC(th);
th->thread = Data_Wrap_Struct(klass, thread_mark, thread_free, th);
if (curr_thread) {
@@ -6654,6 +6964,7 @@ rb_thread_create_0(fn, arg, klass)
VALUE klass;
{
thread_t th = rb_thread_alloc(klass);
+ volatile VALUE thread = th->thread;
enum thread_status status;
int state;
@@ -6673,7 +6984,7 @@ rb_thread_create_0(fn, arg, klass)
FL_SET(ruby_scope, SCOPE_SHARED);
rb_thread_save_context(curr_thread);
if (setjmp(curr_thread->context)) {
- return th->thread;
+ return thread;
}
PUSH_TAG(PROT_THREAD);
@@ -6687,24 +6998,25 @@ rb_thread_create_0(fn, arg, klass)
POP_TAG();
status = th->status;
rb_thread_remove();
- if (state && status != THREAD_TO_KILL && !NIL_P(rb_errinfo)) {
+ 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->rb_errinfo = rb_errinfo;
+ main_thread->errinfo = ruby_errinfo;
rb_thread_cleanup();
}
- else if (rb_obj_is_kind_of(rb_errinfo, rb_eSystemExit)) {
+ else if (rb_obj_is_kind_of(ruby_errinfo, rb_eSystemExit)) {
/* delegate exception to main_thread */
- rb_thread_raise(1, &rb_errinfo, main_thread->thread);
+ rb_thread_raise(1, &ruby_errinfo, main_thread->thread);
}
- else if (rb_thread_abort || curr_thread->abort || RTEST(rb_debug)) {
+ else if (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->thread);
}
else {
- curr_thread->rb_errinfo = rb_errinfo;
+ th->errinfo = ruby_errinfo;
}
}
rb_thread_schedule();
@@ -6731,7 +7043,7 @@ rb_thread_yield(arg, th)
thread_t th;
{
scope_dup(ruby_block->scope);
- return rb_yield_0(th->thread, 0, 0);
+ return rb_yield_0(th->thread, 0, 0, Qfalse);
}
static VALUE
@@ -6751,14 +7063,6 @@ rb_thread_value(thread)
thread_t th = rb_thread_check(thread);
rb_thread_join(thread);
- if (!NIL_P(th->rb_errinfo)) {
- VALUE oldbt = get_backtrace(th->rb_errinfo);
- VALUE errat = make_backtrace();
-
- rb_ary_unshift(errat, rb_ary_entry(oldbt, 0));
- set_backtrace(th->rb_errinfo, errat);
- rb_exc_raise(th->rb_errinfo);
- }
return th->result;
}
@@ -6770,7 +7074,8 @@ rb_thread_status(thread)
thread_t th = rb_thread_check(thread);
if (rb_thread_dead(th)) {
- if (NIL_P(th->rb_errinfo)) return Qfalse;
+ if (NIL_P(th->errinfo) && (th->flags & THREAD_RAISED))
+ return Qfalse;
return Qnil;
}
@@ -6808,8 +7113,8 @@ rb_thread_cleanup()
FOREACH_THREAD(th) {
if (th != curr_thread && th->status != THREAD_KILLED) {
+ rb_thread_ready(th);
th->status = THREAD_TO_KILL;
- th->wait_for = 0;
}
}
END_FOREACH(th);
@@ -6844,7 +7149,27 @@ rb_thread_interrupt()
return;
}
curr_thread = main_thread;
- rb_thread_restore_context(curr_thread, 2);
+ 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);
+ rb_thread_save_context(curr_thread);
+ if (setjmp(curr_thread->context)) {
+ return;
+ }
+ th_signm = sig;
+ curr_thread = main_thread;
+ rb_thread_restore_context(curr_thread, RESTORE_SIGNAL);
}
void
@@ -6866,7 +7191,7 @@ rb_thread_trap_eval(cmd, sig)
th_cmd = cmd;
th_sig = sig;
curr_thread = main_thread;
- rb_thread_restore_context(curr_thread, 3);
+ rb_thread_restore_context(curr_thread, RESTORE_TRAP);
}
static VALUE
@@ -6895,36 +7220,33 @@ rb_thread_raise(argc, argv, thread)
th_raise_argc = argc;
th_raise_file = ruby_sourcefile;
th_raise_line = ruby_sourceline;
- rb_thread_restore_context(curr_thread, 4);
+ rb_thread_restore_context(curr_thread, RESTORE_RAISE);
return Qnil; /* not reached */
}
-static thread_t loading_thread;
-static int loading_nest;
+static st_table *loading_tbl;
static int
rb_thread_loading(feature)
- char *feature;
+ const char *feature;
{
- if (curr_thread != curr_thread->next && loading_thread) {
- while (loading_thread != curr_thread) {
- rb_thread_schedule();
- CHECK_INTS;
- }
- if (rb_provided(feature)) return Qtrue; /* no need to load */
+ if (!rb_provided(feature)) return Qfalse; /* need to load */
+ if (!loading_tbl) {
+ loading_tbl = st_init_strtable();
}
-
- loading_thread = curr_thread;
- loading_nest++;
-
- return Qfalse;
+ while (st_lookup(loading_tbl, feature, 0)) {
+ CHECK_INTS;
+ rb_thread_schedule();
+ }
+ return Qtrue;
}
static void
-rb_thread_loading_done()
+rb_thread_loading_done(feature)
+ const char *feature;
{
- if (--loading_nest == 0) {
- loading_thread = 0;
+ if (loading_tbl) {
+ st_delete(loading_tbl, feature, 0);
}
}
@@ -6957,13 +7279,11 @@ rb_thread_local_aset(thread, id, val)
ID id;
VALUE val;
{
- thread_t th;
-
+ thread_t th = rb_thread_check(thread);
if (safe_level >= 4 && !FL_TEST(thread, FL_TAINT))
rb_raise(rb_eSecurityError, "Insecure: can't modify thread values");
- th = rb_thread_check(thread);
if (!th->locals) {
th->locals = st_init_numtable();
}
@@ -7002,39 +7322,17 @@ rb_callcc(self)
VALUE self;
{
volatile VALUE cont;
- thread_t th = ALLOC(struct thread);
-
- th->status = THREAD_RUNNABLE;
-
- th->status = 0;
- th->result = 0;
- th->rb_errinfo = Qnil;
-
- th->stk_ptr = 0;
- th->stk_len = 0;
- th->stk_max = 0;
- th->wait_for = 0;
- th->fd = 0;
- th->delay = 0.0;
- th->join = 0;
-
- th->frame = 0;
- th->scope = 0;
- th->klass = 0;
- th->dyna_vars = 0;
- th->block = 0;
- th->iter = 0;
- th->tag = 0;
- th->rb_errinfo = 0;
- th->last_status = 0;
- th->last_line = 0;
- th->last_match = 0;
- th->abort = 0;
+ thread_t th;
+ struct tag *tag;
+ THREAD_ALLOC(th);
th->thread = cont = Data_Wrap_Struct(rb_cContinuation, thread_mark,
thread_free, th);
FL_SET(ruby_scope, SCOPE_DONT_RECYCLE);
+ for (tag=prot_tag; tag; tag=tag->prev) {
+ scope_dup(tag->scope);
+ }
rb_thread_save_context(th);
if (setjmp(th->context)) {
return th->result;
@@ -7063,7 +7361,7 @@ rb_continuation_call(argc, argv, cont)
th->result = rb_ary_new4(argc, argv);
break;
}
- rb_thread_restore_context(th, 0);
+ rb_thread_restore_context(th, RESTORE_NORMAL);
return Qnil;
}
@@ -7114,9 +7412,8 @@ Init_Thread()
rb_cContinuation = rb_define_class("Continuation", rb_cObject);
rb_undef_method(CLASS_OF(rb_cContinuation), "new");
rb_define_method(rb_cContinuation, "call", rb_continuation_call, -1);
- rb_define_method(rb_mKernel, "callcc", rb_callcc, 0);
+ rb_define_global_function("callcc", rb_callcc, 0);
}
-#endif
static VALUE
rb_f_catch(dmy, tag)
@@ -7129,7 +7426,7 @@ rb_f_catch(dmy, tag)
t = rb_to_id(tag);
PUSH_TAG(t);
if ((state = EXEC_TAG()) == 0) {
- val = rb_yield_0(tag, 0, 0);
+ val = rb_yield_0(tag, 0, 0, Qfalse);
}
else if (state == TAG_THROW && t == prot_tag->dst) {
val = prot_tag->retval;
@@ -7150,7 +7447,7 @@ catch_i(tag)
VALUE
rb_catch(tag, proc, data)
- char *tag;
+ const char *tag;
VALUE (*proc)();
VALUE data;
{
@@ -7174,13 +7471,11 @@ rb_f_throw(argc, argv)
tt->dst = t;
break;
}
-#ifdef USE_THREAD
if (tt->tag == PROT_THREAD) {
rb_raise(rb_eThreadError, "uncaught throw `%s' in thread 0x%x",
rb_id2name(t),
curr_thread);
}
-#endif
tt = tt->prev;
}
if (!tt) {
@@ -7194,7 +7489,7 @@ rb_f_throw(argc, argv)
void
rb_throw(tag, val)
- char *tag;
+ const char *tag;
VALUE val;
{
VALUE argv[2];
@@ -7208,7 +7503,6 @@ rb_throw(tag, val)
static void
return_check()
{
-#ifdef USE_THREAD
struct tag *tt = prot_tag;
while (tt) {
@@ -7221,6 +7515,5 @@ return_check()
}
tt = tt->prev;
}
-#endif
}
diff --git a/file.c b/file.c
index 11a8dedf14..9ac2db6b35 100644
--- a/file.c
+++ b/file.c
@@ -6,7 +6,7 @@
$Date$
created at: Mon Nov 15 12:24:34 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -28,6 +28,7 @@
# define MAXPATHLEN 1024
#endif
+#include <time.h>
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#else
@@ -39,6 +40,8 @@ struct timeval {
#endif /* NT */
#endif
+VALUE rb_time_new _((time_t, time_t));
+
#ifdef HAVE_UTIME_H
#include <utime.h>
#endif
@@ -48,7 +51,7 @@ struct timeval {
#endif
#ifndef HAVE_STRING_H
-char *strrchr _((char*,char));
+char *strrchr _((const char*,const char));
#endif
#include <sys/types.h>
@@ -58,107 +61,17 @@ char *strrchr _((char*,char));
#include "macruby_missing.h"
extern int fileno(FILE *stream);
extern int utimes();
+ char* strdup(char*);
#endif
+#ifdef __EMX__
+#define lstat stat
+#endif
+
VALUE rb_cFile;
VALUE rb_mFileTest;
static VALUE sStat;
-VALUE
-rb_file_open(fname, mode)
- char *fname, *mode;
-{
- OpenFile *fptr;
- NEWOBJ(port, struct RFile);
- OBJSETUP(port, rb_cFile, T_FILE);
- MakeOpenFile(port, fptr);
-
- fptr->mode = rb_io_mode_flags(mode);
- fptr->f = rb_fopen(fname, mode);
- fptr->path = strdup(fname);
- rb_obj_call_init((VALUE)port);
-
- return (VALUE)port;
-}
-
-static VALUE
-rb_file_s_open(argc, argv, klass)
- int argc;
- VALUE *argv;
- VALUE klass;
-{
- VALUE fname, vmode, file;
- char *mode;
-
- rb_scan_args(argc, argv, "11", &fname, &vmode);
- Check_SafeStr(fname);
- if (!NIL_P(vmode)) {
- mode = STR2CSTR(vmode);
- }
- else {
- mode = "r";
- }
- file = rb_file_open(RSTRING(fname)->ptr, mode);
-
- RBASIC(file)->klass = klass;
- rb_obj_call_init(file);
- if (rb_iterator_p()) {
- return rb_ensure(rb_yield, file, rb_io_close, file);
- }
-
- return file;
-}
-
-static VALUE
-rb_file_reopen(argc, argv, file)
- int argc;
- VALUE *argv;
- VALUE file;
-{
- VALUE fname, nmode;
- char *mode;
- OpenFile *fptr;
-
- rb_secure(4);
- if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) {
- if (TYPE(fname) == T_FILE) { /* fname must be IO */
- return rb_io_reopen(file, fname);
- }
- }
-
- Check_SafeStr(fname);
- if (!NIL_P(nmode)) {
- mode = STR2CSTR(nmode);
- }
- else {
- mode = "r";
- }
-
- GetOpenFile(file, fptr);
- if (fptr->path) free(fptr->path);
- fptr->path = strdup(RSTRING(fname)->ptr);
- fptr->mode = rb_io_mode_flags(mode);
- if (!fptr->f) {
- fptr->f = rb_fopen(RSTRING(fname)->ptr, mode);
- if (fptr->f2) {
- fclose(fptr->f2);
- fptr->f2 = NULL;
- }
- return file;
- }
-
- if (freopen(RSTRING(fname)->ptr, mode, fptr->f) == NULL) {
- rb_sys_fail(fptr->path);
- }
- if (fptr->f2) {
- if (freopen(RSTRING(fname)->ptr, "w", fptr->f2) == NULL) {
- rb_sys_fail(fptr->path);
- }
- }
-
- return file;
-}
-
static int
apply2files(func, vargs, arg)
int (*func)();
@@ -247,6 +160,9 @@ rb_stat(file, st)
return fstat(fileno(fptr->f), st);
}
Check_SafeStr(file);
+#if defined DJGPP
+ if (RSTRING(file)->len == 0) return -1;
+#endif
return stat(RSTRING(file)->ptr, st);
}
@@ -281,7 +197,7 @@ static VALUE
rb_file_s_lstat(obj, fname)
VALUE obj, fname;
{
-#if !defined(MSDOS) && !defined(NT)
+#if !defined(MSDOS) && !defined(NT) && !defined(__EMX__)
struct stat st;
Check_SafeStr(fname);
@@ -299,7 +215,7 @@ static VALUE
rb_file_lstat(obj)
VALUE obj;
{
-#if !defined(MSDOS) && !defined(NT)
+#if !defined(MSDOS) && !defined(NT)
OpenFile *fptr;
struct stat st;
@@ -347,7 +263,7 @@ group_member(gid)
int
eaccess(path, mode)
- char *path;
+ const char *path;
int mode;
{
#ifndef NT
@@ -608,8 +524,8 @@ test_s(obj, fname)
{
struct stat st;
- if (rb_stat(fname, &st) < 0) return Qfalse;
- if (st.st_size == 0) return Qfalse;
+ if (rb_stat(fname, &st) < 0) return Qnil;
+ if (st.st_size == 0) return Qnil;
return rb_int2inum(st.st_size);
}
@@ -651,7 +567,7 @@ test_grpowned(obj, fname)
#if defined(S_ISUID) || defined(S_ISGID) || defined(S_ISVTX)
static VALUE
check3rdbyte(file, mode)
- char *file;
+ const char *file;
int mode;
{
struct stat st;
@@ -693,7 +609,7 @@ test_sticky(obj, fname)
#ifdef S_ISVTX
return check3rdbyte(STR2CSTR(fname), S_ISVTX);
#else
- return Qfalse;
+ return Qnil;
#endif
}
@@ -836,7 +752,7 @@ rb_file_ctime(obj)
static void
chmod_internal(path, mode)
- char *path;
+ const char *path;
int mode;
{
if (chmod(path, mode) == -1)
@@ -870,7 +786,7 @@ rb_file_chmod(obj, vmode)
mode = NUM2INT(vmode);
GetOpenFile(obj, fptr);
-#if defined(DJGPP) || defined(NT) || defined(USE_CWGUSI) || defined(__BEOS__)
+#if defined(DJGPP) || defined(NT) || defined(USE_CWGUSI) || defined(__BEOS__) || defined(__EMX__)
if (chmod(fptr->path, mode) == -1)
rb_sys_fail(fptr->path);
#else
@@ -887,7 +803,7 @@ struct chown_args {
static void
chown_internal(path, args)
- char *path;
+ const char *path;
struct chown_args *args;
{
if (chown(path, args->owner, args->group) < 0)
@@ -929,7 +845,7 @@ rb_file_chown(obj, owner, group)
rb_secure(4);
GetOpenFile(obj, fptr);
-#if defined(DJGPP) || defined(__CYGWIN32__) || defined(NT) || defined(USE_CWGUSI)
+#if defined(DJGPP) || defined(__CYGWIN32__) || defined(NT) || defined(USE_CWGUSI) || defined(__EMX__)
if (chown(fptr->path, NUM2INT(owner), NUM2INT(group)) == -1)
rb_sys_fail(fptr->path);
#else
@@ -993,7 +909,7 @@ struct utimbuf {
static void
utime_internal(path, utp)
- char *path;
+ const char *path;
struct utimbuf *utp;
{
if (utime(path, utp) < 0)
@@ -1043,7 +959,7 @@ static VALUE
rb_file_s_symlink(obj, from, to)
VALUE obj, from, to;
{
-#if !defined(MSDOS) && !defined(NT)
+#if !defined(MSDOS) && !defined(NT) && !defined(__EMX__)
Check_SafeStr(from);
Check_SafeStr(to);
@@ -1060,7 +976,7 @@ static VALUE
rb_file_s_readlink(obj, path)
VALUE obj, path;
{
-#if !defined(MSDOS) && !defined(NT)
+#if !defined(MSDOS) && !defined(NT) && !defined(__EMX__)
char buf[MAXPATHLEN];
int cc;
@@ -1078,7 +994,7 @@ rb_file_s_readlink(obj, path)
static void
unlink_internal(path)
- char *path;
+ const char *path;
{
if (unlink(path) < 0)
rb_sys_fail(path);
@@ -1132,6 +1048,12 @@ rb_file_s_umask(argc, argv)
#endif /* USE_CWGUSI */
}
+#if defined DOSISH
+#define isdirsep(x) ((x) == '/' || (x) == '\\')
+#else
+#define isdirsep(x) ((x) == '/')
+#endif
+
VALUE
rb_file_s_expand_path(argc, argv)
int argc;
@@ -1146,11 +1068,7 @@ rb_file_s_expand_path(argc, argv)
s = STR2CSTR(fname);
p = buf;
if (s[0] == '~') {
- if (s[1] == '/' ||
-#if defined(MSDOS) || defined(NT) || defined(__human68k__)
- s[1] == '\\' ||
-#endif
- s[1] == '\0') {
+ if (isdirsep(s[1]) || s[1] == '\0') {
char *dir = getenv("HOME");
if (!dir) {
@@ -1165,7 +1083,7 @@ rb_file_s_expand_path(argc, argv)
struct passwd *pwPtr;
s++;
#endif
- while (*s && *s != '/') {
+ while (*s && !isdirsep(*s)) {
*p++ = *s++;
}
*p = '\0';
@@ -1181,6 +1099,14 @@ rb_file_s_expand_path(argc, argv)
#endif
}
}
+#if defined DOSISH
+ /* skip drive letter */
+ else if (isalpha(s[0]) && s[1] == ':' && isdirsep(s[2])) {
+ while (*s && !isdirsep(*s)) {
+ *p++ = *s++;
+ }
+ }
+#endif
else if (s[0] != '/') {
if (argc == 2) {
dname = rb_file_s_expand_path(1, &dname);
@@ -1204,10 +1130,10 @@ rb_file_s_expand_path(argc, argv)
if (*(s+1)) {
switch (*++s) {
case '.':
- if (*(s+1) == '\0' || *(s+1) == '/') {
+ if (*(s+1) == '\0' || isdirsep(*(s+1))) {
/* We must go back to the parent */
- if (*p == '/' && p > buf) p--;
- while (p > buf && *p != '/') p--;
+ if (isdirsep(*p) && p > buf) p--;
+ while (p > buf && !isdirsep(*p)) p--;
}
else {
*++p = '.';
@@ -1215,7 +1141,10 @@ rb_file_s_expand_path(argc, argv)
}
break;
case '/':
- if (*p != '/') *++p = '/';
+#if defined DOSISH
+ case '\\':
+#endif
+ if (!isdirsep(*p)) *++p = '/';
break;
default:
*++p = '.'; *++p = *s; break;
@@ -1223,14 +1152,17 @@ rb_file_s_expand_path(argc, argv)
}
break;
case '/':
- if (*p != '/') *++p = '/'; break;
+#if defined DOSISH
+ case '\\':
+#endif
+ if (!isdirsep(*p)) *++p = '/'; break;
default:
*++p = *s;
}
}
/* Place a \0 at end. If path ends with a "/", delete it */
- if (p == buf || *p != '/') p++;
+ if (p == buf || !isdirsep(*p)) p++;
*p = '\0';
return rb_tainted_str_new2(buf);
@@ -1238,7 +1170,7 @@ rb_file_s_expand_path(argc, argv)
static int
rmext(p, e)
- char *p, *e;
+ const char *p, *e;
{
int l1, l2;
@@ -1394,10 +1326,11 @@ rb_file_truncate(obj, len)
# define LOCK_UN 8
# endif
-#if defined(USE_THREAD) && defined(EWOULDBLOCK)
+#if defined(EWOULDBLOCK)
static int
-rb_thread_flock(fd, op)
+rb_thread_flock(fd, op, fptr)
int fd, op;
+ OpenFile *fptr;
{
if (rb_thread_alone() || (op & LOCK_NB)) {
return flock(fd, op);
@@ -1408,6 +1341,7 @@ rb_thread_flock(fd, op)
case EINTR: /* can be happen? */
case EWOULDBLOCK:
rb_thread_schedule(); /* busy wait */
+ rb_io_check_closed(fptr);
break;
default:
return -1;
@@ -1415,7 +1349,7 @@ rb_thread_flock(fd, op)
}
return 0;
}
-#define flock rb_thread_flock
+#define flock(fd, op) rb_thread_flock(fd, op, fptr)
#endif
static VALUE
@@ -1452,7 +1386,7 @@ test_check(n, argc, argv)
int i;
n+=1;
- if (n < argc) rb_raise(rb_eArgError, "Wrong # of arguments(%d for %d)", argc, n);
+ if (n < argc) rb_raise(rb_eArgError, "wrong # of arguments(%d for %d)", argc, n);
for (i=1; i<n; i++) {
switch (TYPE(argv[i])) {
case T_STRING:
@@ -1476,7 +1410,7 @@ rb_f_test(argc, argv)
{
int cmd;
- if (argc == 0) rb_raise(rb_eArgError, "Wrong # of arguments");
+ if (argc == 0) rb_raise(rb_eArgError, "wrong # of arguments");
cmd = NUM2CHR(argv[0]);
if (cmd == 0) return Qfalse;
if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
@@ -1596,15 +1530,24 @@ rb_f_test(argc, argv)
}
}
/* unknown command */
- rb_raise(rb_eArgError, "unknow command ?%c", cmd);
+ rb_raise(rb_eArgError, "unknown command ?%c", cmd);
return Qnil; /* not reached */
}
+static VALUE rb_mConst;
+
void
-Init_File()
+rb_file_const(name, value)
+ const char *name;
+ VALUE value;
{
- VALUE rb_mConst;
+ rb_define_const(rb_cFile, name, value);
+ rb_define_const(rb_mConst, name, value);
+}
+void
+Init_File()
+{
rb_mFileTest = rb_define_module("FileTest");
rb_define_module_function(rb_mFileTest, "directory?", test_d, 1);
@@ -1637,9 +1580,6 @@ Init_File()
rb_cFile = rb_define_class("File", rb_cIO);
rb_extend_object(rb_cFile, CLASS_OF(rb_mFileTest));
- rb_define_singleton_method(rb_cFile, "new", rb_file_s_open, -1);
- rb_define_singleton_method(rb_cFile, "open", rb_file_s_open, -1);
-
rb_define_singleton_method(rb_cFile, "stat", rb_file_s_stat, 1);
rb_define_singleton_method(rb_cFile, "lstat", rb_file_s_lstat, 1);
rb_define_singleton_method(rb_cFile, "ftype", rb_file_s_ftype, 1);
@@ -1668,10 +1608,16 @@ Init_File()
separator = rb_str_new2("/");
rb_define_const(rb_cFile, "Separator", separator);
+ rb_define_const(rb_cFile, "SEPARATOR", separator);
rb_define_singleton_method(rb_cFile, "split", rb_file_s_split, 1);
rb_define_singleton_method(rb_cFile, "join", rb_file_s_join, -2);
- rb_define_method(rb_cFile, "reopen", rb_file_reopen, -1);
+#ifdef DOSISH
+ rb_define_const(rb_cFile, "ALT_SEPARATOR", rb_str_new2("\\"));
+#else
+ rb_define_const(rb_cFile, "ALT_SEPARATOR", Qnil);
+#endif
+ rb_define_const(rb_cFile, "PATH_SEPARATOR", rb_str_new2(PATH_SEP));
rb_define_method(rb_cIO, "stat", rb_io_stat, 0); /* this is IO's method */
rb_define_method(rb_cFile, "lstat", rb_file_lstat, 0);
@@ -1687,15 +1633,10 @@ Init_File()
rb_define_method(rb_cFile, "flock", rb_file_flock, 1);
rb_mConst = rb_define_module_under(rb_cFile, "Constants");
- rb_define_const(rb_cFile, "LOCK_SH", INT2FIX(LOCK_SH));
- rb_define_const(rb_cFile, "LOCK_EX", INT2FIX(LOCK_EX));
- rb_define_const(rb_cFile, "LOCK_UN", INT2FIX(LOCK_UN));
- rb_define_const(rb_cFile, "LOCK_NB", INT2FIX(LOCK_NB));
-
- rb_define_const(rb_mConst, "LOCK_SH", INT2FIX(LOCK_SH));
- rb_define_const(rb_mConst, "LOCK_EX", INT2FIX(LOCK_EX));
- rb_define_const(rb_mConst, "LOCK_UN", INT2FIX(LOCK_UN));
- rb_define_const(rb_mConst, "LOCK_NB", INT2FIX(LOCK_NB));
+ rb_file_const("LOCK_SH", INT2FIX(LOCK_SH));
+ rb_file_const("LOCK_EX", INT2FIX(LOCK_EX));
+ rb_file_const("LOCK_UN", INT2FIX(LOCK_UN));
+ rb_file_const("LOCK_NB", INT2FIX(LOCK_NB));
rb_define_method(rb_cFile, "path", rb_file_path, 0);
diff --git a/fnmatch.c b/fnmatch.c
deleted file mode 100644
index f031749c3d..0000000000
--- a/fnmatch.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/* Copyright (C) 1991 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA. */
-
-#include "config.h"
-#include <errno.h>
-#include "fnmatch.h"
-
-#ifdef USE_CWGUSI
-#include <sys/errno.h>
-#endif
-
-#if !defined (__GNU_LIBRARY__) && !defined (STDC_HEADERS)
-# if !defined (errno)
-extern int errno;
-# endif /* !errno */
-#endif
-
-/* Match STRING against the filename pattern PATTERN, returning zero if
- it matches, FNM_NOMATCH if not. */
-int
-fnmatch (pattern, string, flags)
- char *pattern;
- char *string;
- int flags;
-{
- register char *p = pattern, *n = string;
- register char c;
-
- if ((flags & ~__FNM_FLAGS) != 0)
- {
- errno = EINVAL;
- return (-1);
- }
-
- while ((c = *p++) != '\0')
- {
- switch (c)
- {
- case '?':
- if (*n == '\0')
- return (FNM_NOMATCH);
- else if ((flags & FNM_PATHNAME) && *n == '/')
- /* If we are matching a pathname, `?' can never match a `/'. */
- return (FNM_NOMATCH);
- else if ((flags & FNM_PERIOD) && *n == '.' &&
- (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
- /* `?' cannot match a `.' if it is the first character of the
- string or if it is the first character following a slash and
- we are matching a pathname. */
- return (FNM_NOMATCH);
- break;
-
- case '\\':
- if (!(flags & FNM_NOESCAPE))
- {
- c = *p++;
- if (c == '\0')
- return (FNM_NOMATCH);
- }
- if (*n != c)
- return (FNM_NOMATCH);
- break;
-
- case '*':
- if ((flags & FNM_PERIOD) && *n == '.' &&
- (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
- /* `*' cannot match a `.' if it is the first character of the
- string or if it is the first character following a slash and
- we are matching a pathname. */
- return (FNM_NOMATCH);
-
- /* Collapse multiple consecutive, `*' and `?', but make sure that
- one character of the string is consumed for each `?'. */
- for (c = *p++; c == '?' || c == '*'; c = *p++)
- {
- if ((flags & FNM_PATHNAME) && *n == '/')
- /* A slash does not match a wildcard under FNM_PATHNAME. */
- return (FNM_NOMATCH);
- else if (c == '?')
- {
- if (*n == '\0')
- return (FNM_NOMATCH);
- /* One character of the string is consumed in matching
- this ? wildcard, so *??? won't match if there are
- fewer than three characters. */
- n++;
- }
- }
-
- if (c == '\0')
- return (0);
-
- /* General case, use recursion. */
- {
- char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
- for (--p; *n != '\0'; ++n)
- /* Only call fnmatch if the first character indicates a
- possible match. */
- if ((c == '[' || *n == c1) &&
- fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
- return (0);
- return (FNM_NOMATCH);
- }
-
- case '[':
- {
- /* Nonzero if the sense of the character class is inverted. */
- register int not;
-
- if (*n == '\0')
- return (FNM_NOMATCH);
-
- /* A character class cannot match a `.' if it is the first
- character of the string or if it is the first character
- following a slash and we are matching a pathname. */
- if ((flags & FNM_PERIOD) && *n == '.' &&
- (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
- return (FNM_NOMATCH);
-
- /* POSIX.2 2.8.3.1.2 says: `An expression containing a `[' that
- is not preceded by a backslash and is not part of a bracket
- expression produces undefined results.' This implementation
- treats the `[' as just a character to be matched if there is
- not a closing `]'. This code will have to be changed when
- POSIX.2 character classes are implemented. */
- {
- register char *np;
-
- for (np = p; np && *np && *np != ']'; np++)
- ;
-
- if (np && !*np)
- {
- if (*n != '[')
- return (FNM_NOMATCH);
- break;
- }
- }
-
- not = (*p == '!' || *p == '^');
- if (not)
- ++p;
-
- c = *p++;
- for (;;)
- {
- register char cstart, cend;
-
- /* Initialize cstart and cend in case `-' is the last
- character of the pattern. */
- cstart = cend = c;
-
- if (!(flags & FNM_NOESCAPE) && c == '\\')
- {
- if (*p == '\0')
- return FNM_NOMATCH;
- cstart = cend = *p++;
- }
-
- if (c == '\0')
- /* [ (unterminated) loses. */
- return (FNM_NOMATCH);
-
- c = *p++;
-
- if ((flags & FNM_PATHNAME) && c == '/')
- /* [/] can never match. */
- return (FNM_NOMATCH);
-
- /* This introduces a range, unless the `-' is the last
- character of the class. Find the end of the range
- and move past it. */
- if (c == '-' && *p != ']')
- {
- cend = *p++;
- if (!(flags & FNM_NOESCAPE) && cend == '\\')
- cend = *p++;
- if (cend == '\0')
- return (FNM_NOMATCH);
-
- c = *p++;
- }
-
- if (*n >= cstart && *n <= cend)
- goto matched;
-
- if (c == ']')
- break;
- }
- if (!not)
- return (FNM_NOMATCH);
- break;
-
- matched:
- /* Skip the rest of the [...] that already matched. */
- while (c != ']')
- {
- if (c == '\0')
- /* [... (unterminated) loses. */
- return (FNM_NOMATCH);
-
- c = *p++;
- if (!(flags & FNM_NOESCAPE) && c == '\\')
- {
- if (*p == '\0')
- return FNM_NOMATCH;
- /* XXX 1003.2d11 is unclear if this is right. */
- ++p;
- }
- }
- if (not)
- return (FNM_NOMATCH);
- }
- break;
-
- default:
- if (c != *n)
- return (FNM_NOMATCH);
- }
-
- ++n;
- }
-
- if (*n == '\0')
- return (0);
-
- return (FNM_NOMATCH);
-}
diff --git a/fnmatch.h b/fnmatch.h
deleted file mode 100644
index 62c8c8fa02..0000000000
--- a/fnmatch.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright (C) 1991 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
-
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
-
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Library General Public License for more details.
-
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB. If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA. */
-
-#ifndef _FNMATCH_H
-
-#define _FNMATCH_H 1
-
-/* Bits set in the FLAGS argument to `fnmatch'. */
-#define FNM_PATHNAME (1 << 0)/* No wildcard can ever match `/'. */
-#define FNM_NOESCAPE (1 << 1)/* Backslashes don't quote special chars. */
-#define FNM_PERIOD (1 << 2)/* Leading `.' is matched only explicitly. */
-#define __FNM_FLAGS (FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD)
-
-/* Value returned by `fnmatch' if STRING does not match PATTERN. */
-#define FNM_NOMATCH 1
-
-/* Match STRING against the filename pattern PATTERN,
- returning zero if it matches, FNM_NOMATCH if not. */
-extern int fnmatch();
-
-#endif /* fnmatch.h */
diff --git a/gc.c b/gc.c
index 31ed11196a..7e2a4f7082 100644
--- a/gc.c
+++ b/gc.c
@@ -6,7 +6,7 @@
$Date$
created at: Tue Oct 5 09:44:46 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -42,14 +42,18 @@ static void run_final();
#if defined(MSDOS) || defined(__human68k__)
#define GC_MALLOC_LIMIT 100000
#else
-#define GC_MALLOC_LIMIT 200000
+#define GC_MALLOC_LIMIT 400000
#endif
#endif
-#define GC_NEWOBJ_LIMIT 1000
+#define GC_NEWOBJ_LIMIT 10000
static unsigned long malloc_memories = 0;
static unsigned long alloc_objects = 0;
+static int malloc_called = 0;
+static int free_called = 0;
+
+#ifndef xmalloc
void *
xmalloc(size)
size_t size;
@@ -64,6 +68,7 @@ xmalloc(size)
if (malloc_memories > GC_MALLOC_LIMIT && alloc_objects > GC_NEWOBJ_LIMIT) {
rb_gc();
}
+ malloc_called++;
mem = malloc(size);
if (!mem) {
rb_gc();
@@ -111,6 +116,15 @@ xrealloc(ptr, size)
return mem;
}
+static void
+xfree(x)
+ void *x;
+{
+ free_called++;
+ free(x);
+}
+#endif
+
/* The way of garbage collecting which allows use of the cstack is due to */
/* Scheme In One Defun, but in C this time.
@@ -284,7 +298,7 @@ rb_data_object_alloc(klass, datap, dmark, dfree)
}
extern st_table *rb_class_tbl;
-VALUE *rb_gc_stack_start;
+VALUE *rb_gc_stack_start = 0;
#if defined(__GNUC__) && __GNUC__ >= 2
__inline__
@@ -334,7 +348,7 @@ rb_gc_mark_locations(start, end)
start = end;
end = tmp;
}
- n = end - start;
+ n = end - start + 1;
mark_locations_array(start,n);
}
@@ -389,10 +403,10 @@ rb_gc_mark(ptr)
register RVALUE *obj = RANY(ptr);
Top:
- if (FIXNUM_P(obj)) return; /* fixnum not marked */
+ if (FIXNUM_P(obj)) return; /* fixnum not marked */
if (rb_special_const_p((VALUE)obj)) return; /* special const not marked */
- if (obj->as.basic.flags == 0) return; /* free cell */
- if (obj->as.basic.flags & FL_MARK) return; /* already marked */
+ if (obj->as.basic.flags == 0) return; /* free cell */
+ if (obj->as.basic.flags & FL_MARK) return; /* already marked */
obj->as.basic.flags |= FL_MARK;
@@ -445,7 +459,6 @@ rb_gc_mark(ptr)
case NODE_OR:
case NODE_CASE:
case NODE_SCLASS:
- case NODE_ARGS:
case NODE_DOT2:
case NODE_DOT3:
case NODE_FLIP2:
@@ -479,6 +492,7 @@ rb_gc_mark(ptr)
case NODE_RETURN:
case NODE_YIELD:
case NODE_COLON2:
+ case NODE_ARGS:
obj = RANY(obj->as.node.u1.node);
goto Top;
@@ -598,7 +612,8 @@ rb_gc_mark(ptr)
break;
case T_SCOPE:
- if (obj->as.scope.local_vars) {
+ if (obj->as.scope.local_vars &&
+ obj->as.scope.flag != SCOPE_ALLOCA) {
int n = obj->as.scope.local_tbl[0]+1;
VALUE *vars = &obj->as.scope.local_vars[-1];
@@ -660,7 +675,7 @@ gc_sweep()
if (p->as.basic.flags) {
obj_free((VALUE)p);
}
- if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
+ if (need_call_final && FL_TEST(p, FL_FINALIZE)) {
p->as.free.flag = FL_MARK; /* remain marked */
p->as.free.next = final_list;
final_list = p;
@@ -769,10 +784,10 @@ obj_free(obj)
}
break;
case T_MATCH:
- if (RANY(obj)->as.match.regs)
+ if (RANY(obj)->as.match.regs) {
re_free_registers(RANY(obj)->as.match.regs);
- if (RANY(obj)->as.match.regs)
free(RANY(obj)->as.match.regs);
+ }
break;
case T_FILE:
if (RANY(obj)->as.file.fptr) {
@@ -807,7 +822,8 @@ obj_free(obj)
return; /* no need to free iv_tbl */
case T_SCOPE:
- if (RANY(obj)->as.scope.local_vars) {
+ if (RANY(obj)->as.scope.local_vars &&
+ RANY(obj)->as.scope.flag != SCOPE_ALLOCA) {
VALUE *vars = RANY(obj)->as.scope.local_vars-1;
if (vars[0] == 0)
free(RANY(obj)->as.scope.local_tbl);
@@ -890,7 +906,16 @@ rb_gc()
/* mark frame stack */
for (frame = ruby_frame; frame; frame = frame->prev) {
- rb_gc_mark_frame(frame);
+ rb_gc_mark_frame(frame);
+ }
+ for (frame = ruby_frame; frame; frame = frame->prev) {
+ if (frame->tmp) {
+ struct FRAME *tmp = frame->tmp;
+ while (tmp) {
+ rb_gc_mark_frame(tmp);
+ tmp = tmp->prev;
+ }
+ }
}
rb_gc_mark(ruby_class);
rb_gc_mark(ruby_scope);
@@ -909,10 +934,7 @@ rb_gc()
rb_gc_mark_locations((VALUE*)((char*)rb_gc_stack_start + 2),
(VALUE*)((char*)&stack_end + 2));
#endif
-
-#ifdef USE_THREAD
rb_gc_mark_threads();
-#endif
/* mark protected global variables */
for (list = Global_List; list; list = list->next) {
@@ -937,22 +959,26 @@ gc_start()
}
void
-Init_stack()
+Init_stack(addr)
+ VALUE *addr;
{
#ifdef __human68k__
extern void *_SEND;
- gc_stack_start = _SEND;
+ rb_gc_stack_start = _SEND;
#else
VALUE start;
- rb_gc_stack_start = &start;
+ if (!addr) addr = &start;
+ rb_gc_stack_start = addr;
#endif
}
void
Init_heap()
{
- Init_stack();
+ if (!rb_gc_stack_start) {
+ Init_stack(0);
+ }
add_heap();
}
@@ -1073,15 +1099,26 @@ call_final(os, obj)
return obj;
}
+static VALUE
+run_single_final(args)
+ VALUE *args;
+{
+ rb_eval_cmd(args[0], args[1]);
+ return Qnil;
+}
+
static void
run_final(obj)
VALUE obj;
{
- int i;
+ int i, status;
+ VALUE args[2];
obj = rb_obj_id(obj); /* make obj into id */
+ args[1] = rb_ary_new3(1, obj);
for (i=0; i<RARRAY(finalizers)->len; i++) {
- rb_eval_cmd(RARRAY(finalizers)->ptr[i], rb_ary_new3(1, obj));
+ args[0] = RARRAY(finalizers)->ptr[i];
+ rb_protect(run_single_final, (VALUE)args, &status);
}
}
@@ -1105,9 +1142,12 @@ rb_gc_call_finalizer_at_exit()
p = heaps[i]; pend = p + HEAP_SLOTS;
while (p < pend) {
if (BUILTIN_TYPE(p) == T_DATA &&
- DATA_PTR(p) &&
- RANY(p)->as.data.dfree)
+ DATA_PTR(p) && RANY(p)->as.data.dfree) {
(*RANY(p)->as.data.dfree)(DATA_PTR(p));
+ }
+ else if (BUILTIN_TYPE(p) == T_FILE) {
+ rb_io_fptr_finalize(RANY(p)->as.file.fptr);
+ }
p++;
}
}
diff --git a/glob.c b/glob.c
deleted file mode 100644
index 09a47e0aa4..0000000000
--- a/glob.c
+++ /dev/null
@@ -1,591 +0,0 @@
-/* File-name wildcard pattern matching for GNU.
- Copyright (C) 1985, 1988, 1989 Free Software Foundation, Inc.
-
- 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.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-/* To whomever it may concern: I have never seen the code which most
- Unix programs use to perform this function. I wrote this from scratch
- based on specifications for the pattern matching. --RMS. */
-
-#include "config.h"
-
-#if !defined (__GNUC__) && !defined (HAVE_ALLOCA_H) && defined (_AIX)
- #pragma alloca
-#endif /* _AIX && RISC6000 && !__GNUC__ */
-
-#if defined (HAVE_ALLOCA_H)
-# include <alloca.h>
-#endif
-
-#if defined (HAVE_UNISTD_H)
-# include <unistd.h>
-#endif
-
-#if defined (HAVE_STDLIB_H)
-# include <stdlib.h>
-#else
-# if defined (SHELL)
-# include "ansi_stdlib.h"
-# endif /* SHELL */
-#endif
-
-#include <sys/types.h>
-
-#if defined (HAVE_DIRENT_H)
-# include <dirent.h>
-# define D_NAMLEN(d) strlen ((d)->d_name)
-#elif HAVE_DIRECT_H
-# include <direct.h>
-# define D_NAMLEN(d) strlen ((d)->d_name)
-#else /* !HAVE_DIRENT_H */
-# define D_NAMLEN(d) ((d)->d_namlen)
-# if defined (HAVE_SYS_NDIR_H)
-# include <sys/ndir.h>
-# endif
-# if defined (HAVE_SYS_DIR_H)
-# include <sys/dir.h>
-# endif /* HAVE_SYS_DIR_H */
-# if defined (HAVE_NDIR_H)
-# include <ndir.h>
-# endif
-# if !defined (dirent)
-# define dirent direct
-# endif
-#endif /* !HAVE_DIRENT_H */
-
-#if defined (_POSIX_SOURCE) || defined(DJGPP) || defined(USE_CWGUSI)
-/* Posix does not require that the d_ino field be present, and some
- systems do not provide it. */
-# define REAL_DIR_ENTRY(dp) 1
-#elif defined (__BORLANDC__)
-# define REAL_DIR_ENTRY(dp) 1
-#else
-# define REAL_DIR_ENTRY(dp) (dp->d_ino != 0)
-#endif /* _POSIX_SOURCE */
-
-#if defined (HAVE_STRING_H)
-# include <string.h>
-#else /* !HAVE_STRING_H */
-# include <strings.h>
-#endif /* !HAVE_STRING_H */
-
-#if !defined (HAVE_BCOPY) && !defined (bcopy)
-# define bcopy(s, d, n) ((void) memcpy ((d), (s), (n)))
-#endif /* !HAVE_BCOPY */
-
-/* If the opendir () on your system lets you open non-directory files,
- then we consider that not robust. */
-#if defined (OPENDIR_NOT_ROBUST)
-# if defined (SHELL)
-# include "posixstat.h"
-# else /* !SHELL */
-# include <sys/stat.h>
-# endif /* !SHELL */
-#endif /* OPENDIR_NOT_ROBUST */
-
-#include "fnmatch.h"
-
-extern void *xmalloc (), *xrealloc ();
-#if !defined (HAVE_STDLIB_H)
-extern void free ();
-#endif /* !HAVE_STDLIB_H */
-
-#if !defined (NULL)
-# if defined (__STDC__)
-# define NULL ((void *) 0)
-# else
-# define NULL 0x0
-# endif /* __STDC__ */
-#endif /* !NULL */
-
-#if defined (SHELL)
-extern void throw_to_top_level ();
-
-extern int interrupt_state;
-#endif /* SHELL */
-
-#if defined(NT) && defined(_MSC_VER)
-#include "missing/dir.h"
-#endif
-
-/* Global variable which controls whether or not * matches .*.
- Non-zero means don't match .*. */
-int noglob_dot_filenames = 1;
-
-/* Global variable to return to signify an error in globbing. */
-char *glob_error_return;
-
-/* Return nonzero if PATTERN has any special globbing chars in it. */
-int
-glob_pattern_p (pattern)
- char *pattern;
-{
- register char *p = pattern;
- register char c;
- int open = 0;
-
- while ((c = *p++) != '\0')
- switch (c)
- {
- case '?':
- case '*':
- return (1);
-
- 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 (1);
- continue;
-
- case '\\':
- if (*p++ == '\0')
- return (0);
- }
-
- return (0);
-}
-
-/* Remove backslashes quoting characters in PATHNAME by modifying PATHNAME. */
-static void
-dequote_pathname (pathname)
- char *pathname;
-{
- register int i, j;
-
- for (i = j = 0; pathname && pathname[i]; )
- {
- if (pathname[i] == '\\')
- i++;
-
- pathname[j++] = pathname[i++];
-
- if (!pathname[i - 1])
- break;
- }
- pathname[j] = '\0';
-}
-
-
-/* Return a vector of names of files in directory DIR
- whose names match glob pattern PAT.
- The names are not in any particular order.
- Wildcards at the beginning of PAT do not match an initial period.
-
- The vector is terminated by an element that is a null pointer.
-
- To free the space allocated, first free the vector's elements,
- then free the vector.
-
- Return 0 if cannot get enough memory to hold the pointer
- and the names.
-
- Return -1 if cannot access directory DIR.
- Look in errno for more information. */
-
-char **
-glob_vector (pat, dir)
- char *pat;
- char *dir;
-{
- struct globval
- {
- struct globval *next;
- char *name;
- };
-
- DIR *d;
- register struct dirent *dp;
- struct globval *lastlink;
- register struct globval *nextlink;
- register char *nextname;
- unsigned int count;
- int lose, skip;
- register char **name_vector;
- register unsigned int i;
-#if defined (OPENDIR_NOT_ROBUST)
- struct stat finfo;
-
- if (stat (dir, &finfo) < 0)
- return ((char **) &glob_error_return);
-
- if (!S_ISDIR (finfo.st_mode))
- return ((char **) &glob_error_return);
-#endif /* OPENDIR_NOT_ROBUST */
-
- d = opendir (dir);
- if (d == NULL)
- return ((char **) &glob_error_return);
-
- lastlink = 0;
- count = 0;
- lose = 0;
- skip = 0;
-
- /* If PAT is empty, skip the loop, but return one (empty) filename. */
- if (!pat || !*pat)
- {
- nextlink = (struct globval *)alloca (sizeof (struct globval));
- nextlink->next = lastlink;
- nextname = (char *) xmalloc (1);
- if (!nextname)
- lose = 1;
- else
- {
- lastlink = nextlink;
- nextlink->name = nextname;
- nextname[0] = '\0';
- count++;
- }
- skip = 1;
- }
-
- /* Scan the directory, finding all names that match.
- For each name that matches, allocate a struct globval
- on the stack and store the name in it.
- Chain those structs together; lastlink is the front of the chain. */
- while (!skip)
- {
- int flags; /* Flags passed to fnmatch (). */
-#if defined (SHELL)
- /* Make globbing interruptible in the bash shell. */
- if (interrupt_state)
- {
- closedir (d);
- lose = 1;
- goto lost;
- }
-#endif /* SHELL */
-
- dp = readdir (d);
- if (dp == NULL)
- break;
-
- /* If this directory entry is not to be used, try again. */
- if (!REAL_DIR_ENTRY (dp))
- continue;
-
- /* If a dot must be explicity matched, check to see if they do. */
- if (noglob_dot_filenames && dp->d_name[0] == '.' && pat[0] != '.' &&
- (pat[0] != '\\' || pat[1] != '.'))
- continue;
-
- flags = (noglob_dot_filenames ? FNM_PERIOD : 0) | FNM_PATHNAME;
-
- if (fnmatch (pat, dp->d_name, flags) != FNM_NOMATCH)
- {
- nextlink = (struct globval *) alloca (sizeof (struct globval));
- nextlink->next = lastlink;
- nextname = (char *) xmalloc (D_NAMLEN (dp) + 1);
- if (nextname == NULL)
- {
- lose = 1;
- break;
- }
- lastlink = nextlink;
- nextlink->name = nextname;
- bcopy (dp->d_name, nextname, D_NAMLEN (dp) + 1);
- ++count;
- }
- }
- (void) closedir (d);
-
- if (!lose)
- {
- name_vector = (char **) xmalloc ((count + 1) * sizeof (char *));
- lose |= name_vector == NULL;
- }
-
- /* Have we run out of memory? */
-#if defined (SHELL)
- lost:
-#endif
- if (lose)
- {
- /* Here free the strings we have got. */
- while (lastlink)
- {
- free (lastlink->name);
- lastlink = lastlink->next;
- }
-#if defined (SHELL)
- if (interrupt_state)
- throw_to_top_level ();
-#endif /* SHELL */
- return (NULL);
- }
-
- /* Copy the name pointers from the linked list into the vector. */
- for (i = 0; i < count; ++i)
- {
- name_vector[i] = lastlink->name;
- lastlink = lastlink->next;
- }
-
- name_vector[count] = NULL;
- return (name_vector);
-}
-
-/* Return a new array which is the concatenation of each string in ARRAY
- to DIR. This function expects you to pass in an allocated ARRAY, and
- it takes care of free()ing that array. Thus, you might think of this
- function as side-effecting ARRAY. */
-static char **
-glob_dir_to_array (dir, array)
- char *dir, **array;
-{
- register unsigned int i, l;
- int add_slash;
- char **result;
-
- l = strlen (dir);
- if (l == 0)
- return (array);
-
- add_slash = dir[l - 1] != '/';
-
- i = 0;
- while (array[i] != NULL)
- ++i;
-
- result = (char **) xmalloc ((i + 1) * sizeof (char *));
- if (result == NULL)
- return (NULL);
-
- for (i = 0; array[i] != NULL; i++)
- {
- result[i] = (char *) xmalloc (l + (add_slash ? 1 : 0)
- + strlen (array[i]) + 1);
- if (result[i] == NULL)
- return (NULL);
-#if 1
- strcpy (result[i], dir);
- if (add_slash)
- result[i][l] = '/';
- strcpy (result[i] + l + add_slash, array[i]);
-#else
- (void)sprintf (result[i], "%s%s%s", dir, add_slash ? "/" : "", array[i]);
-#endif
- }
- result[i] = NULL;
-
- /* Free the input array. */
- for (i = 0; array[i] != NULL; i++)
- free (array[i]);
- free ((char *) array);
-
- return (result);
-}
-
-/* Do globbing on PATHNAME. Return an array of pathnames that match,
- marking the end of the array with a null-pointer as an element.
- If no pathnames match, then the array is empty (first element is null).
- If there isn't enough memory, then return NULL.
- If a file system error occurs, return -1; `errno' has the error code. */
-char **
-glob_filename (pathname)
- char *pathname;
-{
-#ifndef strrchr
- char *strrchr();
-#endif
-
- char **result;
- unsigned int result_size;
- char *directory_name, *filename;
- unsigned int directory_len;
-
- result = (char **) xmalloc (sizeof (char *));
- result_size = 1;
- if (result == NULL)
- return (NULL);
-
- result[0] = NULL;
-
- /* Find the filename. */
- filename = strrchr (pathname, '/');
- if (filename == NULL)
- {
- filename = pathname;
- directory_name = "";
- directory_len = 0;
- }
- else
- {
- directory_len = (filename - pathname) + 1;
- directory_name = (char *) alloca (directory_len + 1);
-
- bcopy (pathname, directory_name, directory_len);
- directory_name[directory_len] = '\0';
- ++filename;
- }
-
- /* If directory_name contains globbing characters, then we
- have to expand the previous levels. Just recurse. */
- if (glob_pattern_p (directory_name))
- {
- char **directories;
- register unsigned int i;
-
- if (directory_name[directory_len - 1] == '/')
- directory_name[directory_len - 1] = '\0';
-
- directories = glob_filename (directory_name);
-
- if (directories == NULL)
- goto memory_error;
- else if (directories == (char **)&glob_error_return)
- {
- free ((char *) result);
- return ((char **) &glob_error_return);
- }
- else if (*directories == NULL)
- {
- free ((char *) directories);
- free ((char *) result);
- return ((char **) &glob_error_return);
- }
-
- /* We have successfully globbed the preceding directory name.
- For each name in DIRECTORIES, call glob_vector on it and
- FILENAME. Concatenate the results together. */
- for (i = 0; directories[i] != NULL; ++i)
- {
- char **temp_results;
-
- /* Scan directory even on a NULL pathname. That way, `*h/'
- returns only directories ending in `h', instead of all
- files ending in `h' with a `/' appended. */
- temp_results = glob_vector (filename, directories[i]);
-
- /* Handle error cases. */
- if (temp_results == NULL)
- goto memory_error;
- else if (temp_results == (char **)&glob_error_return)
- /* This filename is probably not a directory. Ignore it. */
- ;
- else
- {
- char **array;
- register unsigned int l;
-
- array = glob_dir_to_array (directories[i], temp_results);
- l = 0;
- while (array[l] != NULL)
- ++l;
-
- result =
- (char **)xrealloc(result, (result_size + l) * sizeof (char *));
-
- if (result == NULL)
- goto memory_error;
-
- for (l = 0; array[l] != NULL; ++l)
- result[result_size++ - 1] = array[l];
-
- result[result_size - 1] = NULL;
-
- /* Note that the elements of ARRAY are not freed. */
- free ((char *) array);
- }
- }
- /* Free the directories. */
- for (i = 0; directories[i]; i++)
- free (directories[i]);
-
- free ((char *) directories);
-
- return (result);
- }
-
- /* If there is only a directory name, return it. */
- if (*filename == '\0')
- {
- result = (char **) xrealloc ((char *) result, 2 * sizeof (char *));
- if (result == NULL)
- return (NULL);
- result[0] = (char *) xmalloc (directory_len + 1);
- if (result[0] == NULL)
- goto memory_error;
- bcopy (directory_name, result[0], directory_len + 1);
- result[1] = NULL;
- return (result);
- }
- else
- {
- char **temp_results;
-
- /* There are no unquoted globbing characters in DIRECTORY_NAME.
- Dequote it before we try to open the directory since there may
- be quoted globbing characters which should be treated verbatim. */
- if (directory_len > 0)
- dequote_pathname (directory_name);
-
- /* We allocated a small array called RESULT, which we won't be using.
- Free that memory now. */
- free (result);
-
- /* Just return what glob_vector () returns appended to the
- directory name. */
- temp_results =
- glob_vector (filename, (directory_len == 0 ? "." : directory_name));
-
- if (temp_results == NULL || temp_results == (char **)&glob_error_return)
- return (temp_results);
-
- return (glob_dir_to_array (directory_name, temp_results));
- }
-
- /* We get to memory_error if the program has run out of memory, or
- if this is the shell, and we have been interrupted. */
- memory_error:
- if (result != NULL)
- {
- register unsigned int i;
- for (i = 0; result[i] != NULL; ++i)
- free (result[i]);
- free ((char *) result);
- }
-#if defined (SHELL)
- if (interrupt_state)
- throw_to_top_level ();
-#endif /* SHELL */
- return (NULL);
-}
-
-#if defined (TEST)
-
-main (argc, argv)
- int argc;
- char **argv;
-{
- unsigned int i;
-
- for (i = 1; i < argc; ++i)
- {
- char **value = glob_filename (argv[i]);
- if (value == NULL)
- puts ("Out of memory.");
- else if (value == &glob_error_return)
- perror (argv[i]);
- else
- for (i = 0; value[i] != NULL; i++)
- puts (value[i]);
- }
-
- exit (0);
-}
-#endif /* TEST. */
diff --git a/hash.c b/hash.c
index 9141406410..608f85d72f 100644
--- a/hash.c
+++ b/hash.c
@@ -6,12 +6,13 @@
$Date$
created at: Mon Nov 22 18:51:18 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include "st.h"
+#include "util.h"
#include "rubysig.h"
#include <sys/types.h>
@@ -21,6 +22,10 @@
char *strchr _((char*,char));
#endif
+#ifdef USE_CWGUSI
+char* strdup(const char*);
+#endif
+
#define HASH_FREEZE FL_USER1
#define HASH_DELETED FL_USER2
@@ -30,7 +35,7 @@ rb_hash_modify(hash)
{
if (FL_TEST(hash, HASH_FREEZE))
rb_raise(rb_eTypeError, "can't modify frozen hash");
- if (rb_safe_level() >= 4 && !FL_TEST(hash, FL_TAINT))
+ if (!FL_TEST(hash, FL_TAINT) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify hash");
}
@@ -63,6 +68,13 @@ rb_hash(obj)
return rb_funcall(obj, hash, 0);
}
+static VALUE
+eql(args)
+ VALUE *args;
+{
+ return (VALUE)rb_eql(args[0], args[1]);
+}
+
static int
rb_any_cmp(a, b)
VALUE a, b;
@@ -73,11 +85,13 @@ rb_any_cmp(a, b)
else if (TYPE(a) == T_STRING) {
if (TYPE(b) == T_STRING) return rb_str_cmp(a, b);
}
+ else {
+ VALUE args[2];
- DEFER_INTS;
- a = !rb_eql(a, b);
- ENABLE_INTS;
- return a;
+ args[0] = a;
+ args[1] = b;
+ return !rb_with_disable_interrupt(eql, (VALUE)args);
+ }
}
static int
@@ -127,7 +141,7 @@ rb_hash_foreach_iter(key, value, arg)
st_table *tbl = RHASH(arg->hash)->tbl;
struct st_table_entry **bins = tbl->bins;
- if (key == Qnil) return ST_CONTINUE;
+ if (value == Qnil) return ST_CONTINUE;
status = (*arg->func)(key, value, arg->arg);
if (RHASH(arg->hash)->tbl != tbl || RHASH(arg->hash)->tbl->bins != bins){
rb_raise(rb_eIndexError, "rehash occurred during iteration");
@@ -143,14 +157,6 @@ rb_hash_foreach_call(arg)
return Qnil;
}
-static int
-rb_hash_delete_nil(key, value)
- VALUE key, value;
-{
- if (value == Qnil) return ST_DELETE;
- return ST_CONTINUE;
-}
-
static VALUE
rb_hash_foreach_ensure(hash)
VALUE hash;
@@ -159,7 +165,7 @@ rb_hash_foreach_ensure(hash)
if (RHASH(hash)->iter_lev == 0) {
if (FL_TEST(hash, HASH_DELETED)) {
- st_foreach(RHASH(hash)->tbl, rb_hash_delete_nil, 0);
+ st_cleanup_safe(RHASH(hash)->tbl, Qnil);
FL_UNSET(hash, HASH_DELETED);
}
}
@@ -187,8 +193,7 @@ rb_hash_s_new(argc, argv, klass)
VALUE *argv;
VALUE klass;
{
- VALUE sz, ifnone;
- int size;
+ VALUE ifnone;
NEWOBJ(hash, struct RHash);
OBJSETUP(hash, klass, T_HASH);
@@ -197,15 +202,10 @@ rb_hash_s_new(argc, argv, klass)
hash->ifnone = Qnil;
hash->tbl = 0; /* avoid GC crashing */
- rb_scan_args(argc, argv, "02", &ifnone, &sz);
- if (NIL_P(sz)) {
- size = 0;
- }
- else size = NUM2INT(sz);
+ rb_scan_args(argc, argv, "01", &ifnone);
hash->ifnone = ifnone;
- hash->tbl = st_init_table_with_size(&objhash, size);
- rb_obj_call_init((VALUE)hash);
+ hash->tbl = st_init_table(&objhash);
return (VALUE)hash;
}
@@ -240,19 +240,22 @@ rb_hash_s_create(argc, argv, klass)
VALUE hash;
int i;
- if (argc == 1 && TYPE(argv[0]) == T_HASH) {
- if (klass == CLASS_OF(argv[0])) return argv[0];
- else {
+ if (argc == 1) {
+ if (TYPE(argv[0]) == T_HASH) {
NEWOBJ(hash, struct RHash);
OBJSETUP(hash, klass, T_HASH);
hash->iter_lev = 0;
hash->ifnone = Qnil;
hash->tbl = 0; /* avoid GC crashing */
- hash->tbl = (st_table*)st_copy(RHASH(argv[0])->tbl);
- rb_obj_call_init((VALUE)hash);
+ hash->tbl = st_copy(RHASH(argv[0])->tbl);
+
return (VALUE)hash;
}
+ else {
+ VALUE a = rb_Array(argv[0]);
+ return rb_hash_s_create(RARRAY(a)->len, RARRAY(a)->ptr, klass);
+ }
}
if (argc % 2 != 0) {
@@ -263,7 +266,6 @@ rb_hash_s_create(argc, argv, klass)
for (i=0; i<argc; i+=2) {
st_insert(RHASH(hash)->tbl, argv[i], argv[i+1]);
}
- rb_obj_call_init(hash);
return hash;
}
@@ -380,6 +382,32 @@ rb_hash_set_default(hash, ifnone)
return hash;
}
+static int
+index_i(key, value, args)
+ VALUE key, value;
+ VALUE *args;
+{
+ if (rb_equal(value, args[0])) {
+ args[1] = key;
+ return ST_STOP;
+ }
+ return ST_CONTINUE;
+}
+
+static VALUE
+rb_hash_index(hash, value)
+ VALUE hash, value;
+{
+ VALUE args[2];
+
+ args[0] = value;
+ args[1] = Qnil;
+
+ st_foreach(RHASH(hash)->tbl, index_i, args);
+
+ return args[1];
+}
+
static VALUE
rb_hash_indexes(argc, argv, hash)
int argc;
@@ -428,7 +456,7 @@ shift_i(key, value, var)
VALUE key, value;
struct shift_var *var;
{
- if (key == Qnil) return ST_CONTINUE;
+ if (value == Qnil) return ST_CONTINUE;
if (var->stop) return ST_STOP;
var->stop = 1;
var->key = key;
@@ -454,8 +482,8 @@ static int
delete_if_i(key, value)
VALUE key, value;
{
- if (key == Qnil) return ST_CONTINUE;
- if (rb_yield(rb_assoc_new(key, value)))
+ if (value == Qnil) return ST_CONTINUE;
+ if (RTEST(rb_yield(rb_assoc_new(key, value))))
return ST_DELETE;
return ST_CONTINUE;
}
@@ -471,8 +499,8 @@ rb_hash_delete_if(hash)
}
static int
-clear_i(key, value)
- VALUE key, value;
+clear_i(key, value, dummy)
+ VALUE key, value, dummy;
{
return ST_DELETE;
}
@@ -482,7 +510,7 @@ rb_hash_clear(hash)
VALUE hash;
{
rb_hash_modify(hash);
- st_foreach(RHASH(hash)->tbl, clear_i);
+ st_foreach(RHASH(hash)->tbl, clear_i, 0);
return hash;
}
@@ -500,7 +528,7 @@ rb_hash_aset(hash, key, val)
st_insert(RHASH(hash)->tbl, key, val);
}
else {
- st_add_direct(RHASH(hash)->tbl, rb_str_dup_frozen(key), val);
+ st_add_direct(RHASH(hash)->tbl, rb_str_new4(key), val);
}
return val;
}
@@ -544,7 +572,7 @@ static int
each_value_i(key, value)
VALUE key, value;
{
- if (key == Qnil) return ST_CONTINUE;
+ if (value == Qnil) return ST_CONTINUE;
rb_yield(value);
return ST_CONTINUE;
}
@@ -561,7 +589,7 @@ static int
each_key_i(key, value)
VALUE key, value;
{
- if (key == Qnil) return ST_CONTINUE;
+ if (value == Qnil) return ST_CONTINUE;
rb_yield(key);
return ST_CONTINUE;
}
@@ -578,7 +606,7 @@ static int
each_pair_i(key, value)
VALUE key, value;
{
- if (key == Qnil) return ST_CONTINUE;
+ if (value == Qnil) return ST_CONTINUE;
rb_yield(rb_assoc_new(key, value));
return ST_CONTINUE;
}
@@ -595,7 +623,7 @@ static int
to_a_i(key, value, ary)
VALUE key, value, ary;
{
- if (key == Qnil) return ST_CONTINUE;
+ if (value == Qnil) return ST_CONTINUE;
rb_ary_push(ary, rb_assoc_new(key, value));
return ST_CONTINUE;
}
@@ -625,7 +653,7 @@ inspect_i(key, value, str)
{
VALUE str2;
- if (key == Qnil) return ST_CONTINUE;
+ if (value == Qnil) return ST_CONTINUE;
if (RSTRING(str)->len > 1) {
rb_str_cat(str, ", ", 2);
}
@@ -687,7 +715,7 @@ static int
keys_i(key, value, ary)
VALUE key, value, ary;
{
- if (key == Qnil) return ST_CONTINUE;
+ if (value == Qnil) return ST_CONTINUE;
rb_ary_push(ary, key);
return ST_CONTINUE;
}
@@ -708,7 +736,7 @@ static int
values_i(key, value, ary)
VALUE key, value, ary;
{
- if (key == Qnil) return ST_CONTINUE;
+ if (value == Qnil) return ST_CONTINUE;
rb_ary_push(ary, value);
return ST_CONTINUE;
}
@@ -740,7 +768,7 @@ static int
rb_hash_search_value(key, value, data)
VALUE key, value, *data;
{
- if (key == Qnil) return ST_CONTINUE;
+ if (value == Qnil) return ST_CONTINUE;
if (rb_equal(value, data[1])) {
data[0] = Qtrue;
return ST_STOP;
@@ -773,7 +801,7 @@ equal_i(key, val1, data)
{
VALUE val2;
- if (key == Qnil) return ST_CONTINUE;
+ if (val1 == Qnil) return ST_CONTINUE;
if (!st_lookup(data->tbl, key, &val2)) {
data->result = Qfalse;
return ST_STOP;
@@ -807,7 +835,7 @@ rb_hash_invert_i(key, value, hash)
VALUE key, value;
VALUE hash;
{
- if (key == Qnil) return ST_CONTINUE;
+ if (value == Qnil) return ST_CONTINUE;
rb_hash_aset(hash, value, key);
return ST_CONTINUE;
}
@@ -827,7 +855,7 @@ rb_hash_update_i(key, value, hash)
VALUE key, value;
VALUE hash;
{
- if (key == Qnil) return ST_CONTINUE;
+ if (value == Qnil) return ST_CONTINUE;
rb_hash_aset(hash, key, value);
return ST_CONTINUE;
}
@@ -841,7 +869,6 @@ rb_hash_update(hash1, hash2)
return hash1;
}
-#ifndef __MACOS__ /* no environment variables on MacOS. */
static int path_tainted = -1;
#ifndef NT
@@ -853,24 +880,20 @@ static VALUE
env_delete(obj, name)
VALUE obj, name;
{
- int i, len;
- char *nam, *val = 0;
+ int len;
+ char *nam, *val;
rb_secure(4);
- nam = STR2CSTR(name);
- if (strcmp(nam, "PATH") == 0) path_tainted = 0;
- len = strlen(nam);
- for(i=0; environ[i]; i++) {
- if (strncmp(environ[i], nam, len) == 0 && environ[i][len] == '=') {
- val = environ[i]+len+1;
- break;
- }
- }
- while (environ[i]) {
- environ[i] = environ[i+1];
- i++;
+ nam = str2cstr(name, &len);
+ if (strlen(nam) != len) {
+ rb_raise(rb_eArgError, "bad environment variable name");
}
+ val = getenv(nam);
if (val) {
+ ruby_setenv(nam, 0);
+ if (strcmp(nam, "PATH") == 0 && !OBJ_TAINTED(name)) {
+ path_tainted = 0;
+ }
return rb_str_new2(val);
}
return Qnil;
@@ -894,7 +917,7 @@ rb_f_getenv(obj, name)
nam = str2cstr(name, &len);
if (strlen(nam) != len) {
- rb_raise(rb_eArgError, "Bad environment variable name");
+ rb_raise(rb_eArgError, "bad environment variable name");
}
env = getenv(nam);
if (env) {
@@ -930,7 +953,7 @@ rb_path_check(path)
char *path;
{
char *p, *pend;
- const char sep = RUBY_PATH_SEP[0];
+ const char sep = PATH_SEP_CHAR;
if (!path) return 1;
@@ -988,12 +1011,12 @@ char *nam;
return i;
}
-static void
-my_setenv(name, value)
- char *name;
- char *value;
+void
+ruby_setenv(name, value)
+ const char *name;
+ const char *value;
{
-#ifdef WIN32
+#if defined(WIN32) && !defined(__CYGWIN32__)
#ifdef USE_WIN32_RTL_ENV
register char *envstr;
STRLEN namlen = strlen(name);
@@ -1049,9 +1072,16 @@ my_setenv(name, value)
SetEnvironmentVariable(name,value);
#endif
+#elif defined __CYGWIN__
+#undef setenv
+#undef unsetenv
+ if (value)
+ setenv(name,value,1);
+ else
+ unsetenv(name);
#else /* WIN32 */
- register int i=envix(name); /* where does it go? */
+ int i=envix(name); /* where does it go? */
if (environ == origenviron) { /* need we copy environment? */
int j;
@@ -1066,6 +1096,7 @@ my_setenv(name, value)
environ = tmpenv; /* tell exec where it is now */
}
if (!value) {
+ free(environ[i]);
while (environ[i]) {
environ[i] = environ[i+1];
i++;
@@ -1095,6 +1126,13 @@ my_setenv(name, value)
#endif /* WIN32 */
}
+void
+ruby_unsetenv(name)
+ const char *name;
+{
+ ruby_setenv(name, 0);
+}
+
static VALUE
rb_f_setenv(obj, nm, val)
VALUE obj, nm, val;
@@ -1112,13 +1150,13 @@ rb_f_setenv(obj, nm, val)
}
name = str2cstr(nm, &nlen);
- value = STR2CSTR(val &vlen);
+ value = str2cstr(val, &vlen);
if (strlen(name) != nlen)
- rb_raise(rb_eArgError, "Bad environment name");
+ rb_raise(rb_eArgError, "bad environment variable name");
if (strlen(value) != vlen)
- rb_raise(rb_eArgError, "Bad environment value");
+ rb_raise(rb_eArgError, "bad environment variable value");
- my_setenv(name, value);
+ ruby_setenv(name, value);
if (strcmp(name, "PATH") == 0) {
if (OBJ_TAINTED(val)) {
/* already tainted, no check */
@@ -1303,10 +1341,8 @@ env_has_value(dmy, value)
VALUE dmy, value;
{
char **env;
- volatile VALUE ary;
if (TYPE(value) != T_STRING) return Qfalse;
- ary = rb_ary_new();
env = environ;
while (*env) {
char *s = strchr(*env, '=')+1;
@@ -1320,6 +1356,26 @@ env_has_value(dmy, value)
}
static VALUE
+env_index(dmy, value)
+ VALUE dmy, value;
+{
+ char **env;
+
+ if (TYPE(value) != T_STRING) return Qnil;
+ env = environ;
+ while (*env) {
+ char *s = strchr(*env, '=')+1;
+ if (s) {
+ if (strncmp(s, RSTRING(value)->ptr, strlen(s)) == 0) {
+ return rb_tainted_str_new(*env, s-*env);
+ }
+ }
+ env++;
+ }
+ return Qnil;
+}
+
+static VALUE
env_indexes(argc, argv)
int argc;
VALUE *argv;
@@ -1363,8 +1419,6 @@ env_to_hash(obj)
return hash;
}
-#endif /* ifndef __MACOS__ no environment variables on MacOS. */
-
void
Init_Hash()
{
@@ -1396,6 +1450,7 @@ Init_Hash()
rb_define_method(rb_cHash,"store", rb_hash_aset, 2);
rb_define_method(rb_cHash,"default", rb_hash_default, 0);
rb_define_method(rb_cHash,"default=", rb_hash_set_default, 1);
+ rb_define_method(rb_cHash,"index", rb_hash_index, 1);
rb_define_method(rb_cHash,"indexes", rb_hash_indexes, -1);
rb_define_method(rb_cHash,"indices", rb_hash_indexes, -1);
rb_define_method(rb_cHash,"length", rb_hash_length, 0);
@@ -1414,12 +1469,14 @@ Init_Hash()
rb_define_method(rb_cHash,"shift", rb_hash_shift, 0);
rb_define_method(rb_cHash,"delete", rb_hash_delete, 1);
rb_define_method(rb_cHash,"delete_if", rb_hash_delete_if, 0);
+ rb_define_method(rb_cHash,"reject!", rb_hash_delete_if, 0);
rb_define_method(rb_cHash,"clear", rb_hash_clear, 0);
rb_define_method(rb_cHash,"invert", rb_hash_invert, 0);
rb_define_method(rb_cHash,"update", rb_hash_update, 1);
rb_define_method(rb_cHash,"replace", rb_hash_replace, 1);
rb_define_method(rb_cHash,"include?", rb_hash_has_key, 1);
+ rb_define_method(rb_cHash,"member?", rb_hash_has_key, 1);
rb_define_method(rb_cHash,"has_key?", rb_hash_has_key, 1);
rb_define_method(rb_cHash,"has_value?", rb_hash_has_value, 1);
rb_define_method(rb_cHash,"key?", rb_hash_has_key, 1);
@@ -1438,9 +1495,11 @@ Init_Hash()
rb_define_singleton_method(envtbl,"each_value", env_each_value, 0);
rb_define_singleton_method(envtbl,"delete", env_delete_method, 1);
rb_define_singleton_method(envtbl,"delete_if", env_delete_if, 0);
+ rb_define_singleton_method(envtbl,"reject!", env_delete_if, 0);
rb_define_singleton_method(envtbl,"to_s", env_to_s, 0);
rb_define_singleton_method(envtbl,"rehash", env_none, 0);
rb_define_singleton_method(envtbl,"to_a", env_to_a, 0);
+ rb_define_singleton_method(envtbl,"index", env_index, 1);
rb_define_singleton_method(envtbl,"indexes", env_indexes, -1);
rb_define_singleton_method(envtbl,"indices", env_indexes, -1);
rb_define_singleton_method(envtbl,"length", env_size, 0);
@@ -1448,6 +1507,7 @@ Init_Hash()
rb_define_singleton_method(envtbl,"keys", env_keys, 0);
rb_define_singleton_method(envtbl,"values", env_values, 0);
rb_define_singleton_method(envtbl,"include?", env_has_key, 1);
+ rb_define_singleton_method(envtbl,"member?", env_has_key, 1);
rb_define_singleton_method(envtbl,"has_key?", env_has_key, 1);
rb_define_singleton_method(envtbl,"has_value?", env_has_value, 1);
rb_define_singleton_method(envtbl,"key?", env_has_key, 1);
diff --git a/inits.c b/inits.c
index 3708edc03a..fdc49f0f4b 100644
--- a/inits.c
+++ b/inits.c
@@ -6,7 +6,7 @@
$Date$
created at: Tue Dec 28 16:01:58 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -31,6 +31,7 @@ void Init_marshal _((void));
void Init_Numeric _((void));
void Init_Object _((void));
void Init_pack _((void));
+void Init_Precision _((void));
void Init_sym _((void));
void Init_process _((void));
void Init_Random _((void));
@@ -51,12 +52,11 @@ rb_call_inits()
Init_Object();
Init_Comparable();
Init_Enumerable();
+ Init_Precision();
Init_eval();
Init_String();
Init_Exception();
-#ifdef USE_THREAD
Init_Thread();
-#endif
Init_Numeric();
Init_Bignum();
Init_Array();
diff --git a/install-sh b/install-sh
index 89fc9b098b..e69de29bb2 100644
--- a/install-sh
+++ b/install-sh
@@ -1,238 +0,0 @@
-#! /bin/sh
-#
-# install - install a program, script, or datafile
-# This comes from X11R5.
-#
-# Calling this script install-sh is preferred over install.sh, to prevent
-# `make' implicit rules from creating a file called install from it
-# when there is no Makefile.
-#
-# This script is compatible with the BSD install script, but was written
-# from scratch.
-#
-
-
-# set DOITPROG to echo to test this script
-
-# Don't use :- since 4.3BSD and earlier shells don't like it.
-doit="${DOITPROG-}"
-
-
-# put in absolute paths if you don't have them in your path; or use env. vars.
-
-mvprog="${MVPROG-mv}"
-cpprog="${CPPROG-cp}"
-chmodprog="${CHMODPROG-chmod}"
-chownprog="${CHOWNPROG-chown}"
-chgrpprog="${CHGRPPROG-chgrp}"
-stripprog="${STRIPPROG-strip}"
-rmprog="${RMPROG-rm}"
-mkdirprog="${MKDIRPROG-mkdir}"
-
-tranformbasename=""
-transform_arg=""
-instcmd="$mvprog"
-chmodcmd="$chmodprog 0755"
-chowncmd=""
-chgrpcmd=""
-stripcmd=""
-rmcmd="$rmprog -f"
-mvcmd="$mvprog"
-src=""
-dst=""
-dir_arg=""
-
-while [ x"$1" != x ]; do
- case $1 in
- -c) instcmd="$cpprog"
- shift
- continue;;
-
- -d) dir_arg=true
- shift
- continue;;
-
- -m) chmodcmd="$chmodprog $2"
- shift
- shift
- continue;;
-
- -o) chowncmd="$chownprog $2"
- shift
- shift
- continue;;
-
- -g) chgrpcmd="$chgrpprog $2"
- shift
- shift
- continue;;
-
- -s) stripcmd="$stripprog"
- shift
- continue;;
-
- -t=*) transformarg=`echo $1 | sed 's/-t=//'`
- shift
- continue;;
-
- -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
- shift
- continue;;
-
- *) if [ x"$src" = x ]
- then
- src=$1
- else
- # this colon is to work around a 386BSD /bin/sh bug
- :
- dst=$1
- fi
- shift
- continue;;
- esac
-done
-
-if [ x"$src" = x ]
-then
- echo "install: no input file specified"
- exit 1
-else
- true
-fi
-
-if [ x"$dir_arg" != x ]; then
- dst=$src
- src=""
-
- if [ -d $dst ]; then
- instcmd=:
- else
- instcmd=mkdir
- fi
-else
-
-# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
-# might cause directories to be created, which would be especially bad
-# if $src (and thus $dsttmp) contains '*'.
-
- if [ -f $src -o -d $src ]
- then
- true
- else
- echo "install: $src does not exist"
- exit 1
- fi
-
- if [ x"$dst" = x ]
- then
- echo "install: no destination specified"
- exit 1
- else
- true
- fi
-
-# If destination is a directory, append the input filename; if your system
-# does not like double slashes in filenames, you may need to add some logic
-
- if [ -d $dst ]
- then
- dst="$dst"/`basename $src`
- else
- true
- fi
-fi
-
-## this sed command emulates the dirname command
-dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
-
-# Make sure that the destination directory exists.
-# this part is taken from Noah Friedman's mkinstalldirs script
-
-# Skip lots of stat calls in the usual case.
-if [ ! -d "$dstdir" ]; then
-defaultIFS='
-'
-IFS="${IFS-${defaultIFS}}"
-
-oIFS="${IFS}"
-# Some sh's can't handle IFS=/ for some reason.
-IFS='%'
-set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
-IFS="${oIFS}"
-
-pathcomp=''
-
-while [ $# -ne 0 ] ; do
- pathcomp="${pathcomp}${1}"
- shift
-
- if [ ! -d "${pathcomp}" ] ;
- then
- $mkdirprog "${pathcomp}"
- else
- true
- fi
-
- pathcomp="${pathcomp}/"
-done
-fi
-
-if [ x"$dir_arg" != x ]
-then
- $doit $instcmd $dst &&
-
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
-else
-
-# If we're going to rename the final executable, determine the name now.
-
- if [ x"$transformarg" = x ]
- then
- dstfile=`basename $dst`
- else
- dstfile=`basename $dst $transformbasename |
- sed $transformarg`$transformbasename
- fi
-
-# don't allow the sed command to completely eliminate the filename
-
- if [ x"$dstfile" = x ]
- then
- dstfile=`basename $dst`
- else
- true
- fi
-
-# Make a temp file name in the proper directory.
-
- dsttmp=$dstdir/#inst.$$#
-
-# Move or copy the file name to the temp name
-
- $doit $instcmd $src $dsttmp &&
-
- trap "rm -f ${dsttmp}" 0 &&
-
-# and set any options; do chmod last to preserve setuid bits
-
-# If any of these fail, we abort the whole thing. If we want to
-# ignore errors from any of these, just make sure not to ignore
-# errors from the above "$doit $instcmd $src $dsttmp" command.
-
- if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
- if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
- if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
- if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
-
-# Now rename the file to the real destination.
-
- $doit $rmcmd -f $dstdir/$dstfile &&
- $doit $mvcmd $dsttmp $dstdir/$dstfile
-
-fi &&
-
-
-exit 0
diff --git a/instruby.rb b/instruby.rb
index d489e0f838..52c7c2397f 100644
--- a/instruby.rb
+++ b/instruby.rb
@@ -7,51 +7,85 @@ destdir = ARGV[0] || ''
$:.unshift CONFIG["srcdir"]+"/lib"
require "ftools"
+require "find"
-binsuffix = CONFIG["binsuffix"]
+exeext = CONFIG["EXEEXT"]
if ENV["prefix"]
prefix = ENV["prefix"]
else
prefix = CONFIG["prefix"]
end
ruby_install_name = CONFIG["ruby_install_name"]
-bindir = CONFIG["bindir"]
-libdir = CONFIG["libdir"]
-pkglibdir = libdir + "/" + ruby_install_name
+bindir = destdir+CONFIG["bindir"]
+libdir = destdir+CONFIG["libdir"]
+#pkglibdir = libdir + "/" + ruby_install_name+"/"+CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
+pkglibdir = libdir + "/ruby/"+CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
archdir = pkglibdir + "/" + CONFIG["arch"]
-mandir = CONFIG["mandir"] + "/man1"
+mandir = destdir+CONFIG["mandir"] + "/man1"
wdir = Dir.getwd
-File.makedirs "#{destdir}#{bindir}", true
-File.install "ruby#{binsuffix}",
- "#{destdir}#{bindir}/#{ruby_install_name}#{binsuffix}", 0755, true
+File.makedirs bindir, true
+File.install ruby_install_name+exeext,
+ "#{bindir}/#{ruby_install_name}#{exeext}", 0755, true
for dll in Dir['*.dll']
- File.install dll, "#{destdir}#{bindir}/#{dll}", 0755, true
+ File.install dll, "#{bindir}/#{dll}", 0755, true
end
-File.makedirs "#{destdir}#{libdir}", true
-for lib in ["libruby.so", "libruby.so.LIB"]
+File.makedirs libdir, true
+for lib in ["libruby.so.LIB", CONFIG["LIBRUBY_SO"]]
if File.exist? lib
- File.install lib, "#{destdir}#{libdir}", 0644, true
+ File.install lib, libdir, 0555, true
end
end
-File.makedirs "#{destdir}#{pkglibdir}", true
-File.makedirs "#{destdir}#{archdir}", true
+Dir.chdir libdir
+if File.exist? CONFIG["LIBRUBY_SO"]
+ for link in CONFIG["LIBRUBY_ALIASES"].split
+ if File.exist? link
+ File.delete link
+ end
+ File.symlink CONFIG["LIBRUBY_SO"], link
+ print "link #{CONFIG['LIBRUBY_SO']} -> #{link}\n"
+ end
+end
+Dir.chdir wdir
+File.makedirs pkglibdir, true
+File.makedirs archdir, true
+File.makedirs pkglibdir+"/site_ruby", true
+File.makedirs pkglibdir+"/site_ruby/"+CONFIG["arch"], true
+
+if RUBY_PLATFORM =~ /cygwin/ and File.exist? "import.h"
+ File.install "import.h", archdir, 0644, true
+end
+
+if RUBY_PLATFORM =~ /-aix/
+ File.install "ruby.imp", archdir, 0644, true
+end
+
Dir.chdir "ext"
-system "../miniruby#{binsuffix} extmk.rb install #{destdir}"
+system "../miniruby#{exeext} extmk.rb install #{destdir}"
Dir.chdir CONFIG["srcdir"]
-for f in Dir["lib/*.rb"]
- File.install f, "#{destdir}#{pkglibdir}", 0644, true
+
+Find.find("lib") do |f|
+ next unless /\.rb$/ =~ f
+ dir = pkglibdir+"/"+File.dirname(f[4..-1])
+ File.makedirs dir, true unless File.directory? dir
+ File.install f, dir, 0644, true
end
-File.makedirs(archdir,true)
for f in Dir["*.h"]
- File.install f, "#{destdir}#{archdir}", 0644, true
+ File.install f, archdir, 0644, true
+end
+if RUBY_PLATFORM =~ /mswin32/
+ File.makedirs archdir + "/win32", true
+ File.install "win32/win32.h", archdir + "/win32", 0644, true
+ if File.exist? wdir+'/rubymw.lib'
+ File.install wdir+'/rubymw.lib', archdir, 0644, true
+ end
end
-File.install "libruby.a", "#{destdir}#{archdir}", 0644, true
+File.install wdir+'/'+CONFIG['LIBRUBY_A'], archdir, 0644, true
-File.makedirs "#{destdir}#{mandir}", true
-File.install "ruby.1", "#{destdir}#{mandir}", 0644, true
+File.makedirs mandir, true
+File.install "ruby.1", mandir, 0644, true
Dir.chdir wdir
-File.install "config.h", "#{destdir}#{archdir}", 0644, true
-File.install "rbconfig.rb", "#{destdir}#{archdir}", 0644, true
+File.install "config.h", archdir, 0644, true
+File.install "rbconfig.rb", archdir, 0644, true
# vi:set sw=2:
diff --git a/intern.h b/intern.h
index 8b88751469..4bfefa2fd1 100644
--- a/intern.h
+++ b/intern.h
@@ -6,18 +6,18 @@
void rb_mem_clear _((register VALUE*, register size_t));
VALUE rb_assoc_new _((VALUE, VALUE));
VALUE rb_ary_new _((void));
-VALUE rb_ary_new2 _((size_t));
-VALUE rb_ary_new3 __((size_t,...));
-VALUE rb_ary_new4 _((size_t, VALUE *));
+VALUE rb_ary_new2 _((long));
+VALUE rb_ary_new3 __((long,...));
+VALUE rb_ary_new4 _((long, VALUE *));
VALUE rb_ary_freeze _((VALUE));
VALUE rb_ary_aref _((int, VALUE*, VALUE));
-void rb_ary_store _((VALUE, size_t, VALUE));
+void rb_ary_store _((VALUE, long, VALUE));
VALUE rb_ary_to_s _((VALUE));
VALUE rb_ary_push _((VALUE, VALUE));
VALUE rb_ary_pop _((VALUE));
VALUE rb_ary_shift _((VALUE));
VALUE rb_ary_unshift _((VALUE, VALUE));
-VALUE rb_ary_entry _((VALUE, size_t));
+VALUE rb_ary_entry _((VALUE, long));
VALUE rb_ary_each _((VALUE));
VALUE rb_ary_join _((VALUE, VALUE));
VALUE rb_ary_print_on _((VALUE, VALUE));
@@ -41,7 +41,7 @@ VALUE rb_uint2big _((unsigned long));
VALUE rb_int2big _((long));
VALUE rb_uint2inum _((unsigned long));
VALUE rb_int2inum _((long));
-VALUE rb_str2inum _((char*, int));
+VALUE rb_str2inum _((const char*, int));
VALUE rb_big2str _((VALUE, int));
long rb_big2long _((VALUE));
#define rb_big2int(x) rb_big2long(x)
@@ -73,28 +73,28 @@ VALUE rb_class_protected_instance_methods _((int, VALUE*, VALUE));
VALUE rb_class_private_instance_methods _((int, VALUE*, VALUE));
VALUE rb_obj_singleton_methods _((VALUE));
void rb_define_method_id _((VALUE, ID, VALUE (*)(), int));
-void rb_undef_method _((VALUE, char*));
-void rb_define_protected_method _((VALUE, char*, VALUE (*)(), int));
-void rb_define_private_method _((VALUE, char*, VALUE (*)(), int));
-void rb_define_singleton_method _((VALUE,char*,VALUE(*)(),int));
-void rb_define_private_method _((VALUE,char*,VALUE(*)(),int));
+void rb_undef_method _((VALUE, const char*));
+void rb_define_protected_method _((VALUE, const char*, VALUE (*)(), int));
+void rb_define_private_method _((VALUE, const char*, VALUE (*)(), int));
+void rb_define_singleton_method _((VALUE,const char*,VALUE(*)(),int));
+void rb_define_private_method _((VALUE,const char*,VALUE(*)(),int));
VALUE rb_singleton_class _((VALUE));
/* enum.c */
VALUE rb_enum_length _((VALUE));
/* error.c */
extern int ruby_nerrs;
-VALUE rb_exc_new _((VALUE, char*, int));
-VALUE rb_exc_new2 _((VALUE, char*));
+VALUE rb_exc_new _((VALUE, const char*, long));
+VALUE rb_exc_new2 _((VALUE, const char*));
VALUE rb_exc_new3 _((VALUE, VALUE));
-void rb_loaderror __((char*, ...)) NORETURN;
-void rb_compile_error __((char*, ...));
-void rb_compile_error_append __((char*, ...));
+void rb_loaderror __((const char*, ...)) NORETURN;
+void rb_compile_error __((const char*, ...));
+void rb_compile_error_append __((const char*, ...));
/* eval.c */
void rb_exc_raise _((VALUE)) NORETURN;
void rb_exc_fatal _((VALUE)) NORETURN;
-void rb_remove_method _((VALUE, char*));
-void rb_disable_super _((VALUE, char*));
-void rb_enable_super _((VALUE, char*));
+void rb_remove_method _((VALUE, const char*));
+void rb_disable_super _((VALUE, const char*));
+void rb_enable_super _((VALUE, const char*));
void rb_clear_cache _((void));
void rb_alias _((VALUE, ID, ID));
void rb_attr _((VALUE,ID,int,int,int));
@@ -104,37 +104,41 @@ VALUE rb_dvar_ref _((ID));
void rb_dvar_asgn _((ID, VALUE));
void rb_dvar_push _((ID, VALUE));
VALUE rb_eval_cmd _((VALUE, VALUE));
-VALUE rb_trap_eval _((VALUE, int));
int rb_respond_to _((VALUE, ID));
void rb_interrupt _((void));
VALUE rb_apply _((VALUE, ID, VALUE));
-VALUE rb_funcall2 _((VALUE, ID, int, VALUE*));
void rb_backtrace _((void));
ID rb_frame_last_func _((void));
VALUE rb_obj_instance_eval _((int, VALUE*, VALUE));
void rb_load _((VALUE, int));
void rb_load_protect _((VALUE, int, int*));
void rb_jump_tag _((int)) NORETURN;
-void rb_provide _((char*));
+void rb_provide _((const char*));
VALUE rb_f_require _((VALUE, VALUE));
-void rb_obj_call_init _((VALUE));
+void rb_obj_call_init _((VALUE, int, VALUE*));
VALUE rb_class_new_instance _((int, VALUE*, VALUE));
VALUE rb_f_lambda _((void));
VALUE rb_protect _((VALUE (*)(), VALUE, int*));
void rb_set_end_proc _((void (*)(), VALUE));
+void rb_exec_end_proc _((void));
void rb_gc_mark_threads _((void));
void rb_thread_start_timer _((void));
void rb_thread_stop_timer _((void));
void rb_thread_schedule _((void));
void rb_thread_wait_fd _((int));
-void rb_thread_fd_writable _((int));
+int rb_thread_fd_writable _((int));
+void rb_thread_fd_close _((int));
int rb_thread_alone _((void));
void rb_thread_sleep _((int));
void rb_thread_sleep_forever _((void));
+VALUE rb_thread_stop _((void));
+VALUE rb_thread_wakeup _((VALUE));
+VALUE rb_thread_run _((VALUE));
VALUE rb_thread_create _((VALUE (*)(), void*));
int rb_thread_scope_shared_p _((void));
void rb_thread_interrupt _((void));
void rb_thread_trap_eval _((VALUE, int));
+void rb_thread_signal_raise _((char*));
int rb_thread_select();
void rb_thread_wait_for();
VALUE rb_thread_current _((void));
@@ -142,9 +146,9 @@ VALUE rb_thread_main _((void));
VALUE rb_thread_local_aref _((VALUE, ID));
VALUE rb_thread_local_aset _((VALUE, ID, VALUE));
/* file.c */
-VALUE rb_file_open _((char*, char*));
-int eaccess _((char*, int));
+int eaccess _((const char*, int));
VALUE rb_file_s_expand_path _((int, VALUE *));
+void rb_file_const _((const char*, VALUE));
/* gc.c */
void rb_global_variable _((VALUE*));
void rb_gc_mark_locations _((VALUE*, VALUE*));
@@ -176,8 +180,7 @@ VALUE rb_io_ungetc _((VALUE, VALUE));
VALUE rb_io_close _((VALUE));
VALUE rb_io_eof _((VALUE));
VALUE rb_io_binmode _((VALUE));
-int rb_io_mode_flags _((char*));
-VALUE rb_io_reopen _((VALUE, VALUE));
+VALUE rb_file_open _((const char*, const char*));
VALUE rb_gets _((void));
void rb_str_setter _((VALUE, ID, VALUE*));
/* numeric.c */
@@ -199,7 +202,7 @@ VALUE rb_obj_taint _((VALUE));
VALUE rb_obj_tainted _((VALUE));
VALUE rb_obj_untaint _((VALUE));
VALUE rb_obj_id _((VALUE));
-VALUE rb_convert_type _((VALUE,int,char*,char*));
+VALUE rb_convert_type _((VALUE,int,const char*,const char*));
VALUE rb_Integer _((VALUE));
VALUE rb_Float _((VALUE));
VALUE rb_String _((VALUE));
@@ -218,11 +221,11 @@ void rb_backref_set _((VALUE));
VALUE rb_lastline_get _((void));
void rb_lastline_set _((VALUE));
/* process.c */
-int rb_proc_exec _((char*));
+int rb_proc_exec _((const char*));
void rb_syswait _((int));
/* range.c */
-VALUE rb_range_new _((VALUE, VALUE));
-VALUE rb_range_beg_end _((VALUE, int*, int*));
+VALUE rb_range_new _((VALUE, VALUE, int));
+VALUE rb_range_beg_len _((VALUE, long*, long*, long, int));
/* re.c */
VALUE rb_reg_nth_defined _((int, VALUE));
VALUE rb_reg_nth_match _((int, VALUE));
@@ -230,20 +233,23 @@ VALUE rb_reg_last_match _((VALUE));
VALUE rb_reg_match_pre _((VALUE));
VALUE rb_reg_match_post _((VALUE));
VALUE rb_reg_match_last _((VALUE));
-VALUE rb_reg_new _((char*, size_t, int));
+VALUE rb_reg_new _((const char*, long, int));
VALUE rb_reg_match _((VALUE, VALUE));
VALUE rb_reg_match2 _((VALUE));
int rb_reg_options _((VALUE));
-char*rb_get_kcode _((void));
-void rb_set_kcode _((char*));
+const char* rb_get_kcode _((void));
+void rb_set_kcode _((const char*));
int rb_ignorecase_p _((void));
+void rb_match_busy _((VALUE, int));
/* ruby.c */
+EXTERN VALUE rb_argv;
+EXTERN VALUE rb_argv0;
void rb_load_file _((char*));
void ruby_script _((char*));
void ruby_prog_init _((void));
void ruby_set_argv _((int, char**));
void ruby_process_options _((int, char**));
-void ruby_require_modules _((void));
+void ruby_require_libraries _((void));
void ruby_load_script _((void));
/* signal.c */
VALUE rb_f_kill _((int, VALUE*));
@@ -257,52 +263,52 @@ void rb_trap_exec _((void));
/* sprintf.c */
VALUE rb_f_sprintf _((int, VALUE*));
/* string.c */
-VALUE rb_str_new _((char*, size_t));
-VALUE rb_str_new2 _((char*));
+VALUE rb_str_new _((const char*, long));
+VALUE rb_str_new2 _((const char*));
VALUE rb_str_new3 _((VALUE));
VALUE rb_str_new4 _((VALUE));
-VALUE rb_tainted_str_new _((char*, size_t));
-VALUE rb_tainted_str_new2 _((char*));
+VALUE rb_tainted_str_new _((const char*, long));
+VALUE rb_tainted_str_new2 _((const char*));
VALUE rb_obj_as_string _((VALUE));
VALUE rb_str_to_str _((VALUE));
VALUE rb_str_dup _((VALUE));
VALUE rb_str_plus _((VALUE, VALUE));
VALUE rb_str_times _((VALUE, VALUE));
-VALUE rb_str_substr _((VALUE, size_t, size_t));
+VALUE rb_str_substr _((VALUE, long, long));
void rb_str_modify _((VALUE));
VALUE rb_str_freeze _((VALUE));
-VALUE rb_str_dup_frozen _((VALUE));
-VALUE rb_str_resize _((VALUE, size_t));
-VALUE rb_str_cat _((VALUE, char*, size_t));
+VALUE rb_str_resize _((VALUE, long));
+VALUE rb_str_cat _((VALUE, const char*, long));
VALUE rb_str_concat _((VALUE, VALUE));
int rb_str_hash _((VALUE));
int rb_str_cmp _((VALUE, VALUE));
-VALUE rb_str_upto _((VALUE, VALUE));
+VALUE rb_str_upto _((VALUE, VALUE, int));
VALUE rb_str_inspect _((VALUE));
-VALUE rb_str_split _((VALUE, char*));
+VALUE rb_str_split _((VALUE, const char*));
/* struct.c */
VALUE rb_struct_new __((VALUE, ...));
-VALUE rb_struct_define __((char*, ...));
+VALUE rb_struct_define __((const char*, ...));
VALUE rb_struct_alloc _((VALUE, VALUE));
VALUE rb_struct_aref _((VALUE, VALUE));
VALUE rb_struct_aset _((VALUE, VALUE, VALUE));
VALUE rb_struct_getmember _((VALUE, ID));
/* time.c */
-VALUE rb_time_new _((int, int));
+VALUE rb_time_new();
/* variable.c */
VALUE rb_mod_name _((VALUE));
VALUE rb_class_path _((VALUE));
-void rb_set_class_path _((VALUE, VALUE, char*));
-VALUE rb_path2class _((char*));
+void rb_set_class_path _((VALUE, VALUE, const char*));
+VALUE rb_path2class _((const char*));
void rb_name_class _((VALUE, ID));
-void rb_autoload _((char*, char*));
+void rb_autoload _((const char*, const char*));
VALUE rb_f_autoload _((VALUE, VALUE, VALUE));
void rb_gc_mark_global_tbl _((void));
VALUE rb_f_trace_var _((int, VALUE*));
VALUE rb_f_untrace_var _((int, VALUE*));
-VALUE rb_gvar_set2 _((char*, VALUE));
+VALUE rb_gvar_set2 _((const char*, VALUE));
VALUE rb_f_global_variables _((void));
void rb_alias_variable _((ID, ID));
+void rb_clone_generic_ivar _((VALUE,VALUE));
void rb_mark_generic_ivar _((VALUE));
void rb_mark_generic_ivar_tbl _((void));
void rb_free_generic_ivar _((VALUE));
diff --git a/io.c b/io.c
index 5573e76a64..fb1e0d894b 100644
--- a/io.c
+++ b/io.c
@@ -6,13 +6,14 @@
$Date$
created at: Fri Oct 15 18:08:59 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include "rubyio.h"
#include "rubysig.h"
+#include "env.h"
#include <ctype.h>
#include <errno.h>
@@ -20,8 +21,10 @@
#if !defined(DJGPP) && !defined(NT) && !defined(__human68k__)
#include <sys/ioctl.h>
#endif
-#if defined(HAVE_FCNTL)
+#if defined(HAVE_FCNTL_H) || defined(NT)
#include <fcntl.h>
+#elif defined(HAVE_SYS_FCNTL_H)
+#include <sys/fcntl.h>
#endif
#ifdef HAVE_SYS_TIME_H
@@ -40,7 +43,8 @@ struct timeval {
#include <sys/stat.h>
-#ifdef HAVE_SYS_PARAM_H
+/* EMX has sys/parm.h, but.. */
+#if defined(HAVE_SYS_PARAM_H) && !defined(__EMX__)
# include <sys/param.h>
#else
# define NOFILE 64
@@ -55,9 +59,17 @@ struct timeval {
#include <unix.mac.h>
#include <compat.h>
#endif
+
+#ifndef strdup
+char *strdup();
+#endif
+
extern void Init_File _((void));
#ifdef __BEOS__
+# ifdef _X86_
+# define NOFILE (OPEN_MAX)
+# endif
#include <net/socket.h>
#endif
@@ -68,6 +80,7 @@ VALUE rb_eEOFError;
VALUE rb_eIOError;
VALUE rb_stdin, rb_stdout, rb_stderr, rb_defout;
+static VALUE orig_stdin, orig_stdout, orig_stderr;
VALUE rb_fs;
VALUE rb_output_fs;
@@ -81,9 +94,9 @@ static ID id_write;
extern char *ruby_inplace_mode;
-struct timeval rb_time_timeval _((VALUE));
+struct timeval rb_time_interval _((VALUE));
-static VALUE filename, file;
+static VALUE filename, current_file;
static int gets_lineno;
static int init_p = 0, next_p = 0;
static VALUE lineno;
@@ -99,20 +112,19 @@ static VALUE lineno;
#elif defined(__BEOS__)
# define ReadDataPending(fp) (fp->_state._eof == 0)
#elif defined(USE_CWGUSI)
-# define ReadDataPending(fp) (fp->state.eof == 0)
+# define READ_DATA_PENDING(fp) (fp->state.eof == 0)
#else
/* requires systems own version of the ReadDataPending() */
extern int ReadDataPending();
# define READ_DATA_PENDING(fp) ReadDataPending(fp)
#endif
-#ifndef USE_THREAD
-# define READ_CHECK(fp) 0
-#else
-# define READ_CHECK(fp) do {\
- if (!READ_DATA_PENDING(fp)) rb_thread_wait_fd(fileno(fp));\
+#define READ_CHECK(fp) do {\
+ if (!READ_DATA_PENDING(fp)) {\
+ rb_thread_wait_fd(fileno(fp));\
+ rb_io_check_closed(fptr);\
+ }\
} while(0)
-#endif
void
rb_eof_error()
@@ -124,6 +136,9 @@ void
rb_io_check_closed(fptr)
OpenFile *fptr;
{
+ if (!fptr) {
+ rb_raise(rb_eIOError, "uninitialized stream");
+ }
if (fptr->f == NULL && fptr->f2 == NULL)
rb_raise(rb_eIOError, "closed stream");
}
@@ -146,9 +161,18 @@ rb_io_check_writable(fptr)
}
}
+void
+rb_read_check(fp)
+ FILE *fp;
+{
+ if (!READ_DATA_PENDING(fp)) {
+ rb_thread_wait_fd(fileno(fp));
+ }
+}
+
/* writing functions */
-VALUE
-rb_io_write(io, str)
+static VALUE
+io_write(io, str)
VALUE io, str;
{
OpenFile *fptr;
@@ -182,7 +206,7 @@ rb_io_write(io, str)
rb_sys_fail(fptr->path);
#else
n = fwrite(RSTRING(str)->ptr, 1, RSTRING(str)->len, f);
- if (n == 0 || ferror(f)) {
+ if (ferror(f)) {
rb_sys_fail(fptr->path);
}
#endif
@@ -193,6 +217,13 @@ rb_io_write(io, str)
return INT2FIX(n);
}
+VALUE
+rb_io_write(io, str)
+ VALUE io, str;
+{
+ return rb_funcall(io, id_write, 1, str);
+}
+
static VALUE
rb_io_addstr(io, str)
VALUE io, str;
@@ -226,7 +257,7 @@ rb_io_tell(io)
GetOpenFile(io, fptr);
pos = ftell(fptr->f);
- if (ferror(fptr->f) != 0) rb_sys_fail(fptr->path);
+ if (ferror(fptr->f)) rb_sys_fail(fptr->path);
return rb_int2inum(pos);
}
@@ -290,11 +321,8 @@ rb_io_eof(io)
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
- if (READ_DATA_PENDING(fptr->f)) return Qfalse;
-#if 0
if (feof(fptr->f)) return Qtrue;
- return Qfalse;
-#else
+ if (READ_DATA_PENDING(fptr->f)) return Qfalse;
READ_CHECK(fptr->f);
TRAP_BEG;
ch = getc(fptr->f);
@@ -305,7 +333,6 @@ rb_io_eof(io)
return Qfalse;
}
return Qtrue;
-#endif
}
static VALUE
@@ -375,13 +402,17 @@ read_all(port)
GetOpenFile(port, fptr);
rb_io_check_readable(fptr);
+ if (feof(fptr->f)) return Qnil;
if (fstat(fileno(fptr->f), &st) == 0 && S_ISREG(st.st_mode)
#ifdef __BEOS__
&& (st.st_dev > 3)
#endif
)
{
- if (st.st_size == 0) return rb_str_new(0, 0);
+ if (st.st_size == 0) {
+ getc(fptr->f); /* force EOF */
+ return rb_str_new(0, 0);
+ }
else {
long pos = ftell(fptr->f);
if (st.st_size > pos && pos >= 0) {
@@ -395,9 +426,9 @@ read_all(port)
TRAP_BEG;
n = fread(RSTRING(str)->ptr+bytes, 1, siz-bytes, fptr->f);
TRAP_END;
- if (n <= 0) {
- if (ferror(fptr->f)) rb_sys_fail(fptr->path);
- return rb_str_new(0,0);
+ if (n == 0) {
+ if (feof(fptr->f)) return Qnil;
+ rb_sys_fail(fptr->path);
}
bytes += n;
if (bytes < siz) break;
@@ -412,7 +443,7 @@ read_all(port)
}
static VALUE
-rb_io_read(argc, argv, io)
+io_read(argc, argv, io)
int argc;
VALUE *argv;
VALUE io;
@@ -430,15 +461,16 @@ rb_io_read(argc, argv, io)
GetOpenFile(io, fptr);
rb_io_check_readable(fptr);
+ if (feof(fptr->f)) return Qnil;
str = rb_str_new(0, len);
READ_CHECK(fptr->f);
TRAP_BEG;
n = fread(RSTRING(str)->ptr, 1, len, fptr->f);
TRAP_END;
- if (n <= 0) {
- if (ferror(fptr->f)) rb_sys_fail(fptr->path);
- return Qnil;
+ if (n == 0) {
+ if (feof(fptr->f)) return Qnil;
+ rb_sys_fail(fptr->path);
}
RSTRING(str)->len = n;
RSTRING(str)->ptr[n] = '\0';
@@ -522,7 +554,7 @@ rb_io_gets_internal(argc, argv, io)
c = getc(f);
TRAP_END;
if (c == EOF) {
- if (errno == EINTR) continue;
+ if (ferror(f) && errno == EINTR) continue;
break;
}
if ((*bp++ = c) == newline) break;
@@ -611,7 +643,7 @@ rb_io_gets(io)
c = getc(f);
TRAP_END;
if (c == EOF) {
- if (errno == EINTR) continue;
+ if (ferror(f) && errno == EINTR) continue;
break;
}
if ((*bp++ = c) == '\n') break;
@@ -691,6 +723,21 @@ lineno_setter(val, id, var)
}
static VALUE
+argf_set_lineno(argf, val)
+ VALUE argf, val;
+{
+ gets_lineno = NUM2INT(val);
+ lineno = INT2FIX(gets_lineno);
+ return Qnil;
+}
+
+static VALUE
+argf_lineno()
+{
+ return lineno;
+}
+
+static VALUE
rb_io_readline(argc, argv, io)
int argc;
VALUE *argv;
@@ -730,7 +777,7 @@ rb_io_each_line(argc, argv, io)
while (!NIL_P(str = rb_io_gets_internal(argc, argv, io))) {
rb_yield(str);
}
- return Qnil;
+ return io;
}
static VALUE
@@ -753,7 +800,7 @@ rb_io_each_byte(io)
if (c == EOF) break;
rb_yield(INT2FIX(c & 0xff));
}
- if (ferror(f) != 0) rb_sys_fail(fptr->path);
+ if (ferror(f)) rb_sys_fail(fptr->path);
return Qnil;
}
@@ -775,12 +822,28 @@ rb_io_getc(io)
TRAP_END;
if (c == EOF) {
- if (ferror(f) != 0) rb_sys_fail(fptr->path);
+ if (ferror(f)) rb_sys_fail(fptr->path);
return Qnil;
}
return INT2FIX(c & 0xff);
}
+int
+rb_getc(f)
+ FILE *f;
+{
+ int c;
+
+ if (!READ_DATA_PENDING(f)) {
+ rb_thread_wait_fd(fileno(f));
+ }
+ TRAP_BEG;
+ c = getc(f);
+ TRAP_END;
+
+ return c;
+}
+
static VALUE
rb_io_readchar(io)
VALUE io;
@@ -830,18 +893,17 @@ fptr_finalize(fptr)
if (fptr->f2 != NULL) {
fclose(fptr->f2);
}
- if (fptr->pid) {
- rb_syswait(fptr->pid);
- fptr->pid = 0;
- }
}
static void
rb_io_fptr_close(fptr)
OpenFile *fptr;
{
+ int fd;
+
if (fptr->f == NULL && fptr->f2 == NULL) return;
+ fd = fileno(fptr->f);
if (fptr->finalize) {
(*fptr->finalize)(fptr);
}
@@ -849,6 +911,7 @@ rb_io_fptr_close(fptr)
fptr_finalize(fptr);
}
fptr->f = fptr->f2 = NULL;
+ rb_thread_fd_close(fd);
}
void
@@ -870,6 +933,10 @@ rb_io_close(io)
GetOpenFile(io, fptr);
rb_io_fptr_close(fptr);
+ if (fptr->pid) {
+ rb_syswait(fptr->pid);
+ fptr->pid = 0;
+ }
return Qnil;
}
@@ -898,6 +965,7 @@ rb_io_close_read(io)
VALUE io;
{
OpenFile *fptr;
+ int n;
rb_secure(4);
GetOpenFile(io, fptr);
@@ -907,10 +975,11 @@ rb_io_close_read(io)
if (fptr->f2 == 0) {
return rb_io_close(io);
}
- fclose(fptr->f);
+ n = fclose(fptr->f);
fptr->mode &= ~FMODE_READABLE;
fptr->f = fptr->f2;
fptr->f2 = 0;
+ if (n != 0) rb_sys_fail(fptr->path);
return Qnil;
}
@@ -920,6 +989,7 @@ rb_io_close_write(io)
VALUE io;
{
OpenFile *fptr;
+ int n;
rb_secure(4);
GetOpenFile(io, fptr);
@@ -929,9 +999,10 @@ rb_io_close_write(io)
if (fptr->f2 == 0) {
return rb_io_close(io);
}
- fclose(fptr->f2);
+ n = fclose(fptr->f2);
fptr->f2 = 0;
fptr->mode &= ~FMODE_WRITABLE;
+ if (n != 0) rb_sys_fail(fptr->path);
return Qnil;
}
@@ -952,9 +1023,9 @@ rb_io_syswrite(io, str)
rb_io_check_writable(fptr);
f = GetWriteFile(fptr);
-#ifdef USE_THREAD
- rb_thread_fd_writable(fileno(f));
-#endif
+ if (!rb_thread_fd_writable(fileno(f))) {
+ rb_io_check_closed(fptr);
+ }
n = write(fileno(f), RSTRING(str)->ptr, RSTRING(str)->len);
if (n == -1) rb_sys_fail(fptr->path);
@@ -976,15 +1047,15 @@ rb_io_sysread(io, len)
str = rb_str_new(0, ilen);
-#ifdef USE_THREAD
rb_thread_wait_fd(fileno(fptr->f));
-#endif
TRAP_BEG;
n = read(fileno(fptr->f), RSTRING(str)->ptr, RSTRING(str)->len);
TRAP_END;
if (n == -1) rb_sys_fail(fptr->path);
- if (n == 0) rb_eof_error();
+ if (n == 0 && ilen > 0) {
+ rb_eof_error();
+ }
RSTRING(str)->len = n;
RSTRING(str)->ptr[n] = '\0';
@@ -997,7 +1068,8 @@ VALUE
rb_io_binmode(io)
VALUE io;
{
-#if defined(NT) || defined(DJGPP) || defined(__CYGWIN32__) || defined(__human68k__) || defined(USE_CWGUSI)
+#if defined(NT) || defined(DJGPP) || defined(__CYGWIN32__)\
+ || defined(__human68k__) || defined(USE_CWGUSI) || defined(__EMX__)
OpenFile *fptr;
GetOpenFile(io, fptr);
@@ -1014,9 +1086,9 @@ rb_io_binmode(io)
rb_sys_fail(fptr->path);
# else /* USE_CWGUSI */
if (fptr->f)
- fptr->f->mode.binrb_ary_io = 1;
+ fptr->f->mode.binary_io = 1;
if (fptr->f2)
- fptr->f2->mode.binrb_ary_io = 1;
+ fptr->f2->mode.binary_io = 1;
# endif /* USE_CWGUSI */
#endif
@@ -1027,7 +1099,7 @@ rb_io_binmode(io)
int
rb_io_mode_flags(mode)
- char *mode;
+ const char *mode;
{
int flags = 0;
@@ -1042,7 +1114,8 @@ rb_io_mode_flags(mode)
flags |= FMODE_WRITABLE;
break;
default:
- rb_raise(rb_eArgError, "illegal access mode");
+ error:
+ rb_raise(rb_eArgError, "illegal access mode %s", mode);
}
if (mode[1] == 'b') {
@@ -1052,48 +1125,193 @@ rb_io_mode_flags(mode)
if (mode[1] == '+') {
flags |= FMODE_READWRITE;
+ if (mode[2] != 0) goto error;
+ }
+ else if (mode[1] != 0) goto error;
+
+ return flags;
+}
+
+static int
+rb_io_mode_flags2(mode)
+ int mode;
+{
+ int flags;
+
+ switch (mode & (O_RDONLY|O_WRONLY|O_RDWR)) {
+ case O_RDONLY:
+ flags = FMODE_READABLE;
+ break;
+ case O_WRONLY:
+ flags = FMODE_WRITABLE;
+ break;
+ case O_RDWR:
+ flags = FMODE_WRITABLE|FMODE_READABLE;
+ break;
}
+#ifdef O_BINARY
+ if (mode & O_BINARY) {
+ flags |= FMODE_BINMODE;
+ }
+#endif
+
return flags;
}
+static char*
+rb_io_flags_mode(flags)
+ int flags;
+{
+ static char mode[4];
+ char *p = mode;
+
+ switch (flags & (O_RDONLY|O_WRONLY|O_RDWR)) {
+ case O_RDONLY:
+ *p++ = 'r';
+ break;
+ case O_WRONLY:
+ *p++ = 'w';
+ break;
+ case O_RDWR:
+ *p++ = 'w';
+ *p++ = '+';
+ break;
+ }
+ *p++ = '\0';
+#ifdef O_BINARY
+ if (flags & O_BINARY) {
+ if (mode[1] == '+') {
+ mode[1] = 'b'; mode[2] = '+'; mode[3] = '\0';
+ }
+ else {
+ mode[1] = 'b'; mode[2] = '\0';
+ }
+ }
+#endif
+ return mode;
+}
+
+static int
+rb_open(fname, flag, mode)
+ char *fname;
+ int flag;
+ unsigned int mode;
+{
+ int fd;
+
+ fd = open(fname, flag, mode);
+ if (fd < 0) {
+ if (errno == EMFILE || errno == ENFILE) {
+ rb_gc();
+ fd = open(fname, flag, mode);
+ }
+ if (fd < 0) {
+ rb_sys_fail(fname);
+ }
+ }
+ return fd;
+}
+
FILE *
rb_fopen(fname, mode)
- char *fname;
- char *mode;
+ const char *fname;
+ const char *mode;
{
- FILE *f;
+ FILE *file;
- f = fopen(fname, mode);
- if (f == NULL) {
+ file = fopen(fname, mode);
+ if (file == NULL) {
if (errno == EMFILE || errno == ENFILE) {
rb_gc();
- f = fopen(fname, mode);
+ file = fopen(fname, mode);
}
- if (f == NULL) {
+ if (file == NULL) {
rb_sys_fail(fname);
}
}
- return f;
+ return file;
}
FILE *
rb_fdopen(fd, mode)
int fd;
- char *mode;
+ const char *mode;
{
- FILE *f;
+ FILE *file;
- f = fdopen(fd, mode);
- if (f == NULL) {
- if (errno == EMFILE) {
- f = fdopen(fd, mode);
+ file = fdopen(fd, mode);
+ if (file == NULL) {
+ if (errno == EMFILE || errno == ENFILE) {
+ rb_gc();
+ file = fdopen(fd, mode);
}
- if (f == NULL) {
+ if (file == NULL) {
rb_sys_fail(0);
}
}
- return f;
+ return file;
+}
+
+static VALUE
+rb_file_open_internal(klass, fname, mode)
+ VALUE klass;
+ const char *fname, *mode;
+{
+ OpenFile *fptr;
+ NEWOBJ(port, struct RFile);
+ OBJSETUP(port, klass, T_FILE);
+ MakeOpenFile(port, fptr);
+
+ fptr->mode = rb_io_mode_flags(mode);
+ fptr->f = rb_fopen(fname, mode);
+ fptr->path = strdup(fname);
+
+ return (VALUE)port;
+}
+
+VALUE
+rb_file_open(fname, mode)
+ const char *fname, *mode;
+{
+ return rb_file_open_internal(rb_cFile, fname, mode);
+}
+
+VALUE
+rb_file_sysopen_internal(klass, fname, flags, mode)
+ VALUE klass;
+ char *fname;
+ int flags, mode;
+{
+#ifdef USE_CWGUSI
+ if (mode != 0666) {
+ rb_warn("can't specify file mode on this platform");
+ }
+ return rb_file_open_internal(klass, fname, rb_io_flags_mode(flags));
+#else
+ OpenFile *fptr;
+ int fd;
+ char *m;
+ NEWOBJ(port, struct RFile);
+ OBJSETUP(port, klass, T_FILE);
+ MakeOpenFile(port, fptr);
+
+ fd = rb_open(fname, flags, mode);
+ m = rb_io_flags_mode(flags);
+ fptr->mode = rb_io_mode_flags2(flags);
+ fptr->f = rb_fdopen(fd, m);
+ fptr->path = strdup(fname);
+
+ return (VALUE)port;
+#endif
+}
+
+VALUE
+rb_file_sysopen(fname, flags, mode)
+ const char *fname;
+ int flags, mode;
+{
+ return rb_file_sysopen_internal(rb_cFile, fname, flags, mode);
}
#if defined (NT) || defined(DJGPP) || defined(__CYGWIN32__) || defined(__human68k__)
@@ -1205,7 +1423,6 @@ pipe_open(pname, mode)
fptr->f2 = f;
rb_io_unbuffered(fptr);
}
- rb_obj_call_init((VALUE)port);
return (VALUE)port;
}
#else
@@ -1242,8 +1459,6 @@ pipe_open(pname, mode)
}
if (doexec) {
- extern char *ruby_sourcefile;
- extern int ruby_sourceline;
int fd;
for (fd = 3; fd < NOFILE; fd++)
@@ -1257,11 +1472,7 @@ pipe_open(pname, mode)
case -1: /* fork failed */
if (errno == EAGAIN) {
-#ifdef USE_THREAD
rb_thread_sleep(1);
-#else
- sleep(1);
-#endif
goto retry;
}
close(pr[0]); close(pw[1]);
@@ -1293,7 +1504,6 @@ pipe_open(pname, mode)
fptr->finalize = pipe_finalize;
pipe_add_fptr(fptr);
#endif
- rb_obj_call_init((VALUE)port);
return (VALUE)port;
}
}
@@ -1311,7 +1521,7 @@ rb_io_s_popen(argc, argv, self)
VALUE self;
{
char *mode;
- VALUE pname, pmode;
+ VALUE pname, pmode, port;
if (rb_scan_args(argc, argv, "11", &pname, &pmode) == 1) {
mode = "r";
@@ -1325,19 +1535,45 @@ rb_io_s_popen(argc, argv, self)
rb_raise(rb_eArgError, "illegal access mode");
}
Check_SafeStr(pname);
- return pipe_open(RSTRING(pname)->ptr, mode);
+ port = pipe_open(RSTRING(pname)->ptr, mode);
+ if (NIL_P(port)) return Qnil;
+ return port;
}
static VALUE
-rb_io_open(fname, mode)
- char *fname, *mode;
+rb_file_s_open(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
{
- if (fname[0] == '|') {
- return pipe_open(fname+1, mode);
+ VALUE fname, vmode, file, perm;
+ char *path, *mode;
+
+ rb_scan_args(argc, argv, "12", &fname, &vmode, &perm);
+ Check_SafeStr(fname);
+ path = RSTRING(fname)->ptr;
+
+ if (FIXNUM_P(vmode)) {
+ int flags = FIX2INT(vmode);
+ int fmode = NIL_P(perm) ? 0666 : FIX2INT(perm);
+
+ file = rb_file_sysopen_internal(klass, path, flags, fmode);
}
else {
- return rb_file_open(fname, mode);
+ if (!NIL_P(vmode)) {
+ mode = STR2CSTR(vmode);
+ }
+ else {
+ mode = "r";
+ }
+ file = rb_file_open_internal(klass, RSTRING(fname)->ptr, mode);
+ }
+
+ if (rb_iterator_p()) {
+ return rb_ensure(rb_yield, file, rb_io_close, file);
}
+
+ return file;
}
static VALUE
@@ -1346,24 +1582,32 @@ rb_f_open(argc, argv)
VALUE *argv;
{
char *mode;
- VALUE pname, pmode;
+ VALUE pname, pmode, perm;
VALUE port;
- rb_scan_args(argc, argv, "11", &pname, &pmode);
+ rb_scan_args(argc, argv, "12", &pname, &pmode, &perm);
Check_SafeStr(pname);
+ if (RSTRING(pname)->ptr[0] != '|') /* open file */
+ return rb_file_s_open(argc, argv, rb_cFile);
+
+ /* open pipe */
if (NIL_P(pmode)) {
mode = "r";
}
+ else if (FIXNUM_P(pmode)) {
+ mode = rb_io_flags_mode(FIX2INT(pmode));
+ }
else {
int len;
mode = STR2CSTR(pmode);
len = strlen(mode);
if (len == 0 || len > 3)
- rb_raise(rb_eArgError, "illegal access mode");
+ rb_raise(rb_eArgError, "illegal access mode %s", mode);
}
- port = rb_io_open(RSTRING(pname)->ptr, mode);
+ port = pipe_open(RSTRING(pname)->ptr+1, mode);
+ if (NIL_P(port)) return Qnil;
if (rb_iterator_p()) {
return rb_ensure(rb_yield, port, rb_io_close, port);
}
@@ -1372,6 +1616,18 @@ rb_f_open(argc, argv)
}
static VALUE
+rb_io_open(fname, mode)
+ char *fname, *mode;
+{
+ if (fname[0] == '|') {
+ return pipe_open(fname+1, mode);
+ }
+ else {
+ return rb_file_open(fname, mode);
+ }
+}
+
+static VALUE
rb_io_get_io(io)
VALUE io;
{
@@ -1393,7 +1649,7 @@ rb_io_mode_string(fptr)
}
}
-VALUE
+static VALUE
rb_io_reopen(io, nfile)
VALUE io, nfile;
{
@@ -1406,12 +1662,14 @@ rb_io_reopen(io, nfile)
nfile = rb_io_get_io(nfile);
GetOpenFile(nfile, orig);
+ if (fptr == orig) return io;
if (orig->f2) {
fflush(orig->f2);
}
else if (orig->mode & FMODE_WRITABLE) {
fflush(orig->f);
}
+ rb_thread_fd_close(fileno(fptr->f));
/* copy OpenFile structure */
fptr->mode = orig->mode;
@@ -1458,6 +1716,56 @@ rb_io_reopen(io, nfile)
}
static VALUE
+rb_file_reopen(argc, argv, file)
+ int argc;
+ VALUE *argv;
+ VALUE file;
+{
+ VALUE fname, nmode;
+ char *mode;
+ OpenFile *fptr;
+
+ rb_secure(4);
+ if (rb_scan_args(argc, argv, "11", &fname, &nmode) == 1) {
+ if (TYPE(fname) == T_FILE) { /* fname must be IO */
+ return rb_io_reopen(file, fname);
+ }
+ }
+
+ Check_SafeStr(fname);
+ if (!NIL_P(nmode)) {
+ mode = STR2CSTR(nmode);
+ }
+ else {
+ mode = "r";
+ }
+
+ GetOpenFile(file, fptr);
+ if (fptr->path) free(fptr->path);
+ fptr->path = strdup(RSTRING(fname)->ptr);
+ fptr->mode = rb_io_mode_flags(mode);
+ if (!fptr->f) {
+ fptr->f = rb_fopen(RSTRING(fname)->ptr, mode);
+ if (fptr->f2) {
+ fclose(fptr->f2);
+ fptr->f2 = NULL;
+ }
+ return file;
+ }
+
+ if (freopen(RSTRING(fname)->ptr, mode, fptr->f) == NULL) {
+ rb_sys_fail(fptr->path);
+ }
+ if (fptr->f2) {
+ if (freopen(RSTRING(fname)->ptr, "w", fptr->f2) == NULL) {
+ rb_sys_fail(fptr->path);
+ }
+ }
+
+ return file;
+}
+
+static VALUE
rb_io_clone(io)
VALUE io;
{
@@ -1466,7 +1774,7 @@ rb_io_clone(io)
char *mode;
NEWOBJ(obj, struct RFile);
- OBJSETUP(obj, CLASS_OF(io), T_FILE);
+ CLONESETUP(obj, io);
GetOpenFile(io, orig);
MakeOpenFile(obj, fptr);
@@ -1601,7 +1909,7 @@ rb_io_putc(io, ch)
rb_io_check_writable(fptr);
f = GetWriteFile(fptr);
- if (fputc(c, f) == EOF || ferror(f))
+ if (fputc(c, f) == EOF)
rb_sys_fail(fptr->path);
if (fptr->mode & FMODE_SYNC)
fflush(f);
@@ -1725,38 +2033,135 @@ rb_io_defset(val, id)
VALUE val;
ID id;
{
- if (TYPE(val) == T_STRING) {
- val = rb_io_open(RSTRING(val)->ptr, "w");
- }
if (!rb_respond_to(val, id_write)) {
- rb_raise(rb_eTypeError, "$< must have write method, %s given",
+ rb_raise(rb_eTypeError, "$> must have write method, %s given",
rb_class2name(CLASS_OF(val)));
}
rb_defout = val;
}
+static int
+rb_dup(orig)
+ int orig;
+{
+ int fd;
+
+ fd = dup(orig);
+ if (fd < 0) {
+ if (errno == EMFILE || errno == ENFILE) {
+ rb_gc();
+ fd = dup(orig);
+ }
+ if (fd < 0) {
+ rb_sys_fail(0);
+ }
+ }
+ return fd;
+}
+
static void
-rb_io_stdio_set(val, id, var)
+set_stdin(val, id, var)
VALUE val;
ID id;
VALUE *var;
{
OpenFile *fptr;
int fd;
+ char *mode;
+ if (val == *var) return;
if (TYPE(val) != T_FILE) {
- rb_raise(rb_eTypeError, "%s must be IO object", rb_id2name(id));
+ *var = val;
+ return;
}
+ if (TYPE(*var) != T_FILE) {
+ *var = orig_stdin;
+ }
+
+ GetOpenFile(val, fptr);
+ rb_io_check_readable(fptr);
+
GetOpenFile(*var, fptr);
- fd = fileno(fptr->f);
+ mode = rb_io_mode_string(fptr);
+ fd = rb_dup(fileno(fptr->f));
+ if (fileno(fptr->f) > 2) {
+ fclose(fptr->f);
+ }
+ fptr->f = rb_fdopen(fd, mode);
+
GetOpenFile(val, fptr);
- if (fd == 0) {
- rb_io_check_readable(fptr);
+ dup2(fileno(fptr->f), 0);
+ fclose(fptr->f);
+ fptr->f = stdin;
+
+ *var = val;
+}
+
+static void
+set_outfile(val, var, orig, stdf)
+ VALUE val;
+ VALUE *var;
+ VALUE orig;
+ FILE *stdf;
+{
+ OpenFile *fptr;
+ FILE *f;
+ int fd;
+ char *mode;
+
+ if (val == *var) return;
+
+ if (TYPE(*var) == T_FILE) {
+ rb_io_flush(*var);
}
- else {
- rb_io_check_writable(fptr);
+ if (TYPE(val) != T_FILE) {
+ *var = val;
+ return;
+ }
+ if (TYPE(*var) != T_FILE) {
+ *var = orig;
+ }
+
+ GetOpenFile(val, fptr);
+ rb_io_check_writable(fptr);
+
+ GetOpenFile(*var, fptr);
+ mode = rb_io_mode_string(fptr);
+ f = GetWriteFile(fptr);
+ fd = rb_dup(fileno(f));
+ if (fileno(f) > 2) {
+ fclose(fptr->f);
}
- rb_io_reopen(*var, val);
+ f = rb_fdopen(fd, mode);
+ if (fptr->f2) fptr->f2 = f;
+ else fptr->f = f;
+
+ GetOpenFile(val, fptr);
+ f = GetWriteFile(fptr);
+ dup2(fileno(f), fileno(stdf));
+ fclose(f);
+ if (fptr->f2) fptr->f2 = stdf;
+ else fptr->f = stdf;
+
+ *var = val;
+}
+
+static void
+set_stdout(val, id, var)
+ VALUE val;
+ ID id;
+ VALUE *var;
+{
+ set_outfile(val, var, orig_stdout, stdout);
+}
+
+static void
+set_stderr(val, id, var)
+ VALUE val;
+ ID id;
+ VALUE *var;
+{
+ set_outfile(val, var, orig_stderr, stderr);
}
static VALUE
@@ -1772,7 +2177,6 @@ prep_stdio(f, mode, klass)
MakeOpenFile(io, fp);
fp->f = f;
fp->mode = mode;
- rb_obj_call_init((VALUE)io);
return (VALUE)io;
}
@@ -1793,6 +2197,28 @@ rb_io_s_new(argc, argv, klass)
return prep_stdio(rb_fdopen(NUM2INT(fnum), m), rb_io_mode_flags(m), klass);
}
+static int binmode = 0;
+
+static VALUE
+argf_forward()
+{
+ return rb_funcall3(current_file, ruby_frame->last_func,
+ ruby_frame->argc, ruby_frame->argv);
+}
+
+static VALUE
+argf_binmode()
+{
+ if (TYPE(current_file) != T_FILE) {
+ argf_forward();
+ }
+ else {
+ rb_io_binmode(current_file);
+ }
+ binmode = 1;
+ return argf;
+}
+
static int
next_argv()
{
@@ -1805,7 +2231,7 @@ next_argv()
}
else {
next_p = -1;
- file = rb_stdin;
+ current_file = rb_stdin;
}
init_p = 1;
gets_lineno = 0;
@@ -1816,9 +2242,9 @@ next_argv()
next_p = 0;
if (RARRAY(rb_argv)->len > 0) {
filename = rb_ary_shift(rb_argv);
- fn = RSTRING(filename)->ptr;
- if (RSTRING(filename)->len == 1 && fn[0] == '-') {
- file = rb_stdin;
+ fn = STR2CSTR(filename);
+ if (strlen(fn) == 1 && fn[0] == '-') {
+ current_file = rb_stdin;
if (ruby_inplace_mode) {
rb_defout = rb_stdout;
}
@@ -1843,7 +2269,7 @@ next_argv()
rb_str_cat(str, ruby_inplace_mode,
strlen(ruby_inplace_mode));
#endif
-#if defined(MSDOS) || defined(__BOW__) || defined(__CYGWIN32__) || defined(NT) || defined(__human68k__)
+#if defined(MSDOS) || defined(__BOW__) || defined(__CYGWIN32__) || defined(NT) || defined(__human68k__) || defined(__EMX__)
(void)fclose(fr);
(void)unlink(RSTRING(str)->ptr);
(void)rename(fn, RSTRING(str)->ptr);
@@ -1870,8 +2296,7 @@ next_argv()
#endif
}
fw = rb_fopen(fn, "w");
-#if !defined(MSDOS) && !defined(__CYGWIN32__) && !(NT) && !defined(__human68k__)\
- && !defined(USE_CWGUSI) && !defined(__BEOS__)
+#if !defined(MSDOS) && !defined(__CYGWIN32__) && !(NT) && !defined(__human68k__) && !defined(USE_CWGUSI) && !defined(__BEOS__) && !defined(__EMX__)
fstat(fileno(fw), &st2);
fchmod(fileno(fw), st.st_mode);
if (st.st_uid!=st2.st_uid || st.st_gid!=st2.st_gid) {
@@ -1880,8 +2305,9 @@ next_argv()
#endif
rb_defout = prep_stdio(fw, FMODE_WRITABLE, rb_cFile);
}
- file = prep_stdio(fr, FMODE_READABLE, rb_cFile);
+ current_file = prep_stdio(fr, FMODE_READABLE, rb_cFile);
}
+ if (binmode) rb_io_binmode(current_file);
}
else {
init_p = 0;
@@ -1891,6 +2317,16 @@ next_argv()
return Qtrue;
}
+static void
+any_close(file)
+ VALUE file;
+{
+ if (TYPE(file) == T_FILE)
+ rb_io_close(file);
+ else
+ rb_funcall3(file, rb_intern("close"), 0, 0);
+}
+
static VALUE
rb_f_gets_internal(argc, argv)
int argc;
@@ -1900,9 +2336,17 @@ rb_f_gets_internal(argc, argv)
retry:
if (!next_argv()) return Qnil;
- line = rb_io_gets_internal(argc, argv, file);
+ if (TYPE(current_file) != T_FILE) {
+ line = rb_funcall3(current_file, rb_intern("gets"), argc, argv);
+ }
+ if (argc == 0 && rb_rs == rb_default_rs) {
+ line = rb_io_gets(current_file);
+ }
+ else {
+ line = rb_io_gets_internal(argc, argv, current_file);
+ }
if (NIL_P(line) && next_p != -1) {
- rb_io_close(file);
+ any_close(current_file);
next_p = 1;
goto retry;
}
@@ -1919,7 +2363,7 @@ rb_f_gets(argc, argv)
{
VALUE line = rb_f_gets_internal(argc, argv);
- if (!NIL_P(line)) rb_lastline_set(line);
+ rb_lastline_set(line);
return line;
}
@@ -1928,16 +2372,20 @@ rb_gets()
{
VALUE line;
+ if (rb_rs != rb_default_rs) {
+ return rb_f_gets(0, 0);
+ }
+
retry:
if (!next_argv()) return Qnil;
- line = rb_io_gets(file);
+ line = rb_io_gets(current_file);
if (NIL_P(line) && next_p != -1) {
- rb_io_close(file);
+ any_close(current_file);
next_p = 1;
goto retry;
}
+ rb_lastline_set(line);
if (!NIL_P(line)) {
- rb_lastline_set(line);
gets_lineno++;
lineno = INT2FIX(gets_lineno);
}
@@ -1960,76 +2408,13 @@ rb_f_readline(argc, argv)
}
static VALUE
-rb_f_tell()
-{
- return rb_io_tell(file);
-}
-
-static VALUE
-rb_f_seek(self, offset, ptrname)
- VALUE self, offset, ptrname;
-{
- if (!next_argv()) {
- rb_raise(rb_eArgError, "no stream to seek");
- }
-
- return rb_io_seek(file, offset, ptrname);
-}
-
-static VALUE
-rb_f_set_pos(self, offset)
- VALUE self, offset;
-{
- if (!next_argv()) {
- rb_raise(rb_eArgError, "no stream to pos");
- }
-
- return rb_io_set_pos(file, offset);
-}
-
-static VALUE
-rb_f_rewind()
-{
- return rb_io_rewind(file);
-}
-
-static VALUE
-rb_f_eof()
-{
- if (init_p == 0 && !next_argv())
- return Qtrue;
- if (rb_io_eof(file)) {
- next_p = 1;
- return Qtrue;
- }
- return Qfalse;
-}
-
-static VALUE
rb_f_getc()
{
+ rb_warn("getc is obsolete; use STDIN.getc instead");
return rb_io_getc(rb_stdin);
}
static VALUE
-rb_f_ungetc(self, c)
- VALUE self, c;
-{
- return rb_io_ungetc(rb_stdin, c);
-}
-
-static VALUE
-rb_f_readchar()
-{
- VALUE c = rb_f_getc();
-
- if (NIL_P(c)) {
- rb_eof_error();
- }
- return c;
-}
-
-static VALUE
rb_f_readlines(argc, argv)
int argc;
VALUE *argv;
@@ -2064,6 +2449,7 @@ rb_f_backquote(obj, str)
Check_SafeStr(str);
port = pipe_open(RSTRING(str)->ptr, "r");
+ if (NIL_P(port)) return rb_str_new(0,0);
result = read_all(port);
rb_io_close(port);
@@ -2075,9 +2461,6 @@ rb_f_backquote(obj, str)
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
-#ifdef NT
-#define select(v, w, x, y, z) (-1) /* anytime fail */
-#endif
static VALUE
rb_f_select(argc, argv, obj)
@@ -2099,7 +2482,7 @@ rb_f_select(argc, argv, obj)
tp = NULL;
}
else {
- timerec = rb_time_timeval(timeout);
+ timerec = rb_time_interval(timeout);
tp = &timerec;
}
@@ -2109,9 +2492,7 @@ rb_f_select(argc, argv, obj)
rp = &rset;
FD_ZERO(rp);
for (i=0; i<RARRAY(read)->len; i++) {
- VALUE io = rb_io_get_io(RARRAY(read)->ptr[i]);
-
- GetOpenFile(io, fptr);
+ GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr);
FD_SET(fileno(fptr->f), rp);
if (READ_DATA_PENDING(fptr->f)) { /* check for buffered data */
pending++;
@@ -2132,9 +2513,7 @@ rb_f_select(argc, argv, obj)
wp = &wset;
FD_ZERO(wp);
for (i=0; i<RARRAY(write)->len; i++) {
- VALUE io = rb_io_get_io(RARRAY(write)->ptr[i]);
-
- GetOpenFile(io, fptr);
+ GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr);
FD_SET(fileno(fptr->f), wp);
if (max < fileno(fptr->f)) max = fileno(fptr->f);
if (fptr->f2) {
@@ -2151,9 +2530,7 @@ rb_f_select(argc, argv, obj)
ep = &eset;
FD_ZERO(ep);
for (i=0; i<RARRAY(except)->len; i++) {
- VALUE io = rb_io_get_io(RARRAY(except)->ptr[i]);
-
- GetOpenFile(io, fptr);
+ GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr);
FD_SET(fileno(fptr->f), ep);
if (max < fileno(fptr->f)) max = fileno(fptr->f);
if (fptr->f2) {
@@ -2167,24 +2544,10 @@ rb_f_select(argc, argv, obj)
max++;
-#ifdef USE_THREAD
n = rb_thread_select(max, rp, wp, ep, tp);
if (n < 0) {
rb_sys_fail(0);
}
-#else
- retry:
- TRAP_BEG;
- n = select(max, rp, wp, ep, tp);
- TRAP_END;
- if (n < 0) {
- if (errno != EINTR) {
- rb_sys_fail(0);
- }
- if (tp == NULL) goto retry;
- interrupt_flag = 1;
- }
-#endif
if (!pending && n == 0) return Qnil; /* returns nil on timeout */
res = rb_ary_new2(3);
@@ -2196,7 +2559,7 @@ rb_f_select(argc, argv, obj)
if (rp) {
list = RARRAY(res)->ptr[0];
for (i=0; i< RARRAY(read)->len; i++) {
- GetOpenFile(RARRAY(read)->ptr[i], fptr);
+ GetOpenFile(rb_io_get_io(RARRAY(read)->ptr[i]), fptr);
if (FD_ISSET(fileno(fptr->f), rp)
|| FD_ISSET(fileno(fptr->f), &pset)) {
rb_ary_push(list, RARRAY(read)->ptr[i]);
@@ -2207,7 +2570,7 @@ rb_f_select(argc, argv, obj)
if (wp) {
list = RARRAY(res)->ptr[1];
for (i=0; i< RARRAY(write)->len; i++) {
- GetOpenFile(RARRAY(write)->ptr[i], fptr);
+ GetOpenFile(rb_io_get_io(RARRAY(write)->ptr[i]), fptr);
if (FD_ISSET(fileno(fptr->f), wp)) {
rb_ary_push(list, RARRAY(write)->ptr[i]);
}
@@ -2220,7 +2583,7 @@ rb_f_select(argc, argv, obj)
if (ep) {
list = RARRAY(res)->ptr[2];
for (i=0; i< RARRAY(except)->len; i++) {
- GetOpenFile(RARRAY(except)->ptr[i], fptr);
+ GetOpenFile(rb_io_get_io(RARRAY(except)->ptr[i]), fptr);
if (FD_ISSET(fileno(fptr->f), ep)) {
rb_ary_push(list, RARRAY(except)->ptr[i]);
}
@@ -2430,8 +2793,8 @@ rb_f_syscall(argc, argv)
#endif /* atarist */
}
TRAP_END;
- if (retval == -1) rb_sys_fail(0);
- return INT2FIX(0);
+ if (retval < 0) rb_sys_fail(0);
+ return INT2NUM(retval);
#else
rb_notimplement();
return Qnil; /* not reached */
@@ -2452,8 +2815,8 @@ rb_io_s_pipe()
#endif
rb_sys_fail(0);
- r = prep_stdio(fdopen(pipes[0], "r"), FMODE_READABLE, rb_cIO);
- w = prep_stdio(fdopen(pipes[1], "w"), FMODE_WRITABLE, rb_cIO);
+ r = prep_stdio(rb_fdopen(pipes[0], "r"), FMODE_READABLE, rb_cIO);
+ w = prep_stdio(rb_fdopen(pipes[1], "w"), FMODE_WRITABLE, rb_cIO);
ary = rb_ary_new2(2);
rb_ary_push(ary, r);
@@ -2498,6 +2861,7 @@ rb_io_s_foreach(argc, argv, io)
arg.argc = argc - 1;
arg.io = rb_io_open(RSTRING(fname)->ptr, "r");
+ if (NIL_P(arg.io)) return Qnil;
return rb_ensure(rb_io_foreach_line, (VALUE)&arg, rb_io_close, arg.io);
}
@@ -2529,37 +2893,103 @@ rb_io_s_readlines(argc, argv, io)
arg.argc = argc - 1;
arg.io = rb_io_open(RSTRING(fname)->ptr, "r");
+ if (NIL_P(arg.io)) return Qnil;
return rb_ensure(rb_io_readline_line, (VALUE)&arg, rb_io_close, arg.io);
}
static VALUE
-arg_fileno()
+argf_tell()
{
- return rb_io_fileno(file);
+ if (!next_argv()) {
+ rb_raise(rb_eArgError, "no stream to tell");
+ }
+
+ if (TYPE(current_file) != T_FILE) {
+ return argf_forward();
+ }
+ return rb_io_tell(current_file);
}
static VALUE
-arg_to_io()
+argf_seek(self, offset, ptrname)
+ VALUE self, offset, ptrname;
{
- return file;
+ if (!next_argv()) {
+ rb_raise(rb_eArgError, "no stream to seek");
+ }
+
+ if (TYPE(current_file) != T_FILE) {
+ return argf_forward();
+ }
+ return rb_io_seek(current_file, offset, ptrname);
+}
+
+static VALUE
+argf_set_pos(self, offset)
+ VALUE self, offset;
+{
+ if (!next_argv()) {
+ rb_raise(rb_eArgError, "no stream to pos");
+ }
+
+ if (TYPE(current_file) != T_FILE) {
+ return argf_forward();
+ }
+ return rb_io_set_pos(current_file, offset);
+}
+
+static VALUE
+argf_rewind()
+{
+ if (!next_argv()) {
+ rb_raise(rb_eArgError, "no stream to rewind");
+ }
+ if (TYPE(current_file) != T_FILE) {
+ return argf_forward();
+ }
+ return rb_io_rewind(current_file);
+}
+
+static VALUE
+argf_fileno()
+{
+ if (!next_argv()) {
+ rb_raise(rb_eArgError, "no stream");
+ }
+ if (TYPE(current_file) != T_FILE) {
+ return argf_forward();
+ }
+ return rb_io_fileno(current_file);
}
static VALUE
-arg_read(argc, argv)
+argf_to_io()
+{
+ return current_file;
+}
+
+static VALUE
+argf_read(argc, argv)
int argc;
VALUE *argv;
{
VALUE tmp, str;
- size_t len;
+ int len;
if (argc == 1) len = NUM2INT(argv[0]);
str = Qnil;
retry:
if (!next_argv()) return str;
- tmp = rb_io_read(argc, argv, file);
+ if (TYPE(current_file) != T_FILE) {
+ tmp = argf_forward();
+ STR2CSTR(tmp);
+ }
+ else {
+ tmp = io_read(argc, argv, current_file);
+ }
if (NIL_P(tmp) && next_p != -1) {
- rb_io_close(file);
+ any_close(current_file);
next_p = 1;
goto retry;
}
@@ -2579,15 +3009,20 @@ arg_read(argc, argv)
}
static VALUE
-arg_getc()
+argf_getc()
{
VALUE byte;
retry:
if (!next_argv()) return Qnil;
- byte = rb_io_getc(file);
+ if (TYPE(current_file) != T_FILE) {
+ byte = rb_funcall3(current_file, rb_intern("getc"), 0, 0);
+ }
+ else {
+ byte = rb_io_getc(current_file);
+ }
if (NIL_P(byte) && next_p != -1) {
- rb_io_close(file);
+ any_close(current_file);
next_p = 1;
goto retry;
}
@@ -2596,9 +3031,9 @@ arg_getc()
}
static VALUE
-arg_readchar()
+argf_readchar()
{
- VALUE c = rb_io_getc(file);
+ VALUE c = argf_getc();
if (NIL_P(c)) {
rb_eof_error();
@@ -2607,7 +3042,22 @@ arg_readchar()
}
static VALUE
-arg_each_line(argc, argv)
+argf_eof()
+{
+ if (init_p == 0 && !next_argv())
+ return Qtrue;
+ if (TYPE(current_file) != T_FILE) {
+ return argf_forward();
+ }
+ if (rb_io_eof(current_file)) {
+ next_p = 1;
+ return Qtrue;
+ }
+ return Qfalse;
+}
+
+static VALUE
+argf_each_line(argc, argv)
int argc;
VALUE *argv;
{
@@ -2616,46 +3066,46 @@ arg_each_line(argc, argv)
while (RTEST(str = rb_f_gets_internal(argc, argv))) {
rb_yield(str);
}
- return Qnil;
+ return argf;
}
static VALUE
-arg_each_byte()
+argf_each_byte()
{
VALUE byte;
- while (!NIL_P(byte = arg_getc())) {
+ while (!NIL_P(byte = argf_getc())) {
rb_yield(byte);
}
return Qnil;
}
static VALUE
-arg_filename()
+argf_filename()
{
return filename;
}
static VALUE
-arg_file()
+argf_file()
{
- return file;
+ return current_file;
}
static VALUE
-arg_skip()
+argf_skip()
{
if (next_p != -1) {
- rb_io_close(file);
+ any_close(current_file);
next_p = 1;
}
return argf;
}
static VALUE
-arg_close()
+argf_close()
{
- rb_io_close(file);
+ any_close(current_file);
if (next_p != -1) {
next_p = 1;
}
@@ -2664,9 +3114,12 @@ arg_close()
}
static VALUE
-arg_closed()
+argf_closed()
{
- return rb_io_closed(file);
+ if (TYPE(current_file) != T_FILE) {
+ return argf_forward();
+ }
+ return rb_io_closed(current_file);
}
static VALUE
@@ -2704,20 +3157,12 @@ Init_IO()
rb_define_global_function("puts", rb_f_puts, -1);
rb_define_global_function("gets", rb_f_gets, -1);
rb_define_global_function("readline", rb_f_readline, -1);
- rb_define_global_function("tell", rb_f_tell, 0);
- rb_define_global_function("seek", rb_f_seek, 2);
- rb_define_global_function("rewind", rb_f_rewind, 0);
- rb_define_global_function("eof", rb_f_eof, 0);
- rb_define_global_function("eof?", rb_f_eof, 0);
rb_define_global_function("getc", rb_f_getc, 0);
- rb_define_global_function("readchar", rb_f_readchar, 0);
rb_define_global_function("select", rb_f_select, -1);
- rb_define_global_function("ungetc", rb_f_ungetc, 1);
rb_define_global_function("readlines", rb_f_readlines, -1);
rb_define_global_function("`", rb_f_backquote, 1);
- rb_define_global_function("pipe", rb_io_s_pipe, 0);
rb_define_global_function("p", rb_f_p, -1);
rb_define_method(rb_mKernel, "display", rb_obj_display, -1);
@@ -2730,6 +3175,7 @@ Init_IO()
rb_define_singleton_method(rb_cIO, "foreach", rb_io_s_foreach, -1);
rb_define_singleton_method(rb_cIO, "readlines", rb_io_s_readlines, -1);
rb_define_singleton_method(rb_cIO, "select", rb_f_select, -1);
+ rb_define_singleton_method(rb_cIO, "pipe", rb_io_s_pipe, 0);
rb_fs = rb_output_fs = Qnil;
rb_define_hooked_variable("$;", &rb_fs, 0, rb_str_setter);
@@ -2773,8 +3219,8 @@ Init_IO()
rb_define_method(rb_cIO, "readlines", rb_io_readlines, -1);
- rb_define_method(rb_cIO, "read", rb_io_read, -1);
- rb_define_method(rb_cIO, "write", rb_io_write, 1);
+ rb_define_method(rb_cIO, "read", io_read, -1);
+ rb_define_method(rb_cIO, "write", io_write, 1);
rb_define_method(rb_cIO, "gets", rb_io_gets_method, -1);
rb_define_method(rb_cIO, "readline", rb_io_readline, -1);
rb_define_method(rb_cIO, "getc", rb_io_getc, 0);
@@ -2805,12 +3251,12 @@ Init_IO()
rb_define_method(rb_cIO, "ioctl", rb_io_ioctl, -1);
rb_define_method(rb_cIO, "fcntl", rb_io_fcntl, -1);
- rb_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO);
- rb_define_hooked_variable("$stdin", &rb_stdin, 0, rb_io_stdio_set);
- rb_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO);
- rb_define_hooked_variable("$stdout", &rb_stdout, 0, rb_io_stdio_set);
- rb_stderr = prep_stdio(stderr, FMODE_WRITABLE, rb_cIO);
- rb_define_hooked_variable("$stderr", &rb_stderr, 0, rb_io_stdio_set);
+ rb_stdin = orig_stdin = prep_stdio(stdin, FMODE_READABLE, rb_cIO);
+ rb_define_hooked_variable("$stdin", &rb_stdin, 0, set_stdin);
+ rb_stdout = orig_stdout = prep_stdio(stdout, FMODE_WRITABLE, rb_cIO);
+ rb_define_hooked_variable("$stdout", &rb_stdout, 0, set_stdout);
+ rb_stderr = orig_stderr = prep_stdio(stderr, FMODE_WRITABLE, rb_cIO);
+ rb_define_hooked_variable("$stderr", &rb_stderr, 0, set_stderr);
rb_defout = rb_stdout;
rb_define_hooked_variable("$>", &rb_defout, 0, rb_io_defset);
@@ -2824,40 +3270,43 @@ Init_IO()
rb_define_readonly_variable("$<", &argf);
rb_define_global_const("ARGF", argf);
- rb_define_singleton_method(argf, "fileno", arg_fileno, 0);
- rb_define_singleton_method(argf, "to_i", arg_fileno, 0);
- rb_define_singleton_method(argf, "to_io", arg_to_io, 0);
- rb_define_singleton_method(argf, "each", arg_each_line, -1);
- rb_define_singleton_method(argf, "each_line", arg_each_line, -1);
- rb_define_singleton_method(argf, "each_byte", arg_each_byte, 0);
+ rb_define_singleton_method(argf, "fileno", argf_fileno, 0);
+ rb_define_singleton_method(argf, "to_i", argf_fileno, 0);
+ rb_define_singleton_method(argf, "to_io", argf_to_io, 0);
+ rb_define_singleton_method(argf, "each", argf_each_line, -1);
+ rb_define_singleton_method(argf, "each_line", argf_each_line, -1);
+ rb_define_singleton_method(argf, "each_byte", argf_each_byte, 0);
- rb_define_singleton_method(argf, "read", arg_read, -1);
+ rb_define_singleton_method(argf, "read", argf_read, -1);
rb_define_singleton_method(argf, "readlines", rb_f_readlines, -1);
rb_define_singleton_method(argf, "to_a", rb_f_readlines, -1);
rb_define_singleton_method(argf, "gets", rb_f_gets, -1);
rb_define_singleton_method(argf, "readline", rb_f_readline, -1);
- rb_define_singleton_method(argf, "getc", arg_getc, 0);
- rb_define_singleton_method(argf, "readchar", arg_readchar, 0);
- rb_define_singleton_method(argf, "tell", rb_f_tell, 0);
- rb_define_singleton_method(argf, "seek", rb_f_seek, 2);
- rb_define_singleton_method(argf, "rewind", rb_f_rewind, 0);
- rb_define_singleton_method(argf, "pos", rb_f_tell, 0);
- rb_define_singleton_method(argf, "pos=", rb_f_set_pos, 1);
- rb_define_singleton_method(argf, "eof", rb_f_eof, 0);
- rb_define_singleton_method(argf, "eof?", rb_f_eof, 0);
- rb_define_singleton_method(argf, "ungetc", rb_f_ungetc, 1);
-
- rb_define_singleton_method(argf, "to_s", arg_filename, 0);
- rb_define_singleton_method(argf, "filename", arg_filename, 0);
- rb_define_singleton_method(argf, "file", arg_file, 0);
- rb_define_singleton_method(argf, "skip", arg_skip, 0);
- rb_define_singleton_method(argf, "close", arg_close, 0);
- rb_define_singleton_method(argf, "closed?", arg_closed, 0);
-
+ rb_define_singleton_method(argf, "getc", argf_getc, 0);
+ rb_define_singleton_method(argf, "readchar", argf_readchar, 0);
+ rb_define_singleton_method(argf, "tell", argf_tell, 0);
+ rb_define_singleton_method(argf, "seek", argf_seek, 2);
+ rb_define_singleton_method(argf, "rewind", argf_rewind, 0);
+ rb_define_singleton_method(argf, "pos", argf_tell, 0);
+ rb_define_singleton_method(argf, "pos=", argf_set_pos, 1);
+ rb_define_singleton_method(argf, "eof", argf_eof, 0);
+ rb_define_singleton_method(argf, "eof?", argf_eof, 0);
+ rb_define_singleton_method(argf, "binmode", argf_binmode, 0);
+
+ rb_define_singleton_method(argf, "to_s", argf_filename, 0);
+ rb_define_singleton_method(argf, "filename", argf_filename, 0);
+ rb_define_singleton_method(argf, "file", argf_file, 0);
+ rb_define_singleton_method(argf, "skip", argf_skip, 0);
+ rb_define_singleton_method(argf, "close", argf_close, 0);
+ rb_define_singleton_method(argf, "closed?", argf_closed, 0);
+
+ rb_define_singleton_method(argf, "lineno", argf_lineno, 0);
+ rb_define_singleton_method(argf, "lineno=", argf_set_lineno, 1);
+
+ current_file = rb_stdin;
+ rb_global_variable(&current_file);
filename = rb_str_new2("-");
rb_define_readonly_variable("$FILENAME", &filename);
- file = rb_stdin;
- rb_global_variable(&file);
rb_define_virtual_variable("$-i", opt_i_get, opt_i_set);
@@ -2866,4 +3315,30 @@ Init_IO()
#endif
Init_File();
+
+ rb_define_method(rb_cFile, "reopen", rb_file_reopen, -1);
+
+ rb_define_singleton_method(rb_cFile, "new", rb_file_s_open, -1);
+ rb_define_singleton_method(rb_cFile, "open", rb_file_s_open, -1);
+
+ rb_file_const("RDONLY", INT2FIX(O_RDONLY));
+ rb_file_const("WRONLY", INT2FIX(O_WRONLY));
+ rb_file_const("RDWR", INT2FIX(O_RDWR));
+ rb_file_const("APPEND", INT2FIX(O_APPEND));
+ rb_file_const("CREAT", INT2FIX(O_CREAT));
+ rb_file_const("EXCL", INT2FIX(O_EXCL));
+#if defined(O_NDELAY) || defined(O_NONBLOCK)
+# ifdef O_NONBLOCK
+ rb_file_const("NONBLOCK", INT2FIX(O_NONBLOCK));
+# else
+ rb_file_const("NONBLOCK", INT2FIX(O_NDELAY));
+# endif
+#endif
+ rb_file_const("TRUNC", INT2FIX(O_TRUNC));
+#ifdef O_NOCTTY
+ rb_file_const("NOCTTY", INT2FIX(O_NOCTTY));
+#endif
+#ifdef O_BINARY
+ rb_file_const("BINARY", INT2FIX(O_BINARY));
+#endif
}
diff --git a/lex.c b/lex.c
index 1abc048638..62e1ef6f61 100644
--- a/lex.c
+++ b/lex.c
@@ -1,5 +1,5 @@
-/* C code produced by gperf version 2.5 (GNU C++ version) */
-/* Command-line: gperf -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$ keywords */
+/* C code produced by gperf version 2.7.1 (19981006 egcs) */
+/* Command-line: gperf -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$ ./keywords */
struct kwtable {char *name; int id[2]; enum lex_state state;};
#define TOTAL_KEYWORDS 40
@@ -10,28 +10,41 @@ struct kwtable {char *name; int id[2]; enum lex_state state;};
/* maximum key range = 50, duplicates = 0 */
#ifdef __GNUC__
-inline
+__inline
#endif
static unsigned int
hash (str, len)
- register char *str;
- register int unsigned len;
+ register const char *str;
+ register unsigned int len;
{
static unsigned char asso_values[] =
{
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 11, 56, 56, 36, 56, 1, 37,
- 31, 1, 56, 56, 56, 56, 29, 56, 1, 56,
- 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
- 56, 56, 56, 56, 56, 1, 56, 32, 1, 2,
- 1, 1, 4, 23, 56, 17, 56, 20, 9, 2,
- 9, 26, 14, 56, 5, 1, 1, 16, 56, 21,
- 20, 9, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 11, 56, 56, 36, 56, 1, 37,
+ 31, 1, 56, 56, 56, 56, 29, 56, 1, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 1, 56, 32, 1, 2,
+ 1, 1, 4, 23, 56, 17, 56, 20, 9, 2,
+ 9, 26, 14, 56, 5, 1, 1, 16, 56, 21,
+ 20, 9, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56, 56, 56, 56, 56,
+ 56, 56, 56, 56, 56, 56
};
register int hval = len;
@@ -39,68 +52,68 @@ hash (str, len)
{
default:
case 3:
- hval += asso_values[str[2]];
+ hval += asso_values[(unsigned char)str[2]];
case 2:
case 1:
- hval += asso_values[str[0]];
+ hval += asso_values[(unsigned char)str[0]];
break;
}
- return hval + asso_values[str[len - 1]];
+ return hval + asso_values[(unsigned char)str[len - 1]];
}
#ifdef __GNUC__
-inline
+__inline
#endif
struct kwtable *
rb_reserved_word (str, len)
- register char *str;
+ register const char *str;
register unsigned int len;
{
static struct kwtable wordlist[] =
{
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"end", kEND, kEND, EXPR_END},
- {"else", kELSE, kELSE, EXPR_BEG},
- {"case", kCASE, kCASE, EXPR_BEG},
- {"ensure", kENSURE, kENSURE, EXPR_BEG},
- {"module", kMODULE, kMODULE, EXPR_BEG},
- {"elsif", kELSIF, kELSIF, EXPR_BEG},
- {"def", kDEF, kDEF, EXPR_FNAME},
- {"rescue", kRESCUE, kRESCUE, EXPR_MID},
- {"not", kNOT, kNOT, EXPR_BEG},
- {"then", kTHEN, kTHEN, EXPR_BEG},
- {"yield", kYIELD, kYIELD, EXPR_END},
- {"for", kFOR, kFOR, EXPR_BEG},
- {"self", kSELF, kSELF, EXPR_END},
- {"false", kFALSE, kFALSE, EXPR_END},
- {"retry", kRETRY, kRETRY, EXPR_END},
- {"return", kRETURN, kRETURN, EXPR_MID},
- {"true", kTRUE, kTRUE, EXPR_END},
- {"if", kIF, kIF_MOD, EXPR_BEG},
- {"defined?", kDEFINED, kDEFINED, EXPR_END},
- {"super", kSUPER, kSUPER, EXPR_END},
- {"undef", kUNDEF, kUNDEF, EXPR_FNAME},
- {"break", kBREAK, kBREAK, EXPR_END},
- {"in", kIN, kIN, EXPR_BEG},
- {"do", kDO, kDO, EXPR_BEG},
- {"nil", kNIL, kNIL, EXPR_END},
- {"until", kUNTIL, kUNTIL_MOD, EXPR_BEG},
- {"unless", kUNLESS, kUNLESS_MOD, EXPR_BEG},
- {"or", kOR, kOR, EXPR_BEG},
- {"next", kNEXT, kNEXT, EXPR_END},
- {"when", kWHEN, kWHEN, EXPR_BEG},
- {"redo", kREDO, kREDO, EXPR_END},
- {"and", kAND, kAND, EXPR_BEG},
- {"begin", kBEGIN, kBEGIN, EXPR_BEG},
- {"__LINE__", k__LINE__, k__LINE__, EXPR_END},
- {"class", kCLASS, kCLASS, EXPR_CLASS},
- {"__FILE__", k__FILE__, k__FILE__, EXPR_END},
- {"END", klEND, klEND, EXPR_END},
- {"BEGIN", klBEGIN, klBEGIN, EXPR_END},
- {"while", kWHILE, kWHILE_MOD, EXPR_BEG},
- {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",}, {"",},
- {"",},
- {"alias", kALIAS, kALIAS, EXPR_FNAME},
+ {""}, {""}, {""}, {""}, {""}, {""},
+ {"end", kEND, kEND, EXPR_END},
+ {"else", kELSE, kELSE, EXPR_BEG},
+ {"case", kCASE, kCASE, EXPR_BEG},
+ {"ensure", kENSURE, kENSURE, EXPR_BEG},
+ {"module", kMODULE, kMODULE, EXPR_BEG},
+ {"elsif", kELSIF, kELSIF, EXPR_BEG},
+ {"def", kDEF, kDEF, EXPR_FNAME},
+ {"rescue", kRESCUE, kRESCUE, EXPR_MID},
+ {"not", kNOT, kNOT, EXPR_BEG},
+ {"then", kTHEN, kTHEN, EXPR_BEG},
+ {"yield", kYIELD, kYIELD, EXPR_END},
+ {"for", kFOR, kFOR, EXPR_BEG},
+ {"self", kSELF, kSELF, EXPR_END},
+ {"false", kFALSE, kFALSE, EXPR_END},
+ {"retry", kRETRY, kRETRY, EXPR_END},
+ {"return", kRETURN, kRETURN, EXPR_MID},
+ {"true", kTRUE, kTRUE, EXPR_END},
+ {"if", kIF, kIF_MOD, EXPR_BEG},
+ {"defined?", kDEFINED, kDEFINED, EXPR_END},
+ {"super", kSUPER, kSUPER, EXPR_END},
+ {"undef", kUNDEF, kUNDEF, EXPR_FNAME},
+ {"break", kBREAK, kBREAK, EXPR_END},
+ {"in", kIN, kIN, EXPR_BEG},
+ {"do", kDO, kDO, EXPR_BEG},
+ {"nil", kNIL, kNIL, EXPR_END},
+ {"until", kUNTIL, kUNTIL_MOD, EXPR_BEG},
+ {"unless", kUNLESS, kUNLESS_MOD, EXPR_BEG},
+ {"or", kOR, kOR, EXPR_BEG},
+ {"next", kNEXT, kNEXT, EXPR_END},
+ {"when", kWHEN, kWHEN, EXPR_BEG},
+ {"redo", kREDO, kREDO, EXPR_END},
+ {"and", kAND, kAND, EXPR_BEG},
+ {"begin", kBEGIN, kBEGIN, EXPR_BEG},
+ {"__LINE__", k__LINE__, k__LINE__, EXPR_END},
+ {"class", kCLASS, kCLASS, EXPR_CLASS},
+ {"__FILE__", k__FILE__, k__FILE__, EXPR_END},
+ {"END", klEND, klEND, EXPR_END},
+ {"BEGIN", klBEGIN, klBEGIN, EXPR_END},
+ {"while", kWHILE, kWHILE_MOD, EXPR_BEG},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""},
+ {"alias", kALIAS, kALIAS, EXPR_FNAME}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
@@ -109,9 +122,9 @@ rb_reserved_word (str, len)
if (key <= MAX_HASH_VALUE && key >= 0)
{
- register char *s = wordlist[key].name;
+ register const char *s = wordlist[key].name;
- if (*s == *str && !strcmp (str + 1, s + 1))
+ if (*str == *s && !strcmp (str + 1, s + 1))
return &wordlist[key];
}
}
diff --git a/lib/Env.rb b/lib/Env.rb
new file mode 100644
index 0000000000..b3ee3bae8a
--- /dev/null
+++ b/lib/Env.rb
@@ -0,0 +1,31 @@
+# Env.rb -- imports environment variables as global variables
+#
+# Usage:
+#
+# require 'Env'
+# p $USER
+# $USER = "matz"
+# p ENV["USER"]
+
+for k,v in ENV
+ next unless /^[a-zA-Z][_a-zA-Z0-9]*/ =~ k
+ eval <<EOS
+ $#{k} = %q!#{v}!
+ trace_var "$#{k}", proc{|v|
+ ENV[%q!#{k}!] = v;
+ $#{k} = %q!#{v}!
+ if v == nil
+ untrace_var "$#{k}"
+ end
+ }
+EOS
+end
+
+if __FILE__ == $0
+ p $TERM
+ $TERM = nil
+ p $TERM
+ p ENV["TERM"]
+ $TERM = "foo"
+ p ENV["TERM"]
+end
diff --git a/lib/README b/lib/README
new file mode 100644
index 0000000000..765c380f7d
--- /dev/null
+++ b/lib/README
@@ -0,0 +1,48 @@
+English.rb access global variables by english names
+Env.rb access environment variables as globals
+README this file
+base64.rb encode/decode base64 (obsolete)
+cgi-lib.rb decode CGI data
+complex.rb complex number suppor
+date.rb date object (compatible)
+date2.rb yet another (better) date object
+debug.rb ruby debugger
+delegate.rb delegate messages to other object
+e2mmap.rb exception utilities
+eregex.rb extended regular expression (just a proof of concept)
+final.rb add finalizer to the object (simple)
+finalize.rb add finalizer to the object
+find.rb traverse directory tree
+ftools.rb file tools
+ftplib.rb ftp access library
+getoptlong.rb GNU getoptlong compatible
+getopts.rb parse command line options
+importenv.rb access environment variables as globals
+jcode.rb japanese text handling (replace String methods)
+mailread.rb read mail headers
+mathn.rb extended math operation
+matrix.rb matrix calculation library
+mkmf.rb Makefile maker
+monitor.rb exclusive region monitor for thread
+mutex_m.rb mutex mixin
+observer.rb observer desing pattern library (provides Observable)
+open3.rb open subprocess connection stdin/stdout/stderr
+ostruct.rb python style object
+parsearg.rb argument parser using getopts
+parsedate.rb parse date string
+ping.rb check whether host is up, using TCP echo.
+profile.rb ruby profiler
+pstore.rb persistent object strage using marshal
+rational.rb rational number support
+readbytes.rb define IO#readbytes
+shell.rb shell like operation under Ruby (imcomplete)
+shellwords.rb split into words like shell
+singleton.rb singleton design pattern library
+sync.rb 2 phase lock
+telnet.rb telnet library
+tempfile.rb temporary file that automatically removed
+thread.rb thread support
+thwait.rb thread syncronization class
+timeout.rb provids timeout
+tracer.rb execution tracer
+weakref.rb weak reference class
diff --git a/lib/cgi-lib.rb b/lib/cgi-lib.rb
index 7033f0f8c1..f599f772ce 100644
--- a/lib/cgi-lib.rb
+++ b/lib/cgi-lib.rb
@@ -1,63 +1,163 @@
-#
-# Get CGI String
-#
-# EXAMPLE:
-# require "cgi-lib.rb"
-# foo = CGI.new
-# foo['field'] <== value of 'field'
-# foo.keys <== array of fields
-# and foo has Hash class methods
-
-# if running on Windows(IIS or PWS) then change cwd.
-if ENV['SERVER_SOFTWARE'] =~ /^Microsoft-/ then
- Dir.chdir ENV['PATH_TRANSLATED'].sub(/[^\\]+$/, '')
-end
+=begin
+
+= simple CGI support library
+
+= example
+
+== get form values
+
+ require "cgi-lib.rb"
+ query = CGI.new
+ query['field'] # <== value of 'field'
+ query.keys # <== array of fields
+
+and query has Hash class methods
+
+
+== get cookie values
+
+ require "cgi-lib.rb"
+ query = CGI.new
+ query.cookie['name'] # <== cookie value of 'name'
+ query.cookie.keys # <== all cookie names
+
+and query.cookie has Hash class methods
+
+
+== print HTTP header and HTML string to $>
+
+ require "cgi-lib.rb"
+ CGI::print{
+ CGI::tag("HTML"){
+ CGI::tag("HEAD"){ CGI::tag("TITLE"){"TITLE"} } +
+ CGI::tag("BODY"){
+ CGI::tag("FORM", {"ACTION"=>"test.rb", "METHOD"=>"POST"}){
+ CGI::tag("INPUT", {"TYPE"=>"submit", "VALUE"=>"submit"})
+ } +
+ CGI::tag("HR")
+ }
+ }
+ }
+
+
+== make raw cookie string
+
+ require "cgi-lib.rb"
+ cookie1 = CGI::cookie({'name' => 'name',
+ 'value' => 'value',
+ 'path' => 'path', # optional
+ 'domain' => 'domain', # optional
+ 'expires' => Time.now, # optional
+ 'secure' => true # optional
+ })
+
+ CGI::print("Content-Type: text/html", cookie1, cookie2){ "string" }
+
+
+== print HTTP header and string to $>
+
+ require "cgi-lib.rb"
+ CGI::print{ "string" }
+ # == CGI::print("Content-Type: text/html"){ "string" }
+ CGI::print("Content-Type: text/html", cookie1, cookie2){ "string" }
+
+
+=== NPH (no-parse-header) mode
+
+ require "cgi-lib.rb"
+ CGI::print("nph"){ "string" }
+ # == CGI::print("nph", "Content-Type: text/html"){ "string" }
+ CGI::print("nph", "Content-Type: text/html", cookie1, cookie2){ "string" }
+
+
+== make HTML tag string
+
+ require "cgi-lib.rb"
+ CGI::tag("element", {"attribute_name"=>"attribute_value"}){"content"}
+
+
+== make HTTP header string
+
+ require "cgi-lib.rb"
+ CGI::header # == CGI::header("Content-Type: text/html")
+ CGI::header("Content-Type: text/html", cookie1, cookie2)
+
+
+=== NPH (no-parse-header) mode
+
+ CGI::header("nph") # == CGI::header("nph", "Content-Type: text/html")
+ CGI::header("nph", "Content-Type: text/html", cookie1, cookie2)
+
+
+== escape url encode
+
+ require "cgi-lib.rb"
+ url_encoded_string = CGI::escape("string")
+
+
+== unescape url encoded
+
+ require "cgi-lib.rb"
+ string = CGI::unescape("url encoded string")
+
+
+== escape HTML &"<>
+
+ require "cgi-lib.rb"
+ CGI::escapeHTML("string")
+
+
+=end
require "delegate"
class CGI < SimpleDelegator
- attr("inputs")
+ CR = "\015"
+ LF = "\012"
+ EOL = CR + LF
- # original is CGI.pm
- def read_from_cmdline
- require "shellwords.rb"
- words = Shellwords.shellwords(if not ARGV.empty? then
- ARGV.join(' ')
- else
- STDERR.print "(offline mode: enter name=value pairs on standard input)\n" if STDIN.tty?
- readlines.join(' ').gsub(/\n/, '')
- end.gsub(/\\=/, '%3D').gsub(/\\&/, '%26'))
-
- if words.find{|x| x =~ /=/} then words.join('&') else words.join('+') end
- end
-
# escape url encode
def escape(str)
- str.gsub!(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) }
- str
+ str.gsub(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) }
end
# unescape url encoded
def unescape(str)
- str.gsub! /\+/, ' '
- str.gsub!(/%([0-9a-fA-F]{2})/){ [$1.hex].pack("c") }
- str
+ str.gsub(/\+/, ' ').gsub(/%([0-9a-fA-F]{2})/){ [$1.hex].pack("c") }
+ end
+
+ # escape HTML
+ def escapeHTML(str)
+ str.gsub(/&/, "&amp;").gsub(/\"/, "&quot;").gsub(/>/, "&gt;").gsub(/</, "&lt;")
+ end
+
+ module_function :escape, :unescape, :escapeHTML
+
+ # offline mode. read name=value pairs on standard input.
+ def read_from_cmdline
+ require "shellwords.rb"
+ words = Shellwords.shellwords(
+ if not ARGV.empty?
+ ARGV.join(' ')
+ else
+ STDERR.print "(offline mode: enter name=value pairs on standard input)\n" if STDIN.tty?
+ readlines.join(' ').gsub(/\n/, '')
+ end.gsub(/\\=/, '%3D').gsub(/\\&/, '%26'))
+
+ if words.find{|x| x =~ /=/} then words.join('&') else words.join('+') end
end
- module_function :escape, :unescape
def initialize(input = $stdin)
@inputs = {}
+ @cookie = {}
+
case ENV['REQUEST_METHOD']
when "GET"
- # exception messages should be printed to stdout.
- STDERR.reopen(STDOUT)
ENV['QUERY_STRING'] or ""
when "POST"
- # exception messages should be printed to stdout.
- STDERR.reopen(STDOUT)
- input.read Integer(ENV['CONTENT_LENGTH'])
+ input.read(Integer(ENV['CONTENT_LENGTH'])) or ""
else
read_from_cmdline
end.split(/&/).each do |x|
@@ -70,27 +170,92 @@ class CGI < SimpleDelegator
end
super(@inputs)
+
+ if ENV.has_key?('HTTP_COOKIE') or ENV.has_key?('COOKIE')
+ (ENV['HTTP_COOKIE'] or ENV['COOKIE']).split("; ").each do |x|
+ key, val = x.split(/=/,2)
+ key = unescape(key)
+ val = val.split(/&/).collect{|x|unescape(x)}.join("\0")
+ if @cookie.include?(key)
+ @cookie[key] += "\0" + val
+ else
+ @cookie[key] = val
+ end
+ end
+ end
end
- def CGI.message(msg, title = "")
- print "Content-type: text/html\n\n"
- print "<html><head><title>"
- print title
- print "</title></head><body>\n"
- print msg
- print "</body></html>\n"
- TRUE
+ attr("inputs")
+ attr("cookie")
+
+ # make HTML tag string
+ def CGI::tag(element, attributes = {})
+ "<" + escapeHTML(element) + attributes.collect{|name, value|
+ " " + escapeHTML(name) + '="' + escapeHTML(value) + '"'
+ }.to_s + ">" +
+ (iterator? ? yield.to_s + "</" + escapeHTML(element) + ">" : "")
+ end
+
+ # make raw cookie string
+ def CGI::cookie(options)
+ "Set-Cookie: " + options['name'] + '=' + escape(options['value']) +
+ (options['domain'] ? '; domain=' + options['domain'] : '') +
+ (options['path'] ? '; path=' + options['path'] : '') +
+ (options['expires'] ? '; expires=' + options['expires'].strftime("%a, %d %b %Y %X %Z") : '') +
+ (options['secure'] ? '; secure' : '')
+ end
+
+ # make HTTP header string
+ def CGI::header(*options)
+ if ENV['MOD_RUBY']
+ options.each{|option|
+ option.sub(/(.*?): (.*)/){
+ Apache::request[$1] = $2
+ }
+ }
+ Apache::request.send_http_header
+ ''
+ else
+ if options.delete("nph") or (ENV['SERVER_SOFTWARE'] =~ /IIS/)
+ [(ENV['SERVER_PROTOCOL'] or "HTTP/1.0") + " 200 OK",
+ "Date: " + Time.now.gmtime.strftime("%a, %d %b %Y %X %Z"),
+ "Server: " + (ENV['SERVER_SOFTWARE'] or ""),
+ "Connection: close"] +
+ (options.empty? ? ["Content-Type: text/html"] : options)
+ else
+ options.empty? ? ["Content-Type: text/html"] : options
+ end.join(EOL) + EOL + EOL
+ end
+ end
+
+ # print HTTP header and string to $>
+ def CGI::print(*options)
+ $>.print CGI::header(*options) + yield.to_s
+ end
+
+ # print message to $>
+ def CGI::message(message, title = "", header = ["Content-Type: text/html"])
+ if message.kind_of?(Hash)
+ title = message['title']
+ header = message['header']
+ message = message['body']
+ end
+ CGI::print(*header){
+ CGI::tag("HTML"){
+ CGI::tag("HEAD"){ CGI.tag("TITLE"){ title } } +
+ CGI::tag("BODY"){ message }
+ }
+ }
+ true
end
- def CGI.error
- m = $!.to_s.dup
- m.gsub!(/&/, '&amp;')
- m.gsub!(/</, '&lt;')
- m.gsub!(/>/, '&gt;')
- msgs = ["<pre>ERROR: <strong>#{m}</strong>"]
- msgs << $@
- msgs << "</pre>"
- CGI.message(msgs.join("\n"), "ERROR")
+ # print error message to $> and exit
+ def CGI::error
+ CGI::message({'title'=>'ERROR', 'body'=>
+ CGI::tag("PRE"){
+ "ERROR: " + CGI::tag("STRONG"){ escapeHTML($!.to_s) } + "\n" + escapeHTML($@.join("\n"))
+ }
+ })
exit
end
end
diff --git a/lib/complex.rb b/lib/complex.rb
index 59caad6ebc..0af8c20b89 100644
--- a/lib/complex.rb
+++ b/lib/complex.rb
@@ -72,6 +72,8 @@ class Complex < Numeric
end
def initialize(a, b = 0)
+ raise "non numeric 1st arg `#{a.inspect}'" if !a.kind_of? Numeric
+ raise "non numeric 2nd arg `#{b.inspect}'" if !b.kind_of? Numeric
@real = a
@image = b
end
@@ -84,7 +86,7 @@ class Complex < Numeric
elsif Complex.generic?(other)
Complex(@real + other, @image)
else
- x , y = a.coerce(self)
+ x , y = other.coerce(self)
x + y
end
end
@@ -97,7 +99,7 @@ class Complex < Numeric
elsif Complex.generic?(other)
Complex(@real - other, @image)
else
- x , y = a.coerce(self)
+ x , y = other.coerce(self)
x - y
end
end
@@ -110,7 +112,7 @@ class Complex < Numeric
elsif Complex.generic?(other)
Complex(@real * other, @image * other)
else
- x , y = a.coerce(self)
+ x , y = other.coerce(self)
x * y
end
end
@@ -121,7 +123,7 @@ class Complex < Numeric
elsif Complex.generic?(other)
Complex(@real / other, @image / other)
else
- x , y = a.coerce(self)
+ x , y = other.coerce(self)
x / y
end
end
@@ -163,7 +165,7 @@ class Complex < Numeric
r, theta = polar
Complex.polar(r.power!(other), theta * other)
else
- x , y = a.coerce(self)
+ x , y = other.coerce(self)
x / y
end
end
@@ -174,7 +176,7 @@ class Complex < Numeric
elsif Complex.generic?(other)
Complex(@real % other, @image % other)
else
- x , y = a.coerce(self)
+ x , y = other.coerce(self)
x % y
end
end
@@ -187,7 +189,7 @@ class Complex < Numeric
elsif Complex.generic?(other)
Complex(@real.divmod(other), @image.divmod(other))
else
- x , y = a.coerce(self)
+ x , y = other.coerce(self)
x.divmod(y)
end
end
@@ -222,7 +224,7 @@ class Complex < Numeric
elsif Complex.generic?(other)
@real == other and @image == 0
else
- x , y = a.coerce(self)
+ x , y = other.coerce(self)
x == y
end
end
diff --git a/lib/date2.rb b/lib/date2.rb
new file mode 100644
index 0000000000..58bfbe5a23
--- /dev/null
+++ b/lib/date2.rb
@@ -0,0 +1,267 @@
+# date2.rb: Written by Tadayoshi Funaba 1998, 1999
+# $Id: date2.rb,v 1.13 1999/08/11 01:10:02 tadf Exp $
+
+class Date
+
+ include Comparable
+
+ MONTHNAMES = [ nil, 'January', 'February', 'March',
+ 'April', 'May', 'June', 'July', 'August',
+ 'September', 'October', 'November', 'December' ]
+
+ DAYNAMES = [ 'Sunday', 'Monday', 'Tuesday',
+ 'Wednesday', 'Thursday', 'Friday', 'Saturday' ]
+
+ ITALY = 2299161 # Oct 15, 1582
+ ENGLAND = 2361222 # Sept 14, 1752
+
+ class << self
+
+ def os? (jd, sg)
+ case sg
+ when Numeric; jd < sg
+ else; not sg
+ end
+ end
+
+ def ns? (jd, sg) not os?(jd, sg) end
+
+ def civil_to_jd(y, m, d, sg=true)
+ if m <= 2
+ y -= 1
+ m += 12
+ end
+ a = (y / 100).to_i
+ b = 2 - a + (a / 4).to_i
+ jd = (365.25 * (y + 4716)).to_i +
+ (30.6001 * (m + 1)).to_i +
+ d + b - 1524
+ if os?(jd, sg)
+ jd -= b
+ end
+ jd
+ end
+
+ def jd_to_civil(jd, sg=true)
+ if os?(jd, sg)
+ a = jd
+ else
+ x = ((jd - 1867216.25) / 36524.25).to_i
+ a = jd + 1 + x - (x / 4).to_i
+ end
+ b = a + 1524
+ c = ((b - 122.1) / 365.25).to_i
+ d = (365.25 * c).to_i
+ e = ((b - d) / 30.6001).to_i
+ dom = b - d - (30.6001 * e).to_i
+ if e <= 13
+ m = e - 1
+ y = c - 4716
+ else
+ m = e - 13
+ y = c - 4715
+ end
+ return y, m, dom
+ end
+
+ def ordinal_to_jd(y, d, sg=true)
+ civil_to_jd(y, 1, d, sg)
+ end
+
+ def jd_to_ordinal(jd, sg=true)
+ y = jd_to_civil(jd, sg)[0]
+ pl = civil_to_jd(y - 1, 12, 31, ns?(jd, sg))
+ doy = jd - pl
+ return y, doy
+ end
+
+ def mjd_to_jd(mjd) mjd + 2400000.5 end
+ def jd_to_mjd(jd) jd - 2400000.5 end
+ def tjd_to_jd(tjd) tjd + 2440000.5 end
+ def jd_to_tjd(jd) jd - 2440000.5 end
+
+ def julian_leap? (y) y % 4 == 0 end
+ def gregorian_leap? (y) y % 4 == 0 and y % 100 != 0 or y % 400 == 0 end
+
+ alias_method :leap?, :gregorian_leap?
+
+ def exist3? (y, m, d, sg=ITALY)
+ if m < 0
+ m += 13
+ end
+ if d < 0
+ ljd = nil
+ 31.downto 1 do |ld|
+ break if ljd = exist3?(y, m, ld, sg)
+ end
+ x = y * 12 + m
+ ny = x / 12
+ nm = x % 12 + 1
+ d = jd_to_civil(civil_to_jd(ny, nm, 1, ns?(ljd, sg)) + d,
+ ns?(ljd, sg))[-1]
+ end
+ jd = civil_to_jd(y, m, d, sg)
+ if [y, m, d] == jd_to_civil(jd, sg)
+ jd
+ end
+ end
+
+ alias_method :exist?, :exist3?
+
+ def new3(y=-4712, m=1, d=1, sg=ITALY)
+ unless jd = exist3?(y, m, d, sg)
+ fail ArgumentError, 'invalid date'
+ end
+ new(jd, sg)
+ end
+
+ def exist2? (y, d, sg=ITALY)
+ if d < 0
+ ljd = nil
+ 366.downto 1 do |ld|
+ break if ljd = exist2?(y, ld, sg)
+ end
+ ny = y + 1
+ d = jd_to_ordinal(ordinal_to_jd(ny, 1, ns?(ljd, sg)) + d,
+ ns?(ljd, sg))[-1]
+ end
+ jd = ordinal_to_jd(y, d, sg)
+ if [y, d] == jd_to_ordinal(jd, sg)
+ jd
+ end
+ end
+
+ def new2(y=-4712, d=1, sg=ITALY)
+ unless jd = exist2?(y, d, sg)
+ fail ArgumentError, 'invalid date'
+ end
+ new(jd, sg)
+ end
+
+ def today(sg=ITALY)
+ new(civil_to_jd(*(Time.now.to_a[3..5].reverse << sg)), sg)
+ end
+
+ end
+
+ def initialize(jd=0, sg=ITALY) @jd, @sg = jd, sg end
+
+ def jd() @jd end
+
+ def mjd
+ def self.mjd() @mjd end
+ @mjd = Date.jd_to_mjd(@jd)
+ end
+
+ def tjd
+ def self.tjd() @tjd end
+ @tjd = Date.jd_to_tjd(@jd)
+ end
+
+ def civil
+ def self.year() @year end
+ def self.mon() @mon end
+ def self.month() @mon end
+ def self.mday() @mday end
+ def self.day() @mday end
+ @year, @mon, @mday = Date.jd_to_civil(@jd, @sg)
+ end
+
+ private :civil
+
+ def year
+ civil
+ @year
+ end
+
+ def yday
+ def self.yday() @yday end
+ @yday = Date.jd_to_ordinal(@jd, @sg)[-1]
+ @yday
+ end
+
+ def mon
+ civil
+ @mon
+ end
+
+ alias_method :month, :mon
+
+ def mday
+ civil
+ @mday
+ end
+
+ alias_method :day, :mday
+
+ def wday
+ def self.wday() @wday end
+ @wday = (@jd + 1) % 7
+ end
+
+ def os? () Date.os?(@jd, @sg) end
+ def ns? () Date.ns?(@jd, @sg) end
+
+ def leap?
+ def self.leap?() @leap_p end
+ @leap_p = Date.jd_to_civil(Date.civil_to_jd(year, 3, 1, ns?) - 1,
+ ns?)[-1] == 29
+ end
+
+ def + (other)
+ case other
+ when Numeric; return Date.new(@jd + other, @sg)
+ end
+ fail TypeError, 'expected numeric'
+ end
+
+ def - (other)
+ case other
+ when Numeric; return Date.new(@jd - other, @sg)
+ when Date; return @jd - other.jd
+ end
+ fail TypeError, 'expected numeric or date'
+ end
+
+ def <=> (other)
+ case other
+ when Numeric; return @jd <=> other
+ when Date; return @jd <=> other.jd
+ end
+ fail TypeError, 'expected numeric or date'
+ end
+
+ def downto(min)
+ @jd.downto(min.jd) do |jd|
+ yield Date.new(jd, @sg)
+ end
+ self
+ end
+
+ def upto(max)
+ @jd.upto(max.jd) do |jd|
+ yield Date.new(jd, @sg)
+ end
+ self
+ end
+
+ def step(limit, step)
+ @jd.step(limit.jd, step) do |jd|
+ yield Date.new(jd, @sg)
+ end
+ self
+ end
+
+ def succ() self + 1 end
+
+ alias_method :next, :succ
+
+ def eql? (other) self == other end
+ def hash() @jd end
+ def inspect() format('#<Date: %s,%s>', @jd, @sg) end
+ def to_s() format('%.4d-%02d-%02d', year, mon, mday) end
+
+ def _dump(limit) Marshal.dump([@jd, @sg], -1) end
+ def Date._load(str) Date.new(*Marshal.load(str)) end
+
+end
diff --git a/lib/debug.rb b/lib/debug.rb
index 90270a3fe7..d2f1da83ff 100644
--- a/lib/debug.rb
+++ b/lib/debug.rb
@@ -1,13 +1,29 @@
-
class DEBUGGER__
+ begin
+ require 'readline'
+ def readline(prompt, hist)
+ Readline::readline(prompt, hist)
+ end
+ rescue LoadError
+ def readline(prompt, hist)
+ STDOUT.print prompt
+ STDOUT.flush
+ line = STDIN.gets
+ line.chomp!
+ line
+ end
+ USE_READLINE = false
+ end
+
trap("INT") { DEBUGGER__::CONTEXT.interrupt }
- $DEBUG = TRUE
+ $DEBUG = true
def initialize
@break_points = []
+ @display = []
@stop_next = 1
@frames = [nil]
- @frame_pos = nil
@last_file = nil
+ @last = [nil, nil]
@scripts = {}
end
@@ -23,185 +39,271 @@ class DEBUGGER__
val
rescue
at = caller(0)
- printf "%s:%s\n", at.shift, $!
+ STDOUT.printf "%s:%s\n", at.shift, $!
for i in at
break if i =~ /`debug_(eval|command)'$/ #`
- printf "\tfrom %s\n", i
+ STDOUT.printf "\tfrom %s\n", i
end
end
end
def debug_command(file, line, id, binding)
+ frame_pos = 0
+ binding_file = file
+ binding_line = line
+ previus_line = nil
if (ENV['EMACS'] == 't')
- printf "\032\032%s:%d:\n", file, line
+ STDOUT.printf "\032\032%s:%d:\n", binding_file, binding_line
else
- printf "%s:%d:%s", file, line, line_at(file, line)
+ STDOUT.printf "%s:%d:%s", binding_file, binding_line,
+ line_at(binding_file, binding_line)
end
- @frames[-1] = binding
- STDOUT.print "(rdb:-) "
- STDOUT.flush
- while input = STDIN.gets
- input.chop!
+ @frames[0] = binding
+ display_expressions(binding)
+ while input = readline("(rdb:-) ", true)
if input == ""
input = DEBUG_LAST_CMD[0]
else
DEBUG_LAST_CMD[0] = input
end
+
case input
- when /^b(reak)?\s+(([^:\n]+:)?.+)/
- pos = $2
- if pos.index ":"
+ when /^b(?:reak)?\s+((?:[^:\n]+:)?.+)$/
+ pos = $1
+ if pos.index(":")
file, pos = pos.split(":")
end
file = File.basename(file)
if pos =~ /^\d+$/
pname = pos
- pos = Integer(pos)
+ pos = pos.to_i
else
pname = pos = pos.intern.id2name
end
- printf "Set breakpoint %d at %s:%s\n", @break_points.size, file, pname
- @break_points.push [file, pos]
- when /^b(reak)?$/, /^info b(reak)?$/
- n = 0
- for f, p in @break_points
- printf "%d %s:%s\n", n, f, p
+ @break_points.push [true, 0, file, pos]
+ STDOUT.printf "Set breakpoint %d at %s:%s\n", @break_points.size, file,
+ pname
+
+ when /^wat(?:ch)?\s+(.+)$/
+ exp = $1
+ @break_points.push [true, 1, exp]
+ STDOUT.printf "Set watchpoint %d\n", @break_points.size, exp
+
+ when /^b(?:reak)?$/, /^info b(?:reak)?$/
+ n = 1
+ STDOUT.print "breakpoints:\n"
+ for b in @break_points
+ if b[0] and (b[1] == 0)
+ STDOUT.printf " %d %s:%s\n", n, b[2], b[3]
+ end
n += 1
end
- when /^del(ete)?(\s+(\d+))?$/
- pos = $3
+ n = 1
+ STDOUT.print "\n"
+ STDOUT.print "watchpoints:\n"
+ for b in @break_points
+ if b[0] and (b[1] == 1)
+ STDOUT.printf " %d %s\n", n, b[2]
+ end
+ n += 1
+ end
+ STDOUT.print "\n"
+
+ when /^del(?:ete)?(?:\s+(\d+))?$/
+ pos = $1
unless pos
- STDOUT.print "clear all breakpoints? (y/n) "
- STDOUT.flush
- input = STDIN.gets.chop!
+ input = readline("clear all breakpoints? (y/n) ", false)
if input == "y"
- for n in @break_points.indexes
- @break_points[n] = nil
+ for b in @break_points
+ b[0] = false
end
end
else
- pos = Integer(pos)
- if @break_points[pos]
- bp = @break_points[pos]
- printf "Clear breakpoint %d at %s:%s\n", pos, bp[0], bp[1]
- @break_points[pos] = nil
+ pos = pos.to_i
+ if @break_points[pos-1]
+ @break_points[pos-1][0] = false
else
- printf "Breakpoint %d is not defined\n", pos
+ STDOUT.printf "Breakpoint %d is not defined\n", pos
end
end
- when /^c(ont)?$/
- return
- when /^s(tep)?\s*(\d+)?$/
- if $1
- lev = Integer($1)
+
+ when /^disp(?:lay)?\s+(.+)$/
+ exp = $1
+ @display.push.push [true, exp]
+ STDOUT.printf " %d: %s = %s\n", @display.size, exp,
+ debug_eval(exp, binding).to_s
+
+ when /^disp(?:lay)?$/, /^info disp(?:lay)?$/
+ display_expressions(binding)
+
+ when /^undisp(?:lay)?(?:\s+(\d+))?$/
+ pos = $1
+ unless pos
+ input = readline("clear all expressions? (y/n) ", false)
+ if input == "y"
+ for d in @display
+ d[0] = false
+ end
+ end
else
- lev = 1
+ pos = pos.to_i
+ if @display[pos-1]
+ @display[pos-1][0] = false
+ else
+ STDOUT.printf "display expression %d is not defined\n", pos
+ end
end
- @stop_next = lev
+
+ when /^c(?:ont)?$/
return
- when /^n(ext)?\s*(\d+)?$/
+
+ when /^s(?:tep)?(?:\s+(\d+))?$/
if $1
- lev = Integer($1)
+ lev = $1.to_i
else
lev = 1
end
@stop_next = lev
- @no_step = @frames.size
return
- when /^up\s*(\d+)?$/
- if $1
- lev = Integer($1)
- else
- lev = 1
- end
- unless @frame_pos
- @frame_pos = @frames.size - 1
- end
- @frame_pos -= lev
- if @frame_pos < 0
- STDOUT.print "at toplevel\n"
- @frame_pos = 0
- else
- binding = @frames[@frame_pos]
- end
- when /^down\s*(\d+)??$/
+
+ when /^n(?:ext)?(?:\s+(\d+))?$/
if $1
- lev = Integer($1)
+ lev = $1.to_i
else
lev = 1
end
- if lev >= @frames.size or @frame_pos and @frame_pos+lev >= @frames.size
- STDOUT.print "at stack bottom\n"
- @frame_pos = nil
- else
- @frame_pos += lev
- binding = @frames[@frame_pos]
- end
- when /^fin(ish)?$/
- @finish_pos = @frames.size
+ @stop_next = lev
+ @no_step = @frames.size - frame_pos
return
- when /^q(uit)?$/
- STDOUT.print "really quit? (y/n) "
- STDOUT.flush
- input = STDIN.gets.chop!
- exit if input == "y"
- when /^where$/
- at = caller(4)
- for i in at
- printf " %s\n", i
- end
- when /^l(ist)?(\s+(.*))?$/
- if $3
- b, e = $3.split(/[-,]/)
- b = Integer(b)-1
- if e
- e = Integer(e)-1
+
+ when /^w(?:here)?$/, /^f(?:rame)?$/
+ at = caller(0)
+ 0.upto(@frames.size - 1) do |n|
+ if frame_pos == n
+ STDOUT.printf "--> #%d %s\n", n, at[-(@frames.size - n)]
else
- e = b + 10
+ STDOUT.printf " #%d %s\n", n, at[-(@frames.size - n)]
end
end
- unless b
- b = line - 1
- e = line + 9
+
+ when /^l(?:ist)?(?:\s+(.+))?$/
+ if not $1
+ b = previus_line ? previus_line + 10 : binding_line - 5
+ e = b + 9
+ elsif $1 == '-'
+ b = previus_line ? previus_line - 10 : binding_line - 5
+ e = b + 9
+ else
+ b, e = $1.split(/[-,]/)
+ if e
+ b = b.to_i
+ e = e.to_i
+ else
+ b = b.to_i - 5
+ e = b + 9
+ end
+ end
+ previus_line = b
+ STDOUT.printf "[%d, %d] in %s\n", b, e, binding_file
+ line_at(binding_file, binding_line)
+ if lines = @scripts[binding_file] and lines != true
+ n = 0
+ b.upto(e) do |n|
+ if n > 0 && lines[n-1]
+ if n == binding_line
+ STDOUT.printf "=> %d %s\n", n, lines[n-1].chomp
+ else
+ STDOUT.printf " %d %s\n", n, lines[n-1].chomp
+ end
+ end
+ end
+ else
+ STDOUT.printf "no sourcefile available for %s\n", binding_file
+ end
+
+ when /^up(?:\s+(\d+))?$/
+ previus_line = nil
+ if $1
+ lev = $1.to_i
+ else
+ lev = 1
+ end
+ frame_pos += lev
+ if frame_pos >= @frames.size
+ frame_pos = @frames.size - 1
+ STDOUT.print "at toplevel\n"
end
- p [b,e]
- line_at(file, line)
- if lines = @scripts[file] and lines != TRUE
- n = b+1
- for l in lines[b..e]
- printf "%4d %s", n, l
- n += 1
- end
- else
- printf "no sourcefile available for %s\n", file
+ binding = @frames[frame_pos]
+ info, binding_file, binding_line = frame_info(frame_pos)
+ STDOUT.printf "#%d %s\n", frame_pos, info
+
+ when /^down(?:\s+(\d+))?$/
+ previus_line = nil
+ if $1
+ lev = $1.to_i
+ else
+ lev = 1
+ end
+ frame_pos -= lev
+ if frame_pos < 0
+ frame_pos = 0
+ STDOUT.print "at stack bottom\n"
end
+ binding = @frames[frame_pos]
+ info, binding_file, binding_line = frame_info(frame_pos)
+ STDOUT.printf "#%d %s\n", frame_pos, info
+
+ when /^fi(?:nish)?$/
+ @finish_pos = @frames.size - frame_pos
+ frame_pos = 0
+ return
+
+ when /^q(?:uit)?$/
+ input = readline("really quit? (y/n) ", false)
+ exit if input == "y"
+
when /^p\s+/
- p debug_eval($', binding) #'
+ p debug_eval($', binding)
+
else
v = debug_eval(input, binding)
- p v unless v == nil
+ p v unless (v == nil)
end
- STDOUT.print "(rdb:-) "
- STDOUT.flush
end
end
+ def display_expressions(binding)
+ n = 1
+ for d in @display
+ if d[0]
+ STDOUT.printf "%d: %s = %s\n", n, d[1], debug_eval(d[1], binding).to_s
+ end
+ n += 1
+ end
+ end
+
+ def frame_info(pos = 0)
+ info = caller(0)[-(@frames.size - pos)]
+ info.sub(/:in `.*'$/, "") =~ /^(.*):(\d+)$/ #`
+ [info, $1, $2.to_i]
+ end
+
def line_at(file, line)
lines = @scripts[file]
if lines
- return "\n" if lines == TRUE
+ return "\n" if lines == true
line = lines[line-1]
return "\n" unless line
return line
end
save = $DEBUG
begin
- $DEBUG = FALSE
+ $DEBUG = false
f = open(file)
lines = @scripts[file] = f.readlines
rescue
$DEBUG = save
- @scripts[file] = TRUE
+ @scripts[file] = true
return "\n"
end
line = lines[line-1]
@@ -219,19 +321,44 @@ class DEBUGGER__
def check_break_points(file, pos, binding, id)
file = File.basename(file)
- if @break_points.include? [file, pos]
- index = @break_points.index([file, pos])
- printf "Breakpoint %d, %s at %s:%s\n",
- index, debug_funcname(id), file, pos
- return TRUE
+ n = 1
+ for b in @break_points
+ if b[0]
+ if b[1] == 0 and b[2] == file and b[3] == pos
+ STDOUT.printf "breakpoint %d, %s at %s:%s\n", n, debug_funcname(id),
+ file, pos
+ return true
+ elsif b[1] == 1 and debug_eval(b[2], binding)
+ STDOUT.printf "watchpoint %d, %s at %s:%s\n", n, debug_funcname(id),
+ file, pos
+ return true
+ end
+ end
+ n += 1
+ end
+ return false
+ end
+
+ def excn_handle(file, line, id, binding)
+ fs = @frames.size
+ tb = caller(0)[-fs..-1]
+
+ STDOUT.printf "%s\n", $!
+ for i in tb
+ STDOUT.printf "\tfrom %s\n", i
end
- return FALSE
+ debug_command(file, line, id, binding)
end
def trace_func(event, file, line, id, binding)
- if event == 'line'
- if @no_step == nil or @no_step >= @frames.size
+ case event
+ when 'line'
+ if !@no_step or @frames.size == @no_step
@stop_next -= 1
+ elsif @frames.size < @no_step
+ @stop_next = 0 # break here before leaving...
+ else
+ # nothing to do. skipped.
end
if @stop_next == 0
if [file, line] == @last
@@ -245,21 +372,25 @@ class DEBUGGER__
if check_break_points(file, line, binding, id)
debug_command(file, line, id, binding)
end
- end
- if event == 'call'
- @frames.push binding
+
+ when 'call'
+ @frames.unshift binding
if check_break_points(file, id.id2name, binding, id)
debug_command(file, line, id, binding)
end
- end
- if event == 'class'
- @frames.push binding
- end
- if event == 'return' or event == 'end'
- if @finish_pos == @frames.size
+
+ when 'class'
+ @frames.unshift binding
+
+ when 'return', 'end'
+ if @frames.size == @finish_pos
@stop_next = 1
end
- @frames.pop
+ @frames.shift
+
+ when 'raise'
+ excn_handle(file, line, id, binding)
+
end
@last_file = file
end
@@ -267,6 +398,6 @@ class DEBUGGER__
CONTEXT = new
end
-set_trace_func proc{|event, file, line, id, binding|
+set_trace_func proc{|event, file, line, id, binding,*rest|
DEBUGGER__::CONTEXT.trace_func event, file, line, id, binding
}
diff --git a/lib/delegate.rb b/lib/delegate.rb
index 0771f2feeb..29f2a5ded2 100644
--- a/lib/delegate.rb
+++ b/lib/delegate.rb
@@ -34,14 +34,8 @@ class Delegator
begin
__getobj__.__send__(:#{method}, *args, &block)
rescue Exception
- c = -caller(0).size
- if /:in `__getobj__'$/ =~ $@[c-1] #`
- n = 1
- else
- c -= 1
- n = 2
- end
- $@[c,n] = nil
+ $@.delete_if{|s| /:in `__getobj__'$/ =~ s} #`
+ $@.delete_if{|s| /^\\(eval\\):/ =~ s}
raise
end
end
diff --git a/lib/e2mmap.rb b/lib/e2mmap.rb
index bf860dc5c1..e04ed4a5b4 100644
--- a/lib/e2mmap.rb
+++ b/lib/e2mmap.rb
@@ -1,17 +1,46 @@
#
# e2mmap.rb - for ruby 1.1
-# $Release Version: 1.2$
-# $Revision: 1.8 $
-# $Date: 1998/08/19 15:22:22 $
+# $Release Version: 2.0$
+# $Revision: 1.10 $
+# $Date: 1999/02/17 12:33:17 $
# by Keiju ISHITSUKA
#
# --
# Usage:
#
+# U1)
# class Foo
# extend Exception2MassageMapper
+# def_e2message ExistingExceptionClass, "message..."
# def_exception :NewExceptionClass, "message..."[, superclass]
+# ...
+# end
+#
+# U2)
+# module Error
+# extend Exception2MassageMapper
# def_e2meggage ExistingExceptionClass, "message..."
+# def_exception :NewExceptionClass, "message..."[, superclass]
+# ...
+# end
+# class Foo
+# include Exp
+# ...
+# end
+#
+# foo = Foo.new
+# foo.Fail ....
+#
+# U3)
+# module Error
+# extend Exception2MassageMapper
+# def_e2message ExistingExceptionClass, "message..."
+# def_exception :NewExceptionClass, "message..."[, superclass]
+# ...
+# end
+# class Foo
+# extend Exception2MessageMapper
+# include Error
# ...
# end
#
@@ -19,113 +48,149 @@
# Foo.Fail ExistingExceptionClass, arg...
#
#
-if VERSION < "1.1"
- require "e2mmap1_0.rb"
-else
+fail "Use Ruby 1.1" if VERSION < "1.1"
+
+module Exception2MessageMapper
+ @RCS_ID='-$Id: e2mmap.rb,v 1.10 1999/02/17 12:33:17 keiju Exp keiju $-'
+
+ E2MM = Exception2MessageMapper
+
+ def E2MM.extend_object(cl)
+ super
+ cl.bind(self) unless cl == E2MM
+ end
- module Exception2MessageMapper
- @RCS_ID='-$Id: e2mmap.rb,v 1.8 1998/08/19 15:22:22 keiju Exp keiju $-'
-
- E2MM = Exception2MessageMapper
+ # °ÊÁ°¤È¤Î¸ß´¹À­¤Î¤¿¤á¤Ë»Ä¤·¤Æ¤¢¤ë.
+ def E2MM.extend_to(b)
+ c = eval("self", b)
+ c.extend(self)
+ end
- def E2MM.extend_object(cl)
+ def bind(cl)
+ self.module_eval %[
+ def Raise(err = nil, *rest)
+ Exception2MessageMapper.Raise(self.type, err, *rest)
+ end
+ alias Fail Raise
+
+ def self.append_features(mod)
+ super
+ mod.extend Exception2MessageMapper
+ end
+ ]
+ end
+
+ # Fail(err, *rest)
+ # err: Îã³°
+ # rest: ¥á¥Ã¥»¡¼¥¸¤ËÅϤ¹¥Ñ¥é¥á¡¼¥¿
+ #
+ def Raise(err = nil, *rest)
+ E2MM.Raise(self, err, *rest)
+ end
+ alias Fail Raise
+
+ # ²áµî¤Î¸ß´¹À­¤Î¤¿¤á
+ alias fail! fail
+ def fail(err = nil, *rest)
+ begin
+ E2MM.Fail(self, err, *rest)
+ rescue E2MM::ErrNotRegisteredException
super
- cl.bind(self)
end
-
- # backward compatibility
- def E2MM.extend_to(b)
- c = eval("self", b)
- c.extend(self)
- end
-
- # public :fail
- alias fail! fail
+ end
+ class << self
+ public :fail
+ end
- #def fail(err = nil, *rest)
- # super
- #end
+
+ # def_e2message(c, m)
+ # c: exception
+ # m: message_form
+ # Îã³°c¤Î¥á¥Ã¥»¡¼¥¸¤òm¤È¤¹¤ë.
+ #
+ def def_e2message(c, m)
+ E2MM.def_e2message(self, c, m)
+ end
+
+ # def_exception(c, m)
+ # n: exception_name
+ # m: message_form
+ # s: Îã³°¥¹¡¼¥Ñ¡¼¥¯¥é¥¹(¥Ç¥Õ¥©¥ë¥È: StandardError)
+ # Î㳰̾``c''¤ò¤â¤ÄÎã³°¤òÄêµÁ¤·, ¤½¤Î¥á¥Ã¥»¡¼¥¸¤òm¤È¤¹¤ë.
+ #
+ def def_exception(n, m, s = StandardError)
+ E2MM.def_exception(self, n, m, s)
+ end
- def Fail(err = nil, *rest)
- Exception2MessageMapper.Fail Exception2MessageMapper::ErrNotRegisteredException, err.inspect
- end
-
- def bind(cl)
- self.module_eval %q^
- E2MM_ErrorMSG = {} unless self.const_defined?(:E2MM_ErrorMSG)
- # fail(err, *rest)
- # err: Exception
- # rest: Parameter accompanied with the exception
- #
- def self.Fail(err = nil, *rest)
- if form = E2MM_ErrorMSG[err]
- $! = err.new(sprintf(form, *rest))
- $@ = caller(0) if $@.nil?
- $@.shift
- # e2mm_fail()
- raise()
-# elsif self == Exception2MessageMapper
-# fail Exception2MessageMapper::ErrNotRegisteredException, err.to_s
- else
-# print "super\n"
- super
- end
- end
+ #
+ # Private definitions.
+ #
+ # {[class, exp] => message, ...}
+ @MessageMap = {}
+
+ # E2MM.def_exception(k, e, m)
+ # k: Îã³°¤òÄêµÁ¤¹¤ë¥¯¥é¥¹
+ # e: exception
+ # m: message_form
+ # Îã³°c¤Î¥á¥Ã¥»¡¼¥¸¤òm¤È¤¹¤ë.
+ #
+ def E2MM.def_e2message(k, c, m)
+ E2MM.instance_eval{@MessageMap[[k, c]] = m}
+ c
+ end
+
+ # E2MM.def_exception(k, c, m)
+ # k: Îã³°¤òÄêµÁ¤¹¤ë¥¯¥é¥¹
+ # n: exception_name
+ # m: message_form
+ # s: Îã³°¥¹¡¼¥Ñ¡¼¥¯¥é¥¹(¥Ç¥Õ¥©¥ë¥È: StandardError)
+ # Î㳰̾``c''¤ò¤â¤ÄÎã³°¤òÄêµÁ¤·, ¤½¤Î¥á¥Ã¥»¡¼¥¸¤òm¤È¤¹¤ë.
+ #
+ def E2MM.def_exception(k, n, m, s = StandardError)
+ n = n.id2name if n.kind_of?(Fixnum)
+ e = Class.new(s)
+ E2MM.instance_eval{@MessageMap[[k, e]] = m}
+ k.const_set(n, e)
+ end
- # ²áµî¤Î¸ß´¹À­¤Î¤¿¤á
- def self.fail(err = nil, *rest)
- if form = E2MM_ErrorMSG[err]
- $! = err.new(sprintf(form, *rest))
- $@ = caller(0) if $@.nil?
- $@.shift
- # e2mm_fail()
- raise()
-# elsif self == Exception2MessageMapper
-# fail Exception2MessageMapper::ErrNotRegisteredException, err.to_s
- else
-# print "super\n"
- super
- end
- end
- class << self
- public :fail
- end
-
- # def_exception(c, m)
- # c: exception
- # m: message_form
- #
- def self.def_e2message(c, m)
- E2MM_ErrorMSG[c] = m
- end
-
- # def_exception(c, m)
- # n: exception_name
- # m: message_form
- # s: superclass_of_exception (default: Exception)
- # defines excaption named ``c'', whose message is ``m''.
- #
- #def def_exception(n, m)
- def self.def_exception(n, m, s = nil)
- n = n.id2name if n.kind_of?(Fixnum)
- unless s
- if defined?(StandardError)
- s = StandardError
- else
- s = Exception
- end
- end
- e = Class.new(s)
+ # Fail(klass, err, *rest)
+ # klass: Îã³°¤ÎÄêµÁ¤µ¤ì¤Æ¤¤¤ë¥¯¥é¥¹
+ # err: Îã³°
+ # rest: ¥á¥Ã¥»¡¼¥¸¤ËÅϤ¹¥Ñ¥é¥á¡¼¥¿
+ #
+ def E2MM.Raise(klass = E2MM, err = nil, *rest)
+ if form = e2mm_message(klass, err)
+ $! = err.new(sprintf(form, *rest))
+ $@ = caller(1) if $@.nil?
+ #p $@
+ #p __FILE__
+ $@.shift if $@[0] =~ /^#{Regexp.quote(__FILE__)}:/
+ raise
+ else
+ E2MM.Fail E2MM, ErrNotRegisteredException, err.inspect
+ end
+ end
+ class <<E2MM
+ alias Fail Raise
+ end
- const_set(n, e)
- E2MM_ErrorMSG[e] = m
- # const_get(:E2MM_ErrorMSG)[e] = m
- end
- ^
+ def E2MM.e2mm_message(klass, exp)
+ for c in klass.ancestors
+ if mes = @MessageMap[[c,exp]]
+ p mes
+ m = klass.instance_eval('"' + mes + '"')
+ return m
end
-
- extend E2MM
- def_exception(:ErrNotClassOrModule, "Not Class or Module")
- def_exception(:ErrNotRegisteredException, "not registerd exception(%s)")
end
+ nil
+ end
+ class <<self
+ alias message e2mm_message
+ end
+
+ E2MM.def_exception(E2MM,
+ :ErrNotRegisteredException,
+ "not registerd exception(%s)")
end
+
+
diff --git a/lib/final.rb b/lib/final.rb
new file mode 100644
index 0000000000..cdffd941e7
--- /dev/null
+++ b/lib/final.rb
@@ -0,0 +1,41 @@
+#
+# $Id$
+# Copyright (C) 1998 Yukihiro Matsumoto. All rights reserved.
+
+# The ObjectSpace extension:
+#
+# ObjectSpace.define_finalizer(obj, proc=lambda())
+#
+# Defines the finalizer for the specified object.
+#
+# ObjectSpace.undefine_finalizer(obj)
+#
+# Removes the finalizers for the object. If multiple finalizers are
+# defined for the object, all finalizers will be removed.
+#
+
+module ObjectSpace
+ Finalizers = {}
+ def define_finalizer(obj, proc=lambda())
+ ObjectSpace.call_finalizer(obj)
+ if assoc = Finalizers[obj.id]
+ assoc.push(proc)
+ else
+ Finalizers[obj.id] = [proc]
+ end
+ end
+ def undefine_finalizer(obj)
+ Finalizers.delete(obj.id)
+ end
+ module_function :define_finalizer, :undefine_finalizer
+
+ Generic_Finalizer = proc {|id|
+ if Finalizers.key? id
+ for proc in Finalizers[id]
+ proc.call(id)
+ end
+ Finalizers.delete(id)
+ end
+ }
+ add_finalizer Generic_Finalizer
+end
diff --git a/lib/finalize.rb b/lib/finalize.rb
index a07e67d093..3cf79ff92f 100644
--- a/lib/finalize.rb
+++ b/lib/finalize.rb
@@ -157,7 +157,7 @@ module Finalizer
# method to call finalize_* safely.
def safe
old_status = Thread.critical
- Thread.critical = TRUE
+ Thread.critical = true
ObjectSpace.remove_finalizer(@proc)
yield
ObjectSpace.add_finalizer(@proc)
diff --git a/lib/ftools.rb b/lib/ftools.rb
index 7ccc7a4468..39d6ca9462 100644
--- a/lib/ftools.rb
+++ b/lib/ftools.rb
@@ -24,6 +24,9 @@ class << File
fsize = 1024 if fsize < 512
fsize = TOO_BIG if fsize > TOO_BIG
+ fmode = stat(from).mode
+ tpath = to
+
from = open(from, "r")
from.binmode
to = open(to, "w")
@@ -47,6 +50,7 @@ class << File
to.close
from.close
end
+ chmod(fmode, tpath)
ret
end
@@ -63,13 +67,24 @@ class << File
to = catname(from, to)
$stderr.print from, " -> ", to, "\n" if verbose
- if PLATFORM =~ /djgpp|cygwin|mswin32/ and FileTest.file? to
+ if RUBY_PLATFORM =~ /djgpp|cygwin|mswin32/ and FileTest.file? to
unlink to
end
+ fstat = stat(from)
begin
rename from, to
rescue
- syscopy from, to and unlink from
+ begin
+ symlink File.readlink(from), to and unlink from
+ rescue
+ from_stat = stat(from)
+ syscopy from, to and unlink from
+ utime(from_stat.atime, from_stat.mtime, to)
+ begin
+ chown(fstat.uid, fstat.gid, tpath)
+ rescue
+ end
+ end
end
end
@@ -98,7 +113,8 @@ class << File
if fr = from.read(fsize)
tr = to.read(fr.size)
else
- ret = !to.read(fsize)
+ ret = to.read(fsize)
+ ret = !ret || ret.length == 0
break
end
end
@@ -137,7 +153,9 @@ class << File
parent = dirname(dir)
makedirs parent unless FileTest.directory? parent
$stderr.print "mkdir ", dir, "\n" if verbose
- Dir.mkdir dir, mode
+ if basename(dir) != ""
+ Dir.mkdir dir, mode
+ end
end
end
@@ -154,7 +172,7 @@ class << File
def install(from, to, mode = nil, verbose = false)
to = catname(from, to)
unless FileTest.exist? to and cmp from, to
- unlink to if FileTest.exist? to
+ safe_unlink to if FileTest.exist? to
cp from, to, verbose
chmod mode, to, verbose if mode
end
diff --git a/lib/ftplib.rb b/lib/ftplib.rb
index 617d85899b..9336e0a8c2 100644
--- a/lib/ftplib.rb
+++ b/lib/ftplib.rb
@@ -150,16 +150,23 @@ class FTP
end
def sendport(host, port)
- hbytes = host.split(".")
- pbytes = [port / 256, port % 256]
- bytes = hbytes + pbytes
- cmd = "PORT " + bytes.join(",")
+ af = (@sock.peeraddr)[0]
+ if af == "AF_INET"
+ hbytes = host.split(".")
+ pbytes = [port / 256, port % 256]
+ bytes = hbytes + pbytes
+ cmd = "PORT " + bytes.join(",")
+ elsif af == "AF_INET6"
+ cmd = "EPRT |2|" + host + "|" + sprintf("%d", port) + "|"
+ else
+ raise FTPProtoError, host
+ end
voidcmd(cmd)
end
private :sendport
def makeport
- sock = TCPserver.open(0)
+ sock = TCPserver.open(@sock.addr[3], 0)
port = sock.addr[1]
host = TCPsocket.getaddress(@sock.addr[2])
resp = sendport(host, port)
@@ -167,9 +174,20 @@ class FTP
end
private :makeport
+ def makepasv
+ if @sock.peeraddr[0] == "AF_INET"
+ host, port = parse227(sendcmd("PASV"))
+ else
+ host, port = parse229(sendcmd("EPSV"))
+# host, port = parse228(sendcmd("LPSV"))
+ end
+ return host, port
+ end
+ private :makepasv
+
def transfercmd(cmd)
if @passive
- host, port = parse227(sendcmd("PASV"))
+ host, port = makepasv
conn = open_socket(host, port)
resp = sendcmd(cmd)
if resp[0] != ?1
@@ -293,11 +311,7 @@ class FTP
buf = file.gets
break if buf == nil
if buf[-2, 2] != CRLF
- if buf[-1] == ?\r or
- buf[-1] == ?\n
- buf = buf[0 .. -2]
- end
- buf = buf + CRLF
+ buf = buf.chop + CRLF
end
conn.write(buf)
callback.call(buf) if use_callback
@@ -545,6 +559,57 @@ class FTP
end
private :parse227
+ def parse228(resp)
+ if resp[0, 3] != "228"
+ raise FTPReplyError, resp
+ end
+ left = resp.index("(")
+ right = resp.index(")")
+ if left == nil or right == nil
+ raise FTPProtoError, resp
+ end
+ numbers = resp[left + 1 .. right - 1].split(",")
+ if numbers[0] == "4"
+ if numbers.length != 9 || numbers[1] != "4" || numbers[2 + 4] != "2"
+ raise FTPProtoError, resp
+ end
+ host = numbers[2, 4].join(".")
+ port = (numbers[7].to_i << 8) + numbers[8].to_i
+ elsif numbers[0] == "6"
+ if numbers.length != 21 || numbers[1] != "16" || numbers[2 + 16] != "2"
+ raise FTPProtoError, resp
+ end
+ v6 = ["", "", "", "", "", "", "", ""]
+ for i in 0 .. 7
+ v6[i] = sprintf("%02x%02x", numbers[(i * 2) + 2].to_i,
+ numbers[(i * 2) + 3].to_i)
+ end
+ host = v6[0, 8].join(":")
+ port = (numbers[19].to_i << 8) + numbers[20].to_i
+ end
+ return host, port
+ end
+ private :parse228
+
+ def parse229(resp)
+ if resp[0, 3] != "229"
+ raise FTPReplyError, resp
+ end
+ left = resp.index("(")
+ right = resp.index(")")
+ if left == nil or right == nil
+ raise FTPProtoError, resp
+ end
+ numbers = resp[left + 1 .. right - 1].split(resp[left + 1, 1])
+ if numbers.length != 4
+ raise FTPProtoError, resp
+ end
+ port = numbers[3].to_i
+ host = (@sock.peeraddr())[3]
+ return host, port
+ end
+ private :parse228
+
def parse257(resp)
if resp[0, 3] != "257"
raise FTPReplyError, resp
diff --git a/lib/getoptlong.rb b/lib/getoptlong.rb
new file mode 100644
index 0000000000..a37714cafd
--- /dev/null
+++ b/lib/getoptlong.rb
@@ -0,0 +1,473 @@
+# -*- Ruby -*-
+# Copyright (C) 1998 Motoyuki Kasahara
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+
+#
+# Documents and latest version of `getoptlong.rb' are found at:
+# http://www.sra.co.jp/people/m-kasahr/ruby/getoptlong/
+#
+
+#
+# Parse command line options just like GNU getopt_long().
+#
+class GetoptLong
+ #
+ # Orderings.
+ #
+ ORDERINGS = [REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2]
+
+ #
+ # Argument flags.
+ #
+ ARGUMENT_FLAGS = [NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1,
+ OPTIONAL_ARGUMENT = 2]
+
+ #
+ # Status codes.
+ #
+ STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0..2
+
+ #
+ # Error types.
+ #
+ class AmbigousOption < StandardError; end
+ class NeedlessArgument < StandardError; end
+ class MissingArgument < StandardError; end
+ class InvalidOption < StandardError; end
+
+ #
+ # Initializer.
+ #
+ def initialize(*arguments)
+ #
+ # Current ordering.
+ #
+ if ENV.include?('POSIXLY_CORRECT')
+ @ordering = REQUIRE_ORDER
+ else
+ @ordering = PERMUTE
+ end
+
+ #
+ # Hash table of option names.
+ # Keyes of the table are option names, and their values are canonical
+ # names of the options.
+ #
+ @canonical_names = Hash.new
+
+ #
+ # Hash table of argument flags.
+ # Keyes of the table are option names, and their values are argument
+ # flags of the options.
+ #
+ @argument_flags = Hash.new
+
+ #
+ # Whether error messages are output to stderr.
+ #
+ @quiet = FALSE
+
+ #
+ # Status code.
+ #
+ @status = STATUS_YET
+
+ #
+ # Error code.
+ #
+ @error = nil
+
+ #
+ # Error message.
+ #
+ @error_message = nil
+
+ #
+ # Rest of catinated short options.
+ #
+ @rest_singles = ''
+
+ #
+ # List of non-option-arguments.
+ # Append them to ARGV when option processing is terminated.
+ #
+ @non_option_arguments = Array.new
+
+ if 0 < arguments.length
+ set_options(*arguments)
+ end
+ end
+
+ #
+ # Set ordering.
+ #
+ def ordering=(ordering)
+ #
+ # The method is failed if option processing has already started.
+ #
+ if @status != STATUS_YET
+ set_error(ArgumentError, "argument error")
+ raise RuntimeError,
+ "invoke ordering=, but option processing has already started"
+ end
+
+ #
+ # Check ordering.
+ #
+ if !ORDERINGS.include?(ordering)
+ raise ArgumentError, "invalid ordering `#{ordering}'"
+ end
+ if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT')
+ @ordering = REQUIRE_ORDER
+ else
+ @ordering = ordering
+ end
+ end
+
+ #
+ # Return ordering.
+ #
+ attr_reader :ordering
+
+ #
+ # Set options
+ #
+ def set_options(*arguments)
+ #
+ # The method is failed if option processing has already started.
+ #
+ if @status != STATUS_YET
+ raise RuntimeError,
+ "invoke set_options, but option processing has already started"
+ end
+
+ #
+ # Clear tables of option names and argument flags.
+ #
+ @canonical_names.clear
+ @argument_flags.clear
+
+ arguments.each do |arg|
+ #
+ # Each argument must be an Array.
+ #
+ if !arg.is_a?(Array)
+ raise ArgumentError, "the option list contains non-Array argument"
+ end
+
+ #
+ # Find an argument flag and it set to `argument_flag'.
+ #
+ argument_flag = nil
+ arg.each do |i|
+ if ARGUMENT_FLAGS.include?(i)
+ if argument_flag != nil
+ raise ArgumentError, "too many argument-flags"
+ end
+ argument_flag = i
+ end
+ end
+ raise ArgumentError, "no argument-flag" if argument_flag == nil
+
+ canonical_name = nil
+ arg.each do |i|
+ #
+ # Check an option name.
+ #
+ next if i == argument_flag
+ begin
+ if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/
+ raise ArgumentError, "an invalid option `#{i}'"
+ end
+ if (@canonical_names.include?(i))
+ raise ArgumentError, "option redefined `#{i}'"
+ end
+ rescue
+ @canonical_names.clear
+ @argument_flags.clear
+ raise
+ end
+
+ #
+ # Register the option (`i') to the `@canonical_names' and
+ # `@canonical_names' Hashes.
+ #
+ if canonical_name == nil
+ canonical_name = i
+ end
+ @canonical_names[i] = canonical_name
+ @argument_flags[i] = argument_flag
+ end
+ raise ArgumentError, "no option name" if canonical_name == nil
+ end
+ return self
+ end
+
+ #
+ # Set/Unset `quit' mode.
+ #
+ attr_writer :quiet
+
+ #
+ # Return the flag of `quiet' mode.
+ #
+ attr_reader :quiet
+
+ #
+ # `quiet?' is an alias of `quiet'.
+ #
+ alias quiet? quiet
+
+ #
+ # Termintate option processing.
+ #
+ def terminate
+ return if @status == STATUS_TERMINATED
+ raise RuntimeError, "an error has occured" if @error != nil
+
+ @status = STATUS_TERMINATED
+ @non_option_arguments.reverse_each do |argument|
+ ARGV.unshift(argument)
+ end
+
+ @canonical_names = nil
+ @argument_flags = nil
+ @rest_singles = nil
+ @non_option_arguments = nil
+
+ return self
+ end
+
+ #
+ # Examine whether option processing is termintated or not.
+ #
+ def terminated?
+ return @status == STATUS_TERMINATED
+ end
+
+ #
+ # Set an error (protected).
+ #
+ def set_error(type, message)
+ $stderr.print("#{$0}: #{message}\n") if !@quiet
+
+ @error = type
+ @error_message = message
+ @canonical_names = nil
+ @argument_flags = nil
+ @rest_singles = nil
+ @non_option_arguments = nil
+
+ raise type, message
+ end
+ protected :set_error
+
+ #
+ # Examine whether an option processing is failed.
+ #
+ attr_reader :error
+
+ #
+ # `error?' is an alias of `error'.
+ #
+ alias error? error
+
+ #
+ # Return an error message.
+ #
+ def error_message
+ return @error_message
+ end
+
+ #
+ # Get next option name and its argument as an array.
+ #
+ def get
+ name, argument = nil, ''
+
+ #
+ # Check status.
+ #
+ return if @error != nil
+ case @status
+ when STATUS_YET
+ @status = STATUS_STARTED
+ when STATUS_TERMINATED
+ return
+ end
+
+ #
+ # Get next option argument.
+ #
+ if 0 < @rest_singles.length
+ $_ = '-' + @rest_singles
+ elsif (ARGV.length == 0)
+ terminate
+ return nil
+ elsif @ordering == PERMUTE
+ while 0 < ARGV.length && ARGV[0] !~ /^-./
+ @non_option_arguments.push(ARGV.shift)
+ end
+ if ARGV.length == 0
+ terminate
+ return
+ end
+ $_ = ARGV.shift
+ elsif @ordering == REQUIRE_ORDER
+ if (ARGV[0] !~ /^-./)
+ terminate
+ return nil
+ end
+ $_ = ARGV.shift
+ else
+ $_ = ARGV.shift
+ end
+
+ #
+ # Check the special argument `--'.
+ # `--' indicates the end of the option list.
+ #
+ if $_ == '--' && @rest_singles.length == 0
+ terminate
+ return nil
+ end
+
+ #
+ # Check for long and short options.
+ #
+ if /^(--[^=]+)/ && @rest_singles.length == 0
+ #
+ # This is a long style option, which start with `--'.
+ #
+ pattern = $1
+ if @canonical_names.include?(pattern)
+ name = pattern
+ else
+ #
+ # The option `name' is not registered in `@canonical_names'.
+ # It may be an abbreviated.
+ #
+ match_count = 0
+ @canonical_names.each_key do |key|
+ if key.index(pattern) == 0
+ name = key
+ match_count += 1
+ end
+ end
+ if 2 <= match_count
+ set_error(AmbigousOption, "option `#{$_}' is ambiguous")
+ elsif match_count == 0
+ set_error(InvalidOption, "unrecognized option `#{$_}'")
+ end
+ end
+
+ #
+ # Check an argument to the option.
+ #
+ if @argument_flags[name] == REQUIRED_ARGUMENT
+ if /=(.*)$/
+ argument = $1
+ elsif 0 < ARGV.length
+ argument = ARGV.shift
+ else
+ set_error(MissingArgument, "option `#{$_}' requires an argument")
+ end
+ elsif @argument_flags[name] == OPTIONAL_ARGUMENT
+ if /=(.*)$/
+ argument = $1
+ elsif 0 < ARGV.length && ARGV[0] !~ /^-./
+ argument = ARGV.shift
+ else
+ argument = ''
+ end
+ elsif /=(.*)$/
+ set_error(NeedlessArgument,
+ "option `#{name}' doesn't allow an argument")
+ end
+
+ elsif /^(-(.))(.*)/
+ #
+ # This is a short style option, which start with `-' (not `--').
+ # Short options may be catinated (e.g. `-l -g' is equivalent to
+ # `-lg').
+ #
+ name, ch, @rest_singles = $1, $2, $3
+
+ if @canonical_names.include?(name)
+ #
+ # The option `name' is found in `@canonical_names'.
+ # Check its argument.
+ #
+ if @argument_flags[name] == REQUIRED_ARGUMENT
+ if 0 < @rest_singles.length
+ argument = @rest_singles
+ @rest_singles = ''
+ elsif 0 < ARGV.length
+ argument = ARGV.shift
+ else
+ # 1003.2 specifies the format of this message.
+ set_error(MissingArgument, "option requires an argument -- #{ch}")
+ end
+ elsif @argument_flags[name] == OPTIONAL_ARGUMENT
+ if 0 < @rest_singles.length
+ argument = @rest_singles
+ @rest_singles = ''
+ elsif 0 < ARGV.length && ARGV[0] !~ /^-./
+ argument = ARGV.shift
+ else
+ argument = ''
+ end
+ end
+ else
+ #
+ # This is an invalid option.
+ # 1003.2 specifies the format of this message.
+ #
+ if ENV.include?('POSIXLY_CORRECT')
+ set_error(InvalidOption, "illegal option -- #{ch}")
+ else
+ set_error(InvalidOption, "invalid option -- #{ch}")
+ end
+ end
+ else
+ #
+ # This is a non-option argument.
+ # Only RETURN_IN_ORDER falled into here.
+ #
+ return '', $_
+ end
+
+ return @canonical_names[name], argument
+ end
+
+ #
+ # `get_option' is an alias of `get'.
+ #
+ alias get_option get
+
+ #
+ # Iterator version of `get'.
+ #
+ def each
+ loop do
+ name, argument = get_option
+ break if name == nil
+ yield name, argument
+ end
+ end
+
+ #
+ # `each_option' is an alias of `each'.
+ #
+ alias each_option each
+end
diff --git a/lib/getopts.rb b/lib/getopts.rb
index 9e1e8a2cf6..5b9562d5b2 100644
--- a/lib/getopts.rb
+++ b/lib/getopts.rb
@@ -15,7 +15,7 @@ $RCS_ID=%q$Header$
def isSingle(lopt)
if lopt.index(":")
if lopt.split(":")[0].length == 1
- return TRUE
+ return true
end
end
return nil
@@ -87,13 +87,13 @@ def getopts(single_opts, *options)
return nil
end
setOption(compare, ARGV[1])
- opts[compare] = TRUE
+ opts[compare] = true
ARGV.shift
count += 1
break
elsif lo == compare
- setOption(compare, TRUE)
- opts[compare] = TRUE
+ setOption(compare, true)
+ opts[compare] = true
count += 1
break
end
@@ -106,19 +106,19 @@ def getopts(single_opts, *options)
for idx in 1..(ARGV[0].length - 1)
compare = ARGV[0][idx, 1]
if single_opts && compare =~ "[" + single_opts + "]"
- setOption(compare, TRUE)
- opts[compare] = TRUE
+ setOption(compare, true)
+ opts[compare] = true
count += 1
elsif single_colon != "" && compare =~ "[" + single_colon + "]"
if ARGV[0][idx..-1].length > 1
setOption(compare, ARGV[0][(idx + 1)..-1])
- opts[compare] = TRUE
+ opts[compare] = true
count += 1
elsif ARGV.length <= 1
return nil
else
setOption(compare, ARGV[1])
- opts[compare] = TRUE
+ opts[compare] = true
ARGV.shift
count += 1
end
@@ -127,7 +127,7 @@ def getopts(single_opts, *options)
end
else
compare = ARGV[0]
- opts[compare] = TRUE
+ opts[compare] = true
newargv << ARGV[0]
end
diff --git a/lib/jcode.rb b/lib/jcode.rb
index 50b7beee9d..92b9284471 100644
--- a/lib/jcode.rb
+++ b/lib/jcode.rb
@@ -12,9 +12,10 @@ class String
private :original_succ
def mbchar?
- if $KCODE =~ /^s/i
+ case $KCODE[0]
+ when ?s, ?S
self =~ /[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc]/n
- elsif $KCODE =~ /^e/i
+ when ?e, ?E
self =~ /[\xa1-\xfe][\xa1-\xfe]/n
else
false
@@ -22,16 +23,15 @@ class String
end
def succ
- if self[-2] && self[-2] & 0x80 != 0
+ if self[-2] and self[-2, 2].mbchar?
s = self.dup
s[-1] += 1
- s[-1] += 1 if !s.mbchar?
+ s[-1] += 1 unless s[-2, 2].mbchar?
return s
else
original_succ
end
end
- alias next succ
def upto(to)
return if self > to
@@ -58,9 +58,11 @@ class String
return nil
end
- def _expand_ch
+ private
+
+ def _expand_ch str
a = []
- self.scan(/(.|\n)-(.|\n)|(.|\n)/) do |r|
+ str.scan(/(.|\n)-(.|\n)|(.|\n)/) do |r|
if $3
a.push $3
elsif $1.length != $2.length
@@ -74,32 +76,35 @@ class String
a
end
+ def expand_ch_hash from, to
+ h = {}
+ afrom = _expand_ch(from)
+ ato = _expand_ch(to)
+ afrom.each_with_index do |x,i| h[x] = ato[i] || ato[-1] end
+ h
+ end
+
+ def bsquote(str)
+ str.gsub(/\\/, '\\\\\\\\')
+ end
+
+ HashCache = {}
+ TrPatternCache = {}
+ DeletePatternCache = {}
+ SqueezePatternCache = {}
+
+ public
+
def tr!(from, to)
return self.delete!(from) if to.length == 0
- if from =~ /^\^/
- comp=TRUE
- from = $'
- end
- afrom = from._expand_ch
- ato = to._expand_ch
- i = 0
- if comp
- self.gsub!(/(.|\n)/) do |c|
- unless afrom.include?(c)
- ato[-1]
- else
- c
- end
- end
+ pattern = TrPatternCache[from] ||= /[#{bsquote(from)}]/
+ if from[0] == ?^
+ last = /.$/.match(to)[0]
+ self.gsub!(pattern, last)
else
- self.gsub!(/(.|\n)/) do |c|
- if i = afrom.index(c)
- if i < ato.size then ato[i] else ato[-1] end
- else
- c
- end
- end
+ h = HashCache[from + "::" + to] ||= expand_ch_hash(from, to)
+ self.gsub!(pattern) do |c| h[c] end
end
end
@@ -108,22 +113,7 @@ class String
end
def delete!(del)
- if del =~ /^\^/
- comp=TRUE
- del = $'
- end
- adel = del._expand_ch
- if comp
- self.gsub!(/(.|\n)/) do |c|
- next unless adel.include?(c)
- c
- end
- else
- self.gsub!(/(.|\n)/) do |c|
- next if adel.include?(c)
- c
- end
- end
+ self.gsub!(DeletePatternCache[del] ||= /[#{bsquote(del)}]+/, '')
end
def delete(del)
@@ -131,27 +121,13 @@ class String
end
def squeeze!(del=nil)
- if del
- if del =~ /^\^/
- comp=TRUE
- del = $'
- end
- adel = del._expand_ch
- if comp
- self.gsub!(/(.|\n)\1+/) do
- next unless adel.include?($1)
- $&
- end
+ pattern =
+ if del
+ SqueezePatternCache[del] ||= /([#{bsquote(del)}])\1+/
else
- for c in adel
- cq = Regexp.quote(c)
- self.gsub!(/#{cq}(#{cq})+/, cq)
- end
+ /(.|\n)\1+/
end
- self
- else
- self.gsub!(/(.|\n)\1+/, '\1')
- end
+ self.gsub!(pattern, '\1')
end
def squeeze(del=nil)
@@ -160,30 +136,14 @@ class String
def tr_s!(from, to)
return self.delete!(from) if to.length == 0
- if from =~ /^\^/
- comp=TRUE
- from = $'
- end
- afrom = from._expand_ch
- ato = to._expand_ch
- i = 0
- c = nil
- last = nil
- self.gsub!(/(.|\n)/) do |c|
- if comp
- unless afrom.include?(c)
- ato[-1]
- else
- c
- end
- elsif i = afrom.index(c)
- c = if i < ato.size then ato[i] else ato[-1] end
- next if c == last
- last = c
- else
- last = nil
- c
- end
+
+ pattern = SqueezePatternCache[from] ||= /([#{bsquote(from)}])\1+"/
+ if from[0] == ?^
+ last = /.$/.match(to)[0]
+ self.gsub!(pattern, last)
+ else
+ h = HashCache[from + "::" + to] ||= expand_ch_hash(from, to)
+ self.gsub!(pattern) do h[$1] end
end
end
@@ -191,18 +151,17 @@ class String
(str = self.dup).tr_s!(from,to) or str
end
- alias original_chop! chop!
- private :original_chop!
-
def chop!
- if self =~ /(.)$/ and $1.size == 2
- original_chop!
- end
- original_chop!
+ self.gsub!(/(?:.|\r?\n)\z/, '')
end
def chop
(str = self.dup).chop! or str
end
+
+ def jcount(str)
+ self.delete("^#{str}").jlength
+ end
+
end
$VERBOSE = $vsave
diff --git a/lib/mailread.rb b/lib/mailread.rb
index 5e46606c09..2edcca002a 100644
--- a/lib/mailread.rb
+++ b/lib/mailread.rb
@@ -43,6 +43,6 @@ class Mail
end
def [](field)
- @header[field]
+ @header[field.capitalize]
end
end
diff --git a/lib/mathn.rb b/lib/mathn.rb
index 265ef1337f..8d92272159 100644
--- a/lib/mathn.rb
+++ b/lib/mathn.rb
@@ -121,7 +121,7 @@ class Bignum
end
class Rational
- Unify = TRUE
+ Unify = true
alias power! **
@@ -304,6 +304,6 @@ module Math
end
class Complex
- Unify = TRUE
+ Unify = true
end
diff --git a/lib/matrix.rb b/lib/matrix.rb
index 64b0738e1b..f5c8491146 100644
--- a/lib/matrix.rb
+++ b/lib/matrix.rb
@@ -1,8 +1,9 @@
+#!/usr/local/bin/ruby
#
# matrix.rb -
# $Release Version: 1.0$
-# $Revision: 1.6 $
-# $Date: 1998/07/31 03:39:49 $
+# $Revision: 1.8 $
+# $Date: 1999/02/17 12:34:19 $
# Original Version from Smalltalk-80 version
# on July 23, 1985 at 8:37:17 am
# by Keiju ISHITSUKA
@@ -17,6 +18,8 @@
# :
# rown]
#
+# column: Îó
+# row: ¹Ô
#
# module ExceptionForMatrix::
# Exceptions:
@@ -36,7 +39,7 @@
# creates a matrix where `rows' indicates rows.
# `rows' is an array of arrays,
# e.g, Matrix[[11, 12], [21, 22]]
-# Matrix.rows(rows, copy = TRUE)
+# Matrix.rows(rows, copy = true)
# creates a matrix where `rows' indicates rows.
# if optional argument `copy' is false, use the array as
# internal structure of the metrix without copying.
@@ -142,7 +145,7 @@
#
# INSTANCE CREATION:
# Vector.[](*array)
-# Vector.elements(array, copy = TRUE)
+# Vector.elements(array, copy = true)
# ACCSESSING:
# [](i)
# size
@@ -173,29 +176,29 @@
require "e2mmap.rb"
module ExceptionForMatrix
- Exception2MessageMapper.extend_to(binding)
-
+ extend Exception2MessageMapper
def_e2message(TypeError, "wrong argument type %s (expected %s)")
def_e2message(ArgumentError, "Wrong # of arguments(%d for %d)")
- def_exception("ErrDimensionMismatch", "\#{self.type} dimemsion mismatch")
+ def_exception("ErrDimensionMismatch", "\#{self.name} dimension mismatch")
def_exception("ErrNotRegular", "Not Regular Matrix")
def_exception("ErrOperationNotDefined", "This operation(%s) can\\'t defined")
end
class Matrix
- @RCS_ID='-$Id: matrix.rb,v 1.6 1998/07/31 03:39:49 keiju Exp keiju $-'
-
+ @RCS_ID='-$Id: matrix.rb,v 1.8 1999/02/17 12:34:19 keiju Exp keiju $-'
+
+# extend Exception2MessageMapper
include ExceptionForMatrix
# instance creations
private_class_method :new
def Matrix.[](*rows)
- new(:init_rows, rows, FALSE)
+ new(:init_rows, rows, false)
end
- def Matrix.rows(rows, copy = TRUE)
+ def Matrix.rows(rows, copy = true)
new(:init_rows, rows, copy)
end
@@ -207,7 +210,7 @@ class Matrix
columns[j][i]
}
}
- Matrix.rows(rows, FALSE)
+ Matrix.rows(rows, false)
end
def Matrix.diagonal(*values)
@@ -218,8 +221,7 @@ class Matrix
row[j] = values[j]
row
}
- self
- rows(rows, FALSE)
+ rows(rows, false)
end
def Matrix.scalar(n, value)
@@ -241,11 +243,11 @@ class Matrix
def Matrix.row_vector(row)
case row
when Vector
- Matrix.rows([row.to_a], FALSE)
+ Matrix.rows([row.to_a], false)
when Array
- Matrix.rows([row.dup], FALSE)
+ Matrix.rows([row.dup], false)
else
- Matrix.row([[row]], FALSE)
+ Matrix.row([[row]], false)
end
end
@@ -310,13 +312,13 @@ class Matrix
|i|
@rows[i][j]
}
- Vector.elements(col, FALSE)
+ Vector.elements(col, false)
end
end
def collect
rows = @rows.collect{|row| row.collect{|e| yield e}}
- Matrix.rows(rows, FALSE)
+ Matrix.rows(rows, false)
end
alias map collect
@@ -337,14 +339,14 @@ class Matrix
from_col = param[2]
size_col = param[3]
else
- Matrix.fail ArgumentError, param.inspect
+ Matrix.Raise ArgumentError, param.inspect
end
rows = @rows[from_row, size_row].collect{
|row|
row[from_col, size_col]
}
- Matrix.rows(rows, FALSE)
+ Matrix.rows(rows, false)
end
# TESTING
@@ -362,20 +364,20 @@ class Matrix
# COMPARING
def ==(other)
- return FALSE unless Matrix === other
+ return false unless Matrix === other
other.compare_by_row_vectors(@rows)
end
alias eql? ==
def compare_by_row_vectors(rows)
- return FALSE unless @rows.size == rows.size
+ return false unless @rows.size == rows.size
0.upto(@rows.size - 1) do
|i|
- return FALSE unless @rows[i] == rows[i]
+ return false unless @rows[i] == rows[i]
end
- TRUE
+ true
end
def clone
@@ -404,13 +406,13 @@ class Matrix
e * m
}
}
- return Matrix.rows(rows, FALSE)
+ return Matrix.rows(rows, false)
when Vector
m = Matrix.column_vector(m)
r = self * m
return r.column(0)
when Matrix
- Matrix.fail ErrDimensionMismatch if column_size != m.row_size
+ Matrix.Raise ErrDimensionMismatch if column_size != m.row_size
rows = (0 .. row_size - 1).collect {
|i|
@@ -424,7 +426,7 @@ class Matrix
vij
}
}
- return Matrix.rows(rows, FALSE)
+ return Matrix.rows(rows, false)
else
x, y = m.coerce(self)
return x * y
@@ -434,7 +436,7 @@ class Matrix
def +(m)
case m
when Numeric
- Matrix.fail ErrOperationNotDefined, "+"
+ Matrix.Raise ErrOperationNotDefined, "+"
when Vector
m = Matrix.column_vector(m)
when Matrix
@@ -443,7 +445,7 @@ class Matrix
return x + y
end
- Matrix.fail ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size
+ Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size
rows = (0 .. row_size - 1).collect {
|i|
@@ -452,13 +454,13 @@ class Matrix
self[i, j] + m[i, j]
}
}
- Matrix.rows(rows, FALSE)
+ Matrix.rows(rows, false)
end
def -(m)
case m
when Numeric
- Matrix.fail ErrOperationNotDefined, "-"
+ Matrix.Raise ErrOperationNotDefined, "-"
when Vector
m = Matrix.column_vector(m)
when Matrix
@@ -467,7 +469,7 @@ class Matrix
return x - y
end
- Matrix.fail ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size
+ Matrix.Raise ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size
rows = (0 .. row_size - 1).collect {
|i|
@@ -476,7 +478,7 @@ class Matrix
self[i, j] - m[i, j]
}
}
- Matrix.rows(rows, FALSE)
+ Matrix.rows(rows, false)
end
def /(other)
@@ -489,7 +491,7 @@ class Matrix
e / other
}
}
- return Matrix.rows(rows, FALSE)
+ return Matrix.rows(rows, false)
when Matrix
return self * other.inverse
else
@@ -499,7 +501,7 @@ class Matrix
end
def inverse
- Matrix.fail ErrDimensionMismatch unless square?
+ Matrix.Raise ErrDimensionMismatch unless square?
Matrix.I(row_size).inverse_from(self)
end
alias inv inverse
@@ -512,7 +514,7 @@ class Matrix
if (akk = a[k][k]) == 0
i = k
begin
- fail ErrNotRegular if (i += 1) > size
+ Matrix.Raise ErrNotRegular if (i += 1) > size
end while a[i][k] == 0
a[i], a[k] = a[k], a[i]
@rows[i], @rows[k] = @rows[k], @rows[i]
@@ -568,9 +570,9 @@ class Matrix
end
z
elsif other.kind_of?(Float) || defined?(Rational) && other.kind_of?(Rational)
- fail ErrOperationNotDefined, "**"
+ Matrix.Raise ErrOperationNotDefined, "**"
else
- fail ErrOperationNotDefined, "**"
+ Matrix.Raise ErrOperationNotDefined, "**"
end
end
@@ -618,10 +620,10 @@ class Matrix
begin
if (akk = a[k][k]) == 0
i = -1
- nothing = FALSE
+ nothing = false
begin
if (i += 1) > column_size - 1
- nothing = TRUE
+ nothing = true
break
end
end while a[i][k] == 0
@@ -663,6 +665,8 @@ class Matrix
case other
when Numeric
return Scalar.new(other), self
+ else
+ raise TypeError, "#{type} can't be coerced into #{other.type}"
end
end
@@ -725,7 +729,7 @@ class Matrix
when Numeric
Scalar.new(@value + other)
when Vector, Matrix
- Scalar.fail WrongArgType, other.type, "Numeric or Scalar"
+ Scalar.Raise WrongArgType, other.type, "Numeric or Scalar"
when Scalar
Scalar.new(@value + other.value)
else
@@ -739,7 +743,7 @@ class Matrix
when Numeric
Scalar.new(@value - other)
when Vector, Matrix
- Scalar.fail WrongArgType, other.type, "Numeric or Scalar"
+ Scalar.Raise WrongArgType, other.type, "Numeric or Scalar"
when Scalar
Scalar.new(@value - other.value)
else
@@ -765,7 +769,7 @@ class Matrix
when Numeric
Scalar.new(@value / other)
when Vector
- Scalar.fail WrongArgType, other.type, "Numeric or Scalar or Matrix"
+ Scalar.Raise WrongArgType, other.type, "Numeric or Scalar or Matrix"
when Matrix
self * _M.inverse
else
@@ -779,7 +783,7 @@ class Matrix
when Numeric
Scalar.new(@value ** other)
when Vector
- Scalar.fail WrongArgType, other.type, "Numeric or Scalar or Matrix"
+ Scalar.Raise WrongArgType, other.type, "Numeric or Scalar or Matrix"
when Matrix
other.powered_by(self)
else
@@ -802,10 +806,10 @@ class Vector
private_class_method :new
def Vector.[](*array)
- new(:init_elements, array, FALSE)
+ new(:init_elements, array, copy = false)
end
- def Vector.elements(array, copy = TRUE)
+ def Vector.elements(array, copy = true)
new(:init_elements, array, copy)
end
@@ -833,7 +837,7 @@ class Vector
# ENUMRATIONS
def each2(v)
- Vector.fail ErrDimensionMismatch if size != v.size
+ Vector.Raise ErrDimensionMismatch if size != v.size
0.upto(size - 1) do
|i|
yield @elements[i], v[i]
@@ -841,7 +845,7 @@ class Vector
end
def collect2(v)
- Vector.fail ErrDimensionMismatch if size != v.size
+ Vector.Raise ErrDimensionMismatch if size != v.size
(0 .. size - 1).collect do
|i|
yield @elements[i], v[i]
@@ -850,7 +854,7 @@ class Vector
# COMPARING
def ==(other)
- return FALSE unless Vector === other
+ return false unless Vector === other
other.compare_by(@elements)
end
@@ -870,15 +874,15 @@ class Vector
# ARITHMETIC
- def *(x) "is matrix or number"
+ def *(x) # is matrix or number
case x
when Numeric
els = @elements.collect{|e| e * x}
- Vector.elements(els, FALSE)
+ Vector.elements(els, false)
when Matrix
self.covector * x
else
- s, x = X.corece(self)
+ s, x = X.coerce(self)
s * x
end
end
@@ -886,16 +890,16 @@ class Vector
def +(v)
case v
when Vector
- Vector.fail ErrDimensionMismatch if size != v.size
+ Vector.Raise ErrDimensionMismatch if size != v.size
els = collect2(v) {
|v1, v2|
v1 + v2
}
- Vector.elements(els, FALSE)
+ Vector.elements(els, false)
when Matrix
Matrix.column_vector(self) + v
else
- s, x = v.corece(self)
+ s, x = v.coerce(self)
s + x
end
end
@@ -903,16 +907,16 @@ class Vector
def -(v)
case v
when Vector
- Vector.fail ErrDimensionMismatch if size != v.size
+ Vector.Raise ErrDimensionMismatch if size != v.size
els = collect2(v) {
|v1, v2|
v1 - v2
}
- Vector.elements(els, FALSE)
+ Vector.elements(els, false)
when Matrix
Matrix.column_vector(self) - v
else
- s, x = v.corece(self)
+ s, x = v.coerce(self)
s - x
end
end
@@ -920,7 +924,7 @@ class Vector
# VECTOR FUNCTIONS
def inner_product(v)
- Vector.fail ErrDimensionMismatch if size != v.size
+ Vector.Raise ErrDimensionMismatch if size != v.size
p = 0
each2(v) {
@@ -935,7 +939,7 @@ class Vector
|v|
yield v
}
- Vector.elements(els, FALSE)
+ Vector.elements(els, false)
end
alias map collect
@@ -944,7 +948,7 @@ class Vector
|v1, v2|
yield v1, v2
}
- Vector.elements(els, FALSE)
+ Vector.elements(els, false)
end
def r
@@ -980,6 +984,8 @@ class Vector
case other
when Numeric
return Scalar.new(other), self
+ else
+ raise TypeError, "#{type} can't be coerced into #{other.type}"
end
end
diff --git a/lib/mkmf.rb b/lib/mkmf.rb
index 7e131fe890..50920a0cda 100644
--- a/lib/mkmf.rb
+++ b/lib/mkmf.rb
@@ -6,7 +6,9 @@ require 'find'
include Config
-$found = false;
+SRC_EXT = ["c", "cc", "m", "cxx", "cpp", "C"]
+
+$cache_mod = false
$lib_cache = {}
$lib_found = {}
$func_cache = {}
@@ -31,14 +33,8 @@ if File.exist?($config_cache) then
end
$srcdir = CONFIG["srcdir"]
-$libdir = CONFIG["libdir"]+"/"+CONFIG["ruby_install_name"]
+$libdir = CONFIG["libdir"]+"/ruby/"+CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
$archdir = $libdir+"/"+CONFIG["arch"]
-$install = CONFIG["INSTALL_PROGRAM"]
-$install_data = CONFIG["INSTALL_DATA"]
-if $install !~ /^\// then
- $install = CONFIG["srcdir"]+"/"+$install
- $install_data = CONFIG["srcdir"]+"/"+$install_data
-end
if File.exist? $archdir + "/ruby.h"
$hdrdir = $archdir
@@ -48,18 +44,22 @@ else
STDERR.print "can't find header files for ruby.\n"
exit 1
end
+$topdir = $hdrdir
+$hdrdir.gsub!('/', '\\') if RUBY_PLATFORM =~ /mswin32/
CFLAGS = CONFIG["CFLAGS"]
-if PLATFORM == "m68k-human"
+if RUBY_PLATFORM == "m68k-human"
CFLAGS.gsub!(/-c..-stack=[0-9]+ */, '')
+elsif RUBY_PLATFORM =~ /-nextstep|-rhapsody/
+ CFLAGS.gsub!( /-arch\s\w*/, '' )
end
-if /win32|djgpp|mingw32|m68k-human/i =~ PLATFORM
+if /win32|djgpp|mingw32|m68k-human|i386-os2_emx/i =~ RUBY_PLATFORM
$null = open("nul", "w")
else
$null = open("/dev/null", "w")
end
-LINK = "#{CONFIG['CC']} -o conftest -I#{$srcdir} -I#{CONFIG['includedir']} #{CFLAGS} %s #{CONFIG['LDFLAGS']} %s conftest.c #{CONFIG['LIBS']} %s"
-CPP = "#{CONFIG['CPP']} -E -I#{$srcdir} -I#{CONFIG['includedir']} #{CFLAGS} %s conftest.c"
+LINK = "#{CONFIG['CC']} -o conftest -I#{$hdrdir} #{CFLAGS} -I#{CONFIG['includedir']} %s #{CONFIG['LDFLAGS']} %s conftest.c %s %s #{CONFIG['LIBS']}"
+CPP = "#{CONFIG['CPP']} -E -I#{$hdrdir} #{CFLAGS} -I#{CONFIG['includedir']} %s %s conftest.c"
$orgerr = $stderr.dup
$orgout = $stdout.dup
@@ -76,29 +76,84 @@ 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
+ xsystem(format(LINK, $CFLAGS, $LDFLAGS, opt, $LOCAL_LIBS))
end
-def try_cpp
- xsystem(format(CPP, $CFLAGS))
+def try_link(src, opt="")
+ begin
+ try_link0(src, opt)
+ ensure
+ system "rm -f conftest*"
+ end
end
-def install_rb(mfile)
+def try_cpp(src, opt="")
+ cfile = open("conftest.c", "w")
+ cfile.print src
+ cfile.close
+ begin
+ xsystem(format(CPP, $CFLAGS, opt))
+ ensure
+ system "rm -f conftest*"
+ end
+end
+
+def egrep_cpp(pat, src, opt="")
+ cfile = open("conftest.c", "w")
+ cfile.print src
+ cfile.close
+ begin
+ xsystem(format(CPP+"|egrep #{pat}", $CFLAGS, opt))
+ ensure
+ system "rm -f conftest*"
+ end
+end
+
+def try_run(src, opt="")
+ begin
+ if try_link0(src, opt)
+ if xsystem("./conftest")
+ true
+ else
+ false
+ end
+ else
+ nil
+ end
+ ensure
+ system "rm -f conftest*"
+ end
+end
+
+def install_rb(mfile, srcdir = nil)
+ libdir = "lib"
+ libdir = srcdir + "/" + libdir if srcdir
path = []
dir = []
- Find.find("lib") do |f|
+ Find.find(libdir) do |f|
next unless /\.rb$/ =~ f
- f = f[4..-1]
+ f = f[libdir.length+1..-1]
path.push f
dir |= File.dirname(f)
end
for f in dir
next if f == "."
- mfile.printf "\t@test -d $(libdir)/%s || mkdir $(libdir)/%s\n", f, f
+ mfile.printf "\t@$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' $(libdir)/%s\n", f
end
for f in path
- mfile.printf "\t$(INSTALL_DATA) lib/%s $(libdir)/%s\n", f, f
+ mfile.printf "\t@$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0644, true)' lib/%s $(libdir)/%s\n", f, f
+ end
+end
+
+def append_library(libs, lib)
+ if /mswin32/ =~ RUBY_PLATFORM
+ lib + ".lib " + libs
+ else
+ "-l" + lib + " " + libs
end
end
@@ -107,55 +162,75 @@ def have_library(lib, func="main")
STDOUT.flush
if $lib_cache[lib]
if $lib_cache[lib] == "yes"
- if $libs
- $libs = "-l" + lib + " " + $libs
- else
- $libs = "-l" + lib
- end
+ $libs = append_library($libs, lib)
print "(cached) yes\n"
- return TRUE
+ return true
else
print "(cached) no\n"
- return FALSE
+ return false
end
end
if func && func != ""
- cfile = open("conftest.c", "w")
- cfile.printf "\
+ libs = append_library($libs, lib)
+ if /mswin32/ =~ RUBY_PLATFORM
+ r = try_link(<<"SRC", libs)
+#include <windows.h>
+#include <winsock.h>
int main() { return 0; }
-int t() { %s(); return 0; }
-", func
- cfile.close
-
- begin
- if $libs
- libs = "-l" + lib + " " + $libs
- else
- libs = "-l" + lib
- end
- unless try_link(libs)
- $lib_cache[lib] = 'no'
- $cache_mod = TRUE
- print "no\n"
- return FALSE
+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
- ensure
- system "rm -f conftest*"
- end
- else
- if $libs
- libs = "-l" + lib + " " + $libs
else
- libs = "-l" + lib
+ r = try_link(<<"SRC", libs)
+int main() { return 0; }
+int t() { #{func}(); return 0; }
+SRC
+ end
+ unless r
+ $lib_cache[lib] = 'no'
+ $cache_mod = true
+ print "no\n"
+ return false
end
+ else
+ libs = append_library($libs, lib)
end
$libs = libs
$lib_cache[lib] = 'yes'
- $cache_mod = TRUE
+ $cache_mod = true
+ print "yes\n"
+ return true
+end
+
+def find_library(lib, func, *paths)
+ printf "checking for %s() in -l%s... ", func, lib
+ STDOUT.flush
+
+ ldflags = $LDFLAGS
+ libs = append_library($libs, lib)
+ until try_link(<<"SRC", libs)
+int main() { return 0; }
+int t() { #{func}(); return 0; }
+SRC
+ if paths.size == 0
+ $LDFLAGS = ldflags
+ print "no\n"
+ return false
+ end
+ $LDFLAGS = ldflags + " -L"+paths.shift
+ end
+ $libs = libs
print "yes\n"
- return TRUE
+ return true
end
def have_func(func)
@@ -165,39 +240,47 @@ def have_func(func)
if $func_cache[func] == "yes"
$defs.push(format("-DHAVE_%s", func.upcase))
print "(cached) yes\n"
- return TRUE
+ return true
else
print "(cached) no\n"
- return FALSE
+ return false
end
end
- cfile = open("conftest.c", "w")
- cfile.printf "\
-char %s();
-int main() { return 0; }
-int t() { %s(); return 0; }
-", func, func
- cfile.close
-
libs = $libs
- libs = "" if libs == nil
- begin
- unless try_link(libs)
- $func_found[func] = 'no'
- $found = TRUE
- print "no\n"
- return FALSE
+ if /mswin32/ =~ 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
- ensure
- system "rm -f conftest*"
+ else
+ r = try_link(<<"SRC", libs)
+int main() { return 0; }
+int t() { #{func}(); return 0; }
+SRC
+ end
+ unless r
+ $func_found[func] = 'no'
+ $cache_mod = true
+ print "no\n"
+ return false
end
$defs.push(format("-DHAVE_%s", func.upcase))
$func_found[func] = 'yes'
- $found = TRUE
+ $cache_mod = true
print "yes\n"
- return TRUE
+ return true
end
def have_header(header)
@@ -208,35 +291,59 @@ def have_header(header)
header.tr!("a-z./\055", "A-Z___")
$defs.push(format("-DHAVE_%s", header))
print "(cached) yes\n"
- return TRUE
+ return true
else
print "(cached) no\n"
- return FALSE
+ return false
end
end
- cfile = open("conftest.c", "w")
- cfile.printf "\
-#include <%s>
-", header
- cfile.close
-
- begin
- unless try_cpp
- $hdr_found[header] = 'no'
- $found = TRUE
- print "no\n"
- return FALSE
- end
- ensure
- system "rm -f conftest*"
+ unless try_cpp(<<"SRC")
+#include <#{header}>
+SRC
+ $hdr_found[header] = 'no'
+ $cache_mod = true
+ print "no\n"
+ return false
end
$hdr_found[header] = 'yes'
header.tr!("a-z./\055", "A-Z___")
$defs.push(format("-DHAVE_%s", header))
- $found = TRUE
+ $cache_mod = true
print "yes\n"
- return TRUE
+ return true
+end
+
+def arg_config(config, default=nil)
+ unless defined? $configure_args
+ $configure_args = {}
+ for arg in CONFIG["configure_args"].split + ARGV
+ next unless /^--/ =~ arg
+ if /=/ =~ arg
+ $configure_args[$`] = $'
+ else
+ $configure_args[arg] = true
+ end
+ end
+ end
+ $configure_args.fetch(config, default)
+end
+
+def with_config(config, default=nil)
+ unless /^--with-/ =~ config
+ config = '--with-' + config
+ end
+ arg_config(config, default)
+end
+
+def enable_config(config, default=nil)
+ if arg_config("--enable-"+config, default)
+ true
+ elsif arg_config("--disable-"+config, false)
+ false
+ else
+ default
+ end
end
def create_header()
@@ -252,28 +359,58 @@ def create_header()
end
end
+def dir_config(target)
+ dir = with_config("%s-dir"%target)
+ if dir
+ idir = " -I"+dir+"/include"
+ ldir = " -L"+dir+"/lib"
+ end
+ unless idir
+ dir = with_config("%s-include"%target)
+ idir = " -I"+dir if dir
+ end
+ unless ldir
+ dir = with_config("%s-lib"%target)
+ ldir = " -L"+dir if dir
+ end
+
+ $CFLAGS += idir if idir
+ $LDFLAGS += ldir if ldir
+end
+
def create_makefile(target)
print "creating Makefile\n"
+ system "rm -f conftest*"
STDOUT.flush
- if $libs and CONFIG["DLEXT"] == "o"
+ if CONFIG["DLEXT"] == $OBJEXT
libs = $libs.split
for lib in libs
lib.sub!(/-l(.*)/, '"lib\1.a"')
end
$defs.push(format("-DEXTLIB='%s'", libs.join(",")))
end
- $libs = "" unless $libs
$DLDFLAGS = CONFIG["DLDFLAGS"]
- if PLATFORM =~ /beos/
+ if RUBY_PLATFORM =~ /beos/
$libs = $libs + " -lruby"
$DLDFLAGS = $DLDFLAGS + " -L" + CONFIG["prefix"] + "/lib"
end
+ defflag = ''
+ if RUBY_PLATFORM =~ /cygwin/
+ if File.exist? target + ".def"
+ defflag = "--def=" + target + ".def"
+ end
+ $libs = $libs + " " + CONFIG["LIBRUBYARG"]
+ $DLDFLAGS = $DLDFLAGS + " -L$(topdir)"
+ end
+
unless $objs then
- $objs = Dir["*.{c,cc}"]
- for f in $objs
- f.sub!(/\.(c|cc)$/, ".o")
+ $objs = []
+ for f in Dir["*.{#{SRC_EXT.join(%q{,})}}"]
+ f = File.basename(f)
+ f.sub!(/(#{SRC_EXT.join(%q{|})})$/, $OBJEXT)
+ $objs.push f
end
end
$objs = $objs.join(" ")
@@ -285,15 +422,15 @@ SHELL = /bin/sh
#### Start of system configuration section. ####
srcdir = #{$srcdir}
+topdir = #{$topdir}
hdrdir = #{$hdrdir}
CC = #{CONFIG["CC"]}
-prefix = #{CONFIG["prefix"]}
-CFLAGS = #{CONFIG["CCDLFLAGS"]} -I$(hdrdir) -I#{CONFIG["includedir"]} #{CFLAGS} #{$CFLAGS} #{$defs.join(" ")}
+CFLAGS = #{CONFIG["CCDLFLAGS"]} -I$(hdrdir) #{CFLAGS} #{$CFLAGS} -I#{CONFIG["includedir"]} #{$defs.join(" ")}
CXXFLAGS = $(CFLAGS)
DLDFLAGS = #{$DLDFLAGS} #{$LDFLAGS}
-LDSHARED = #{CONFIG["LDSHARED"]}
+LDSHARED = #{CONFIG["LDSHARED"]} #{defflag}
prefix = #{CONFIG["prefix"]}
exec_prefix = #{CONFIG["exec_prefix"]}
@@ -302,49 +439,47 @@ archdir = #{$archdir}
#### End of system configuration section. ####
-LOCAL_LIBS = #{$local_libs}
+LOCAL_LIBS = #{$LOCAL_LIBS} #{$local_flags}
LIBS = #{$libs}
OBJS = #{$objs}
-TARGET = #{target}.#{CONFIG["DLEXT"]}
+TARGET = #{target}
+DLLIB = $(TARGET).#{CONFIG["DLEXT"]}
-INSTALL = #{$install}
-INSTALL_DATA = #{$install_data}
+RUBY = #{CONFIG["ruby_install_name"]}
-binsuffix = #{CONFIG["binsuffix"]}
+EXEEXT = #{CONFIG["EXEEXT"]}
-all: $(TARGET)
+all: $(DLLIB)
-clean:; @rm -f *.o *.so *.sl
+clean:; @rm -f *.#{$OBJEXT} *.so *.sl *.a $(DLLIB)
+ @rm -f $(TARGET).lib $(TARGET).exp
@rm -f Makefile extconf.h conftest.*
- @rm -f core ruby$(binsuffix) *~
+ @rm -f core ruby$(EXEEXT) *~
realclean: clean
-install: $(archdir)/$(TARGET)
+install: $(archdir)/$(DLLIB)
-$(archdir)/$(TARGET): $(TARGET)
- @test -d $(libdir) || mkdir $(libdir)
- @test -d $(archdir) || mkdir $(archdir)
- $(INSTALL) $(TARGET) $(archdir)/$(TARGET)
+$(archdir)/$(DLLIB): $(DLLIB)
+ @$(RUBY) -r ftools -e 'File::makedirs(*ARGV)' $(libdir) $(archdir)
+ @$(RUBY) -r ftools -e 'File::install(ARGV[0], ARGV[1], 0555, true)' $(DLLIB) $(archdir)/$(DLLIB)
EOMF
install_rb(mfile)
mfile.printf "\n"
- if CONFIG["DLEXT"] != "o"
+ if CONFIG["DLEXT"] != $OBJEXT
mfile.printf <<EOMF
-$(TARGET): $(OBJS)
- $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LIBS) $(LOCAL_LIBS)
+$(DLLIB): $(OBJS)
+ $(LDSHARED) $(DLDFLAGS) -o $(DLLIB) $(OBJS) $(LIBS) $(LOCAL_LIBS)
EOMF
- elsif not File.exist?(target + ".c") and not File.exist?(target + ".cc") or
- mfile.print "$(TARGET): $(OBJS)\n"
- case PLATFORM
+ elsif not File.exist?(target + ".c") and not File.exist?(target + ".cc")
+ mfile.print "$(DLLIB): $(OBJS)\n"
+ case RUBY_PLATFORM
when "m68k-human"
- mfile.printf "ar cru $(TARGET) $(OBJS)\n"
- when /-nextstep/
- mfile.printf "cc -r $(CFLAGS) -o $(TARGET) $(OBJS)\n"
+ mfile.printf "ar cru $(DLLIB) $(OBJS)\n"
else
- mfile.printf "ld $(DLDFLAGS) -r -o $(TARGET) $(OBJS)\n"
+ mfile.printf "ld $(DLDFLAGS) -r -o $(DLLIB) $(OBJS)\n"
end
end
@@ -352,13 +487,13 @@ EOMF
dfile = open("depend", "r")
mfile.printf "###\n"
while line = dfile.gets()
- mfile.print line
+ mfile.printf "%s", line.gsub(/\.o/, ".#{$OBJEXT}")
end
dfile.close
end
mfile.close
- if $found
+ if $cache_mod
begin
f = open($config_cache, "w")
for k,v in $lib_cache
@@ -384,18 +519,47 @@ EOMF
end
end
- if PLATFORM =~ /beos/
- print "creating ruby.def\n"
- open("ruby.def", "w") do |file|
- file.print("EXPORTS\n") if PLATFORM =~ /^i/
+ if RUBY_PLATFORM =~ /beos/
+ if RUBY_PLATFORM =~ /^powerpc/ then
+ deffilename = "ruby.exp"
+ else
+ deffilename = "ruby.def"
+ end
+ print "creating #{deffilename}\n"
+ open(deffilename, "w") do |file|
+ file.print("EXPORTS\n") if RUBY_PLATFORM =~ /^i/
file.print("Init_#{target}\n")
end
end
end
-$libs = PLATFORM =~ /cygwin32|beos/ ? nil : "-lc"
+$OBJEXT = CONFIG["OBJEXT"]
$objs = nil
-$local_libs = ""
-$CFLAGS = ""
-$LDFLAGS = ""
+$libs = "-lc"
+$local_flags = ""
+case RUBY_PLATFORM
+when /cygwin|beos|openstep|nextstep|rhapsody/
+ $libs = ""
+when /mswin32/
+ $libs = ""
+ $local_flags = "rubymw.lib -link /LIBPATH:$(topdir) /EXPORT:Init_$(TARGET)"
+end
+$LOCAL_LIBS = ""
$defs = []
+
+dir = with_config("opt-dir")
+if dir
+ idir = "-I"+dir+"/include"
+ ldir = "-L"+dir+"/lib"
+end
+unless idir
+ dir = with_config("opt-include")
+ idir = "-I"+dir if dir
+end
+unless ldir
+ dir = with_config("opt-lib")
+ ldir = "-L"+dir if dir
+end
+
+$CFLAGS = idir || ""
+$LDFLAGS = ldir || ""
diff --git a/lib/monitor.rb b/lib/monitor.rb
new file mode 100644
index 0000000000..75d9c35821
--- /dev/null
+++ b/lib/monitor.rb
@@ -0,0 +1,229 @@
+=begin
+
+monitor.rb
+Author: Shugo Maeda <shugo@netlab.co.jp>
+Version: 1.2.1
+
+USAGE:
+
+ foo = Foo.new
+ foo.extend(MonitorMixin)
+ cond = foo.new_cond
+
+ thread1:
+ foo.synchronize {
+ ...
+ cond.wait_until { foo.done? }
+ ...
+ }
+
+ thread2:
+ foo.synchronize {
+ foo.do_something
+ cond.signal
+ }
+
+=end
+
+module MonitorMixin
+ module Accessible
+ protected
+ attr_accessor :mon_owner, :mon_count
+ attr_reader :mon_entering_queue, :mon_waiting_queue
+ end
+
+ module Initializable
+ protected
+ def mon_initialize
+ @mon_owner = nil
+ @mon_count = 0
+ @mon_entering_queue = []
+ @mon_waiting_queue = []
+ end
+ end
+
+ class ConditionVariable
+ class Timeout < Exception; end
+
+ include Accessible
+
+ def wait(timeout = nil)
+ if @monitor.mon_owner != Thread.current
+ raise ThreadError, "current thread not owner"
+ end
+
+ Thread.critical = true
+ count = @monitor.mon_count
+ @monitor.mon_count = 0
+ @monitor.mon_owner = nil
+ if @monitor.mon_waiting_queue.empty?
+ t = @monitor.mon_entering_queue.shift
+ else
+ t = @monitor.mon_waiting_queue.shift
+ end
+ t.wakeup if t
+ @waiters.push(Thread.current)
+
+ if timeout
+ t = Thread.current
+ timeout_thread = Thread.start {
+ sleep(timeout)
+ t.raise(Timeout.new)
+ }
+ end
+ begin
+ Thread.stop
+ rescue Timeout
+ @waiters.delete(Thread.current)
+ ensure
+ if timeout && timeout_thread.alive?
+ Thread.kill(timeout_thread)
+ end
+ end
+
+ Thread.critical = true
+ while @monitor.mon_owner &&
+ @monitor.mon_owner != Thread.current
+ @monitor.mon_waiting_queue.push(Thread.current)
+ Thread.stop
+ Thread.critical = true
+ end
+ @monitor.mon_owner = Thread.current
+ @monitor.mon_count = count
+ Thread.critical = false
+ end
+
+ def wait_while
+ while yield
+ wait
+ end
+ end
+
+ def wait_until
+ until yield
+ wait
+ end
+ end
+
+ def signal
+ if @monitor.mon_owner != Thread.current
+ raise ThreadError, "current thread not owner"
+ end
+ Thread.critical = true
+ t = @waiters.shift
+ t.wakeup if t
+ Thread.critical = false
+ Thread.pass
+ end
+
+ def broadcast
+ if @monitor.mon_owner != Thread.current
+ raise ThreadError, "current thread not owner"
+ end
+ Thread.critical = true
+ for t in @waiters
+ t.wakeup
+ end
+ @waiters.clear
+ Thread.critical = false
+ Thread.pass
+ end
+
+ def count_waiters
+ return @waiters.length
+ end
+
+ private
+ def initialize(monitor)
+ @monitor = monitor
+ @waiters = []
+ end
+ end
+
+ include Accessible
+ include Initializable
+ extend Initializable
+
+ def self.extend_object(obj)
+ super(obj)
+ obj.mon_initialize
+ end
+
+ def try_mon_enter
+ result = false
+ Thread.critical = true
+ if mon_owner.nil?
+ self.mon_owner = Thread.current
+ end
+ if mon_owner == Thread.current
+ self.mon_count += 1
+ result = true
+ end
+ Thread.critical = false
+ return result
+ end
+
+ def mon_enter
+ Thread.critical = true
+ while mon_owner != nil && mon_owner != Thread.current
+ mon_entering_queue.push(Thread.current)
+ Thread.stop
+ Thread.critical = true
+ end
+ self.mon_owner = Thread.current
+ self.mon_count += 1
+ Thread.critical = false
+ end
+
+ def mon_exit
+ if mon_owner != Thread.current
+ raise ThreadError, "current thread not owner"
+ end
+ Thread.critical = true
+ self.mon_count -= 1
+ if mon_count == 0
+ self.mon_owner = nil
+ if mon_waiting_queue.empty?
+ t = mon_entering_queue.shift
+ else
+ t = mon_waiting_queue.shift
+ end
+ end
+ t.wakeup if t
+ Thread.critical = false
+ Thread.pass
+ end
+
+ def mon_synchronize
+ mon_enter
+ begin
+ yield
+ ensure
+ mon_exit
+ end
+ end
+ alias synchronize mon_synchronize
+
+ def new_cond
+ return ConditionVariable.new(self)
+ end
+
+private
+ def initialize(*args)
+ super
+ mon_initialize
+ end
+end
+
+class Monitor
+ include MonitorMixin
+ alias try_enter try_mon_enter
+ alias enter mon_enter
+ alias exit mon_exit
+ alias owner mon_owner
+end
+
+# Local variables:
+# mode: Ruby
+# tab-width: 8
+# End:
diff --git a/lib/mutex_m.rb b/lib/mutex_m.rb
index 4b8d64438e..e0fcf0f209 100644
--- a/lib/mutex_m.rb
+++ b/lib/mutex_m.rb
@@ -12,54 +12,27 @@
# obj = Object.new
# obj.extend Mutex_m
# ...
-# ¸å¤ÏMutex¤ÈƱ¤¸»È¤¤Êý
+# extended object can be handled like Mutex
#
-require "finalize"
-
module Mutex_m
- def Mutex_m.extendable_module(obj)
- if Fixnum === obj or TRUE === obj or FALSE === obj or nil == obj
- raise TypeError, "Mutex_m can't extend to this class(#{obj.type})"
- else
- begin
- obj.instance_eval "@mu_locked"
- For_general_object
- rescue TypeError
- For_primitive_object
- end
+ def Mutex_m.append_features(cl)
+ super
+ unless cl.instance_of?(Module)
+ cl.module_eval %q{
+ alias locked? mu_locked?
+ alias lock mu_lock
+ alias unlock mu_unlock
+ alias try_lock mu_try_lock
+ alias synchronize mu_synchronize
+ }
end
- end
-
- def Mutex_m.includable_module(cl)
- begin
- dummy = cl.new
- Mutex_m.extendable_module(dummy)
- rescue NameError
- # new¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤¤»þ¤Ï, DATA¤È¤ß¤Ê¤¹.
- For_primitive_object
- end
- end
-
- def Mutex_m.extend_class(cl)
- return super if cl.instance_of?(Module)
-
- # ¥â¥¸¥å¡¼¥ë¤Î»þ¤Ï²¿¤â¤·¤Ê¤¤. ¥¯¥é¥¹¤Î¾ì¹ç, ŬÀڤʥ⥸¥å¡¼¥ë¤Î·èÄê
- # ¤Èalias¤ò¹Ô¤¦.
- real = includable_module(cl)
- cl.module_eval %q{
- include real
-
- alias locked? mu_locked?
- alias lock mu_lock
- alias unlock mu_unlock
- alias try_lock mu_try_lock
- alias synchronize mu_synchronize
- }
+ return self
end
def Mutex_m.extend_object(obj)
- obj.extend(Mutex_m.extendable_module(obj))
+ super
+ obj.mu_extended
end
def mu_extended
@@ -76,6 +49,7 @@ module Mutex_m
alias synchronize mu_synchronize
end"
end
+ initialize
end
# locking
@@ -88,132 +62,50 @@ module Mutex_m
end
end
- # internal class
- module For_general_object
- include Mutex_m
-
- def For_general_object.extend_object(obj)
- super
- obj.mu_extended
- end
-
- def mu_extended
- super
- @mu_waiting = []
- @mu_locked = FALSE;
- end
-
- def mu_locked?
- @mu_locked
- end
-
- def mu_try_lock
- result = FALSE
- Thread.critical = TRUE
- unless @mu_locked
- @mu_locked = TRUE
- result = TRUE
- end
- Thread.critical = FALSE
- result
- end
-
- def mu_lock
- while (Thread.critical = TRUE; @mu_locked)
- @mu_waiting.push Thread.current
- Thread.stop
- end
- @mu_locked = TRUE
- Thread.critical = FALSE
- self
- end
-
- def mu_unlock
- return unless @mu_locked
- Thread.critical = TRUE
- wait = @mu_waiting
- @mu_waiting = []
- @mu_locked = FALSE
- Thread.critical = FALSE
- for w in wait
- w.run
- end
- self
- end
-
+ def mu_locked?
+ @mu_locked
end
-
- module For_primitive_object
- include Mutex_m
- Mu_Locked = Hash.new
-
- def For_primitive_object.extend_object(obj)
- super
-
- obj.mu_extended
- Finalizer.add(obj, For_primitive_object, :mu_finalize)
- end
-
- def mu_extended
- super
- initialize
- end
-
- def For_primitive_object.mu_finalize(id)
- Thread.critical = TRUE
- if wait = Mu_Locked.delete(id)
- # wait == [] ¤È¤­¤À¤± GC¤µ¤ì¤ë¤Î¤Ç, for w in wait ¤Ï°ÕÌ£¤Ê¤·.
- Thread.critical = FALSE
- for w in wait
- w.run
- end
- else
- Thread.critical = FALSE
- end
- self
- end
-
- def mu_locked?
- Mu_Locked.key?(self.id)
- end
-
- def mu_try_lock
- Thread.critical = TRUE
- if Mu_Locked.key?(self.id)
- ret = FALSE
- else
- Mu_Locked[self.id] = []
- Finalizer.add(self, For_primitive_object, :mu_finalize)
- ret = TRUE
- end
- Thread.critical = FALSE
- ret
- end
-
- def mu_lock
- while (Thread.critical = TRUE; w = Mu_Locked[self.id])
- w.push Thread.current
- Thread.stop
- end
- Mu_Locked[self.id] = []
- Finalizer.add(self, For_primitive_object, :mu_finalize)
- Thread.critical = FALSE
- self
- end
-
- def mu_unlock
- Thread.critical = TRUE
- if wait = Mu_Locked.delete(self.id)
- Finalizer.delete(self, For_primitive_object, :mu_finalize)
- Thread.critical = FALSE
- for w in wait
- w.run
- end
- else
- Thread.critical = FALSE
- end
- self
- end
+
+ def mu_try_lock
+ result = false
+ Thread.critical = true
+ unless @mu_locked
+ @mu_locked = true
+ result = true
+ end
+ Thread.critical = false
+ result
+ end
+
+ def mu_lock
+ while (Thread.critical = true; @mu_locked)
+ @mu_waiting.push Thread.current
+ Thread.stop
+ end
+ @mu_locked = true
+ Thread.critical = false
+ self
+ end
+
+ def mu_unlock
+ return unless @mu_locked
+ Thread.critical = true
+ wait = @mu_waiting
+ @mu_waiting = []
+ @mu_locked = false
+ Thread.critical = false
+ for w in wait
+ w.run
+ end
+ self
+ end
+
+ private
+
+ def initialize(*args)
+ ret = super
+ @mu_waiting = []
+ @mu_locked = false;
+ return ret
end
end
-
diff --git a/lib/observer.rb b/lib/observer.rb
index 5928367a7d..0c74b49750 100644
--- a/lib/observer.rb
+++ b/lib/observer.rb
@@ -23,7 +23,7 @@ module Observable
0
end
end
- def changed(state=TRUE)
+ def changed(state=true)
@observer_state = state
end
def changed?
@@ -36,7 +36,7 @@ module Observable
i.update(*arg)
end
end
- @observer_state = FALSE
+ @observer_state = false
end
end
end
diff --git a/lib/open3.rb b/lib/open3.rb
new file mode 100644
index 0000000000..9e34acffc9
--- /dev/null
+++ b/lib/open3.rb
@@ -0,0 +1,55 @@
+# Usage:
+# require "open3"
+#
+# in, out, err = Open3.popen3('nroff -man')
+# or
+# include Open3
+# in, out, err = popen3('nroff -man')
+#
+
+module Open3
+ #[stdin, stdout, stderr] = popen3(command);
+ def popen3(cmd)
+ pw = IO::pipe # pipe[0] for read, pipe[1] for write
+ pr = IO::pipe
+ pe = IO::pipe
+
+ pid = fork
+ if pid == nil then # child
+ pw[1].close
+ STDIN.reopen(pw[0])
+ pw[0].close
+
+ pr[0].close
+ STDOUT.reopen(pr[1])
+ pr[1].close
+
+ pe[0].close
+ STDERR.reopen(pe[1])
+ pe[1].close
+
+ exec(cmd)
+ exit
+ else
+ pw[0].close
+ pr[1].close
+ pe[1].close
+ pi = [ pw[1], pr[0], pe[0] ]
+ end
+ end
+ module_function :popen3
+end
+
+if $0 == __FILE__
+ a = Open3.popen3("nroff -man")
+ Thread.start do
+ while gets
+ a[0].print $_
+ end
+ a[0].close
+ end
+ while a[1].gets
+ print ":", $_
+ end
+end
+
diff --git a/lib/parsedate.rb b/lib/parsedate.rb
index 68550c6505..6afec0ff06 100644
--- a/lib/parsedate.rb
+++ b/lib/parsedate.rb
@@ -8,8 +8,8 @@ module ParseDate
'sun' => 0, 'mon' => 1, 'tue' => 2, 'wed' => 3,
'thu' => 4, 'fri' => 5, 'sat' => 6 }
DAYPAT = DAYS.keys.join('|')
-
- def parsedate(date)
+
+ def parsedate(date, guess=false)
# part of ISO 8601
# yyyy-mm-dd | yyyy-mm | yyyy
# date hh:mm:ss | date Thh:mm:ss
@@ -46,7 +46,7 @@ module ParseDate
if $3
year = $3.to_i
end
- elsif date.sub!(/(#{MONTHPAT})\S*\s+(\d+)\S*\s*,?(?:\s+(\d+))?/i, ' ')
+ elsif date.sub!(/(#{MONTHPAT})\S*\s+(\d+)\S*,?(?:\s+(\d+))?/i, ' ')
mon = MONTHS[$1.downcase]
mday = $2.to_i
if $3
@@ -58,6 +58,23 @@ module ParseDate
if $3
year = $3.to_i
end
+ elsif date.sub!(/(\d+)-(#{MONTHPAT})-(\d+)/i, ' ')
+ mday = $1.to_i
+ mon = MONTHS[$2.downcase]
+ year = $3.to_i
+ end
+ if guess
+ if year < 100
+ if year >= 69
+ year += 1900
+ else
+ year += 2000
+ end
+ end
+ elsif date.sub!(/(\d+)-(#{MONTHPAT})-(\d+)/i, ' ')
+ mday = $1.to_i
+ mon = MONTHS[$2.downcase]
+ year = $3.to_i
end
return year, mon, mday, hour, min, sec, zone, wday
end
diff --git a/lib/profile.rb b/lib/profile.rb
new file mode 100644
index 0000000000..e4b1b4b189
--- /dev/null
+++ b/lib/profile.rb
@@ -0,0 +1,55 @@
+
+module Profiler__
+ Start = Float(Time.times[0])
+ top = "toplevel".intern
+ Stack = [[0, 0, top]]
+ MAP = {top => [1, 0, 0, "#toplevel"]}
+
+ p = proc{|event, file, line, id, binding, klass|
+ case event
+ when "call", "c-call"
+ now = Float(Time.times[0])
+ Stack.push [now, 0.0, id]
+ when "return", "c-return"
+ now = Float(Time.times[0])
+ tick = Stack.pop
+ data = MAP[id]
+ unless data
+ name = klass.to_s
+ if name.nil? then name = '' end
+ if klass.kind_of? Class
+ name += "#"
+ else
+ name += "."
+ end
+ data = [0.0, 0.0, 0.0, name+id.id2name]
+ MAP[id] = data
+ end
+ data[0] += 1
+ cost = now - tick[0]
+ data[1] += cost
+ data[2] += cost - tick[1]
+ Stack[-1][1] += cost
+ end
+ }
+ END {
+ set_trace_func nil
+ total = Float(Time.times[0]) - Start
+ if total == 0 then total = 0.01 end
+ MAP[:toplevel][1] = total
+# f = open("./rmon.out", "w")
+ f = STDERR
+ data = MAP.values.sort!{|a,b| b[2] <=> a[2]}
+ sum = 0
+ f.printf " %% cumulative self self total\n"
+ f.printf " time seconds seconds calls ms/call ms/call name\n"
+ for d in data
+ sum += d[2]
+ f.printf "%6.2f %8.2f %8.2f %8d ", d[2]/total*100, sum, d[2], d[0]
+ f.printf "%8.2f %8.2f %s\n", d[2]*1000/d[0], d[1]*1000/d[0], d[3]
+ end
+ p total
+ f.close
+ }
+ set_trace_func p
+end
diff --git a/lib/rational.rb b/lib/rational.rb
index 1282f56410..f976cf034f 100644
--- a/lib/rational.rb
+++ b/lib/rational.rb
@@ -77,7 +77,7 @@ class Rational < Numeric
@denominator = den
else
@numerator = num.to_i
- @denoninator = den.to_i
+ @denominator = den.to_i
end
end
diff --git a/lib/readbytes.rb b/lib/readbytes.rb
new file mode 100644
index 0000000000..d6a3b10afe
--- /dev/null
+++ b/lib/readbytes.rb
@@ -0,0 +1,36 @@
+# readbytes.rb
+#
+# add IO#readbytes, which reads fixed sized data.
+# it guarantees read data size.
+
+class TruncatedDataError<IOError
+ def initialize(mesg, data)
+ @data = data
+ super(mesg)
+ end
+ attr_reader :data
+end
+
+class IO
+ def readbytes(n)
+ str = read(n)
+ if str == nil
+ raise EOFError, "End of file reached"
+ end
+ if str.size < n
+ raise TruncatedDataError.new("data truncated", str)
+ end
+ str
+ end
+end
+
+if __FILE__ == $0
+ begin
+ loop do
+ print STDIN.readbytes(6)
+ end
+ rescue TruncatedDataError
+ p $!.data
+ raise
+ end
+end
diff --git a/lib/shellwords.rb b/lib/shellwords.rb
index 9154cd84c1..60996be17c 100644
--- a/lib/shellwords.rb
+++ b/lib/shellwords.rb
@@ -17,7 +17,7 @@ module Shellwords
words = []
while line != ''
field = ''
- while TRUE
+ while true
if line.sub! /^"(([^"\\]|\\.)*)"/, '' then #"
snippet = $1
snippet.gsub! /\\(.)/, '\1'
diff --git a/lib/singleton.rb b/lib/singleton.rb
new file mode 100644
index 0000000000..8167a01aa8
--- /dev/null
+++ b/lib/singleton.rb
@@ -0,0 +1,37 @@
+# Singleton module that ensures only one object to be allocated.
+#
+# Usage:
+# class SomeSingletonClass
+# include Singleton
+# #....
+# end
+# a = SomeSingletonClass.instance
+# b = SomeSingletonClass.instance # a and b are same object
+# p [a,b]
+# a = SomeSingletonClass.new # error (`new' is private)
+
+module Singleton
+ def Singleton.append_features(klass)
+ klass.private_class_method(:new)
+ klass.instance_eval %{
+ def instance
+ unless @__instance__
+ @__instance__ = new
+ end
+ return @__instance__
+ end
+ }
+ end
+end
+
+if __FILE__ == $0
+ class SomeSingletonClass
+ include Singleton
+ #....
+ end
+
+ a = SomeSingletonClass.instance
+ b = SomeSingletonClass.instance # a and b are same object
+ p [a,b]
+ a = SomeSingletonClass.new # error (`new' is private)
+end
diff --git a/lib/sync.rb b/lib/sync.rb
index 9f9706d9ee..f1410af1a9 100644
--- a/lib/sync.rb
+++ b/lib/sync.rb
@@ -1,5 +1,5 @@
#
-# sync.rb - ¥«¥¦¥ó¥ÈÉÕ2-¥Õ¥§¡¼¥º¥í¥Ã¥¯¥¯¥é¥¹
+# sync.rb - 2 phase lock with counter
# $Release Version: 0.2$
# $Revision$
# $Date$
@@ -44,8 +44,6 @@ unless defined? Thread
fail "Thread not available for this ruby interpreter"
end
-require "final"
-
module Sync_m
RCS_ID='-$Header$-'
@@ -54,7 +52,7 @@ module Sync_m
SH = :SH
EX = :EX
- # Îã³°ÄêµÁ
+ # exceptions
class Err < StandardError
def Err.Fail(*opt)
fail self, sprintf(self::Message, *opt)
@@ -78,51 +76,27 @@ module Sync_m
end
end
- # include and extend initialize methods.
- def Sync_m.extendable_module(obj)
- if Fixnum === obj or TRUE === obj or FALSE === obj or nil == obj
- raise TypeError, "Sync_m can't extend to this class(#{obj.type})"
- else
- begin
- obj.instance_eval "@sync_locked"
- For_general_object
- rescue TypeError
- For_primitive_object
- end
- end
- end
-
- def Sync_m.includable_module(cl)
- begin
- dummy = cl.new
- Sync_m.extendable_module(dummy)
- rescue NameError
- # new¤¬ÄêµÁ¤µ¤ì¤Æ¤¤¤Ê¤¤»þ¤Ï, DATA¤È¤ß¤Ê¤¹.
- For_primitive_object
+ def Sync_m.append_features(cl)
+ super
+ unless cl.instance_of?(Module)
+ # do nothing for Modules
+ # make aliases and include the proper module.
+ cl.module_eval %q{
+ alias locked? sync_locked?
+ alias shared? sync_shared?
+ alias exclusive? sync_exclusive?
+ alias lock sync_lock
+ alias unlock sync_unlock
+ alias try_lock sync_try_lock
+ alias synchronize sync_synchronize
+ }
end
- end
-
- def Sync_m.extend_class(cl)
- return super if cl.instance_of?(Module)
-
- # ¥â¥¸¥å¡¼¥ë¤Î»þ¤Ï²¿¤â¤·¤Ê¤¤. ¥¯¥é¥¹¤Î¾ì¹ç, ŬÀڤʥ⥸¥å¡¼¥ë¤Î·èÄê
- # ¤Èalias¤ò¹Ô¤¦.
- real = includable_module(cl)
- cl.module_eval %q{
- include real
-
- alias locked? sync_locked?
- alias shared? sync_shared?
- alias exclusive? sync_exclusive?
- alias lock sync_lock
- alias unlock sync_unlock
- alias try_lock sync_try_lock
- alias synchronize sync_synchronize
- }
+ return self
end
def Sync_m.extend_object(obj)
- obj.extend(Sync_m.extendable_module(obj))
+ super
+ obj.sync_extended
end
def sync_extended
@@ -143,6 +117,7 @@ module Sync_m
alias synchronize sync_synchronize
end"
end
+ initialize
end
# accessing
@@ -162,16 +137,16 @@ module Sync_m
def sync_try_lock(mode = EX)
return unlock if sync_mode == UN
- Thread.critical = TRUE
+ Thread.critical = true
ret = sync_try_lock_sub(sync_mode)
- Thread.critical = FALSE
+ Thread.critical = false
ret
end
def sync_lock(m = EX)
return unlock if m == UN
- until (Thread.critical = TRUE; sync_try_lock_sub(m))
+ until (Thread.critical = true; sync_try_lock_sub(m))
if sync_sh_locker[Thread.current]
sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]]
sync_sh_locker.delete(Thread.current)
@@ -180,23 +155,23 @@ module Sync_m
end
Thread.stop
end
- Thread.critical = FALSE
+ Thread.critical = false
self
end
def sync_unlock(m = EX)
- Thread.critical = TRUE
+ Thread.critical = true
if sync_mode == UN
- Thread.critical = FALSE
+ Thread.critical = false
Err::UnknownLocker.Fail(Thread.current)
end
m = sync_mode if m == EX and sync_mode == SH
- runnable = FALSE
+ runnable = false
case m
when UN
- Thread.critical = FALSE
+ Thread.critical = false
Err::UnknownLocker.Fail(Thread.current)
when EX
@@ -208,7 +183,7 @@ module Sync_m
else
self.sync_mode = UN
end
- runnable = TRUE
+ runnable = true
end
else
Err::UnknownLocker.Fail(Thread.current)
@@ -222,7 +197,7 @@ module Sync_m
sync_sh_locker.delete(Thread.current)
if sync_sh_locker.empty? and sync_ex_count == 0
self.sync_mode = UN
- runnable = TRUE
+ runnable = true
end
end
end
@@ -235,7 +210,7 @@ module Sync_m
end
wait = sync_upgrade_waiting
self.sync_upgrade_waiting = []
- Thread.critical = FALSE
+ Thread.critical = false
for w, v in wait
w.run
@@ -243,17 +218,46 @@ module Sync_m
else
wait = sync_waiting
self.sync_waiting = []
- Thread.critical = FALSE
+ Thread.critical = false
for w in wait
w.run
end
end
end
- Thread.critical = FALSE
+ Thread.critical = false
self
end
+ def sync_synchronize(mode = EX)
+ sync_lock(mode)
+ begin
+ yield
+ ensure
+ sync_unlock
+ end
+ end
+
+ attr :sync_mode, true
+ attr :sync_waiting, true
+ attr :sync_upgrade_waiting, true
+ attr :sync_sh_locker, true
+ attr :sync_ex_locker, true
+ attr :sync_ex_count, true
+
+ private
+
+ def initialize(*args)
+ ret = super
+ @sync_mode = UN
+ @sync_waiting = []
+ @sync_upgrade_waiting = []
+ @sync_sh_locker = Hash.new
+ @sync_ex_locker = nil
+ @sync_ex_count = 0
+ return ret
+ end
+
def sync_try_lock_sub(m)
case m
when SH
@@ -261,18 +265,18 @@ module Sync_m
when UN
self.sync_mode = m
sync_sh_locker[Thread.current] = 1
- ret = TRUE
+ ret = true
when SH
count = 0 unless count = sync_sh_locker[Thread.current]
sync_sh_locker[Thread.current] = count + 1
- ret = TRUE
+ ret = true
when EX
- # ´û¤Ë, ¥â¡¼¥É¤¬EX¤Ç¤¢¤ë»þ¤Ï, ɬ¤ºEX¥í¥Ã¥¯¤È¤Ê¤ë.
+ # in EX mode, lock will upgrade to EX lock
if sync_ex_locker == Thread.current
self.sync_ex_count = sync_ex_count + 1
- ret = TRUE
+ ret = true
else
- ret = FALSE
+ ret = false
end
end
when EX
@@ -281,157 +285,29 @@ module Sync_m
self.sync_mode = m
self.sync_ex_locker = Thread.current
self.sync_ex_count = 1
- ret = TRUE
+ ret = true
elsif sync_mode == EX && sync_ex_locker == Thread.current
self.sync_ex_count = sync_ex_count + 1
- ret = TRUE
+ ret = true
else
- ret = FALSE
+ ret = false
end
else
- Thread.critical = FALSE
+ Thread.critical = false
Err::LockModeFailer.Fail mode
end
return ret
end
- private :sync_try_lock_sub
-
- def sync_synchronize(mode = EX)
- sync_lock(mode)
- begin
- yield
- ensure
- sync_unlock
- end
- end
-
- # internal class
- module For_primitive_object
- include Sync_m
-
- LockState = Struct.new("LockState",
- :mode,
- :waiting,
- :upgrade_waiting,
- :sh_locker,
- :ex_locker,
- :ex_count)
-
- Sync_Locked = Hash.new
-
- def For_primitive_object.extend_object(obj)
- super
- obj.sync_extended
- # Changed to use `final.rb'.
- # Finalizer.add(obj, For_primitive_object, :sync_finalize)
- ObjectSpace.define_finalizer(obj) do |id|
- For_primitive_object.sync_finalize(id)
- end
- end
-
- def initialize
- super
- Sync_Locked[id] = LockState.new(UN, [], [], Hash.new, nil, 0 )
- self
- end
-
- def sync_extended
- super
- initialize
- end
-
- def For_primitive_object.sync_finalize(id)
- wait = Sync_Locked.delete(id)
- # waiting == [] ¤È¤­¤À¤± GC¤µ¤ì¤ë¤Î¤Ç, ÂÔ¤Á¹ÔÎó¤Î²òÊü¤Ï°ÕÌ£¤¬¤Ê¤¤.
- end
-
- def sync_mode
- Sync_Locked[id].mode
- end
- def sync_mode=(value)
- Sync_Locked[id].mode = value
- end
-
- def sync_waiting
- Sync_Locked[id].waiting
- end
- def sync_waiting=(v)
- Sync_Locked[id].waiting = v
- end
-
- def sync_upgrade_waiting
- Sync_Locked[id].upgrade_waiting
- end
- def sync_upgrade_waiting=(v)
- Sync_Locked[id].upgrade_waiting = v
- end
-
- def sync_sh_locker
- Sync_Locked[id].sh_locker
- end
- def sync_sh_locker=(v)
- Sync_Locked[id].sh_locker = v
- end
-
- def sync_ex_locker
- Sync_Locked[id].ex_locker
- end
- def sync_ex_locker=(value)
- Sync_Locked[id].ex_locker = value
- end
-
- def sync_ex_count
- Sync_Locked[id].ex_count
- end
- def sync_ex_count=(value)
- Sync_Locked[id].ex_count = value
- end
-
- end
-
- module For_general_object
- include Sync_m
-
- def For_general_object.extend_object(obj)
- super
- obj.sync_extended
- end
-
- def initialize
- super
- @sync_mode = UN
- @sync_waiting = []
- @sync_upgrade_waiting = []
- @sync_sh_locker = Hash.new
- @sync_ex_locker = nil
- @sync_ex_count = 0
- self
- end
-
- def sync_extended
- super
- initialize
- end
-
- attr :sync_mode, TRUE
-
- attr :sync_waiting, TRUE
- attr :sync_upgrade_waiting, TRUE
- attr :sync_sh_locker, TRUE
- attr :sync_ex_locker, TRUE
- attr :sync_ex_count, TRUE
-
- end
end
Synchronizer_m = Sync_m
class Sync
- Sync_m.extend_class self
- #include Sync_m
+ include Sync_m
+
+ private
def initialize
super
end
-
end
Synchronizer = Sync
diff --git a/lib/telnet.rb b/lib/telnet.rb
new file mode 100644
index 0000000000..96e2cac100
--- /dev/null
+++ b/lib/telnet.rb
@@ -0,0 +1,636 @@
+=begin
+$Date: 1999/08/10 05:20:21 $
+
+== SIMPLE TELNET CLIANT LIBRARY
+
+telnet.rb
+
+Version 0.232
+
+Wakou Aoyama <wakou@fsinet.or.jp>
+
+
+=== MAKE NEW TELNET OBJECT
+
+ host = Telnet.new({"Binmode" => false, # default: false
+ "Host" => "localhost", # default: "localhost"
+ "Output_log" => "output_log", # default: not output
+ "Dump_log" => "dump_log", # default: not output
+ "Port" => 23, # default: 23
+ "Prompt" => /[$%#>] \z/n, # default: /[$%#>] \z/n
+ "Telnetmode" => true, # default: true
+ "Timeout" => 10, # default: 10
+ # if ignore timeout then set "Timeout" to false.
+ "Waittime" => 0, # default: 0
+ "Proxy" => proxy}) # default: nil
+ # proxy is Telnet or TCPsocket object
+
+Telnet object has socket class methods.
+
+if set "Telnetmode" option to false. not telnet command interpretation.
+"Waittime" is time to confirm "Prompt". There is a possibility that
+the same character as "Prompt" is included in the data, and, when
+the network or the host is very heavy, the value is enlarged.
+
+=== STATUS OUTPUT
+
+ host = Telnet.new({"Host" => "localhost"){|c| print c }
+
+connection status output.
+
+example
+
+ Trying localhost...
+ Connected to localhost.
+
+
+=== WAIT FOR MATCH
+
+ line = host.waitfor(/match/)
+ line = host.waitfor({"Match" => /match/,
+ "String" => "string",
+ "Timeout" => secs})
+ # if ignore timeout then set "Timeout" to false.
+
+if set "String" option, then Match == Regexp.new(quote("string"))
+
+
+==== REALTIME OUTPUT
+
+ host.waitfor(/match/){|c| print c }
+ host.waitfor({"Match" => /match/,
+ "String" => "string",
+ "Timeout" => secs}){|c| print c}
+
+of cource, set sync=true or flush is necessary.
+
+
+=== SEND STRING AND WAIT PROMPT
+
+ line = host.cmd("string")
+ line = host.cmd({"String" => "string",
+ "Prompt" => /[$%#>] \z/n,
+ "Timeout" => 10})
+
+
+==== REALTIME OUTPUT
+
+ host.cmd("string"){|c| print c }
+ host.cmd({"String" => "string",
+ "Prompt" => /[$%#>] \z/n,
+ "Timeout" => 10}){|c| print c }
+
+of cource, set sync=true or flush is necessary.
+
+
+=== SEND STRING
+
+ host.print("string")
+
+
+=== TURN TELNET COMMAND INTERPRETATION
+
+ host.telnetmode # turn on/off
+ host.telnetmode(true) # on
+ host.telnetmode(false) # off
+
+
+=== TOGGLE NEWLINE TRANSLATION
+
+ host.binmode # turn true/false
+ host.binmode(true) # no translate newline
+ host.binmode(false) # translate newline
+
+
+=== LOGIN
+
+ host.login("username", "password")
+ host.login({"Name" => "username",
+ "Password" => "password",
+ "Prompt" => /[$%#>] \z/n,
+ "Timeout" => 10})
+
+
+==== REALTIME OUTPUT
+
+ host.login("username", "password"){|c| print c }
+ host.login({"Name" => "username",
+ "Password" => "password",
+ "Prompt" => /[$%#>] \z/n,
+ "Timeout" => 10}){|c| print c }
+
+of cource, set sync=true or flush is necessary.
+
+
+== EXAMPLE
+
+=== LOGIN AND SEND COMMAND
+
+ localhost = Telnet.new({"Host" => "localhost",
+ "Timeout" => 10,
+ "Prompt" => /[$%#>] \z/n})
+ localhost.login("username", "password"){|c| print c }
+ localhost.cmd("command"){|c| print c }
+ localhost.close
+
+
+=== CHECKS A POP SERVER TO SEE IF YOU HAVE MAIL
+
+ pop = Telnet.new({"Host" => "your_destination_host_here",
+ "Port" => 110,
+ "Telnetmode" => false,
+ "Prompt" => /^\+OK/n})
+ pop.cmd("user " + "your_username_here"){|c| print c}
+ pop.cmd("pass " + "your_password_here"){|c| print c}
+ pop.cmd("list"){|c| print c}
+
+
+== HISTORY
+
+=== Version 0.232
+
+1999/08/10 05:20:21
+
+- STATUS OUTPUT sample code typo. thanks to Tadayoshi Funaba <tadf@kt.rim.or.jp>
+ host = Telnet.new({"Hosh" => "localhost"){|c| print c }
+ host = Telnet.new({"Host" => "localhost"){|c| print c }
+
+=== Version 0.231
+
+1999/07/16 13:39:42
+
+- TRUE --> true, FALSE --> false
+
+=== Version 0.23
+
+1999/07/15 22:32:09
+
+- waitfor: if end of file reached, then return nil.
+
+=== Version 0.22
+
+1999/06/29 09:08:51
+
+- new, waitfor, cmd: {"Timeout" => false} # ignore timeout
+
+=== Version 0.21
+
+1999/06/28 18:18:55
+
+- waitfor: not rescue (EOFError)
+
+=== Version 0.20
+
+1999/06/04 06:24:58
+
+- waitfor: support for divided telnet command
+
+=== Version 0.181
+
+1999/05/22
+
+- bug fix: print method
+
+=== Version 0.18
+
+1999/05/14
+
+- respond to "IAC WON'T SGA" with "IAC DON'T SGA"
+- DON'T SGA : end of line --> CR + LF
+- bug fix: preprocess method
+
+=== Version 0.17
+
+1999/04/30
+
+- bug fix: $! + "\n" --> $!.to_s + "\n"
+
+=== Version 0.163
+
+1999/04/11
+
+- STDOUT.write(message) --> yield(message) if iterator?
+
+=== Version 0.162
+
+1999/03/17
+
+- add "Proxy" option
+- required timeout.rb
+
+=== Version 0.161
+
+1999/02/03
+
+- select --> IO::select
+
+=== Version 0.16
+
+1998/10/09
+
+- preprocess method change for the better
+- add binmode method.
+- change default Binmode. TRUE --> FALSE
+
+=== Version 0.15
+
+1998/10/04
+
+- add telnetmode method.
+
+=== Version 0.141
+
+1998/09/22
+
+- change default prompt. /[$%#>] $/ --> /[$%#>] \Z/
+
+=== Version 0.14
+
+1998/09/01
+
+- IAC WILL SGA send EOL --> CR+NULL
+- IAC WILL SGA IAC DO BIN send EOL --> CR
+- NONE send EOL --> LF
+- add Dump_log option.
+
+=== Version 0.13
+
+1998/08/25
+
+- add print method.
+
+=== Version 0.122
+
+1998/08/05
+
+- support for HP-UX 10.20 thanks to WATANABE Tetsuya <tetsu@jpn.hp.com>
+- socket.<< --> socket.write
+
+=== Version 0.121
+
+1998/07/15
+
+- string.+= --> string.concat
+
+=== Version 0.12
+
+1998/06/01
+
+- add timeout, waittime.
+
+=== Version 0.11
+
+1998/04/21
+
+- add realtime output.
+
+=== Version 0.10
+
+1998/04/13
+
+- first release.
+
+=end
+
+require "socket"
+require "delegate"
+require "thread"
+require "timeout"
+TimeOut = TimeoutError
+
+class Telnet < SimpleDelegator
+
+ IAC = 255.chr # "\377" # interpret as command:
+ DONT = 254.chr # "\376" # you are not to use option
+ DO = 253.chr # "\375" # please, you use option
+ WONT = 252.chr # "\374" # I won't use option
+ WILL = 251.chr # "\373" # I will use option
+ SB = 250.chr # "\372" # interpret as subnegotiation
+ GA = 249.chr # "\371" # you may reverse the line
+ EL = 248.chr # "\370" # erase the current line
+ EC = 247.chr # "\367" # erase the current character
+ AYT = 246.chr # "\366" # are you there
+ AO = 245.chr # "\365" # abort output--but let prog finish
+ IP = 244.chr # "\364" # interrupt process--permanently
+ BREAK = 243.chr # "\363" # break
+ DM = 242.chr # "\362" # data mark--for connect. cleaning
+ NOP = 241.chr # "\361" # nop
+ SE = 240.chr # "\360" # end sub negotiation
+ EOR = 239.chr # "\357" # end of record (transparent mode)
+ ABORT = 238.chr # "\356" # Abort process
+ SUSP = 237.chr # "\355" # Suspend process
+ EOF = 236.chr # "\354" # End of file
+ SYNCH = 242.chr # "\362" # for telfunc calls
+
+ OPT_BINARY = 0.chr # "\000" # Binary Transmission
+ OPT_ECHO = 1.chr # "\001" # Echo
+ OPT_RCP = 2.chr # "\002" # Reconnection
+ OPT_SGA = 3.chr # "\003" # Suppress Go Ahead
+ OPT_NAMS = 4.chr # "\004" # Approx Message Size Negotiation
+ OPT_STATUS = 5.chr # "\005" # Status
+ OPT_TM = 6.chr # "\006" # Timing Mark
+ OPT_RCTE = 7.chr # "\a" # Remote Controlled Trans and Echo
+ OPT_NAOL = 8.chr # "\010" # Output Line Width
+ OPT_NAOP = 9.chr # "\t" # Output Page Size
+ OPT_NAOCRD = 10.chr # "\n" # Output Carriage-Return Disposition
+ OPT_NAOHTS = 11.chr # "\v" # Output Horizontal Tab Stops
+ OPT_NAOHTD = 12.chr # "\f" # Output Horizontal Tab Disposition
+ OPT_NAOFFD = 13.chr # "\r" # Output Formfeed Disposition
+ OPT_NAOVTS = 14.chr # "\016" # Output Vertical Tabstops
+ OPT_NAOVTD = 15.chr # "\017" # Output Vertical Tab Disposition
+ OPT_NAOLFD = 16.chr # "\020" # Output Linefeed Disposition
+ OPT_XASCII = 17.chr # "\021" # Extended ASCII
+ OPT_LOGOUT = 18.chr # "\022" # Logout
+ OPT_BM = 19.chr # "\023" # Byte Macro
+ OPT_DET = 20.chr # "\024" # Data Entry Terminal
+ OPT_SUPDUP = 21.chr # "\025" # SUPDUP
+ OPT_SUPDUPOUTPUT = 22.chr # "\026" # SUPDUP Output
+ OPT_SNDLOC = 23.chr # "\027" # Send Location
+ OPT_TTYPE = 24.chr # "\030" # Terminal Type
+ OPT_EOR = 25.chr # "\031" # End of Record
+ OPT_TUID = 26.chr # "\032" # TACACS User Identification
+ OPT_OUTMRK = 27.chr # "\e" # Output Marking
+ OPT_TTYLOC = 28.chr # "\034" # Terminal Location Number
+ OPT_3270REGIME = 29.chr # "\035" # Telnet 3270 Regime
+ OPT_X3PAD = 30.chr # "\036" # X.3 PAD
+ OPT_NAWS = 31.chr # "\037" # Negotiate About Window Size
+ OPT_TSPEED = 32.chr # " " # Terminal Speed
+ OPT_LFLOW = 33.chr # "!" # Remote Flow Control
+ OPT_LINEMODE = 34.chr # "\"" # Linemode
+ OPT_XDISPLOC = 35.chr # "#" # X Display Location
+ OPT_OLD_ENVIRON = 36.chr # "$" # Environment Option
+ OPT_AUTHENTICATION = 37.chr # "%" # Authentication Option
+ OPT_ENCRYPT = 38.chr # "&" # Encryption Option
+ OPT_NEW_ENVIRON = 39.chr # "'" # New Environment Option
+ OPT_EXOPL = 255.chr # "\377" # Extended-Options-List
+
+ NULL = "\000"
+ CR = "\015"
+ LF = "\012"
+ EOL = CR + LF
+v = $-v
+$-v = false
+ VERSION = "0.232"
+ RELEASE_DATE = "$Date: 1999/08/10 05:20:21 $"
+$-v = v
+
+ def initialize(options)
+ @options = options
+ @options["Binmode"] = false unless @options.key?("Binmode")
+ @options["Host"] = "localhost" unless @options.key?("Host")
+ @options["Port"] = 23 unless @options.key?("Port")
+ @options["Prompt"] = /[$%#>] \z/n unless @options.key?("Prompt")
+ @options["Telnetmode"] = true unless @options.key?("Telnetmode")
+ @options["Timeout"] = 10 unless @options.key?("Timeout")
+ @options["Waittime"] = 0 unless @options.key?("Waittime")
+
+ @telnet_option = { "SGA" => false, "BINARY" => false }
+
+ if @options.key?("Output_log")
+ @log = File.open(@options["Output_log"], 'a+')
+ @log.sync = true
+ @log.binmode
+ end
+
+ if @options.key?("Dump_log")
+ @dumplog = File.open(@options["Dump_log"], 'a+')
+ @dumplog.sync = true
+ @dumplog.binmode
+ end
+
+ if @options.key?("Proxy")
+ if @options["Proxy"].kind_of?(Telnet)
+ @sock = @options["Proxy"].sock
+ elsif @options["Proxy"].kind_of?(TCPsocket)
+ @sock = @options["Proxy"]
+ else
+ raise "Error; Proxy is Telnet or TCPSocket object."
+ end
+ else
+ message = "Trying " + @options["Host"] + "...\n"
+ yield(message) if iterator?
+ @log.write(message) if @options.key?("Output_log")
+ @dumplog.write(message) if @options.key?("Dump_log")
+
+ begin
+ if @options["Timeout"] == false
+ @sock = TCPsocket.open(@options["Host"], @options["Port"])
+ else
+ timeout(@options["Timeout"]){
+ @sock = TCPsocket.open(@options["Host"], @options["Port"])
+ }
+ end
+ rescue TimeoutError
+ raise TimeOut, "timed-out; opening of the host"
+ rescue
+ @log.write($!.to_s + "\n") if @options.key?("Output_log")
+ @dumplog.write($!.to_s + "\n") if @options.key?("Dump_log")
+ raise
+ end
+ @sock.sync = true
+ @sock.binmode
+
+ message = "Connected to " + @options["Host"] + ".\n"
+ yield(message) if iterator?
+ @log.write(message) if @options.key?("Output_log")
+ @dumplog.write(message) if @options.key?("Dump_log")
+ end
+
+ super(@sock)
+ end # initialize
+
+ attr :sock
+
+ def telnetmode(mode = 'turn')
+ if 'turn' == mode
+ @options["Telnetmode"] = @options["Telnetmode"] ? false : true
+ else
+ @options["Telnetmode"] = mode ? true : false
+ end
+ end
+
+ def binmode(mode = 'turn')
+ if 'turn' == mode
+ @options["Binmode"] = @options["Binmode"] ? false : true
+ else
+ @options["Binmode"] = mode ? true : false
+ end
+ end
+
+ def preprocess(string)
+ str = string.dup
+
+ # combine CR+NULL into CR
+ str.gsub!(/#{CR}#{NULL}/no, CR) if @options["Telnetmode"]
+
+ # combine EOL into "\n"
+ str.gsub!(/#{EOL}/no, "\n") unless @options["Binmode"]
+
+ # respond to "IAC DO x"
+ str.gsub!(/([^#{IAC}]?)#{IAC}#{DO}([#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}])/no){
+ if OPT_BINARY == $2
+ @telnet_option["BINARY"] = true
+ @sock.write(IAC + WILL + OPT_BINARY)
+ else
+ @sock.write(IAC + WONT + $2)
+ end
+ $1
+ }
+
+ # respond to "IAC DON'T x" with "IAC WON'T x"
+ str.gsub!(/([^#{IAC}]?)#{IAC}#{DONT}([#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}])/no){
+ @sock.write(IAC + WONT + $2)
+ $1
+ }
+
+ # respond to "IAC WILL x"
+ str.gsub!(/([^#{IAC}]?)#{IAC}#{WILL}([#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}])/no){
+ if OPT_ECHO == $2
+ @sock.write(IAC + DO + OPT_ECHO)
+ elsif OPT_SGA == $2
+ @telnet_option["SGA"] = true
+ @sock.write(IAC + DO + OPT_SGA)
+ end
+ $1
+ }
+
+ # respond to "IAC WON'T x"
+ str.gsub!(/([^#{IAC}]?)#{IAC}#{WONT}([#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}])/no){
+ if OPT_ECHO == $2
+ @sock.write(IAC + DONT + OPT_ECHO)
+ elsif OPT_SGA == $2
+ @telnet_option["SGA"] = false
+ @sock.write(IAC + DONT + OPT_SGA)
+ end
+ $1
+ }
+
+ # respond to "IAC AYT" (are you there)
+ str.gsub!(/([^#{IAC}]?)#{IAC}#{AYT}/no){
+ @sock.write("nobody here but us pigeons" + EOL)
+ $1
+ }
+
+ str.gsub!(/#{IAC}#{IAC}/no, IAC) # handle escaped IAC characters
+
+ str
+ end # preprocess
+
+ def waitfor(options)
+ time_out = @options["Timeout"]
+ waittime = @options["Waittime"]
+
+ if options.kind_of?(Hash)
+ prompt = if options.key?("Match")
+ options["Match"]
+ elsif options.key?("Prompt")
+ options["Prompt"]
+ elsif options.key?("String")
+ Regexp.new( Regexp.quote(options["String"]) )
+ end
+ time_out = options["Timeout"] if options.key?("Timeout")
+ waittime = options["Waittime"] if options.key?("Waittime")
+ else
+ prompt = options
+ end
+
+ if time_out == false
+ time_out = nil
+ end
+
+ line = ''
+ buf = ''
+ until(not IO::select([@sock], nil, nil, waittime) and prompt === line)
+ unless IO::select([@sock], nil, nil, time_out)
+ raise TimeOut, "timed-out; wait for the next data"
+ end
+ begin
+ c = @sock.sysread(1024 * 1024)
+ @dumplog.print(c) if @options.key?("Dump_log")
+ buf.concat c
+ if @options["Telnetmode"]
+ buf = preprocess(buf)
+ if /#{IAC}.?\z/no === buf
+ next
+ end
+ end
+ @log.print(buf) if @options.key?("Output_log")
+ yield buf if iterator?
+ line.concat(buf)
+ buf = ''
+ rescue EOFError # End of file reached
+ if line == ''
+ line = nil
+ yield nil if iterator?
+ end
+ break
+ end
+ end
+ line
+ end
+
+ def print(string)
+ str = string.dup + "\n"
+
+ str.gsub!(/#{IAC}/no, IAC + IAC) if @options["Telnetmode"]
+
+ unless @options["Binmode"]
+ if @telnet_option["BINARY"] and @telnet_option["SGA"]
+ # IAC WILL SGA IAC DO BIN send EOL --> CR
+ str.gsub!(/\n/n, CR)
+ elsif @telnet_option["SGA"]
+ # IAC WILL SGA send EOL --> CR+NULL
+ str.gsub!(/\n/n, CR + NULL)
+ else
+ # NONE send EOL --> CR+LF
+ str.gsub!(/\n/n, EOL)
+ end
+ end
+
+ @sock.write(str)
+ end
+
+ def cmd(options)
+ match = @options["Prompt"]
+ time_out = @options["Timeout"]
+
+ if options.kind_of?(Hash)
+ string = options["String"]
+ match = options["Match"] if options.key?("Match")
+ time_out = options["Timeout"] if options.key?("Timeout")
+ else
+ string = options
+ end
+
+ IO::select(nil, [@sock])
+ self.print(string)
+ if iterator?
+ waitfor({"Prompt" => match, "Timeout" => time_out}){|c| yield c }
+ else
+ waitfor({"Prompt" => match, "Timeout" => time_out})
+ end
+ end
+
+ def login(options, password = '')
+ if options.kind_of?(Hash)
+ username = options["Name"]
+ password = options["Password"]
+ else
+ username = options
+ end
+
+ if iterator?
+ line = waitfor(/login[: ]*\z/n){|c| yield c }
+ line.concat( cmd({"String" => username,
+ "Match" => /Password[: ]*\z/n}){|c| yield c } )
+ line.concat( cmd(password){|c| yield c } )
+ else
+ line = waitfor(/login[: ]*\z/n)
+ line.concat( cmd({"String" => username,
+ "Match" => /Password[: ]*\z/n}) )
+ line.concat( cmd(password) )
+ end
+ line
+ end
+
+end
diff --git a/lib/tempfile.rb b/lib/tempfile.rb
new file mode 100644
index 0000000000..11a8fba979
--- /dev/null
+++ b/lib/tempfile.rb
@@ -0,0 +1,94 @@
+#
+# $Id$
+#
+# The class for temporary files.
+# o creates a temporary file, which name is "basename.pid.n" with mode "w+".
+# o Tempfile objects can be used like IO object.
+# o with tmpfile.close(true) created temporary files are removed.
+# o created files are also removed on script termination.
+# o with Tempfile#open, you can reopen the temporary file.
+# o file mode of the temporary files are 0600.
+
+require 'delegate'
+require 'final'
+
+class Tempfile < SimpleDelegator
+ Max_try = 10
+
+ def Tempfile.callback(path)
+ lambda{
+ print "removing ", path, "..." if $DEBUG
+ if File.exist?(path)
+ File.unlink(path)
+ end
+ if File.exist?(path + '.lock')
+ Dir.rmdir(path + '.lock')
+ end
+ print "done\n" if $DEBUG
+ }
+ end
+
+ def initialize(basename, tmpdir=ENV['TMPDIR']||ENV['TMP']||ENV['TEMP']||'/tmp')
+ umask = File.umask(0177)
+ begin
+ n = 0
+ while true
+ begin
+ tmpname = sprintf('%s/%s%d.%d', tmpdir, basename, $$, n)
+ lock = tmpname + '.lock'
+ unless File.exist?(tmpname) or File.exist?(lock)
+ Dir.mkdir(lock)
+ break
+ end
+ rescue
+ raise "cannot generate tmpfile `%s'" % tmpname if n >= Max_try
+ #sleep(1)
+ end
+ n += 1
+ end
+
+ @clean_files = Tempfile.callback(tmpname)
+ ObjectSpace.define_finalizer(self, @clean_files)
+
+ @tmpfile = File.open(tmpname, 'w+')
+ @tmpname = tmpname
+ super(@tmpfile)
+ Dir.rmdir(lock)
+ ensure
+ File.umask(umask)
+ end
+ end
+
+ def Tempfile.open(*args)
+ Tempfile.new(*args)
+ end
+
+ def open
+ @tmpfile.close if @tmpfile
+ @tmpfile = File.open(@tmpname, 'r+')
+ __setobj__(@tmpfile)
+ end
+
+ def close(real=false)
+ @tmpfile.close if @tmpfile
+ @tmpfile = nil
+ if real
+ @clean_files.call
+ ObjectSpace.undefine_finalizer(self)
+ end
+ end
+
+ def path
+ @tmpname
+ end
+end
+
+if __FILE__ == $0
+# $DEBUG = true
+ f = Tempfile.new("foo")
+ f.print("foo\n")
+ f.close
+ f.open
+ p f.gets # => "foo\n"
+ f.close(true)
+end
diff --git a/lib/thread.rb b/lib/thread.rb
index ec75144374..22610f2992 100644
--- a/lib/thread.rb
+++ b/lib/thread.rb
@@ -17,6 +17,16 @@ if $DEBUG
Thread.abort_on_exception = true
end
+def Thread.exclusive
+ begin
+ Thread.critical = true
+ r = yield
+ ensure
+ Thread.critical = false
+ end
+ r
+end
+
class Mutex
def initialize
@waiting = []
@@ -52,10 +62,10 @@ class Mutex
def unlock
return unless @locked
- Thread.critical = TRUE
+ Thread.critical = true
t = @waiting.shift
- @locked = FALSE
- Thread.critical = FALSE
+ @locked = false
+ Thread.critical = false
t.run if t
self
end
@@ -68,39 +78,46 @@ class Mutex
unlock
end
end
+
+ def exclusive_unlock
+ return unless @locked
+ Thread.exclusive do
+ t = @waiting.shift
+ @locked = false
+ t.wakeup if t
+ yield
+ end
+ self
+ end
end
class ConditionVariable
def initialize
@waiters = []
- @waiters_mutex = Mutex.new
- @waiters.taint # enable tainted comunication
- self.taint
end
def wait(mutex)
- mutex.unlock
- @waiters_mutex.synchronize {
+ mutex.exclusive_unlock do
@waiters.push(Thread.current)
- }
- Thread.stop
+ Thread.stop
+ end
mutex.lock
end
def signal
- @waiters_mutex.synchronize {
- t = @waiters.shift
- t.run if t
- }
+ t = @waiters.shift
+ t.run if t
end
def broadcast
- @waiters_mutex.synchronize {
- for t in @waiters
- t.run
- end
+ waiters0 = nil
+ Thread.exclusive do
+ waiters0 = @waiters.dup
@waiters.clear
- }
+ end
+ for t in waiters0
+ t.run
+ end
end
end
@@ -120,6 +137,7 @@ class Queue
Thread.critical = false
t.run if t
end
+ alias enq push
def pop non_block=false
Thread.critical = true
@@ -139,11 +157,17 @@ class Queue
Thread.critical = false
end
end
+ alias shift pop
+ alias deq pop
def empty?
@que.length == 0
end
+ def clear
+ @que.replace([])
+ end
+
def length
@que.length
end
@@ -168,14 +192,14 @@ class SizedQueue<Queue
end
def max=(max)
- Thread.critical = TRUE
+ Thread.critical = true
if @max >= max
@max = max
- Thread.critical = FALSE
+ Thread.critical = false
else
diff = max - @max
@max = max
- Thread.critical = FALSE
+ Thread.critical = false
diff.times do
t = @queue_wait.shift
t.run if t
diff --git a/lib/timeout.rb b/lib/timeout.rb
new file mode 100644
index 0000000000..d4ea758acd
--- /dev/null
+++ b/lib/timeout.rb
@@ -0,0 +1,42 @@
+#
+# timeout.rb -- execution timeout
+#
+#= SYNOPSIS
+#
+# require 'timeout'
+# status = timeout(5) {
+# # something may take time
+# }
+#
+#= DESCRIPTION
+#
+# timeout executes the block. If the block execution terminates successfully
+# before timeout, it returns true. If not, it terminates the execution and
+# raise TimeoutError exception.
+#
+#== Parameters
+#
+# : timout
+#
+# The time in seconds to wait for block teminatation.
+#
+#=end
+
+class TimeoutError<StandardError
+end
+
+Thread.abort_on_exception = true
+
+def timeout(sec)
+ begin
+ x = Thread.current
+ y = Thread.start {
+ sleep sec
+ x.raise TimeoutError, "execution expired" if x.status
+ }
+ yield sec
+ return true
+ ensure
+ Thread.kill y if y.status
+ end
+end
diff --git a/lib/tracer.rb b/lib/tracer.rb
index fbfca24fe5..a8dc2a104d 100644
--- a/lib/tracer.rb
+++ b/lib/tracer.rb
@@ -54,7 +54,7 @@ class Tracer
off
end
else
- set_trace_func proc{|event, file, line, id, binding|
+ set_trace_func proc{|event, file, line, id, binding, klass|
trace_func event, file, line, id, binding
}
print "Trace on\n" if Tracer.verbose?
diff --git a/lib/weakref.rb b/lib/weakref.rb
index c31e959e74..c6fe8cd21b 100644
--- a/lib/weakref.rb
+++ b/lib/weakref.rb
@@ -2,11 +2,12 @@
#
# Usage:
# foo = Object.new
-# foo.hash
+# foo = Object.new
+# p foo.to_s # original's class
# foo = WeakRef.new(foo)
-# foo.hash
+# p foo.to_s # should be same class
# ObjectSpace.garbage_collect
-# foo.hash # => Raises WeakRef::RefError (because original GC'ed)
+# p foo.to_s # should raise exception (recycled)
require "delegate"
@@ -15,27 +16,31 @@ class WeakRef<Delegator
class RefError<StandardError
end
- ID_MAP = {}
- ID_REV_MAP = {}
+ ID_MAP = {} # obj -> [ref,...]
+ ID_REV_MAP = {} # ref -> obj
ObjectSpace.add_finalizer(lambda{|id|
- rid = ID_MAP[id]
- if rid
- ID_REV_MAP[rid] = nil
+ rids = ID_MAP[id]
+ if rids
+ for rid in rids
+ ID_REV_MAP[rid] = nil
+ end
ID_MAP[id] = nil
end
rid = ID_REV_MAP[id]
if rid
ID_REV_MAP[id] = nil
- ID_MAP[rid] = nil
+ ID_MAP[rid].delete(id)
+ ID_MAP[rid] = nil if ID_MAP[rid].empty?
end
})
-
+
def initialize(orig)
super
@__id = orig.__id__
ObjectSpace.call_finalizer orig
ObjectSpace.call_finalizer self
- ID_MAP[@__id] = self.__id__
+ ID_MAP[@__id] = [] unless ID_MAP[@__id]
+ ID_MAP[@__id].concat self.__id__
ID_REV_MAP[self.id] = @__id
end
@@ -60,10 +65,11 @@ class WeakRef<Delegator
end
if __FILE__ == $0
+ require 'thread'
foo = Object.new
- p foo.hash # original's hash value
+ p foo.to_s # original's class
foo = WeakRef.new(foo)
- p foo.hash # should be same hash value
+ p foo.to_s # should be same class
ObjectSpace.garbage_collect
- p foo.hash # should raise exception (recycled)
+ p foo.to_s # should raise exception (recycled)
end
diff --git a/main.c b/main.c
index 5fd27cba4c..dccf0a8953 100644
--- a/main.c
+++ b/main.c
@@ -11,13 +11,17 @@
#include "ruby.h"
#ifdef DJGPP
-unsigned int _stklen = 0x100000;
+unsigned int _stklen = 0x180000;
#endif
#ifdef __human68k__
int _stacksize = 131072;
#endif
+#if defined(__MACOS__) && defined(__MWERKS__)
+#include <console.h>
+#endif
+
int
main(argc, argv, envp)
int argc;
@@ -26,6 +30,9 @@ main(argc, argv, envp)
#if defined(NT)
NtInitialize(&argc, &argv);
#endif
+#if defined(__MACOS__) && defined(__MWERKS__)
+ argc = ccommand(&argv);
+#endif
ruby_init();
ruby_options(argc, argv);
diff --git a/marshal.c b/marshal.c
index 6a68b04352..9d4808b8ab 100644
--- a/marshal.c
+++ b/marshal.c
@@ -12,8 +12,12 @@
#include "rubyio.h"
#include "st.h"
+#ifndef atof
+double strtod();
+#endif
+
#define MARSHAL_MAJOR 4
-#define MARSHAL_MINOR 0
+#define MARSHAL_MINOR 1
#define TYPE_NIL '0'
#define TYPE_TRUE 'T'
@@ -37,8 +41,6 @@
#define TYPE_LINK '@'
-VALUE rb_path2class _((char*));
-
static ID s_dump, s_load;
struct dump_arg {
@@ -164,7 +166,7 @@ w_unique(s, arg)
static void w_object _((VALUE,struct dump_arg*,int));
static int
-rb_hash_each(key, value, arg)
+hash_each(key, value, arg)
VALUE key, value;
struct dump_call_arg *arg;
{
@@ -174,7 +176,7 @@ rb_hash_each(key, value, arg)
}
static int
-rb_obj_each(id, value, arg)
+obj_each(id, value, arg)
ID id;
VALUE value;
struct dump_call_arg *arg;
@@ -249,9 +251,9 @@ w_object(obj, arg, limit)
w_byte(TYPE_USERDEF, arg);
w_unique(rb_class2name(CLASS_OF(obj)), arg);
- v = rb_funcall(obj, s_dump, 1, limit);
+ v = rb_funcall(obj, s_dump, 1, INT2NUM(limit));
if (TYPE(v) != T_STRING) {
- rb_raise(rb_eTypeError, "_dump_to must return String");
+ rb_raise(rb_eTypeError, "_dump() must return String");
}
w_bytes(RSTRING(v)->ptr, RSTRING(v)->len, arg);
return;
@@ -320,7 +322,7 @@ w_object(obj, arg, limit)
w_uclass(obj, rb_cHash, arg);
w_byte(TYPE_HASH, arg);
w_long(RHASH(obj)->tbl->num_entries, arg);
- st_foreach(RHASH(obj)->tbl, rb_hash_each, &c_arg);
+ st_foreach(RHASH(obj)->tbl, hash_each, &c_arg);
break;
case T_STRUCT:
@@ -357,7 +359,7 @@ w_object(obj, arg, limit)
w_unique(path, arg);
if (ROBJECT(obj)->iv_tbl) {
w_long(ROBJECT(obj)->iv_tbl->num_entries, arg);
- st_foreach(ROBJECT(obj)->iv_tbl, rb_obj_each, &c_arg);
+ st_foreach(ROBJECT(obj)->iv_tbl, obj_each, &c_arg);
}
else {
w_long(0, arg);
@@ -455,9 +457,19 @@ static int
r_byte(arg)
struct load_arg *arg;
{
- if (arg->fp) return getc(arg->fp);
- if (arg->ptr < arg->end) return *(unsigned char*)arg->ptr++;
- return EOF;
+ int c;
+
+ if (arg->fp) {
+ c = rb_getc(arg->fp);
+ if (c == EOF) rb_eof_error();
+ }
+ else if (arg->ptr < arg->end) {
+ c = *(unsigned char*)arg->ptr++;
+ }
+ else {
+ rb_raise(rb_eArgError, "marshal data too short");
+ }
+ return c;
}
static unsigned short
@@ -602,10 +614,6 @@ r_object(arg)
int type = r_byte(arg);
switch (type) {
- case EOF:
- rb_eof_error();
- return Qnil;
-
case TYPE_LINK:
if (st_lookup(arg->data, r_long(arg), &v)) {
return v;
@@ -641,13 +649,10 @@ r_object(arg)
case TYPE_FLOAT:
{
-#ifndef atof
- double atof();
-#endif
char *buf;
r_bytes(buf, arg);
- v = rb_float_new(atof(buf));
+ v = rb_float_new(strtod(buf, 0));
return r_regist(v, arg);
}
@@ -754,7 +759,7 @@ r_object(arg)
v = rb_funcall(klass, s_load, 1, r_string(arg));
return r_regist(v, arg);
}
- rb_raise(rb_eTypeError, "class %s needs to have method `_load_from'",
+ rb_raise(rb_eTypeError, "class %s needs to have method `_load'",
rb_class2name(klass));
}
break;
@@ -850,7 +855,7 @@ marshal_load(argc, argv)
v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg);
}
else {
- rb_raise(rb_eTypeError, "Old marshal file format (can't read)");
+ rb_raise(rb_eTypeError, "old marshal file format (can't read)");
}
return v;
diff --git a/math.c b/math.c
index 3ea30bdbba..978a23c73c 100644
--- a/math.c
+++ b/math.c
@@ -6,7 +6,7 @@
$Date$
created at: Tue Jan 25 14:12:56 JST 1994
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
diff --git a/misc/README b/misc/README
new file mode 100644
index 0000000000..adc119d02e
--- /dev/null
+++ b/misc/README
@@ -0,0 +1,5 @@
+README this file
+inf-ruby.el program to run ruby under emacs
+ruby-mode.el ruby mode for emacs
+rubydb2x.el ruby debugger support for emacs 19.2x or before
+rubydb3x.el ruby debugger support for emacs 19.3x or later
diff --git a/misc/inf-ruby.el b/misc/inf-ruby.el
new file mode 100644
index 0000000000..eaa904951c
--- /dev/null
+++ b/misc/inf-ruby.el
@@ -0,0 +1,322 @@
+;;; -*-Emacs-Lisp-*-
+;;;
+;;; $Id$
+;;; $Author$
+;;; $Date$
+;;;
+;;; Inferior Ruby Mode - ruby process in a buffer.
+;;; adapted from cmuscheme.el
+;;;
+;;; Usage:
+;;;
+;;; (0) check ruby-program-name variable that can run your environment.
+;;;
+;;; (1) modify .emacs to use ruby-mode
+;;; for example :
+;;;
+;;; (autoload 'ruby-mode "ruby-mode"
+;;; "Mode for editing ruby source files")
+;;; (setq auto-mode-alist
+;;; (append '(("\\.rb$" . ruby-mode)) auto-mode-alist))
+;;; (setq interpreter-mode-alist (append '(("^#!.*ruby" . ruby-mode))
+;;; interpreter-mode-alist))
+;;;
+;;; (2) set to road inf-ruby and set inf-ruby key definition in ruby-mode.
+;;;
+;;; (autoload 'run-ruby "inf-ruby"
+;;; "Run an inferior Ruby process")
+;;; (autoload 'inf-ruby-keys "inf-ruby"
+;;; "Set local key defs for inf-ruby in ruby-mode")
+;;; (add-hook 'ruby-mode-hook
+;;; '(lambda ()
+;;; (inf-ruby-keys)
+;;; ))
+;;;
+;;; HISTORY
+;;; senda - 8 Apr 1998: Created.
+;;; $Log$
+;;; Revision 1.2 1999/08/13 05:45:18 matz
+;;; 1.4.0
+;;;
+;;; Revision 1.1.1.1.2.1 1999/07/15 07:59:59 matz
+;;; 990715
+;;;
+;;; Revision 1.1.1.1 1999/01/20 04:59:36 matz
+;;; ruby 1.3 cycle
+;;;
+;;; Revision 1.1.2.1 1998/12/16 07:30:36 matz
+;;; first public release of 1.1d (pre1.2) series
+;;;
+;;; Revision 1.4 1998/05/20 02:45:58 senda
+;;; default program to irb
+;;;
+;;; Revision 1.3 1998/04/10 04:11:30 senda
+;;; modification by Matsumoto san (1.1b9_09)
+;;; remove-in-string defined
+;;; global variable :
+;;; inferior-ruby-first-prompt-pattern
+;;; inferior-ruby-prompt-pattern
+;;; defined
+;;;
+;;; Revision 1.2 1998/04/09 07:53:42 senda
+;;; remove M-C-x in inferior-ruby-mode
+;;;
+;;; Revision 1.1 1998/04/09 07:28:36 senda
+;;; Initial revision
+;;;
+;;;
+
+(require 'comint)
+(require 'ruby-mode)
+
+;;
+;; you may change these variables
+;;
+;(defvar ruby-program-name "rbc --noreadline"
+; "*Program invoked by the run-ruby command")
+;
+;(defvar inferior-ruby-first-prompt-pattern "^rbc0> *"
+; "first prompt regex pattern of ruby interpreter.")
+;
+;(defvar inferior-ruby-prompt-pattern "^\\(rbc.[>*\"'] *\\)+"
+; "prompt regex pattern of ruby interpreter.")
+
+;;;; for irb
+(defvar ruby-program-name "irb --inf-ruby-mode"
+ "*Program invoked by the run-ruby command")
+
+(defvar inferior-ruby-first-prompt-pattern "^irb(.*)[0-9:]+0> *"
+ "first prompt regex pattern of ruby interpreter.")
+
+(defvar inferior-ruby-prompt-pattern "^\\(irb(.*)[0-9:]+[>*\"'] *\\)+"
+ "prompt regex pattern of ruby interpreter.")
+
+;;
+;; mode variables
+;;
+(defvar inferior-ruby-mode-hook nil
+ "*Hook for customising inferior-ruby mode.")
+(defvar inferior-ruby-mode-map nil
+ "*Mode map for inferior-ruby-mode")
+
+(cond ((not inferior-ruby-mode-map)
+ (setq inferior-ruby-mode-map
+ (copy-keymap comint-mode-map))
+; (define-key inferior-ruby-mode-map "\M-\C-x" ;gnu convention
+; 'ruby-send-definition)
+; (define-key inferior-ruby-mode-map "\C-x\C-e" 'ruby-send-last-sexp)
+ (define-key inferior-ruby-mode-map "\C-c\C-l" 'ruby-load-file)
+))
+
+(defun inf-ruby-keys ()
+ "Set local key defs for inf-ruby in ruby-mode"
+ (define-key ruby-mode-map "\M-\C-x" 'ruby-send-definition)
+; (define-key ruby-mode-map "\C-x\C-e" 'ruby-send-last-sexp)
+ (define-key ruby-mode-map "\C-c\C-e" 'ruby-send-definition)
+ (define-key ruby-mode-map "\C-c\M-e" 'ruby-send-definition-and-go)
+ (define-key ruby-mode-map "\C-c\C-r" 'ruby-send-region)
+ (define-key ruby-mode-map "\C-c\M-r" 'ruby-send-region-and-go)
+ (define-key ruby-mode-map "\C-c\C-z" 'switch-to-ruby)
+ (define-key ruby-mode-map "\C-c\C-l" 'ruby-load-file)
+ (define-key ruby-mode-map "\C-c\C-s" 'run-ruby)
+)
+
+(defvar ruby-buffer nil "current ruby (actually irb) process buffer.")
+
+(defun inferior-ruby-mode ()
+ "Major mode for interacting with an inferior ruby (irb) process.
+
+The following commands are available:
+\\{inferior-ruby-mode-map}
+
+A ruby process can be fired up with M-x run-ruby.
+
+Customisation: Entry to this mode runs the hooks on comint-mode-hook and
+inferior-ruby-mode-hook (in that order).
+
+You can send text to the inferior ruby process from other buffers containing
+Ruby source.
+ switch-to-ruby switches the current buffer to the ruby process buffer.
+ ruby-send-definition sends the current definition to the ruby process.
+ ruby-send-region sends the current region to the ruby process.
+
+ ruby-send-definition-and-go, ruby-send-region-and-go,
+ switch to the ruby process buffer after sending their text.
+For information on running multiple processes in multiple buffers, see
+documentation for variable ruby-buffer.
+
+Commands:
+Return after the end of the process' output sends the text from the
+ end of process to point.
+Return before the end of the process' output copies the sexp ending at point
+ to the end of the process' output, and sends it.
+Delete converts tabs to spaces as it moves back.
+Tab indents for ruby; with argument, shifts rest
+ of expression rigidly with the current line.
+C-M-q does Tab on each line starting within following expression.
+Paragraphs are separated only by blank lines. # start comments.
+If you accidentally suspend your process, use \\[comint-continue-subjob]
+to continue it."
+ (interactive)
+ (comint-mode)
+ ;; Customise in inferior-ruby-mode-hook
+ ;(setq comint-prompt-regexp "^[^>\n]*>+ *")
+ (setq comint-prompt-regexp inferior-ruby-prompt-pattern)
+ ;;(scheme-mode-variables)
+ (ruby-mode-variables)
+ (setq major-mode 'inferior-ruby-mode)
+ (setq mode-name "Inferior Ruby")
+ (setq mode-line-process '(":%s"))
+ (use-local-map inferior-ruby-mode-map)
+ (setq comint-input-filter (function ruby-input-filter))
+ (setq comint-get-old-input (function ruby-get-old-input))
+ (run-hooks 'inferior-ruby-mode-hook))
+
+(defvar inferior-ruby-filter-regexp "\\`\\s *\\S ?\\S ?\\s *\\'"
+ "*Input matching this regexp are not saved on the history list.
+Defaults to a regexp ignoring all inputs of 0, 1, or 2 letters.")
+
+(defun ruby-input-filter (str)
+ "Don't save anything matching inferior-ruby-filter-regexp"
+ (not (string-match inferior-ruby-filter-regexp str)))
+
+;; adapted from replace-in-string in XEmacs (subr.el)
+(defun remove-in-string (str regexp)
+ "Remove all matches in STR for REGEXP and returns the new string."
+ (let ((rtn-str "") (start 0) match prev-start)
+ (while (setq match (string-match regexp str start))
+ (setq prev-start start
+ start (match-end 0)
+ rtn-str (concat rtn-str (substring str prev-start match))))
+ (concat rtn-str (substring str start))))
+
+(defun ruby-get-old-input ()
+ "Snarf the sexp ending at point"
+ (save-excursion
+ (let ((end (point)))
+ (re-search-backward inferior-ruby-first-prompt-pattern)
+ (remove-in-string (buffer-substring (point) end)
+ inferior-ruby-prompt-pattern)
+ )))
+
+(defun ruby-args-to-list (string)
+ (let ((where (string-match "[ \t]" string)))
+ (cond ((null where) (list string))
+ ((not (= where 0))
+ (cons (substring string 0 where)
+ (ruby-args-to-list (substring string (+ 1 where)
+ (length string)))))
+ (t (let ((pos (string-match "[^ \t]" string)))
+ (if (null pos)
+ nil
+ (ruby-args-to-list (substring string pos
+ (length string)))))))))
+
+(defun run-ruby (cmd)
+ "Run an inferior Ruby process, input and output via buffer *ruby*.
+If there is a process already running in `*ruby*', switch to that buffer.
+With argument, allows you to edit the command line (default is value
+of `ruby-program-name'). Runs the hooks `inferior-ruby-mode-hook'
+\(after the `comint-mode-hook' is run).
+\(Type \\[describe-mode] in the process buffer for a list of commands.)"
+
+ (interactive (list (if current-prefix-arg
+ (read-string "Run Ruby: " ruby-program-name)
+ ruby-program-name)))
+ (if (not (comint-check-proc "*ruby*"))
+ (let ((cmdlist (ruby-args-to-list cmd)))
+ (set-buffer (apply 'make-comint "ruby" (car cmdlist)
+ nil (cdr cmdlist)))
+ (inferior-ruby-mode)))
+ (setq ruby-program-name cmd)
+ (setq ruby-buffer "*ruby*")
+ (pop-to-buffer "*ruby*"))
+
+(defun ruby-send-region (start end)
+ "Send the current region to the inferior Ruby process."
+ (interactive "r")
+ (comint-send-region (ruby-proc) start end)
+ (comint-send-string (ruby-proc) "\n"))
+
+(defun ruby-send-definition ()
+ "Send the current definition to the inferior Ruby process."
+ (interactive)
+ (save-excursion
+ (ruby-end-of-defun)
+ (let ((end (point)))
+ (ruby-beginning-of-defun)
+ (ruby-send-region (point) end))))
+
+;(defun ruby-send-last-sexp ()
+; "Send the previous sexp to the inferior Ruby process."
+; (interactive)
+; (ruby-send-region (save-excursion (backward-sexp) (point)) (point)))
+
+(defun switch-to-ruby (eob-p)
+ "Switch to the ruby process buffer.
+With argument, positions cursor at end of buffer."
+ (interactive "P")
+ (if (get-buffer ruby-buffer)
+ (pop-to-buffer ruby-buffer)
+ (error "No current process buffer. See variable ruby-buffer."))
+ (cond (eob-p
+ (push-mark)
+ (goto-char (point-max)))))
+
+(defun ruby-send-region-and-go (start end)
+ "Send the current region to the inferior Ruby process.
+Then switch to the process buffer."
+ (interactive "r")
+ (ruby-send-region start end)
+ (switch-to-ruby t))
+
+(defun ruby-send-definition-and-go ()
+ "Send the current definition to the inferior Ruby.
+Then switch to the process buffer."
+ (interactive)
+ (ruby-send-definition)
+ (switch-to-ruby t))
+
+(defvar ruby-source-modes '(ruby-mode)
+ "*Used to determine if a buffer contains Ruby source code.
+If it's loaded into a buffer that is in one of these major modes, it's
+considered a ruby source file by ruby-load-file.
+Used by these commands to determine defaults.")
+
+(defvar ruby-prev-l/c-dir/file nil
+ "Caches the last (directory . file) pair.
+Caches the last pair used in the last ruby-load-file command.
+Used for determining the default in the
+next one.")
+
+(defun ruby-load-file (file-name)
+ "Load a Ruby file into the inferior Ruby process."
+ (interactive (comint-get-source "Load Ruby file: " ruby-prev-l/c-dir/file
+ ruby-source-modes t)) ; T because LOAD
+ ; needs an exact name
+ (comint-check-source file-name) ; Check to see if buffer needs saved.
+ (setq ruby-prev-l/c-dir/file (cons (file-name-directory file-name)
+ (file-name-nondirectory file-name)))
+ (comint-send-string (ruby-proc) (concat "(load \""
+ file-name
+ "\"\)\n")))
+
+(defun ruby-proc ()
+ "Returns the current ruby process. See variable ruby-buffer."
+ (let ((proc (get-buffer-process (if (eq major-mode 'inferior-ruby-mode)
+ (current-buffer)
+ ruby-buffer))))
+ (or proc
+ (error "No current process. See variable ruby-buffer"))))
+
+;;; Do the user's customisation...
+
+(defvar inf-ruby-load-hook nil
+ "This hook is run when inf-ruby is loaded in.
+This is a good place to put keybindings.")
+
+(run-hooks 'inf-ruby-load-hook)
+
+(provide 'inf-ruby)
+
+;;; inf-ruby.el ends here
diff --git a/misc/ruby-mode.el b/misc/ruby-mode.el
new file mode 100644
index 0000000000..61c6d9378b
--- /dev/null
+++ b/misc/ruby-mode.el
@@ -0,0 +1,724 @@
+;;;
+;;; ruby-mode.el -
+;;;
+;;; $Author$
+;;; $Date$
+;;; created at: Fri Feb 4 14:49:13 JST 1994
+;;;
+
+(defconst ruby-mode-revision "$Revision$")
+
+(defconst ruby-mode-version
+ (progn
+ (string-match "[0-9.]+" ruby-mode-revision)
+ (substring ruby-mode-revision (match-beginning 0) (match-end 0))))
+
+(defconst ruby-block-beg-re
+ "class\\|module\\|def\\|if\\|unless\\|case\\|while\\|until\\|for\\|begin\\|do"
+ )
+
+(defconst ruby-indent-beg-re
+ "\\(\\s *\\(class\\|module\\|def\\)\\)\\|if\\|unless\\|case\\|while\\|until\\|for\\|begin"
+ )
+
+(defconst ruby-modifier-re
+ "if\\|unless\\|while\\|until"
+ )
+
+(defconst ruby-block-mid-re
+ "then\\|else\\|elsif\\|when\\|rescue\\|ensure"
+ )
+
+(defconst ruby-block-op-re
+ "and\\|or\\|not"
+ )
+
+(defconst ruby-block-end-re "end")
+
+(defconst ruby-delimiter
+ (concat "[?$/%(){}#\"'`.:]\\|\\[\\|\\]\\|\\<\\("
+ ruby-block-beg-re
+ "\\|" ruby-block-end-re
+ "\\)\\>\\|^=begin")
+ )
+
+(defconst ruby-negative
+ (concat "^[ \t]*\\(\\(" ruby-block-mid-re "\\)\\>\\|\\("
+ ruby-block-end-re "\\)\\>\\|\\}\\|\\]\\)")
+ )
+
+(defconst ruby-operator-chars ",.+*/%-&|^~=<>:")
+(defconst ruby-operator-re (concat "[" ruby-operator-chars "]"))
+
+(defconst ruby-symbol-chars "a-zA-Z0-9_")
+(defconst ruby-symbol-re (concat "[" ruby-symbol-chars "]"))
+
+(defvar ruby-mode-abbrev-table nil
+ "Abbrev table in use in ruby-mode buffers.")
+
+(define-abbrev-table 'ruby-mode-abbrev-table ())
+
+(defvar ruby-mode-map nil "Keymap used in ruby mode.")
+
+(if ruby-mode-map
+ nil
+ (setq ruby-mode-map (make-sparse-keymap))
+ (define-key ruby-mode-map "{" 'ruby-electric-brace)
+ (define-key ruby-mode-map "}" 'ruby-electric-brace)
+ (define-key ruby-mode-map "\e\C-a" 'ruby-beginning-of-defun)
+ (define-key ruby-mode-map "\e\C-e" 'ruby-end-of-defun)
+ (define-key ruby-mode-map "\e\C-b" 'ruby-beginning-of-block)
+ (define-key ruby-mode-map "\e\C-f" 'ruby-end-of-block)
+ (define-key ruby-mode-map "\e\C-p" 'ruby-beginning-of-block)
+ (define-key ruby-mode-map "\e\C-n" 'ruby-end-of-block)
+ (define-key ruby-mode-map "\e\C-h" 'ruby-mark-defun)
+ (define-key ruby-mode-map "\t" 'ruby-indent-command)
+ (define-key ruby-mode-map "\C-c\C-e" 'ruby-insert-end)
+ (define-key ruby-mode-map "\C-j" 'ruby-reindent-then-newline-and-indent)
+ (define-key ruby-mode-map "\C-m" 'newline))
+
+(defvar ruby-mode-syntax-table nil
+ "Syntax table in use in ruby-mode buffers.")
+
+(if ruby-mode-syntax-table
+ ()
+ (setq ruby-mode-syntax-table (make-syntax-table))
+ (modify-syntax-entry ?\' "\"" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\" "\"" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\` "\"" ruby-mode-syntax-table)
+ (modify-syntax-entry ?# "<" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\n ">" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\\ "\\" ruby-mode-syntax-table)
+ (modify-syntax-entry ?$ "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?? "_" ruby-mode-syntax-table)
+ (modify-syntax-entry ?_ "_" ruby-mode-syntax-table)
+ (modify-syntax-entry ?< "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?> "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?& "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?| "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?% "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?= "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?/ "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?+ "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?* "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?- "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?\; "." ruby-mode-syntax-table)
+ (modify-syntax-entry ?\( "()" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\) ")(" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\{ "(}" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\} "){" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\[ "(]" ruby-mode-syntax-table)
+ (modify-syntax-entry ?\] ")[" ruby-mode-syntax-table)
+ )
+
+(defvar ruby-indent-level 2
+ "*Indentation of ruby statements.")
+
+(defun ruby-mode-variables ()
+ (set-syntax-table ruby-mode-syntax-table)
+ (setq local-abbrev-table ruby-mode-abbrev-table)
+ (make-local-variable 'indent-line-function)
+ (setq indent-line-function 'ruby-indent-line)
+ (make-local-variable 'require-final-newline)
+ (setq require-final-newline t)
+ (make-variable-buffer-local 'comment-start)
+ (setq comment-start "# ")
+ (make-variable-buffer-local 'comment-end)
+ (setq comment-end "")
+ (make-variable-buffer-local 'comment-column)
+ (setq comment-column 32)
+ (make-variable-buffer-local 'comment-start-skip)
+ (setq comment-start-skip "\\(^\\|\\s-\\);?#+ *")
+ (make-local-variable 'parse-sexp-ignore-comments)
+ (setq parse-sexp-ignore-comments t)
+ (make-local-variable 'paragraph-start)
+ (setq paragraph-start (concat "$\\|" page-delimiter))
+ (make-local-variable 'paragraph-separate)
+ (setq paragraph-separate paragraph-start)
+ (make-local-variable 'paragraph-ignore-fill-prefix)
+ (setq paragraph-ignore-fill-prefix t))
+
+(defun ruby-mode ()
+ "Major mode for editing ruby scripts.
+\\[ruby-indent-command] properly indents subexpressions of multi-line
+class, module, def, if, while, for, do, and case statements, taking
+nesting into account.
+
+The variable ruby-indent-level controls the amount of indentation.
+\\{ruby-mode-map}"
+ (interactive)
+ (kill-all-local-variables)
+ (use-local-map ruby-mode-map)
+ (setq mode-name "Ruby")
+ (setq major-mode 'ruby-mode)
+ (ruby-mode-variables)
+
+ (run-hooks 'ruby-mode-hook))
+
+(defun ruby-current-indentation ()
+ (save-excursion
+ (beginning-of-line)
+ (back-to-indentation)
+ (current-column)))
+
+(defun ruby-indent-line (&optional flag)
+ "Correct indentation of the current ruby line."
+ (ruby-indent-to (ruby-calculate-indent)))
+
+(defun ruby-indent-command ()
+ (interactive)
+ (ruby-indent-line t))
+
+(defun ruby-indent-to (x)
+ (if x
+ (let (shift top beg)
+ (and (< x 0)
+ (error "invalid nest"))
+ (setq shift (current-column))
+ (beginning-of-line)
+ (setq beg (point))
+ (back-to-indentation)
+ (setq top (current-column))
+ (skip-chars-backward " \t")
+ (cond
+ ((>= x shift)
+ (setq shift 0))
+ ((>= shift top)
+ (setq shift (- shift top)))
+ (t (setq shift 0)))
+ (if (and (bolp)
+ (= x top))
+ (move-to-column (+ x shift))
+ (move-to-column top)
+ (delete-region beg (point))
+ (beginning-of-line)
+ (indent-to x)
+ (move-to-column (+ x shift))))))
+
+(defun ruby-expr-beg (&optional modifier)
+ (save-excursion
+ (if (looking-at "\\?")
+ (progn
+ (or (bolp) (forward-char -1))
+ (not (looking-at "\\sw")))
+ (store-match-data nil)
+ (skip-chars-backward " \t")
+ (or (bolp) (forward-char -1))
+ (or (bolp)
+ (looking-at ruby-operator-re)
+ (looking-at "[\\[({]")
+ (and (not modifier) (looking-at "[!?]"))
+ (and (looking-at ruby-symbol-re)
+ (forward-word -1)
+ (if (and (not modifier) (bolp))
+ t
+ (if (or (looking-at ruby-block-beg-re)
+ (looking-at ruby-block-op-re)
+ (looking-at ruby-block-mid-re))
+ (progn
+ (goto-char (match-end 0))
+ (looking-at "\\>"))
+ (looking-at "[a-zA-Z][a-zA-z0-9_]* +/[^ \t]"))))))))
+
+(defun ruby-parse-region (start end)
+ (let ((indent-point end)
+ (indent 0)
+ (in-string nil)
+ (in-paren nil)
+ (depth 0)
+ (nest nil)
+ (pcol nil))
+ (save-excursion
+ (if start
+ (goto-char start)
+ (ruby-beginning-of-indent))
+ (save-restriction
+ (narrow-to-region (point) end)
+ (while (and (> indent-point (point))
+ (re-search-forward ruby-delimiter indent-point t))
+ (or depth (setq depth 0))
+ (let ((pnt (point)) w)
+ (goto-char (match-beginning 0))
+ (cond
+ ((or (looking-at "\"") ;skip string
+ (looking-at "'")
+ (looking-at "`"))
+ (setq w (char-after (point)))
+ (cond
+ ((and (not (eobp))
+ (re-search-forward (format "[^\\]\\(\\\\\\\\\\)*%c" w) indent-point t))
+ nil)
+ (t
+ (setq in-string (point))
+ (goto-char indent-point))))
+ ((looking-at "/")
+ (cond
+ ((and (not (eobp)) (ruby-expr-beg))
+ (if (re-search-forward "[^\\]/" indent-point t)
+ nil
+ (setq in-string (point))
+ (goto-char indent-point)))
+ (t
+ (goto-char pnt))))
+ ((looking-at "%")
+ (cond
+ ((and (not (eobp)) (ruby-expr-beg)
+ (not (looking-at "%="))
+ (looking-at "%[Qqrxw]?\\(.\\)"))
+ (setq w (buffer-substring (match-beginning 1)
+ (match-end 1)))
+ (cond
+ ((string= w "[") (setq w "]"))
+ ((string= w "{") (setq w "}"))
+ ((string= w "(") (setq w ")"))
+ ((string= w "<") (setq w ">")))
+ (goto-char (match-end 0))
+ (if (search-forward w indent-point t)
+ nil
+ (setq in-string (point))
+ (goto-char indent-point)))
+ (t
+ (goto-char pnt))))
+ ((looking-at "\\?") ;skip ?char
+ (cond
+ ((ruby-expr-beg)
+ (looking-at "?\\(\\\\C-\\|\\\\M-\\)*.")
+ (goto-char (match-end 0)))
+ (t
+ (goto-char pnt))))
+ ((looking-at "\\$") ;skip $char
+ (goto-char pnt)
+ (forward-char 1))
+ ((looking-at "#") ;skip comment
+ (forward-line 1)
+ (goto-char (point))
+ )
+ ((looking-at "(")
+ (setq nest (cons (cons (char-after (point)) pnt) nest))
+ (setq pcol (cons (cons pnt depth) pcol))
+ (setq depth 0)
+ (goto-char pnt)
+ )
+ ((looking-at "[\\[{]")
+ (setq nest (cons (cons (char-after (point)) pnt) nest))
+ (setq depth (1+ depth))
+ (goto-char pnt)
+ )
+ ((looking-at ")")
+ (setq nest (cdr nest))
+ (setq depth (cdr (car pcol)))
+ (setq pcol (cdr pcol))
+ (goto-char pnt))
+ ((looking-at "[])}]")
+ (setq nest (cdr nest))
+ (setq depth (1- depth))
+ (goto-char pnt))
+ ((looking-at ruby-block-end-re)
+ (if (or (and (not (bolp))
+ (progn
+ (forward-char -1)
+ (eq ?_ (char-after (point)))))
+ (progn
+ (goto-char pnt)
+ (setq w (char-after (point)))
+ (or (eq ?_ w)
+ (eq ?! w)
+ (eq ?? w))))
+ nil
+ (setq nest (cdr nest))
+ (setq depth (1- depth)))
+ (goto-char pnt))
+ ((looking-at "def\\s +[^(\n;]*")
+ (if (or (bolp)
+ (progn
+ (forward-char -1)
+ (not (eq ?_ (char-after (point))))))
+ (progn
+ (setq nest (cons (cons nil pnt) nest))
+ (setq depth (1+ depth))))
+ (goto-char (match-end 0)))
+ ((looking-at ruby-block-beg-re)
+ (and
+ (or (bolp)
+ (progn
+ (forward-char -1)
+ (not (eq ?_ (char-after (point))))))
+ (goto-char pnt)
+ (setq w (char-after (point)))
+ (not (eq ?_ w))
+ (not (eq ?! w))
+ (not (eq ?? w))
+ (skip-chars-forward " \t")
+ (if (not (eolp))
+ (progn
+ (goto-char (match-beginning 0))
+ (if (looking-at ruby-modifier-re)
+ (ruby-expr-beg t)
+ t))
+ t)
+ (goto-char pnt)
+ (setq nest (cons (cons nil pnt) nest))
+ (setq depth (1+ depth)))
+ (goto-char pnt))
+ ((looking-at ":\\([a-zA-Z_][a-zA-Z_0-9]*\\)?")
+ (goto-char (match-end 0)))
+ ((or (looking-at "\\.")
+ (looking-at "\\.\\.\\.?")
+ (looking-at "\\.[0-9]+")
+ (looking-at "\\.[a-zA-Z_0-9]+"))
+ (goto-char (match-end 0)))
+ ((looking-at "^=begin")
+ (if (re-search-forward "^=end" indent-point t)
+ (forward-line 1)
+ (setq in-string (match-end 0))
+ (goto-char indent-point)))
+ (t
+ (error (format "bad string %s"
+ (buffer-substring (point) pnt)
+ )))))))
+ (list in-string (car nest) depth (car (car pcol))))))
+
+(defun ruby-indent-size (pos nest)
+ (+ pos (* (if nest nest 1) ruby-indent-level)))
+
+(defun ruby-calculate-indent (&optional parse-start)
+ (save-excursion
+ (beginning-of-line)
+ (let ((indent-point (point))
+ (case-fold-search nil)
+ state bol eol
+ (indent 0))
+ (if parse-start
+ (goto-char parse-start)
+ (ruby-beginning-of-indent)
+ (setq parse-start (point)))
+ (back-to-indentation)
+ (setq indent (current-column))
+ (setq state (ruby-parse-region parse-start indent-point))
+ (cond
+ ((nth 0 state) ; within string
+ (setq indent nil)) ; do nothing
+
+ ((car (nth 1 state)) ; in paren
+ (goto-char (cdr (nth 1 state)))
+ (if (eq (car (nth 1 state)) ?\( )
+ (let ((column (current-column))
+ (s (ruby-parse-region (point) indent-point)))
+ (cond
+ ((and (nth 2 s) (> (nth 2 s) 0))
+ (goto-char (cdr (nth 1 s)))
+ (forward-word -1)
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))
+ (t
+ (setq indent (current-column)))))
+ (cond
+ ((nth 3 state)
+ (goto-char (nth 3 state))
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))
+ (t
+ (goto-char parse-start)
+ (back-to-indentation)
+ (setq indent (ruby-indent-size (current-column) (nth 2 state)))))
+ ))
+
+ ((and (nth 2 state)(> (nth 2 state) 0)) ; in nest
+ (if (null (cdr (nth 1 state)))
+ (error "invalid nest"))
+ (goto-char (cdr (nth 1 state)))
+ (forward-word -1) ; skip back a keyword
+ (cond
+ ((looking-at "do") ; iter block is a special case
+ (cond
+ ((nth 3 state)
+ (goto-char (nth 3 state))
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))
+ (t
+ (goto-char parse-start)
+ (back-to-indentation)
+ (setq indent (ruby-indent-size (current-column) (nth 2 state))))))
+ (t
+ (setq indent (+ (current-column) ruby-indent-level)))))
+
+ ((and (nth 2 state) (< (nth 2 state) 0)) ; in negative nest
+ (setq indent (ruby-indent-size (current-column) (nth 2 state)))))
+
+ (cond
+ (indent
+ (goto-char indent-point)
+ (end-of-line)
+ (setq eol (point))
+ (beginning-of-line)
+ (cond
+ ((re-search-forward ruby-negative eol t)
+ (and (not (eq ?_ (char-after (match-end 0))))
+ (setq indent (- indent ruby-indent-level))))
+ ;;operator terminated lines
+ ((and
+ (save-excursion
+ (beginning-of-line)
+ (not (bobp)))
+ (or (null (car (nth 1 state))) ;not in parens
+ (and (eq (car (nth 1 state)) ?\{)
+ (save-excursion ;except non-block braces
+ (goto-char (cdr (nth 1 state)))
+ (or (bobp) (forward-char -1))
+ (not (ruby-expr-beg))))))
+ ;; goto beginning of non-empty no-comment line
+ (let (end done)
+ (while (not done)
+ (skip-chars-backward " \t\n")
+ (setq end (point))
+ (beginning-of-line)
+ (if (re-search-forward "^\\s *#" end t)
+ (beginning-of-line)
+ (setq done t))))
+ (setq bol (point))
+ (end-of-line)
+ (skip-chars-backward " \t")
+ (and (re-search-backward "#" (save-excursion
+ (beginning-of-line)
+ (point)) t)
+ (setq state (ruby-parse-region parse-start (point)))
+ (nth 0 state)
+ (goto-char (nth 0 state)))
+ (or (bobp) (forward-char -1))
+ (and
+ (or (and (looking-at ruby-symbol-re)
+ (skip-chars-backward ruby-symbol-chars)
+ (looking-at ruby-block-op-re)
+ (save-excursion
+ (goto-char (match-end 0))
+ (not (looking-at "[a-z_]"))))
+ (and (looking-at ruby-operator-re)
+ (or (not (eq ?/ (char-after (point))))
+ (null (nth 0 (ruby-parse-region parse-start (point)))))
+ (not (eq (char-after (1- (point))) ?$))
+ (or (not (eq ?| (char-after (point))))
+ (save-excursion
+ (or (eolp) (forward-char -1))
+ (and (search-backward "|")
+ (skip-chars-backward " \t\n")
+ (and (not (eolp))
+ (progn
+ (forward-char -1)
+ (not (looking-at "\\{")))
+ (progn
+ (forward-word -1)
+ (not (looking-at "do\\>[^_]")))))))))
+ (setq indent (+ indent ruby-indent-level)))))))
+ indent)))
+
+(defun ruby-electric-brace (arg)
+ (interactive "P")
+ (self-insert-command (prefix-numeric-value arg))
+ (ruby-indent-line t))
+
+(defun ruby-beginning-of-defun (&optional arg)
+ "Move backward to next beginning-of-defun.
+With argument, do this that many times.
+Returns t unless search stops due to end of buffer."
+ (interactive "p")
+ (and (re-search-backward (concat "^\\(" ruby-block-beg-re "\\)\\b")
+ nil 'move (or arg 1))
+ (progn (beginning-of-line) t)))
+
+(defun ruby-beginning-of-indent ()
+ (and (re-search-backward (concat "^\\(" ruby-indent-beg-re "\\)\\b")
+ nil 'move)
+ (progn
+ (beginning-of-line)
+ t)))
+
+(defun ruby-end-of-defun (&optional arg)
+ "Move forward to next end of defun.
+An end of a defun is found by moving forward from the beginning of one."
+ (interactive "p")
+ (and (re-search-forward (concat "^\\(" ruby-block-end-re "\\)\\($\\|\\b[^_]\\)")
+ nil 'move (or arg 1))
+ (progn (beginning-of-line) t))
+ (forward-line 1))
+
+(defun ruby-move-to-block (n)
+ (let (start pos done down)
+ (setq start (ruby-calculate-indent))
+ (if (eobp)
+ nil
+ (while (and (not (bobp)) (not done))
+ (forward-line n)
+ (cond
+ ((looking-at "^$"))
+ ((looking-at "^\\s *#"))
+ (t
+ (setq pos (current-indentation))
+ (cond
+ ((< start pos)
+ (setq down t))
+ ((and down (= pos start))
+ (setq done t))
+ ((> start pos)
+ (setq done t)))))
+ (if done
+ (progn
+ (back-to-indentation)
+ (if (looking-at ruby-block-mid-re)
+ (setq done nil)))))))
+ (back-to-indentation))
+
+(defun ruby-beginning-of-block ()
+ "Move backward to next beginning-of-block"
+ (interactive)
+ (ruby-move-to-block -1))
+
+(defun ruby-end-of-block ()
+ "Move forward to next beginning-of-block"
+ (interactive)
+ (ruby-move-to-block 1))
+
+(defun ruby-reindent-then-newline-and-indent ()
+ (interactive "*")
+ (save-excursion
+ (delete-region (point) (progn (skip-chars-backward " \t") (point))))
+ (newline)
+ (save-excursion
+ (forward-line -1)
+ (indent-according-to-mode))
+ (indent-according-to-mode))
+
+(fset 'ruby-encomment-region (symbol-function 'comment-region))
+
+(defun ruby-decomment-region (beg end)
+ (interactive "r")
+ (save-excursion
+ (goto-char beg)
+ (while (re-search-forward "^\\([ \t]*\\)#" end t)
+ (replace-match "\\1" nil nil)
+ (save-excursion
+ (ruby-indent-line)))))
+
+(defun ruby-insert-end ()
+ (interactive)
+ (insert "end")
+ (ruby-indent-line t)
+ (end-of-line))
+
+(defun ruby-mark-defun ()
+ "Put mark at end of this Ruby function, point at beginning."
+ (interactive)
+ (push-mark (point))
+ (ruby-end-of-defun)
+ (push-mark (point) nil t)
+ (ruby-beginning-of-defun)
+ (re-search-backward "^\n" (- (point) 1) t))
+
+(cond
+ ((featurep 'font-lock)
+ (or (boundp 'font-lock-variable-name-face)
+ (setq font-lock-variable-name-face font-lock-type-face))
+
+ (add-hook 'ruby-mode-hook
+ '(lambda ()
+ (make-local-variable 'font-lock-syntactic-keywords)
+ (setq font-lock-syntactic-keywords
+ '(("\\$\\([#\"'`$\\]\\)" 1 (1 . nil))
+ ("\\(#\\)[{$@]" 1 (1 . nil))))
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults '((ruby-font-lock-keywords) nil nil))
+ (setq font-lock-keywords ruby-font-lock-keywords)))
+
+ (defun ruby-font-lock-docs (limit)
+ (if (re-search-forward "^=begin\\s *$" limit t)
+ (let (beg)
+ (beginning-of-line)
+ (setq beg (point))
+ (forward-line 1)
+ (if (re-search-forward "^=end\\s *$" limit t)
+ (progn
+ (set-match-data (list beg (point)))
+ t)))))
+
+ (defvar ruby-font-lock-keywords
+ (list
+ (cons (concat
+ "\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\("
+ (mapconcat
+ 'identity
+ '("alias"
+ "and"
+ "begin"
+ "break"
+ "case"
+ "catch"
+ "class"
+ "def"
+ "do"
+ "elsif"
+ "else"
+ "fail"
+ "ensure"
+ "for"
+ "end"
+ "if"
+ "in"
+ "module"
+ "next"
+ "not"
+ "or"
+ "raise"
+ "redo"
+ "rescue"
+ "retry"
+ "return"
+ "then"
+ "throw"
+ "self"
+ "super"
+ "unless"
+ "undef"
+ "until"
+ "when"
+ "while"
+ )
+ "\\|")
+ "\\)\\>[^_]")
+ 2)
+ ;; variables
+ '("\\b\\(nil\\|self\\|true\\|false\\)\\b"
+ 1 font-lock-variable-name-face)
+ ;; variables
+ '("[$@].\\(\\w\\|_\\)*"
+ 0 font-lock-variable-name-face)
+ ;; embedded document
+ '(ruby-font-lock-docs
+ 0 font-lock-comment-face t)
+ ;; constants
+ '("\\(^\\|[^_]\\)\\b\\([A-Z]+\\(\\w\\|_\\)*\\)"
+ 2 font-lock-type-face)
+ ;; functions
+ '("^\\s *def\\s *\\<\\(\\(\\w\\|_\\)+\\(\\.\\|::\\)\\)?\\(\\(\\w\\|_\\)+\\??\\)\\>"
+ 4 font-lock-function-name-face t)
+ ;; symbols
+ '("\\(^\\|[^:]\\)\\(:\\(\\w\\|_\\)+\\??\\)\\b"
+ 2 font-lock-reference-face))
+ "*Additional expressions to highlight in ruby mode."))
+
+ ((featurep 'hilit19)
+ (hilit-set-mode-patterns
+ 'ruby-mode
+ '(("[^$\\?]\\(\"[^\\\"]*\\(\\\\\\(.\\|\n\\)[^\\\"]*\\)*\"\\)" 1 string)
+ ("[^$\\?]\\('[^\\']*\\(\\\\\\(.\\|\n\\)[^\\']*\\)*'\\)" 1 string)
+ ("[^$\\?]\\(`[^\\`]*\\(\\\\\\(.\\|\n\\)[^\\`]*\\)*`\\)" 1 string)
+ ("^\\s *#.*$" nil comment)
+ ("[^$@?\\]\\(#[^$@{\n].*$\\)" 1 comment)
+ ("[^a-zA-Z_]\\(\\?\\(\\\\[CM]-\\)*.\\)" 1 string)
+ ("^\\s *\\(require\\|load\\).*$" nil include)
+ ("^\\s *\\(include\\|alias\\|undef\\).*$" nil decl)
+ ("^\\s *\\<\\(class\\|def\\|module\\)\\>" "[)\n;]" defun)
+ ("[^_]\\<\\(begin\\|case\\|else\\|elsif\\|end\\|ensure\\|for\\|if\\|unless\\|rescue\\|then\\|when\\|while\\|until\\|do\\)\\>[^_]" 1 defun)
+ ("[^_]\\<\\(and\\|break\\|next\\|raise\\|fail\\|in\\|not\\|or\\|redo\\|retry\\|return\\|super\\|yield\\|catch\\|throw\\|self\\|nil\\)\\>[^_]" 1 keyword)
+ ("\\$\\(.\\|\\sw+\\)" nil type)
+ ("[$@].[a-zA-Z_0-9]*" nil struct)
+ ("^__END__" nil label))))
+ )
+
+
+(provide 'ruby-mode)
diff --git a/misc/rubydb2x.el b/misc/rubydb2x.el
new file mode 100644
index 0000000000..a74265fb0e
--- /dev/null
+++ b/misc/rubydb2x.el
@@ -0,0 +1,104 @@
+(require 'gud)
+(provide 'rubydb)
+
+;; ======================================================================
+;; rubydb functions
+
+;;; History of argument lists passed to rubydb.
+(defvar gud-rubydb-history nil)
+
+(defun gud-rubydb-massage-args (file args)
+ (cons "-I" (cons "." (cons "-r" (cons "debug" (cons file args))))))
+
+;; There's no guarantee that Emacs will hand the filter the entire
+;; marker at once; it could be broken up across several strings. We
+;; might even receive a big chunk with several markers in it. If we
+;; receive a chunk of text which looks like it might contain the
+;; beginning of a marker, we save it here between calls to the
+;; filter.
+(defvar gud-rubydb-marker-acc "")
+
+(defun gud-rubydb-marker-filter (string)
+ (save-match-data
+ (setq gud-marker-acc (concat gud-marker-acc string))
+ (let ((output ""))
+
+ ;; Process all the complete markers in this chunk.
+ (while (string-match "\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n"
+ gud-marker-acc)
+ (setq
+
+ ;; Extract the frame position from the marker.
+ gud-last-frame
+ (cons (substring gud-marker-acc (match-beginning 1) (match-end 1))
+ (string-to-int (substring gud-marker-acc
+ (match-beginning 2)
+ (match-end 2))))
+
+ ;; Append any text before the marker to the output we're going
+ ;; to return - we don't include the marker in this text.
+ output (concat output
+ (substring gud-marker-acc 0 (match-beginning 0)))
+
+ ;; Set the accumulator to the remaining text.
+ gud-marker-acc (substring gud-marker-acc (match-end 0))))
+
+ ;; Does the remaining text look like it might end with the
+ ;; beginning of another marker? If it does, then keep it in
+ ;; gud-marker-acc until we receive the rest of it. Since we
+ ;; know the full marker regexp above failed, it's pretty simple to
+ ;; test for marker starts.
+ (if (string-match "\032.*\\'" gud-marker-acc)
+ (progn
+ ;; Everything before the potential marker start can be output.
+ (setq output (concat output (substring gud-marker-acc
+ 0 (match-beginning 0))))
+
+ ;; Everything after, we save, to combine with later input.
+ (setq gud-marker-acc
+ (substring gud-marker-acc (match-beginning 0))))
+
+ (setq output (concat output gud-marker-acc)
+ gud-marker-acc ""))
+
+ output)))
+
+(defun gud-rubydb-find-file (f)
+ (find-file-noselect f))
+
+(defvar rubydb-command-name "ruby"
+ "File name for executing ruby.")
+
+;;;###autoload
+(defun rubydb (command-line)
+ "Run rubydb on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger."
+ (interactive
+ (list (read-from-minibuffer "Run rubydb (like this): "
+ (if (consp gud-rubydb-history)
+ (car gud-rubydb-history)
+ (concat rubydb-command-name " "))
+ nil nil
+ '(gud-rubydb-history . 1))))
+
+ (gud-overload-functions '((gud-massage-args . gud-rubydb-massage-args)
+ (gud-marker-filter . gud-rubydb-marker-filter)
+ (gud-find-file . gud-rubydb-find-file)
+ ))
+ (gud-common-init command-line)
+
+ (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.")
+; (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "s" "\C-s" "Step one source line with display.")
+ (gud-def gud-next "n" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "c" "\C-r" "Continue with display.")
+ (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
+ (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
+ (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
+ (gud-def gud-print "p %e" "\C-p" "Evaluate ruby expression at point.")
+
+ (setq comint-prompt-regexp "^(rdb:-) ")
+ (setq paragraph-start comint-prompt-regexp)
+ (run-hooks 'rubydb-mode-hook)
+ )
diff --git a/misc/rubydb3x.el b/misc/rubydb3x.el
new file mode 100644
index 0000000000..14e3dac83b
--- /dev/null
+++ b/misc/rubydb3x.el
@@ -0,0 +1,113 @@
+(require 'gud)
+(provide 'rubydb)
+
+;; ======================================================================
+;; rubydb functions
+
+;;; History of argument lists passed to rubydb.
+(defvar gud-rubydb-history nil)
+
+(if (fboundp 'gud-overload-functions)
+ (defun gud-rubydb-massage-args (file args)
+ (cons "-r" (cons "debug" (cons file args))))
+ (defun gud-rubydb-massage-args (file args)
+ (cons "-r" (cons "debug" args))))
+
+;; There's no guarantee that Emacs will hand the filter the entire
+;; marker at once; it could be broken up across several strings. We
+;; might even receive a big chunk with several markers in it. If we
+;; receive a chunk of text which looks like it might contain the
+;; beginning of a marker, we save it here between calls to the
+;; filter.
+(defvar gud-rubydb-marker-acc "")
+(make-variable-buffer-local 'gud-rubydb-marker-acc)
+
+(defun gud-rubydb-marker-filter (string)
+ (setq gud-rubydb-marker-acc (concat gud-rubydb-marker-acc string))
+ (let ((output ""))
+
+ ;; Process all the complete markers in this chunk.
+ (while (string-match "\032\032\\([^:\n]*\\):\\([0-9]*\\):.*\n"
+ gud-rubydb-marker-acc)
+ (setq
+
+ ;; Extract the frame position from the marker.
+ gud-last-frame
+ (cons (substring gud-rubydb-marker-acc (match-beginning 1) (match-end 1))
+ (string-to-int (substring gud-rubydb-marker-acc
+ (match-beginning 2)
+ (match-end 2))))
+
+ ;; Append any text before the marker to the output we're going
+ ;; to return - we don't include the marker in this text.
+ output (concat output
+ (substring gud-rubydb-marker-acc 0 (match-beginning 0)))
+
+ ;; Set the accumulator to the remaining text.
+ gud-rubydb-marker-acc (substring gud-rubydb-marker-acc (match-end 0))))
+
+ ;; Does the remaining text look like it might end with the
+ ;; beginning of another marker? If it does, then keep it in
+ ;; gud-rubydb-marker-acc until we receive the rest of it. Since we
+ ;; know the full marker regexp above failed, it's pretty simple to
+ ;; test for marker starts.
+ (if (string-match "\032.*\\'" gud-rubydb-marker-acc)
+ (progn
+ ;; Everything before the potential marker start can be output.
+ (setq output (concat output (substring gud-rubydb-marker-acc
+ 0 (match-beginning 0))))
+
+ ;; Everything after, we save, to combine with later input.
+ (setq gud-rubydb-marker-acc
+ (substring gud-rubydb-marker-acc (match-beginning 0))))
+
+ (setq output (concat output gud-rubydb-marker-acc)
+ gud-rubydb-marker-acc ""))
+
+ output))
+
+(defun gud-rubydb-find-file (f)
+ (save-excursion
+ (let ((buf (find-file-noselect f)))
+ (set-buffer buf)
+;; (gud-make-debug-menu)
+ buf)))
+
+(defvar rubydb-command-name "ruby"
+ "File name for executing ruby.")
+
+;;;###autoload
+(defun rubydb (command-line)
+ "Run rubydb on program FILE in buffer *gud-FILE*.
+The directory containing FILE becomes the initial working directory
+and source-file directory for your debugger."
+ (interactive
+ (list (read-from-minibuffer "Run rubydb (like this): "
+ (if (consp gud-rubydb-history)
+ (car gud-rubydb-history)
+ (concat rubydb-command-name " "))
+ nil nil
+ '(gud-rubydb-history . 1))))
+
+ (if (not (fboundp 'gud-overload-functions))
+ (gud-common-init command-line 'gud-rubydb-massage-args
+ 'gud-rubydb-marker-filter 'gud-rubydb-find-file)
+ (gud-overload-functions '((gud-massage-args . gud-rubydb-massage-args)
+ (gud-marker-filter . gud-rubydb-marker-filter)
+ (gud-find-file . gud-rubydb-find-file)))
+ (gud-common-init command-line rubydb-command-name))
+
+ (gud-def gud-break "b %l" "\C-b" "Set breakpoint at current line.")
+; (gud-def gud-remove "clear %l" "\C-d" "Remove breakpoint at current line")
+ (gud-def gud-step "s" "\C-s" "Step one source line with display.")
+ (gud-def gud-next "n" "\C-n" "Step one line (skip functions).")
+ (gud-def gud-cont "c" "\C-r" "Continue with display.")
+ (gud-def gud-finish "finish" "\C-f" "Finish executing current function.")
+ (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).")
+ (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).")
+ (gud-def gud-print "p %e" "\C-p" "Evaluate ruby expression at point.")
+
+ (setq comint-prompt-regexp "^(rdb:-) ")
+ (set (make-local-variable 'paragraph-start) comint-prompt-regexp)
+ (run-hooks 'rubydb-mode-hook)
+ )
diff --git a/missing/dup2.c b/missing/dup2.c
index c541149d4b..e7cc46f4c1 100644
--- a/missing/dup2.c
+++ b/missing/dup2.c
@@ -1,36 +1,61 @@
-/*
- * Copyright (c) 1991, Larry Wall
+/*
+ * Public domain dup2() lookalike
+ * by Curtis Jackson @ AT&T Technologies, Burlington, NC
+ * electronic address: burl!rcj
*
- * You may distribute under the terms of either the GNU General Public
- * License or the Artistic License, as specified in the README file.
+ * dup2 performs the following functions:
+ *
+ * Check to make sure that fd1 is a valid open file descriptor.
+ * Check to see if fd2 is already open; if so, close it.
+ * Duplicate fd1 onto fd2; checking to make sure fd2 is a valid fd.
+ * Return fd2 if all went well; return BADEXIT otherwise.
*/
-#include "defines.h"
+#include "config.h"
-#if defined(HAVE_FCNTL) && defined(F_DUPFD)
+#if defined(HAVE_FCNTL)
# include <fcntl.h>
#endif
+#if !defined(HAVE_FCNTL) || !defined(F_DUPFD)
+# include <errno.h>
+#endif
+
+#define BADEXIT -1
+
int
-dup2(oldfd,newfd)
-int oldfd;
-int newfd;
+dup2(fd1, fd2)
+int fd1, fd2;
{
#if defined(HAVE_FCNTL) && defined(F_DUPFD)
- close(newfd);
- return fcntl(oldfd, F_DUPFD, newfd);
+ if (fd1 != fd2) {
+#ifdef F_GETFL
+ if (fcntl(fd1, F_GETFL) < 0)
+ return BADEXIT;
+ if (fcntl(fd2, F_GETFL) >= 0)
+ close(fd2);
+#else
+ close(fd2);
+#endif
+ if (fcntl(fd1, F_DUPFD, fd2) < 0)
+ return BADEXIT;
+ }
+ return fd2;
#else
- int fdtmp[256];
- int fdx = 0;
- int fd;
+ extern int errno;
+ int i, fd, fds[256];
- if (oldfd == newfd)
- return 0;
- close(newfd);
- while ((fd = dup(oldfd)) != newfd) /* good enough for low fd's */
- fdtmp[fdx++] = fd;
- while (fdx > 0)
- close(fdtmp[--fdx]);
- return 0;
+ if (fd1 == fd2) return 0;
+ close(fd2);
+ for (i=0; i<256; i++) {
+ fd = fds[i] = dup(fd1);
+ if (fd == fd2) break;
+ }
+ while (i) {
+ close(fds[i--]);
+ }
+ if (fd == fd2) return 0;
+ errno = EMFILE;
+ return BADEXIT;
#endif
}
diff --git a/missing/finite.c b/missing/finite.c
new file mode 100644
index 0000000000..07fe3263e9
--- /dev/null
+++ b/missing/finite.c
@@ -0,0 +1,6 @@
+int
+finite(n)
+ double n;
+{
+ return !isnan(n) && !isinf(n);
+}
diff --git a/missing/fnmatch.c b/missing/fnmatch.c
new file mode 100644
index 0000000000..4cf746118a
--- /dev/null
+++ b/missing/fnmatch.c
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
+ * Compares a filename or pathname to a pattern.
+ */
+
+#include "missing/fnmatch.h"
+#include <string.h>
+
+#define EOS '\0'
+
+static char *rangematch();
+
+int
+fnmatch(pattern, string, flags)
+ char *pattern;
+ char *string;
+ int flags;
+{
+ char *stringstart;
+ char c, test;
+
+ for (stringstart = string;;) {
+ switch (c = *pattern++) {
+ case EOS:
+ return (*string == EOS ? 0 : FNM_NOMATCH);
+ case '?':
+ if (*string == EOS) {
+ return (FNM_NOMATCH);
+ }
+ if (*string == '/' && (flags & FNM_PATHNAME)) {
+ return (FNM_NOMATCH);
+ }
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
+ return (FNM_NOMATCH);
+ }
+ ++string;
+ break;
+ case '*':
+ c = *pattern;
+ /* Collapse multiple stars. */
+ while (c == '*') {
+ c = *++pattern;
+ }
+
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
+ return (FNM_NOMATCH);
+ }
+
+ /* Optimize for pattern with * at end or before /. */
+ if (c == EOS) {
+ if (flags & FNM_PATHNAME) {
+ return (strchr(string, '/') == NULL ? 0 : FNM_NOMATCH);
+ }
+ else {
+ return (0);
+ }
+ }
+ else if (c == '/' && flags & FNM_PATHNAME) {
+ if ((string = strchr(string, '/')) == NULL) {
+ return (FNM_NOMATCH);
+ }
+ break;
+ }
+
+ /* General case, use recursion. */
+ while ((test = *string) != EOS) {
+ if (!fnmatch(pattern, string, flags & ~FNM_PERIOD)) {
+ return (0);
+ }
+ if (test == '/' && flags & FNM_PATHNAME) {
+ break;
+ }
+ ++string;
+ }
+ return (FNM_NOMATCH);
+ case '[':
+ if (*string == EOS) {
+ return (FNM_NOMATCH);
+ }
+ if (*string == '/' && flags & FNM_PATHNAME) {
+ return (FNM_NOMATCH);
+ }
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) {
+ return (FNM_NOMATCH);
+ }
+ if ((pattern = rangematch(pattern, *string, flags)) == NULL) {
+ return (FNM_NOMATCH);
+ }
+ ++string;
+ break;
+ case '\\':
+ if (!(flags & FNM_NOESCAPE)) {
+ if ((c = *pattern++) == EOS) {
+ c = '\\';
+ --pattern;
+ }
+ }
+ /* FALLTHROUGH */
+ default:
+ if (c != *string) {
+ return (FNM_NOMATCH);
+ }
+ string++;
+ break;
+ }
+ /* NOTREACHED */
+ }
+}
+
+static char*
+rangematch(pattern, test, flags)
+ char *pattern;
+ int test, flags;
+{
+ int negate, ok;
+ char c, c2;
+
+ /*
+ * A bracket expression starting with an unquoted circumflex
+ * character produces unspecified results (IEEE 1003.2-1992,
+ * 3.13.2). This implementation treats it like '!', for
+ * consistency with the regular expression syntax.
+ * J.T. Conklin (conklin@ngai.kaleida.com)
+ */
+ if ((negate = (*pattern == '!' || *pattern == '^'))) {
+ ++pattern;
+ }
+
+ for (ok = 0; (c = *pattern++) != ']';) {
+ if (c == '\\' && !(flags & FNM_NOESCAPE)) {
+ c = *pattern++;
+ }
+ if (c == EOS) {
+ return (NULL);
+ }
+ if (*pattern == '-' && (c2 = *(pattern + 1)) != EOS && c2 != ']') {
+ pattern += 2;
+ if (c2 == '\\' && !(flags & FNM_NOESCAPE)) {
+ c2 = *pattern++;
+ }
+ if (c2 == EOS) {
+ return (NULL);
+ }
+ if (c <= test && test <= c2) {
+ ok = 1;
+ }
+ }
+ else if (c == test) {
+ ok = 1;
+ }
+ }
+ return (ok == negate ? NULL : pattern);
+}
diff --git a/missing/fnmatch.h b/missing/fnmatch.h
new file mode 100644
index 0000000000..773851625a
--- /dev/null
+++ b/missing/fnmatch.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93
+ */
+
+/* This file has been modified by matz@netlab.co.jp */
+
+#ifndef _FNMATCH_H_
+#define _FNMATCH_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define FNM_NOMATCH 1 /* Match failed. */
+
+#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
+#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
+#define FNM_PERIOD 0x04 /* Period must be matched by period. */
+
+int fnmatch();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_FNMATCH_H_ */
diff --git a/missing/isinf.c b/missing/isinf.c
new file mode 100644
index 0000000000..e0cd6ac1a2
--- /dev/null
+++ b/missing/isinf.c
@@ -0,0 +1,44 @@
+#ifdef __osf__
+
+#define _IEEE 1
+#include <nan.h>
+
+int
+isinf(n)
+ double n;
+{
+ if (IsNANorINF(n) && IsINF(n)) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+#else
+
+#include "config.h"
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+static double zero() { return 0.0; }
+static double one() { return 1.0; }
+static double inf() { return one() / zero(); }
+
+int
+isinf(n)
+ double n;
+{
+ static double pinf = 0.0;
+ static double ninf = 0.0;
+
+ if (pinf == 0.0) {
+ pinf = inf();
+ ninf = -pinf;
+ }
+ return memcmp(&n, &pinf, sizeof n) == 0
+ || memcmp(&n, &ninf, sizeof n) == 0;
+}
+#endif
diff --git a/missing/isnan.c b/missing/isnan.c
new file mode 100644
index 0000000000..96bb93ba6a
--- /dev/null
+++ b/missing/isnan.c
@@ -0,0 +1,16 @@
+static int double_ne();
+
+int
+isnan(n)
+ double n;
+{
+ return double_ne(n, n);
+}
+
+static
+int
+double_ne(n1, n2)
+ double n1, n2;
+{
+ return n1 != n2;
+}
diff --git a/missing/memcmp.c b/missing/memcmp.c
new file mode 100644
index 0000000000..762eaf5260
--- /dev/null
+++ b/missing/memcmp.c
@@ -0,0 +1,21 @@
+/*
+ * memcmp --- compare memories.
+ *
+ */
+
+int
+memcmp(s1,s2,len)
+ char *s1;
+ char *s2;
+ register int len;
+{
+ register unsigned char *a = (unsigned char*)s1;
+ register unsigned char *b = (unsigned char*)s2;
+ register int tmp;
+
+ while (len--) {
+ if (tmp = *a++ - *b++)
+ return tmp;
+ }
+ return 0;
+}
diff --git a/missing/os2.c b/missing/os2.c
new file mode 100644
index 0000000000..aeb181f648
--- /dev/null
+++ b/missing/os2.c
@@ -0,0 +1,111 @@
+#include "ruby.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <process.h>
+#include <limits.h>
+#include <errno.h>
+
+#define INCL_DOS
+#include <os2.h>
+
+int
+chown(char *path, int owner, int group)
+{
+ return 0;
+}
+
+int
+link(char *from, char *to)
+{
+ return -1;
+}
+
+typedef char* CHARP;
+
+int
+do_spawn(cmd)
+char *cmd;
+{
+ register char **a;
+ register char *s;
+ char **argv;
+ char *shell, *sw, *cmd2;
+ int status;
+
+ if ((shell = getenv("RUBYSHELL")) != NULL && *shell != '\0') {
+ s = shell;
+ do
+ *s = isupper(*s) ? tolower(*s) : *s;
+ while (*++s);
+ if (strstr(shell, "cmd") || strstr(shell, "4os2"))
+ sw = "/c";
+ else
+ sw = "-c";
+ } else if ((shell = getenv("SHELL")) != NULL && *shell != '\0') {
+ s = shell;
+ do
+ *s = isupper(*s) ? tolower(*s) : *s;
+ while (*++s);
+ if (strstr(shell, "cmd") || strstr(shell, "4os2"))
+ sw = "/c";
+ else
+ sw = "-c";
+ } else if ((shell = getenv("COMSPEC")) != NULL && *shell != '\0') {
+ s = shell;
+ do
+ *s = isupper(*s) ? tolower(*s) : *s;
+ while (*++s);
+ if (strstr(shell, "cmd") || strstr(shell, "4os2"))
+ sw = "/c";
+ else
+ sw = "-c";
+ }
+ /* see if there are shell metacharacters in it */
+ /*SUPPRESS 530*/
+ /* for (s = cmd; *s && isalpha(*s); s++) ;
+ if (*s == '=')
+ goto doshell; */
+ for (s = cmd; *s; s++) {
+ if (*sw == '-' && *s != ' ' &&
+ !isalpha(*s) && index("$&*(){}[]'\";\\|?<>~`\n",*s)) {
+ if (*s == '\n' && !s[1]) {
+ *s = '\0';
+ break;
+ }
+ goto doshell;
+ } else if (*sw == '/' && *s != ' ' &&
+ !isalpha(*s) && index("^()<>|&\n",*s)) {
+ if (*s == '\n' && !s[1]) {
+ *s = '\0';
+ break;
+ }
+ doshell:
+ status = spawnlp(P_WAIT,shell,shell,sw,cmd,(char*)NULL);
+ return status;
+ }
+ }
+ argv = ALLOC_N(CHARP,(strlen(cmd) / 2 + 2));
+ cmd2 = ALLOC_N(char, (strlen(cmd) + 1));
+ strcpy(cmd2, cmd);
+ a = argv;
+ for (s = cmd2; *s;) {
+ while (*s && isspace(*s)) s++;
+ if (*s)
+ *(a++) = s;
+ while (*s && !isspace(*s)) s++;
+ if (*s)
+ *s++ = '\0';
+ }
+ *a = NULL;
+ if (argv[0]) {
+ if ((status = spawnvp(P_WAIT, argv[0], argv)) == -1) {
+ free(argv);
+ free(cmd2);
+ return -1;
+ }
+ }
+ free(cmd2);
+ free(argv);
+ return status;
+}
diff --git a/missing/strcasecmp.c b/missing/strcasecmp.c
index 83aa50d9c3..ba7bf78ea4 100644
--- a/missing/strcasecmp.c
+++ b/missing/strcasecmp.c
@@ -1,6 +1,5 @@
#include <ctype.h>
-#define min(a,b) (((a)>(b))?(b):(a))
int
strcasecmp(p1, p2)
char *p1, *p2;
diff --git a/missing/strchr.c b/missing/strchr.c
new file mode 100644
index 0000000000..50714c9942
--- /dev/null
+++ b/missing/strchr.c
@@ -0,0 +1,45 @@
+/*
+ * strchr --- search a string for a character
+ *
+ * We supply this routine for those systems that aren't standard yet.
+ */
+
+#include <stdio.h>
+
+char *
+strchr(str, c)
+register const char *str, c;
+{
+ if (c == '\0') {
+ /* thanks to Mike Brennan ... */
+ do {
+ if (*str == c)
+ return (char *) str;
+ } while (*str++);
+ } else {
+ for (; *str; str++)
+ if (*str == c)
+ return (char *) str;
+ }
+
+ return NULL;
+}
+
+/*
+ * strrchr --- find the last occurrence of a character in a string
+ *
+ * We supply this routine for those systems that aren't standard yet.
+ */
+
+char *
+strrchr(str, c)
+register const char *str, c;
+{
+ register const char *save = NULL;
+
+ for (; *str; str++)
+ if (*str == c)
+ save = str;
+
+ return (char *) save;
+}
diff --git a/missing/strftime.c b/missing/strftime.c
index 478471c37d..cc3f1a8070 100644
--- a/missing/strftime.c
+++ b/missing/strftime.c
@@ -45,6 +45,8 @@
* January 1996
*/
+#include "config.h"
+
#ifndef GAWK
#include <stdio.h>
#include <ctype.h>
@@ -92,23 +94,25 @@
#ifndef __STDC__
#define const /**/
-extern void *malloc();
-extern void *realloc();
extern void tzset();
-extern char *strchr();
-extern char *getenv();
static int weeknumber();
adddecl(static int iso8601wknum();)
#else
-extern void *malloc(unsigned count);
-extern void *realloc(void *ptr, unsigned count);
extern void tzset(void);
-extern char *strchr(const char *str, int ch);
-extern char *getenv(const char *v);
static int weeknumber(const struct tm *timeptr, int firstweekday);
adddecl(static int iso8601wknum(const struct tm *timeptr);)
#endif
+#ifdef STDC_HEADERS
+#include <stdlib.h>
+#include <string.h>
+#else
+extern void *malloc();
+extern void *realloc();
+extern char *getenv();
+extern char *strchr();
+#endif
+
#ifdef __GNUC__
#define inline __inline__
#else
@@ -348,8 +352,8 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
strcpy(tbuf, ampm[1]);
break;
- case 'S': /* second, 00 - 61 */
- i = range(0, timeptr->tm_sec, 61);
+ case 'S': /* second, 00 - 60 */
+ i = range(0, timeptr->tm_sec, 60);
sprintf(tbuf, "%02d", i);
break;
@@ -504,7 +508,7 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
#ifdef VMS_EXT
case 'v': /* date as dd-bbb-YYYY */
- sprintf(tbuf, "%02d-%3.3s-%4d",
+ sprintf(tbuf, "%2d-%3.3s-%4d",
range(1, timeptr->tm_mday, 31),
months_a[range(0, timeptr->tm_mon, 11)],
timeptr->tm_year + 1900);
@@ -562,7 +566,7 @@ strftime(char *s, size_t maxsize, const char *format, const struct tm *timeptr)
else
sprintf(tbuf, "%02d", y % 100);
break;
-#endif ISO_DATE_EXT
+#endif /* ISO_DATE_EXT */
default:
tbuf[0] = '%';
tbuf[1] = *format;
@@ -826,7 +830,7 @@ static char *array[] =
"(%%M) minute (00..59) %M",
"(%%O) Locale extensions (ignored) %O",
"(%%R) time, 24-hour (%%H:%%M) %R",
- "(%%S) second (00..61) %S",
+ "(%%S) second (00..60) %S",
"(%%T) time, 24-hour (%%H:%%M:%%S) %T",
"(%%U) week of year, Sunday as first day of week (00..53) %U",
"(%%V) week of year according to ISO 8601 %V",
diff --git a/missing/strncasecmp.c b/missing/strncasecmp.c
new file mode 100644
index 0000000000..c136703415
--- /dev/null
+++ b/missing/strncasecmp.c
@@ -0,0 +1,18 @@
+#include <ctype.h>
+
+int
+strncasecmp(p1, p2, len)
+ char *p1;
+ char *p2;
+ int len;
+{
+ for (; len != 0; len--, p1++, p2++) {
+ if (toupper(*p1) != toupper(*p2)) {
+ return toupper(*p1) - toupper(*p2);
+ }
+ if (*p1 == '\0') {
+ return 0;
+ }
+ }
+ return 0;
+}
diff --git a/missing/strtod.c b/missing/strtod.c
new file mode 100644
index 0000000000..e052cbc067
--- /dev/null
+++ b/missing/strtod.c
@@ -0,0 +1,266 @@
+/*
+ * strtod.c --
+ *
+ * Source code for the "strtod" library procedure.
+ *
+ * Copyright (c) 1988-1993 The Regents of the University of California.
+ * Copyright (c) 1994 Sun Microsystems, Inc.
+ *
+ * See the file "license.terms" for information on usage and redistribution
+ * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+ *
+ * RCS: @(#) $Id$
+ */
+
+#include "config.h"
+#ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+extern int errno;
+
+#ifndef __STDC__
+# ifdef __GNUC__
+# define const __const__
+# else
+# define const
+# endif
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#define FALSE 0
+#endif
+#ifndef NULL
+#define NULL 0
+#endif
+
+static int maxExponent = 511; /* Largest possible base 10 exponent. Any
+ * exponent larger than this will already
+ * produce underflow or overflow, so there's
+ * no need to worry about additional digits.
+ */
+static double powersOf10[] = { /* Table giving binary powers of 10. Entry */
+ 10., /* is 10^2^i. Used to convert decimal */
+ 100., /* exponents into floating-point numbers. */
+ 1.0e4,
+ 1.0e8,
+ 1.0e16,
+ 1.0e32,
+ 1.0e64,
+ 1.0e128,
+ 1.0e256
+};
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * strtod --
+ *
+ * This procedure converts a floating-point number from an ASCII
+ * decimal representation to internal double-precision format.
+ *
+ * Results:
+ * The return value is the double-precision floating-point
+ * representation of the characters in string. If endPtr isn't
+ * NULL, then *endPtr is filled in with the address of the
+ * next character after the last one that was part of the
+ * floating-point number.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+double
+strtod(string, endPtr)
+ const char *string; /* A decimal ASCII floating-point number,
+ * optionally preceded by white space.
+ * Must have form "-I.FE-X", where I is the
+ * integer part of the mantissa, F is the
+ * fractional part of the mantissa, and X
+ * is the exponent. Either of the signs
+ * may be "+", "-", or omitted. Either I
+ * or F may be omitted, or both. The decimal
+ * point isn't necessary unless F is present.
+ * The "E" may actually be an "e". E and X
+ * may both be omitted (but not just one).
+ */
+ char **endPtr; /* If non-NULL, store terminating character's
+ * address here. */
+{
+ int sign, expSign = FALSE;
+ double fraction, dblExp, *d;
+ register const char *p;
+ register int c;
+ int exp = 0; /* Exponent read from "EX" field. */
+ int fracExp = 0; /* Exponent that derives from the fractional
+ * part. Under normal circumstatnces, it is
+ * the negative of the number of digits in F.
+ * However, if I is very long, the last digits
+ * of I get dropped (otherwise a long I with a
+ * large negative exponent could cause an
+ * unnecessary overflow on I alone). In this
+ * case, fracExp is incremented one for each
+ * dropped digit. */
+ int mantSize; /* Number of digits in mantissa. */
+ int decPt; /* Number of mantissa digits BEFORE decimal
+ * point. */
+ const char *pExp; /* Temporarily holds location of exponent
+ * in string. */
+
+ /*
+ * Strip off leading blanks and check for a sign.
+ */
+
+ p = string;
+ while (isspace(*p)) {
+ p += 1;
+ }
+ if (*p == '-') {
+ sign = TRUE;
+ p += 1;
+ } else {
+ if (*p == '+') {
+ p += 1;
+ }
+ sign = FALSE;
+ }
+
+ /*
+ * Count the number of digits in the mantissa (including the decimal
+ * point), and also locate the decimal point.
+ */
+
+ decPt = -1;
+ for (mantSize = 0; ; mantSize += 1)
+ {
+ c = *p;
+ if (!isdigit(c)) {
+ if ((c != '.') || (decPt >= 0)) {
+ break;
+ }
+ decPt = mantSize;
+ }
+ p += 1;
+ }
+
+ /*
+ * Now suck up the digits in the mantissa. Use two integers to
+ * collect 9 digits each (this is faster than using floating-point).
+ * If the mantissa has more than 18 digits, ignore the extras, since
+ * they can't affect the value anyway.
+ */
+
+ pExp = p;
+ p -= mantSize;
+ if (decPt < 0) {
+ decPt = mantSize;
+ } else {
+ mantSize -= 1; /* One of the digits was the point. */
+ }
+ if (mantSize > 18) {
+ fracExp = decPt - 18;
+ mantSize = 18;
+ } else {
+ fracExp = decPt - mantSize;
+ }
+ if (mantSize == 0) {
+ fraction = 0.0;
+ p = string;
+ goto done;
+ } else {
+ int frac1, frac2;
+ frac1 = 0;
+ for ( ; mantSize > 9; mantSize -= 1)
+ {
+ c = *p;
+ p += 1;
+ if (c == '.') {
+ c = *p;
+ p += 1;
+ }
+ frac1 = 10*frac1 + (c - '0');
+ }
+ frac2 = 0;
+ for (; mantSize > 0; mantSize -= 1)
+ {
+ c = *p;
+ p += 1;
+ if (c == '.') {
+ c = *p;
+ p += 1;
+ }
+ frac2 = 10*frac2 + (c - '0');
+ }
+ fraction = (1.0e9 * frac1) + frac2;
+ }
+
+ /*
+ * Skim off the exponent.
+ */
+
+ p = pExp;
+ if ((*p == 'E') || (*p == 'e')) {
+ p += 1;
+ if (*p == '-') {
+ expSign = TRUE;
+ p += 1;
+ } else {
+ if (*p == '+') {
+ p += 1;
+ }
+ expSign = FALSE;
+ }
+ while (isdigit(*p)) {
+ exp = exp * 10 + (*p - '0');
+ p += 1;
+ }
+ }
+ if (expSign) {
+ exp = fracExp - exp;
+ } else {
+ exp = fracExp + exp;
+ }
+
+ /*
+ * Generate a floating-point number that represents the exponent.
+ * Do this by processing the exponent one bit at a time to combine
+ * many powers of 2 of 10. Then combine the exponent with the
+ * fraction.
+ */
+
+ if (exp < 0) {
+ expSign = TRUE;
+ exp = -exp;
+ } else {
+ expSign = FALSE;
+ }
+ if (exp > maxExponent) {
+ exp = maxExponent;
+ errno = ERANGE;
+ }
+ dblExp = 1.0;
+ for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
+ if (exp & 01) {
+ dblExp *= *d;
+ }
+ }
+ if (expSign) {
+ fraction /= dblExp;
+ } else {
+ fraction *= dblExp;
+ }
+
+done:
+ if (endPtr != NULL) {
+ *endPtr = (char *) p;
+ }
+
+ if (sign) {
+ return -fraction;
+ }
+ return fraction;
+}
diff --git a/missing/vsnprintf.c b/missing/vsnprintf.c
new file mode 100644
index 0000000000..5865be7f9b
--- /dev/null
+++ b/missing/vsnprintf.c
@@ -0,0 +1,1128 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* SNPRINTF.C
+ * fjc 7-31-97 Modified by Mib Software to be a standalone snprintf.c module.
+ * http://www.mibsoftware.com
+ * Mib Software does not warrant this software any differently than the
+ * University of California, Berkeley as described above. All warranties
+ * are disclaimed. Use this software at your own risk.
+ *
+ * All code referencing FILE * functions was eliminated, since it could
+ * never be called. All header files and necessary files are collapsed
+ * into one file, internal functions are declared static. This should
+ * allow inclusion into libraries with less chance of namespace collisions.
+ *
+ * snprintf should be the only externally visible item.
+ *
+ * As of 7-31-97 FLOATING_POINT is NOT provided. The code is somewhat
+ * non-portable, so it is disabled.
+ */
+
+/* Define FLOATING_POINT to get floating point. */
+/*
+#define FLOATING_POINT
+*/
+
+#include <sys/types.h>
+#define u_long unsigned long
+#define u_short unsigned short
+#define u_int unsigned int
+
+#undef __P
+#if defined(__STDC__)
+# include <stdarg.h>
+# if !defined(__P)
+# define __P(x) x
+# endif
+#else
+# define __P(x) ()
+# if !defined(const)
+# define const
+# endif
+# include <varargs.h>
+#endif
+#ifndef _BSD_VA_LIST_
+#define _BSD_VA_LIST_ va_list
+#endif
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# ifndef LONG_MAX
+# ifdef HAVE_LIMITS_H
+# include <limits.h>
+# else
+ /* assuming 32bit(2's compliment) long */
+# define LONG_MAX 2147483647
+# endif
+# endif
+#endif
+
+#if defined(__hpux) && !defined(__GNUC__)
+#define const
+#endif
+
+#if defined(sgi)
+#undef __const
+#define __const
+#endif /* People who don't like const sys_error */
+
+#ifdef NT
+typedef long size_t;
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/*
+ * NB: to fit things in six character monocase externals, the stdio
+ * code uses the prefix `__s' for stdio objects, typically followed
+ * by a three-character attempt at a mnemonic.
+ */
+
+/* stdio buffers */
+struct __sbuf {
+ unsigned char *_base;
+ int _size;
+};
+
+
+/*
+ * stdio state variables.
+ *
+ * The following always hold:
+ *
+ * if (_flags&(__SLBF|__SWR)) == (__SLBF|__SWR),
+ * _lbfsize is -_bf._size, else _lbfsize is 0
+ * if _flags&__SRD, _w is 0
+ * if _flags&__SWR, _r is 0
+ *
+ * This ensures that the getc and putc macros (or inline functions) never
+ * try to write or read from a file that is in `read' or `write' mode.
+ * (Moreover, they can, and do, automatically switch from read mode to
+ * write mode, and back, on "r+" and "w+" files.)
+ *
+ * _lbfsize is used only to make the inline line-buffered output stream
+ * code as compact as possible.
+ *
+ * _ub, _up, and _ur are used when ungetc() pushes back more characters
+ * than fit in the current _bf, or when ungetc() pushes back a character
+ * that does not match the previous one in _bf. When this happens,
+ * _ub._base becomes non-nil (i.e., a stream has ungetc() data iff
+ * _ub._base!=NULL) and _up and _ur save the current values of _p and _r.
+ *
+ * NB: see WARNING above before changing the layout of this structure!
+ */
+typedef struct __sFILE {
+ unsigned char *_p; /* current position in (some) buffer */
+ int _r; /* read space left for getc() */
+ int _w; /* write space left for putc() */
+ short _flags; /* flags, below; this FILE is free if 0 */
+ short _file; /* fileno, if Unix descriptor, else -1 */
+ struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
+ int _lbfsize; /* 0 or -_bf._size, for inline putc */
+} FILE;
+
+
+#define __SLBF 0x0001 /* line buffered */
+#define __SNBF 0x0002 /* unbuffered */
+#define __SRD 0x0004 /* OK to read */
+#define __SWR 0x0008 /* OK to write */
+ /* RD and WR are never simultaneously asserted */
+#define __SRW 0x0010 /* open for reading & writing */
+#define __SEOF 0x0020 /* found EOF */
+#define __SERR 0x0040 /* found error */
+#define __SMBF 0x0080 /* _buf is from malloc */
+#define __SAPP 0x0100 /* fdopen()ed in append mode */
+#define __SSTR 0x0200 /* this is an sprintf/snprintf string */
+#define __SOPT 0x0400 /* do fseek() optimisation */
+#define __SNPT 0x0800 /* do not do fseek() optimisation */
+#define __SOFF 0x1000 /* set iff _offset is in fact correct */
+#define __SMOD 0x2000 /* true => fgetln modified _p text */
+
+
+#define EOF (-1)
+
+
+#define __sfeof(p) (((p)->_flags & __SEOF) != 0)
+#define __sferror(p) (((p)->_flags & __SERR) != 0)
+#define __sclearerr(p) ((void)((p)->_flags &= ~(__SERR|__SEOF)))
+#define __sfileno(p) ((p)->_file)
+
+#define feof(p) __sfeof(p)
+#define ferror(p) __sferror(p)
+#define clearerr(p) __sclearerr(p)
+
+#ifndef _ANSI_SOURCE
+#define fileno(p) __sfileno(p)
+#endif
+
+
+#if defined(__hpux) && !defined(__GNUC__)
+#include <string.h>
+#endif
+
+/*
+ * I/O descriptors for __sfvwrite().
+ */
+struct __siov {
+ void *iov_base;
+ size_t iov_len;
+};
+struct __suio {
+ struct __siov *uio_iov;
+ int uio_iovcnt;
+ int uio_resid;
+};
+
+/*
+ * Write some memory regions. Return zero on success, EOF on error.
+ *
+ * This routine is large and unsightly, but most of the ugliness due
+ * to the three different kinds of output buffering is handled here.
+ */
+static BSD__sfvwrite(fp, uio)
+ register FILE *fp;
+ register struct __suio *uio;
+{
+ register size_t len;
+ register char *p;
+ register struct __siov *iov;
+ register int w;
+
+ if ((len = uio->uio_resid) == 0)
+ return (0);
+#ifndef __hpux
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+#define COPY(n) (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n))
+
+ iov = uio->uio_iov;
+ p = iov->iov_base;
+ len = iov->iov_len;
+ iov++;
+#define GETIOV(extra_work) \
+ while (len == 0) { \
+ extra_work; \
+ p = iov->iov_base; \
+ len = iov->iov_len; \
+ iov++; \
+ }
+ if (fp->_flags & __SNBF) {
+ /* fjc 7-31-97 Will never happen. We are working with
+ strings only
+ */
+ } else if ((fp->_flags & __SLBF) == 0) {
+ /*
+ * Fully buffered: fill partially full buffer, if any,
+ * and then flush. If there is no partial buffer, write
+ * one _bf._size byte chunk directly (without copying).
+ *
+ * String output is a special case: write as many bytes
+ * as fit, but pretend we wrote everything. This makes
+ * snprintf() return the number of bytes needed, rather
+ * than the number used, and avoids its write function
+ * (so that the write function can be invalid).
+ */
+ do {
+ GETIOV(;);
+ w = fp->_w;
+ if (fp->_flags & __SSTR) {
+ if (len < w)
+ w = len;
+ COPY(w); /* copy MIN(fp->_w,len), */
+ fp->_w -= w;
+ fp->_p += w;
+ w = len; /* but pretend copied all */
+ } else {
+ /* fjc 7-31-97 Will never happen. We are working with
+ strings only
+ */
+ }
+ p += w;
+ len -= w;
+ } while ((uio->uio_resid -= w) != 0);
+ } else {
+ /* fjc 7-31-97 Will never happen. We are working with
+ strings only
+ */
+ }
+ return (0);
+
+err:
+ fp->_flags |= __SERR;
+ return (EOF);
+}
+
+/*
+ * Actual printf innards.
+ *
+ * This code is large and complicated...
+ */
+
+#if !defined(__CYGWIN32__) && defined(__hpux) && !defined(__GNUC__)
+#include <stdlib.h>
+#endif
+
+/*
+ * Flush out all the vectors defined by the given uio,
+ * then reset it so that it can be reused.
+ */
+static int
+BSD__sprint(fp, uio)
+ FILE *fp;
+ register struct __suio *uio;
+{
+ register int err;
+
+ if (uio->uio_resid == 0) {
+ uio->uio_iovcnt = 0;
+ return (0);
+ }
+ err = BSD__sfvwrite(fp, uio);
+ uio->uio_resid = 0;
+ uio->uio_iovcnt = 0;
+ return (err);
+}
+
+
+/*
+ * Helper function for `fprintf to unbuffered unix file': creates a
+ * temporary buffer. We only work on write-only files; this avoids
+ * worries about ungetc buffers and so forth.
+ */
+static int
+BSD__sbprintf(fp, fmt, ap)
+ register FILE *fp;
+ const char *fmt;
+ va_list ap;
+{
+/* We don't support files. */
+ return 0;
+}
+
+
+/*
+ * Macros for converting digits to letters and vice versa
+ */
+#define to_digit(c) ((c) - '0')
+#define is_digit(c) ((unsigned)to_digit(c) <= 9)
+#define to_char(n) ((n) + '0')
+
+/*
+ * Convert an unsigned long to ASCII for printf purposes, returning
+ * a pointer to the first character of the string representation.
+ * Octal numbers can be forced to have a leading zero; hex numbers
+ * use the given digits.
+ */
+static char *
+BSD__ultoa(val, endp, base, octzero, xdigs)
+ register u_long val;
+ char *endp;
+ int base, octzero;
+ char *xdigs;
+{
+ register char *cp = endp;
+ register long sval;
+
+ /*
+ * Handle the three cases separately, in the hope of getting
+ * better/faster code.
+ */
+ switch (base) {
+ case 10:
+ if (val < 10) { /* many numbers are 1 digit */
+ *--cp = to_char(val);
+ return (cp);
+ }
+ /*
+ * On many machines, unsigned arithmetic is harder than
+ * signed arithmetic, so we do at most one unsigned mod and
+ * divide; this is sufficient to reduce the range of
+ * the incoming value to where signed arithmetic works.
+ */
+ if (val > LONG_MAX) {
+ *--cp = to_char(val % 10);
+ sval = val / 10;
+ } else
+ sval = val;
+ do {
+ *--cp = to_char(sval % 10);
+ sval /= 10;
+ } while (sval != 0);
+ break;
+
+ case 8:
+ do {
+ *--cp = to_char(val & 7);
+ val >>= 3;
+ } while (val);
+ if (octzero && *cp != '0')
+ *--cp = '0';
+ break;
+
+ case 16:
+ do {
+ *--cp = xdigs[val & 15];
+ val >>= 4;
+ } while (val);
+ break;
+
+ default: /* oops */
+ /*
+ abort();
+ */
+ break; /* fjc 7-31-97. Don't reference abort() here */
+ }
+ return (cp);
+}
+
+#ifdef FLOATING_POINT
+#include <math.h>
+/* #include "floatio.h" */
+
+#ifndef MAXEXP
+# define MAXEXP 1024
+#endif
+
+#ifndef MAXFRACT
+# define MAXFRACT 64
+#endif
+
+#define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */
+#define DEFPREC 6
+
+static char *cvt __P((double, int, int, char *, int *, int, int *));
+static int exponent __P((char *, int, int));
+
+#else /* no FLOATING_POINT */
+
+#define BUF 68
+
+#endif /* FLOATING_POINT */
+
+
+/*
+ * Flags used during conversion.
+ */
+#define ALT 0x001 /* alternate form */
+#define HEXPREFIX 0x002 /* add 0x or 0X prefix */
+#define LADJUST 0x004 /* left adjustment */
+#define LONGDBL 0x008 /* long double; unimplemented */
+#define LONGINT 0x010 /* long integer */
+
+#ifdef _HAVE_SANE_QUAD_
+#define QUADINT 0x020 /* quad integer */
+#endif /* _HAVE_SANE_QUAD_ */
+
+#define SHORTINT 0x040 /* short integer */
+#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
+#define FPT 0x100 /* Floating point number */
+static int
+BSD_vfprintf(fp, fmt0, ap)
+ FILE *fp;
+ const char *fmt0;
+ va_list ap;
+{
+ register char *fmt; /* format string */
+ register int ch; /* character from fmt */
+ register int n; /* handy integer (short term usage) */
+ register char *cp; /* handy char pointer (short term usage) */
+ register struct __siov *iovp;/* for PRINT macro */
+ register int flags; /* flags as above */
+ int ret; /* return value accumulator */
+ int width; /* width from format (%8d), or 0 */
+ int prec; /* precision from format (%.3d), or -1 */
+ char sign; /* sign prefix (' ', '+', '-', or \0) */
+#ifdef FLOATING_POINT
+ char softsign; /* temporary negative sign for floats */
+ double _double; /* double precision arguments %[eEfgG] */
+ int expt; /* integer value of exponent */
+ int expsize; /* character count for expstr */
+ int ndig; /* actual number of digits returned by cvt */
+ char expstr[7]; /* buffer for exponent string */
+#endif
+ u_long ulval; /* integer arguments %[diouxX] */
+#ifdef _HAVE_SANE_QUAD_
+ u_quad_t uqval; /* %q integers */
+#endif /* _HAVE_SANE_QUAD_ */
+ int base; /* base for [diouxX] conversion */
+ int dprec; /* a copy of prec if [diouxX], 0 otherwise */
+ int fieldsz; /* field size expanded by sign, etc */
+ int realsz; /* field size expanded by dprec */
+ int size; /* size of converted field or string */
+ char *xdigs; /* digits for [xX] conversion */
+#define NIOV 8
+ struct __suio uio; /* output information: summary */
+ struct __siov iov[NIOV];/* ... and individual io vectors */
+ char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */
+ char ox[2]; /* space for 0x hex-prefix */
+
+ /*
+ * Choose PADSIZE to trade efficiency vs. size. If larger printf
+ * fields occur frequently, increase PADSIZE and make the initialisers
+ * below longer.
+ */
+#define PADSIZE 16 /* pad chunk size */
+ static char blanks[PADSIZE] =
+ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
+ static char zeroes[PADSIZE] =
+ {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
+
+ /*
+ * BEWARE, these `goto error' on error, and PAD uses `n'.
+ */
+#define PRINT(ptr, len) { \
+ iovp->iov_base = (ptr); \
+ iovp->iov_len = (len); \
+ uio.uio_resid += (len); \
+ iovp++; \
+ if (++uio.uio_iovcnt >= NIOV) { \
+ if (BSD__sprint(fp, &uio)) \
+ goto error; \
+ iovp = iov; \
+ } \
+}
+#define PAD(howmany, with) { \
+ if ((n = (howmany)) > 0) { \
+ while (n > PADSIZE) { \
+ PRINT(with, PADSIZE); \
+ n -= PADSIZE; \
+ } \
+ PRINT(with, n); \
+ } \
+}
+#define FLUSH() { \
+ if (uio.uio_resid && BSD__sprint(fp, &uio)) \
+ goto error; \
+ uio.uio_iovcnt = 0; \
+ iovp = iov; \
+}
+
+ /*
+ * To extend shorts properly, we need both signed and unsigned
+ * argument extraction methods.
+ */
+#define SARG() \
+ (flags&LONGINT ? va_arg(ap, long) : \
+ flags&SHORTINT ? (long)(short)va_arg(ap, int) : \
+ (long)va_arg(ap, int))
+#define UARG() \
+ (flags&LONGINT ? va_arg(ap, u_long) : \
+ flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \
+ (u_long)va_arg(ap, u_int))
+
+ /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+ fp->_file >= 0)
+ return (BSD__sbprintf(fp, fmt0, ap));
+
+ fmt = (char *)fmt0;
+ uio.uio_iov = iovp = iov;
+ uio.uio_resid = 0;
+ uio.uio_iovcnt = 0;
+ ret = 0;
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
+ /* void */;
+ if ((n = fmt - cp) != 0) {
+ PRINT(cp, n);
+ ret += n;
+ }
+ if (ch == '\0')
+ goto done;
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+ dprec = 0;
+ width = 0;
+ prec = -1;
+ sign = '\0';
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ /*
+ * ``If the space and + flags both appear, the space
+ * flag will be ignored.''
+ * -- ANSI X3J11
+ */
+ if (!sign)
+ sign = ' ';
+ goto rflag;
+ case '#':
+ flags |= ALT;
+ goto rflag;
+ case '*':
+ /*
+ * ``A negative field width argument is taken as a
+ * - flag followed by a positive field width.''
+ * -- ANSI X3J11
+ * They don't exclude field widths read from args.
+ */
+ if ((width = va_arg(ap, int)) >= 0)
+ goto rflag;
+ width = -width;
+ /* FALLTHROUGH */
+ case '-':
+ flags |= LADJUST;
+ goto rflag;
+ case '+':
+ sign = '+';
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ n = va_arg(ap, int);
+ prec = n < 0 ? -1 : n;
+ goto rflag;
+ }
+ n = 0;
+ while (is_digit(ch)) {
+ n = 10 * n + to_digit(ch);
+ ch = *fmt++;
+ }
+ prec = n < 0 ? -1 : n;
+ goto reswitch;
+ case '0':
+ /*
+ * ``Note that 0 is taken as a flag, not as the
+ * beginning of a field width.''
+ * -- ANSI X3J11
+ */
+ flags |= ZEROPAD;
+ goto rflag;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ do {
+ n = 10 * n + to_digit(ch);
+ ch = *fmt++;
+ } while (is_digit(ch));
+ width = n;
+ goto reswitch;
+#ifdef FLOATING_POINT
+ case 'L':
+ flags |= LONGDBL;
+ goto rflag;
+#endif
+ case 'h':
+ flags |= SHORTINT;
+ goto rflag;
+ case 'l':
+ flags |= LONGINT;
+ goto rflag;
+#ifdef _HAVE_SANE_QUAD_
+ case 'q':
+ flags |= QUADINT;
+ goto rflag;
+#endif /* _HAVE_SANE_QUAD_ */
+ case 'c':
+ *(cp = buf) = va_arg(ap, int);
+ size = 1;
+ sign = '\0';
+ break;
+ case 'D':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
+#ifdef _HAVE_SANE_QUAD_
+ if (flags & QUADINT) {
+ uqval = va_arg(ap, quad_t);
+ if ((quad_t)uqval < 0) {
+ uqval = -uqval;
+ sign = '-';
+ }
+ } else {
+#else /* _HAVE_SANE_QUAD_ */
+ {
+#endif /* _HAVE_SANE_QUAD_ */
+ ulval = SARG();
+ if ((long)ulval < 0) {
+ ulval = -ulval;
+ sign = '-';
+ }
+ }
+ base = 10;
+ goto number;
+#ifdef FLOATING_POINT
+ case 'e': /* anomalous precision */
+ case 'E':
+ prec = (prec == -1) ?
+ DEFPREC + 1 : prec + 1;
+ /* FALLTHROUGH */
+ goto fp_begin;
+ case 'f': /* always print trailing zeroes */
+ if (prec != 0)
+ flags |= ALT;
+ case 'g':
+ case 'G':
+ if (prec == -1)
+ prec = DEFPREC;
+fp_begin: _double = va_arg(ap, double);
+ /* do this before tricky precision changes */
+ if (isinf(_double)) {
+ if (_double < 0)
+ sign = '-';
+ cp = "Inf";
+ size = 3;
+ break;
+ }
+ if (isnan(_double)) {
+ cp = "NaN";
+ size = 3;
+ break;
+ }
+ flags |= FPT;
+ cp = cvt(_double, prec, flags, &softsign,
+ &expt, ch, &ndig);
+ if (ch == 'g' || ch == 'G') {
+ if (expt <= -4 || expt > prec)
+ ch = (ch == 'g') ? 'e' : 'E';
+ else
+ ch = 'g';
+ }
+ if (ch <= 'e') { /* 'e' or 'E' fmt */
+ --expt;
+ expsize = exponent(expstr, expt, ch);
+ size = expsize + ndig;
+ if (ndig > 1 || flags & ALT)
+ ++size;
+ } else if (ch == 'f') { /* f fmt */
+ if (expt > 0) {
+ size = expt;
+ if (prec || flags & ALT)
+ size += prec + 1;
+ } else /* "0.X" */
+ size = prec + 2;
+ } else if (expt >= ndig) { /* fixed g fmt */
+ size = expt;
+ if (flags & ALT)
+ ++size;
+ } else
+ size = ndig + (expt > 0 ?
+ 1 : 2 - expt);
+
+ if (softsign)
+ sign = '-';
+ break;
+#endif /* FLOATING_POINT */
+ case 'n':
+#ifdef _HAVE_SANE_QUAD_
+ if (flags & QUADINT)
+ *va_arg(ap, quad_t *) = ret;
+ else if (flags & LONGINT)
+#else /* _HAVE_SANE_QUAD_ */
+ if (flags & LONGINT)
+#endif /* _HAVE_SANE_QUAD_ */
+ *va_arg(ap, long *) = ret;
+ else if (flags & SHORTINT)
+ *va_arg(ap, short *) = ret;
+ else
+ *va_arg(ap, int *) = ret;
+ continue; /* no output */
+ case 'O':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'o':
+#ifdef _HAVE_SANE_QUAD_
+ if (flags & QUADINT)
+ uqval = va_arg(ap, u_quad_t);
+ else
+#endif /* _HAVE_SANE_QUAD_ */
+ ulval = UARG();
+ base = 8;
+ goto nosign;
+ case 'p':
+ /*
+ * ``The argument shall be a pointer to void. The
+ * value of the pointer is converted to a sequence
+ * of printable characters, in an implementation-
+ * defined manner.''
+ * -- ANSI X3J11
+ */
+ ulval = (u_long)va_arg(ap, void *);
+ base = 16;
+ xdigs = "0123456789abcdef";
+#ifdef _HAVE_SANE_QUAD_
+ flags = (flags & ~QUADINT) | HEXPREFIX;
+#else /* _HAVE_SANE_QUAD_ */
+ flags = (flags) | HEXPREFIX;
+#endif /* _HAVE_SANE_QUAD_ */
+ ch = 'x';
+ goto nosign;
+ case 's':
+ if ((cp = va_arg(ap, char *)) == NULL)
+ cp = "(null)";
+ if (prec >= 0) {
+ /*
+ * can't use strlen; can only look for the
+ * NUL in the first `prec' characters, and
+ * strlen() will go further.
+ */
+ char *p = (char *)memchr(cp, 0, prec);
+
+ if (p != NULL) {
+ size = p - cp;
+ if (size > prec)
+ size = prec;
+ } else
+ size = prec;
+ } else
+ size = strlen(cp);
+ sign = '\0';
+ break;
+ case 'U':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'u':
+#ifdef _HAVE_SANE_QUAD_
+ if (flags & QUADINT)
+ uqval = va_arg(ap, u_quad_t);
+ else
+#endif /* _HAVE_SANE_QUAD_ */
+ ulval = UARG();
+ base = 10;
+ goto nosign;
+ case 'X':
+ xdigs = "0123456789ABCDEF";
+ goto hex;
+ case 'x':
+ xdigs = "0123456789abcdef";
+hex:
+#ifdef _HAVE_SANE_QUAD_
+ if (flags & QUADINT)
+ uqval = va_arg(ap, u_quad_t);
+ else
+#endif /* _HAVE_SANE_QUAD_ */
+ ulval = UARG();
+ base = 16;
+ /* leading 0x/X only if non-zero */
+ if (flags & ALT &&
+#ifdef _HAVE_SANE_QUAD_
+ (flags & QUADINT ? uqval != 0 : ulval != 0))
+#else /* _HAVE_SANE_QUAD_ */
+ ulval != 0)
+#endif /* _HAVE_SANE_QUAD_ */
+ flags |= HEXPREFIX;
+
+ /* unsigned conversions */
+nosign: sign = '\0';
+ /*
+ * ``... diouXx conversions ... if a precision is
+ * specified, the 0 flag will be ignored.''
+ * -- ANSI X3J11
+ */
+number: if ((dprec = prec) >= 0)
+ flags &= ~ZEROPAD;
+
+ /*
+ * ``The result of converting a zero value with an
+ * explicit precision of zero is no characters.''
+ * -- ANSI X3J11
+ */
+ cp = buf + BUF;
+#ifdef _HAVE_SANE_QUAD_
+ if (flags & QUADINT) {
+ if (uqval != 0 || prec != 0)
+ cp = __uqtoa(uqval, cp, base,
+ flags & ALT, xdigs);
+ } else {
+#else /* _HAVE_SANE_QUAD_ */
+ {
+#endif /* _HAVE_SANE_QUAD_ */
+ if (ulval != 0 || prec != 0)
+ cp = BSD__ultoa(ulval, cp, base,
+ flags & ALT, xdigs);
+ }
+ size = buf + BUF - cp;
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ /* pretend it was %c with argument ch */
+ cp = buf;
+ *cp = ch;
+ size = 1;
+ sign = '\0';
+ break;
+ }
+
+ /*
+ * All reasonable formats wind up here. At this point, `cp'
+ * points to a string which (if not flags&LADJUST) should be
+ * padded out to `width' places. If flags&ZEROPAD, it should
+ * first be prefixed by any sign or other prefix; otherwise,
+ * it should be blank padded before the prefix is emitted.
+ * After any left-hand padding and prefixing, emit zeroes
+ * required by a decimal [diouxX] precision, then print the
+ * string proper, then emit zeroes required by any leftover
+ * floating precision; finally, if LADJUST, pad with blanks.
+ *
+ * Compute actual size, so we know how much to pad.
+ * fieldsz excludes decimal prec; realsz includes it.
+ */
+ fieldsz = size;
+ if (sign)
+ fieldsz++;
+ else if (flags & HEXPREFIX)
+ fieldsz += 2;
+ realsz = dprec > fieldsz ? dprec : fieldsz;
+
+ /* right-adjusting blank padding */
+ if ((flags & (LADJUST|ZEROPAD)) == 0)
+ PAD(width - realsz, blanks);
+
+ /* prefix */
+ if (sign) {
+ PRINT(&sign, 1);
+ } else if (flags & HEXPREFIX) {
+ ox[0] = '0';
+ ox[1] = ch;
+ PRINT(ox, 2);
+ }
+
+ /* right-adjusting zero padding */
+ if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
+ PAD(width - realsz, zeroes);
+
+ /* leading zeroes from decimal precision */
+ PAD(dprec - fieldsz, zeroes);
+
+ /* the string or number proper */
+#ifdef FLOATING_POINT
+ if ((flags & FPT) == 0) {
+ PRINT(cp, size);
+ } else { /* glue together f_p fragments */
+ if (ch >= 'f') { /* 'f' or 'g' */
+ if (_double == 0) {
+ /* kludge for __dtoa irregularity */
+ if (prec == 0 ||
+ (flags & ALT) == 0) {
+ PRINT("0", 1);
+ } else {
+ PRINT("0.", 2);
+ PAD(ndig - 1, zeroes);
+ }
+ } else if (expt <= 0) {
+ PRINT("0.", 2);
+ PAD(-expt, zeroes);
+ PRINT(cp, ndig);
+ } else if (expt >= ndig) {
+ PRINT(cp, ndig);
+ PAD(expt - ndig, zeroes);
+ if (flags & ALT)
+ PRINT(".", 1);
+ } else {
+ PRINT(cp, expt);
+ cp += expt;
+ PRINT(".", 1);
+ PRINT(cp, ndig-expt);
+ }
+ } else { /* 'e' or 'E' */
+ if (ndig > 1 || flags & ALT) {
+ ox[0] = *cp++;
+ ox[1] = '.';
+ PRINT(ox, 2);
+ if (_double || flags & ALT == 0) {
+ PRINT(cp, ndig-1);
+ } else /* 0.[0..] */
+ /* __dtoa irregularity */
+ PAD(ndig - 1, zeroes);
+ } else /* XeYYY */
+ PRINT(cp, 1);
+ PRINT(expstr, expsize);
+ }
+ }
+#else
+ PRINT(cp, size);
+#endif
+ /* left-adjusting padding (always blank) */
+ if (flags & LADJUST)
+ PAD(width - realsz, blanks);
+
+ /* finally, adjust ret */
+ ret += width > realsz ? width : realsz;
+
+ FLUSH(); /* copy out the I/O vectors */
+ }
+done:
+ FLUSH();
+error:
+ return (__sferror(fp) ? EOF : ret);
+ /* NOTREACHED */
+}
+
+#ifdef FLOATING_POINT
+
+extern char *BSD__dtoa __P((double, int, int, int *, int *, char **));
+
+static char *
+cvt(value, ndigits, flags, sign, decpt, ch, length)
+ double value;
+ int ndigits, flags, *decpt, ch, *length;
+ char *sign;
+{
+ int mode, dsgn;
+ char *digits, *bp, *rve;
+
+ if (ch == 'f')
+ mode = 3;
+ else {
+ mode = 2;
+ }
+ if (value < 0) {
+ value = -value;
+ *sign = '-';
+ } else
+ *sign = '\000';
+ digits = BSD__dtoa(value, mode, ndigits, decpt, &dsgn, &rve);
+ if (flags & ALT) { /* Print trailing zeros */
+ bp = digits + ndigits;
+ if (ch == 'f') {
+ if (*digits == '0' && value)
+ *decpt = -ndigits + 1;
+ bp += *decpt;
+ }
+ if (value == 0) /* kludge for __dtoa irregularity */
+ rve = bp;
+ while (rve < bp)
+ *rve++ = '0';
+ }
+ *length = rve - digits;
+ return (digits);
+}
+
+static int
+exponent(p0, exp, fmtch)
+ char *p0;
+ int exp, fmtch;
+{
+ register char *p, *t;
+ char expbuf[MAXEXP];
+
+ p = p0;
+ *p++ = fmtch;
+ if (exp < 0) {
+ exp = -exp;
+ *p++ = '-';
+ }
+ else
+ *p++ = '+';
+ t = expbuf + MAXEXP;
+ if (exp > 9) {
+ do {
+ *--t = to_char(exp % 10);
+ } while ((exp /= 10) > 9);
+ *--t = to_char(exp);
+ for (; t < expbuf + MAXEXP; *p++ = *t++);
+ }
+ else {
+ *p++ = '0';
+ *p++ = to_char(exp);
+ }
+ return (p - p0);
+}
+#endif /* FLOATING_POINT */
+
+int
+vsnprintf(str, n, fmt, ap)
+ char *str;
+ size_t n;
+ const char *fmt;
+ _BSD_VA_LIST_ ap;
+{
+ int ret;
+ FILE f;
+
+ if ((int)n < 1)
+ return (EOF);
+ f._flags = __SWR | __SSTR;
+ f._bf._base = f._p = (unsigned char *)str;
+ f._bf._size = f._w = n - 1;
+ ret = BSD_vfprintf(&f, fmt, ap);
+ *f._p = 0;
+ return (ret);
+}
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)snprintf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stddef.h>
+
+#if defined(__STDC__)
+# include <stdarg.h>
+#else
+# include <varargs.h>
+#endif
+
+int
+#if defined(__STDC__)
+snprintf(char *str, size_t n, char const *fmt, ...)
+#else
+snprintf(str, n, fmt, va_alist)
+char *str, *fmt;
+size_t n;
+va_dcl
+#endif
+{
+ int ret;
+ va_list ap;
+ FILE f;
+
+ if ((int)n < 1)
+ return (EOF);
+
+#if defined(__STDC__)
+ va_start(ap, fmt);
+#else
+ va_start(ap);
+#endif
+ f._flags = __SWR | __SSTR;
+ f._bf._base = f._p = (unsigned char *)str;
+ f._bf._size = f._w = n - 1;
+ ret = BSD_vfprintf(&f, fmt, ap);
+ *f._p = 0;
+ va_end(ap);
+ return (ret);
+}
diff --git a/mkconfig.rb b/mkconfig.rb
index 903cddad3c..093d02344d 100644
--- a/mkconfig.rb
+++ b/mkconfig.rb
@@ -9,7 +9,7 @@ version = VERSION
config = open(rbconfig_rb, "w")
$stdout.reopen(config)
-fast = {'prefix'=>TRUE, 'INSTALL'=>TRUE, 'binsuffix'=>TRUE}
+fast = {'prefix'=>TRUE, 'INSTALL'=>TRUE, 'EXEEXT'=>TRUE}
print %[
module Config
@@ -23,6 +23,7 @@ module Config
print " CONFIG = {}\n"
v_fast = []
v_others = []
+has_version = false
File.foreach "config.status" do |$_|
next if /^#/
if /^s%@program_transform_name@%s,(.*)%g$/
@@ -33,7 +34,7 @@ File.foreach "config.status" do |$_|
val = $2 || ""
next if name =~ /^(INSTALL|DEFS|configure_input|srcdir|top_srcdir)$/
v = " CONFIG[\"" + name + "\"] = " +
- val.sub(/^\s*(.*)\s*$/, '"\1"').gsub(/\$[{(]?([^})]+)[})]?/) {
+ val.sub(/^\s*(.*)\s*$/, '"\1"').gsub(/\$\{?([^(){}]+)\}?/) {
"\#{CONFIG[\\\"#{$1}\\\"]}"
} + "\n"
if fast[name]
@@ -41,6 +42,7 @@ File.foreach "config.status" do |$_|
else
v_others << v
end
+ has_version = true if name == "MAJOR"
if /DEFS/
val.split(/\s*-D/).each do |i|
if i =~ /(.*)=(\\")?([^\\]*)(\\")?/
@@ -55,23 +57,36 @@ File.foreach "config.status" do |$_|
end
end
elsif /^ac_given_srcdir=(.*)/
- path = $1
- cwd = Dir.pwd
- begin
- Dir.chdir path
- v_fast << " CONFIG[\"srcdir\"] = \"" + Dir.pwd + "\"\n"
- ensure
- Dir.chdir cwd
- end
+ v_fast << " CONFIG[\"srcdir\"] = \"" + File.expand_path($1) + "\"\n"
elsif /^ac_given_INSTALL=(.*)/
v_fast << " CONFIG[\"INSTALL\"] = " + $1 + "\n"
end
# break if /^CEOF/
end
+if not has_version
+ VERSION.scan(/(\d+)\.(\d+)\.(\d+)/) {
+ print " CONFIG[\"MAJOR\"] = \"" + $1 + "\"\n"
+ print " CONFIG[\"MINOR\"] = \"" + $2 + "\"\n"
+ print " CONFIG[\"TEENY\"] = \"" + $3 + "\"\n"
+ }
+end
+
print v_fast, v_others
-Dir.chdir File.dirname($0)
-print " CONFIG[\"compile_dir\"] = \"#{Dir.pwd}\"\n"
-print "end\n"
+print <<EOS
+ CONFIG["compile_dir"] = "#{Dir.pwd}"
+ CONFIG.each_value do |val|
+ val.gsub!(/\\$\\(([^()]+)\\)/) do |var|
+ key = $1
+ if CONFIG.key? key
+ "\#{CONFIG[\\\"\#{key}\\\"]}"
+ else
+ var
+ end
+ end
+ end
+end
+EOS
config.close
+
# vi:set sw=2:
diff --git a/node.h b/node.h
index c1923fba75..4add37b47c 100644
--- a/node.h
+++ b/node.h
@@ -6,7 +6,7 @@
$Date$
created at: Fri May 28 15:14:02 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -144,7 +144,7 @@ typedef struct RNode {
RNODE(n)->flags=((RNODE(n)->flags&~FL_UMASK)|(((t)<<FL_USHIFT)&FL_UMASK))
#define NODE_LSHIFT (FL_USHIFT+8)
-#define NODE_LMASK ((1<<(sizeof(NODE*)*CHAR_BIT-NODE_LSHIFT))-1)
+#define NODE_LMASK (((long)1<<(sizeof(NODE*)*CHAR_BIT-NODE_LSHIFT))-1)
#define nd_line(n) (((RNODE(n))->flags>>NODE_LSHIFT)&NODE_LMASK)
#define nd_set_line(n,l) \
RNODE(n)->flags=((RNODE(n)->flags&~(-1<<NODE_LSHIFT))|(((l)&NODE_LMASK)<<NODE_LSHIFT))
@@ -225,17 +225,9 @@ typedef struct RNode {
#define NEW_RFUNC(b1,b2) NEW_SCOPE(block_append(b1,b2))
#define NEW_SCOPE(b) rb_node_newnode(NODE_SCOPE,local_tbl(),cur_cref,(b))
#define NEW_BLOCK(a) rb_node_newnode(NODE_BLOCK,a,0,0)
-#ifdef NOBLOCK_RECUR
-#define NEW_IF(c,t,e) block_append(c,rb_node_newnode(NODE_IF,0,t,e))
-#else
#define NEW_IF(c,t,e) rb_node_newnode(NODE_IF,c,t,e)
-#endif
#define NEW_UNLESS(c,t,e) NEW_IF(c,e,t)
-#ifdef NOBLOCK_RECUR
-#define NEW_CASE(h,b) block_append(h,rb_node_newnode(NODE_CASE,0,b,0))
-#else
#define NEW_CASE(h,b) rb_node_newnode(NODE_CASE,h,b,0)
-#endif
#define NEW_WHEN(c,t,e) rb_node_newnode(NODE_WHEN,c,t,e)
#define NEW_OPT_N(b) rb_node_newnode(NODE_OPT_N,0,b,0)
#define NEW_WHILE(c,b,n) rb_node_newnode(NODE_WHILE,c,b,n)
@@ -285,11 +277,7 @@ typedef struct RNode {
#define NEW_XSTR(s) rb_node_newnode(NODE_XSTR,s,0,0)
#define NEW_DXSTR(s) rb_node_newnode(NODE_DXSTR,s,0,0)
#define NEW_EVSTR(s,l) rb_node_newnode(NODE_EVSTR,rb_str_new(s,l),0,0)
-#ifdef NOBLOCK_RECUR_incomplete
-#define NEW_CALL(r,m,a) block_append(r,rb_node_newnode(NODE_CALL,0,m,a))
-#else
#define NEW_CALL(r,m,a) rb_node_newnode(NODE_CALL,r,m,a)
-#endif
#define NEW_FCALL(m,a) rb_node_newnode(NODE_FCALL,0,m,a)
#define NEW_VCALL(m) rb_node_newnode(NODE_VCALL,0,m,0)
#define NEW_SUPER(a) rb_node_newnode(NODE_SUPER,0,0,a)
@@ -331,9 +319,9 @@ VALUE rb_method_booundp();
#define NOEX_PRIVATE 2
#define NOEX_PROTECTED 4
-NODE *rb_compile_cstr _((char *, char *, int));
-NODE *rb_compile_string _((char *, VALUE));
-NODE *rb_compile_file _((char *, VALUE, int));
+NODE *rb_compile_cstr _((const char*, const char*, int, int));
+NODE *rb_compile_string _((const char*, VALUE, int));
+NODE *rb_compile_file _((const char*, VALUE, int));
void rb_add_method _((VALUE, ID, NODE *, int));
NODE *rb_node_newnode();
diff --git a/numeric.c b/numeric.c
index e8ea6075a9..568d6c0ea1 100644
--- a/numeric.c
+++ b/numeric.c
@@ -6,13 +6,16 @@
$Date$
created at: Fri Aug 13 18:33:09 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include <math.h>
#include <stdio.h>
+#ifdef __FreeBSD__
+#include <floatingpoint.h>
+#endif
static ID coerce;
static ID to_i;
@@ -22,7 +25,8 @@ VALUE rb_cFloat;
VALUE rb_cInteger;
VALUE rb_cFixnum;
-VALUE rb_eZeroDiv;
+VALUE rb_eZeroDivError;
+VALUE rb_eFloatDomainError;
ID rb_frame_last_func();
VALUE rb_float_new();
@@ -31,7 +35,7 @@ double rb_big2dbl();
void
rb_num_zerodiv()
{
- rb_raise(rb_eZeroDiv, "divided by 0");
+ rb_raise(rb_eZeroDivError, "divided by 0");
}
static VALUE
@@ -163,7 +167,7 @@ num_nonzero_p(num)
VALUE num;
{
if (RTEST(rb_funcall(num, rb_intern("zero?"), 0, 0))) {
- return Qfalse;
+ return Qnil;
}
return num;
}
@@ -183,10 +187,19 @@ static VALUE
flo_to_s(flt)
VALUE flt;
{
- char buf[32];
-
- sprintf(buf, "%g", RFLOAT(flt)->value);
- if (strchr(buf, '.') == 0) {
+ char buf[24];
+ char *s;
+ double value = RFLOAT(flt)->value;
+
+ if (isinf(value))
+ return rb_str_new2(value < 0 ? "-Infinity" : "Infinity");
+ else if(isnan(value))
+ return rb_str_new2("NaN");
+ else
+ sprintf(buf, "%-.10g", value);
+ if (s = strchr(buf, ' ')) *s = '\0';
+ s = buf; if (s[0] == '-') s++;
+ if (strchr(s, '.') == 0) {
int len = strlen(buf);
char *ind = strchr(buf, 'e');
@@ -274,14 +287,11 @@ flo_div(x, y)
switch (TYPE(y)) {
case T_FIXNUM:
f_y = FIX2LONG(y);
- if (f_y == 0) rb_num_zerodiv();
return rb_float_new(RFLOAT(x)->value / (double)f_y);
case T_BIGNUM:
d = rb_big2dbl(y);
- if (d == 0.0) rb_num_zerodiv();
return rb_float_new(RFLOAT(x)->value / d);
case T_FLOAT:
- if (RFLOAT(y)->value == 0.0) rb_num_zerodiv();
return rb_float_new(RFLOAT(x)->value / RFLOAT(y)->value);
default:
return rb_num_coerce_bin(x, y);
@@ -433,7 +443,8 @@ flo_cmp(x, y)
}
if (a == b) return INT2FIX(0);
if (a > b) return INT2FIX(1);
- return INT2FIX(-1);
+ if (a < b) return INT2FIX(-1);
+ rb_raise(rb_eFloatDomainError, "comparing NaN");
}
static VALUE
@@ -666,8 +677,12 @@ rb_num2long(val)
return (long)(RFLOAT(val)->value);
}
else {
- rb_raise(rb_eTypeError, "float %g out of rang of integer",
- RFLOAT(val)->value);
+ char buf[24];
+ char *s;
+
+ sprintf(buf, "%-.10g", RFLOAT(val)->value);
+ if (s = strchr(buf, ' ')) *s = '\0';
+ rb_raise(rb_eTypeError, "float %s out of rang of integer", buf);
}
case T_BIGNUM:
@@ -677,6 +692,11 @@ rb_num2long(val)
rb_raise(rb_eTypeError, "no implicit conversion from string");
return Qnil; /* not reached */
+ case T_TRUE:
+ case T_FALSE:
+ rb_raise(rb_eTypeError, "no implicit conversion from boolean");
+ return Qnil; /* not reached */
+
default:
val = rb_rescue(to_integer, val, fail_to_integer, val);
if (!rb_obj_is_kind_of(val, rb_cInteger)) {
@@ -704,7 +724,7 @@ rb_num2int(val)
long num = rb_num2long(val);
if (num < INT_MIN || INT_MAX < num) {
- rb_raise(rb_eArgError, "integer %d too big to convert to `int'.", num);
+ rb_raise(rb_eArgError, "integer %d too big to convert to `int'", num);
}
return (int)num;
}
@@ -716,7 +736,7 @@ rb_fix2int(val)
long num = FIXNUM_P(val)?FIX2LONG(val):rb_num2long(val);
if (num < INT_MIN || INT_MAX < num) {
- rb_raise(rb_eArgError, "integer %d too big to convert to `int'.", num);
+ rb_raise(rb_eArgError, "integer %d too big to convert to `int'", num);
}
return (int)num;
}
@@ -778,6 +798,45 @@ int_chr(num)
}
static VALUE
+rb_fix_induced_from(klass, x)
+ VALUE klass, x;
+{
+ return rb_num2fix(x);
+}
+
+static VALUE
+rb_int_induced_from(klass, x)
+ VALUE klass, x;
+{
+ switch (TYPE(x)) {
+ case T_FIXNUM:
+ case T_BIGNUM:
+ return x;
+ case T_FLOAT:
+ return rb_funcall(x, rb_intern("to_i"), 0);
+ default:
+ rb_raise(rb_eTypeError, "failed to convert %s into Integer",
+ rb_class2name(CLASS_OF(x)));
+ }
+}
+
+static VALUE
+rb_flo_induced_from(klass, x)
+ VALUE klass, x;
+{
+ switch (TYPE(x)) {
+ case T_FIXNUM:
+ case T_BIGNUM:
+ return rb_funcall(x, rb_intern("to_f"), 0);
+ case T_FLOAT:
+ return x;
+ default:
+ rb_raise(rb_eTypeError, "failed to convert %s into Float",
+ rb_class2name(CLASS_OF(x)));
+ }
+}
+
+static VALUE
fix_uminus(num)
VALUE num;
{
@@ -797,7 +856,7 @@ rb_fix2str(x, base)
else if (base == 8) fmt[2] = 'o';
else rb_fatal("fixnum cannot treat base %d", base);
- sprintf(buf, fmt, FIX2LONG(x));
+ snprintf(buf, 22, fmt, FIX2LONG(x));
return rb_str_new2(buf);
}
@@ -892,7 +951,7 @@ fix_div(x, y)
i = FIX2LONG(y);
if (i == 0) rb_num_zerodiv();
i = FIX2LONG(x)/i;
- return INT2FIX(i);
+ return INT2NUM(i); /* FIXNUM_MIN / -1 > FIXNUM_MAX */
}
return rb_num_coerce_bin(x, y);
}
@@ -940,15 +999,13 @@ fix_pow(x, y)
b = FIX2LONG(y);
if (b == 0) return INT2FIX(1);
+ if (b == 1) return x;
a = FIX2LONG(x);
if (b > 0) {
return rb_big_pow(rb_int2big(a), y);
}
return rb_float_new(pow((double)a, (double)b));
}
- else if (NIL_P(y)) {
- return INT2FIX(1);
- }
return rb_num_coerce_bin(x, y);
}
@@ -1044,7 +1101,7 @@ static VALUE
fix_rev(num)
VALUE num;
{
- unsigned long val = FIX2ULONG(num);
+ long val = FIX2LONG(num);
val = ~val;
return rb_int2inum(val);
@@ -1309,20 +1366,23 @@ fix_step(from, to, step)
if (!FIXNUM_P(to) || !FIXNUM_P(step))
return int_step(from, to, step);
+ i = FIX2LONG(from);
end = FIX2LONG(to);
diff = FIX2LONG(step);
if (diff == 0) {
rb_raise(rb_eArgError, "step cannot be 0");
}
- else if (diff > 0) {
- for (i=FIX2LONG(from); i <= end; i+=diff) {
+ if (diff > 0) {
+ while (i <= end) {
rb_yield(INT2FIX(i));
+ i += diff;
}
}
else {
- for (i=FIX2LONG(from); i >= end; i+=diff) {
+ while (i >= end) {
rb_yield(INT2FIX(i));
+ i += diff;
}
}
return from;
@@ -1354,10 +1414,15 @@ fix_zero_p(num)
void
Init_Numeric()
{
+#ifdef __FreeBSD__
+ /* allow divide by zero -- Inf */
+ fpsetmask(fpgetmask() & ~(FP_X_DZ|FP_X_INV|FP_X_OFL));
+#endif
coerce = rb_intern("coerce");
to_i = rb_intern("to_i");
- rb_eZeroDiv = rb_define_class("ZeroDivisionError", rb_eStandardError);
+ rb_eZeroDivError = rb_define_class("ZeroDivisionError", rb_eStandardError);
+ rb_eFloatDomainError = rb_define_class("FloatDomainError", rb_eStandardError);
rb_cNumeric = rb_define_class("Numeric", rb_cObject);
rb_include_module(rb_cNumeric, rb_mComparable);
@@ -1380,11 +1445,15 @@ Init_Numeric()
rb_define_method(rb_cInteger, "downto", int_downto, 1);
rb_define_method(rb_cInteger, "step", int_step, 2);
rb_define_method(rb_cInteger, "times", int_dotimes, 0);
+ rb_include_module(rb_cInteger, rb_mPrecision);
rb_define_method(rb_cInteger, "succ", int_succ, 0);
rb_define_method(rb_cInteger, "next", int_succ, 0);
rb_define_method(rb_cInteger, "chr", int_chr, 0);
rb_cFixnum = rb_define_class("Fixnum", rb_cInteger);
+ rb_include_module(rb_cFixnum, rb_mPrecision);
+ rb_define_singleton_method(rb_cFixnum, "induced_from", rb_fix_induced_from, 1);
+ rb_define_singleton_method(rb_cInteger, "induced_from", rb_int_induced_from, 1);
rb_undef_method(CLASS_OF(rb_cFixnum), "new");
@@ -1437,6 +1506,9 @@ Init_Numeric()
rb_undef_method(CLASS_OF(rb_cFloat), "new");
+ rb_define_singleton_method(rb_cFloat, "induced_from", rb_flo_induced_from, 1);
+ rb_include_module(rb_cFloat, rb_mPrecision);
+
rb_define_method(rb_cFloat, "to_s", flo_to_s, 0);
rb_define_method(rb_cFloat, "coerce", flo_coerce, 1);
rb_define_method(rb_cFloat, "-@", flo_uminus, 0);
diff --git a/object.c b/object.c
index 15e757d054..9c5163a248 100644
--- a/object.c
+++ b/object.c
@@ -6,7 +6,7 @@
$Date$
created at: Thu Jul 15 12:01:24 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -47,7 +47,7 @@ int
rb_eql(obj1, obj2)
VALUE obj1, obj2;
{
- return rb_funcall(obj1, eql, 1, obj2);
+ return rb_funcall(obj1, eql, 1, obj2) == Qtrue;
}
static VALUE
@@ -130,7 +130,7 @@ rb_any_to_s(obj)
VALUE str;
s = ALLOCA_N(char, strlen(cname)+6+16+1); /* 6:tags 16:addr 1:eos */
- sprintf(s, "#<%s:0x%x>", cname, obj);
+ sprintf(s, "#<%s:0x%lx>", cname, obj);
str = rb_str_new2(s);
if (OBJ_TAINTED(obj)) OBJ_TAINT(str);
@@ -368,13 +368,6 @@ true_to_s(obj)
}
static VALUE
-true_to_i(obj)
- VALUE obj;
-{
- return INT2FIX(1);
-}
-
-static VALUE
true_type(obj)
VALUE obj;
{
@@ -410,13 +403,6 @@ false_to_s(obj)
}
static VALUE
-false_to_i(obj)
- VALUE obj;
-{
- return INT2FIX(0);
-}
-
-static VALUE
false_type(obj)
VALUE obj;
{
@@ -474,13 +460,17 @@ rb_mod_clone(module)
VALUE module;
{
NEWOBJ(clone, struct RClass);
- OBJSETUP(clone, CLASS_OF(module), TYPE(module));
+ CLONESETUP(clone, module);
clone->super = RCLASS(module)->super;
clone->iv_tbl = 0;
clone->m_tbl = 0; /* avoid GC crashing */
- clone->iv_tbl = st_copy(RCLASS(module)->iv_tbl);
- clone->m_tbl = st_copy(RCLASS(module)->m_tbl);
+ if (RCLASS(module)->iv_tbl) {
+ clone->iv_tbl = st_copy(RCLASS(module)->iv_tbl);
+ }
+ if (RCLASS(module)->m_tbl) {
+ clone->m_tbl = st_copy(RCLASS(module)->m_tbl);
+ }
return (VALUE)clone;
}
@@ -540,7 +530,7 @@ rb_mod_ge(mod, arg)
rb_raise(rb_eTypeError, "compared with non class/module");
}
- return rb_mod_lt(arg, mod);
+ return rb_mod_le(arg, mod);
}
static VALUE
@@ -579,12 +569,9 @@ rb_module_s_new(klass)
VALUE mod = rb_module_new();
RBASIC(mod)->klass = klass;
- rb_obj_call_init(mod);
return mod;
}
-VALUE rb_class_new_instance();
-
static VALUE
rb_class_s_new(argc, argv)
int argc;
@@ -603,7 +590,6 @@ rb_class_s_new(argc, argv)
/* make metaclass */
RBASIC(klass)->klass = rb_singleton_class_new(RBASIC(super)->klass);
rb_singleton_class_attached(RBASIC(klass)->klass, klass);
- rb_obj_call_init(klass);
return klass;
}
@@ -754,46 +740,9 @@ rb_obj_private_methods(obj)
return rb_class_private_instance_methods(1, argv, CLASS_OF(obj));
}
-VALUE
-rb_Integer(val)
- VALUE val;
-{
- long i;
-
- switch (TYPE(val)) {
- case T_FLOAT:
- if (RFLOAT(val)->value <= (double)FIXNUM_MAX
- && RFLOAT(val)->value >= (double)FIXNUM_MIN) {
- i = (long)RFLOAT(val)->value;
- break;
- }
- return rb_dbl2big(RFLOAT(val)->value);
-
- case T_BIGNUM:
- return val;
-
- case T_STRING:
- return rb_str2inum(RSTRING(val)->ptr, 0);
-
- case T_NIL:
- return INT2FIX(0);
-
- default:
- i = NUM2LONG(val);
- }
- return INT2NUM(i);
-}
-
-static VALUE
-rb_f_integer(obj, arg)
- VALUE obj, arg;
-{
- return rb_Integer(arg);
-}
-
struct arg_to {
VALUE val;
- char *s;
+ const char *s;
};
static VALUE
@@ -819,7 +768,7 @@ VALUE
rb_convert_type(val, type, tname, method)
VALUE val;
int type;
- char *tname, *method;
+ const char *tname, *method;
{
struct arg_to arg1, arg2;
@@ -832,6 +781,50 @@ rb_convert_type(val, type, tname, method)
return val;
}
+VALUE
+rb_Integer(val)
+ VALUE val;
+{
+ struct arg_to arg1, arg2;
+
+ switch (TYPE(val)) {
+ case T_FLOAT:
+ if (RFLOAT(val)->value <= (double)FIXNUM_MAX
+ && RFLOAT(val)->value >= (double)FIXNUM_MIN) {
+ break;
+ }
+ return rb_dbl2big(RFLOAT(val)->value);
+
+ case T_BIGNUM:
+ return val;
+
+ case T_STRING:
+ return rb_str2inum(RSTRING(val)->ptr, 0);
+
+ case T_NIL:
+ return INT2FIX(0);
+
+ default:
+ break;
+ }
+
+ arg1.val = arg2.val = val;
+ arg1.s = "to_i";
+ arg2.s = "Integer";
+ val = rb_rescue(to_type, (VALUE)&arg1, fail_to_type, (VALUE)&arg2);
+ if (!rb_obj_is_kind_of(val, rb_cInteger)) {
+ rb_raise(rb_eTypeError, "to_i should return Integer");
+ }
+ return val;
+}
+
+static VALUE
+rb_f_integer(obj, arg)
+ VALUE obj, arg;
+{
+ return rb_Integer(arg);
+}
+
double rb_big2dbl _((VALUE));
VALUE
@@ -848,6 +841,9 @@ rb_Float(val)
case T_BIGNUM:
return rb_float_new(rb_big2dbl(val));
+ case T_NIL:
+ return rb_float_new(0.0);
+
default:
return rb_convert_type(val, T_FLOAT, "Float", "to_f");
}
@@ -864,8 +860,23 @@ double
rb_num2dbl(val)
VALUE val;
{
- VALUE v = rb_Float(val);
- return RFLOAT(v)->value;
+ switch (TYPE(val)) {
+ case T_FLOAT:
+ return RFLOAT(val)->value;
+
+ case T_STRING:
+ rb_raise(rb_eTypeError, "no implicit conversion from String");
+ break;
+
+ case T_NIL:
+ rb_raise(rb_eTypeError, "no implicit conversion from nil");
+ break;
+
+ default:
+ break;
+ }
+
+ return RFLOAT(rb_Float(val))->value;
}
char*
@@ -1010,6 +1021,8 @@ Init_Object()
rb_define_method(rb_mKernel, "kind_of?", rb_obj_is_kind_of, 1);
rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1);
+ rb_define_global_function("singleton_method_added", rb_obj_dummy, 1);
+
rb_define_global_function("sprintf", rb_f_sprintf, -1);
rb_define_global_function("format", rb_f_sprintf, -1);
@@ -1025,18 +1038,14 @@ Init_Object()
rb_define_method(rb_cNilClass, "to_s", nil_to_s, 0);
rb_define_method(rb_cNilClass, "to_a", nil_to_a, 0);
rb_define_method(rb_cNilClass, "inspect", nil_inspect, 0);
+ rb_define_method(rb_cNilClass, "&", false_and, 1);
+ rb_define_method(rb_cNilClass, "|", false_or, 1);
+ rb_define_method(rb_cNilClass, "^", false_xor, 1);
rb_define_method(rb_cNilClass, "nil?", rb_true, 0);
rb_undef_method(CLASS_OF(rb_cNilClass), "new");
rb_define_global_const("NIL", Qnil);
- /* default addition */
-#ifdef NIL_PLUS
- rb_define_method(rb_cNilClass, "+", nil_plus, 1);
-#endif
-
- rb_define_global_function("singleton_method_added", rb_obj_dummy, 1);
-
rb_define_method(rb_cModule, "===", rb_mod_eqq, 1);
rb_define_method(rb_cModule, "<=>", rb_mod_cmp, 1);
rb_define_method(rb_cModule, "<", rb_mod_lt, 1);
@@ -1083,7 +1092,6 @@ Init_Object()
rb_cTrueClass = rb_define_class("TrueClass", rb_cObject);
rb_define_method(rb_cTrueClass, "to_s", true_to_s, 0);
- rb_define_method(rb_cTrueClass, "to_i", true_to_i, 0);
rb_define_method(rb_cTrueClass, "type", true_type, 0);
rb_define_method(rb_cTrueClass, "&", true_and, 1);
rb_define_method(rb_cTrueClass, "|", true_or, 1);
@@ -1093,7 +1101,6 @@ Init_Object()
rb_cFalseClass = rb_define_class("FalseClass", rb_cObject);
rb_define_method(rb_cFalseClass, "to_s", false_to_s, 0);
- rb_define_method(rb_cFalseClass, "to_i", false_to_i, 0);
rb_define_method(rb_cFalseClass, "type", false_type, 0);
rb_define_method(rb_cFalseClass, "&", false_and, 1);
rb_define_method(rb_cFalseClass, "|", false_or, 1);
diff --git a/pack.c b/pack.c
index dc393b83fe..38e970cad1 100644
--- a/pack.c
+++ b/pack.c
@@ -6,7 +6,7 @@
$Date$
created at: Thu Feb 10 15:17:05 JST 1994
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -14,11 +14,141 @@
#include <sys/types.h>
#include <ctype.h>
+#define SIZE16 2
+#define SIZE32 4
+
+#if SIZEOF_SHORT != 2 || SIZEOF_LONG != 4
+# define NATINT_PACK
+#endif
+
+#ifdef NATINT_PACK
+# define NATINT_LEN(type,len) (natint?sizeof(type):(len))
+#else
+# define NATINT_LEN(type,len) sizeof(type)
+#endif
+
+#define define_swapx(x, xtype) \
+static xtype \
+TOKEN_PASTE(swap,x)(z) \
+ xtype z; \
+{ \
+ xtype r; \
+ xtype *zp; \
+ unsigned char *s, *t; \
+ int i; \
+ \
+ zp = (xtype *)malloc(sizeof(xtype));\
+ *zp = z; \
+ s = (char *)zp; \
+ t = (char *)malloc(sizeof(xtype)); \
+ for (i=0; i<sizeof(xtype); i++) { \
+ t[sizeof(xtype)-i-1] = s[i]; \
+ } \
+ r = *(xtype *)t; \
+ free(t); \
+ free(zp); \
+ return r; \
+}
+
+#if SIZEOF_SHORT == 2
#define swaps(x) ((((x)&0xFF)<<8) + (((x)>>8)&0xFF))
+#else
+#if SIZEOF_SHORT == 4
+#define swaps(x) ((((x)&0xFF)<<24) \
+ +(((x)>>24)&0xFF) \
+ +(((x)&0x0000FF00)<<8) \
+ +(((x)&0x00FF0000)>>8) )
+#else
+define_swapx(s,short);
+#endif
+#endif
+
+#if SIZEOF_LONG == 4
#define swapl(x) ((((x)&0xFF)<<24) \
+(((x)>>24)&0xFF) \
+(((x)&0x0000FF00)<<8) \
+(((x)&0x00FF0000)>>8) )
+#else
+#if SIZEOF_LONG == 8
+#define swapl(x) ((((x)&0x00000000000000FF)<<56) \
+ +(((x)&0xFF00000000000000)>>56) \
+ +(((x)&0x000000000000FF00)<<40) \
+ +(((x)&0x00FF000000000000)>>40) \
+ +(((x)&0x0000000000FF0000)<<24) \
+ +(((x)&0x0000FF0000000000)>>24) \
+ +(((x)&0x00000000FF000000)<<8) \
+ +(((x)&0x000000FF00000000)>>8))
+#else
+define_swapx(l,long);
+#endif
+#endif
+
+#if SIZEOF_FLOAT == 4
+#if SIZEOF_LONG == 4 /* SIZEOF_FLOAT == 4 == SIZEOF_LONG */
+#define swapf(x) swapl(x)
+#define FLOAT_SWAPPER unsigned long
+#else
+#if SIZEOF_SHORT == 4 /* SIZEOF_FLOAT == 4 == SIZEOF_SHORT */
+#define swapf(x) swaps(x)
+#define FLOAT_SWAPPER unsigned short
+#else /* SIZEOF_FLOAT == 4 but undivide by known size of int */
+define_swapx(f,float);
+#endif /* #if SIZEOF_SHORT == 4 */
+#endif /* #if SIZEOF_LONG == 4 */
+#else /* SIZEOF_FLOAT != 4 */
+define_swapx(f,float);
+#endif /* #if SIZEOF_FLOAT == 4 */
+
+#if SIZEOF_DOUBLE == 8
+#if SIZEOF_LONG == 8 /* SIZEOF_DOUBLE == 8 == SIZEOF_LONG */
+#define swapd(x) swapl(x)
+#define DOUBLE_SWAPPER unsigned long
+#else
+#if SIZEOF_LONG == 4 /* SIZEOF_DOUBLE == 8 && 4 == SIZEOF_LONG */
+static double
+swapd(d)
+ const double d;
+{
+ double dtmp = d;
+ unsigned long utmp[2];
+ unsigned long utmp0;
+
+ utmp[0] = 0; utmp[1] = 0;
+ memcpy(utmp,&dtmp,sizeof(double));
+ utmp0 = utmp[0];
+ utmp[0] = swapl(utmp[1]);
+ utmp[1] = swapl(utmp0);
+ memcpy(&dtmp,utmp,sizeof(double));
+ return dtmp;
+}
+#else
+#if SIZEOF_SHORT == 4 /* SIZEOF_DOUBLE == 8 && 4 == SIZEOF_SHORT */
+static double
+swapd(d)
+ const double d;
+{
+ double dtmp = d;
+ unsigned short utmp[2];
+ unsigned short utmp0;
+
+ utmp[0] = 0; utmp[1] = 0;
+ memcpy(utmp,&dtmp,sizeof(double));
+ utmp0 = utmp[0];
+ utmp[0] = swaps(utmp[1]);
+ utmp[1] = swaps(utmp0);
+ memcpy(&dtmp,utmp,sizeof(double));
+ return dtmp;
+}
+#else /* SIZEOF_DOUBLE == 8 but undivied by known size of int */
+define_swapx(d, double);
+#endif /* #if SIZEOF_SHORT == 4 */
+#endif /* #if SIZEOF_LONG == 4 */
+#endif /* #if SIZEOF_LONG == 8 */
+#else /* SIZEOF_DOUBLE != 8 */
+define_swapx(d, double);
+#endif /* #if SIZEOF_DPOUBLE == 8 */
+
+#undef define_swapx
#ifdef DYNAMIC_ENDIAN
#ifdef ntohs
@@ -42,12 +172,20 @@ endian()
#define ntohs(x) (endian()?(x):swaps(x))
#define ntohl(x) (endian()?(x):swapl(x))
+#define ntohf(x) (endian()?(x):swapf(x))
+#define ntohd(x) (endian()?(x):swapd(x))
#define htons(x) (endian()?(x):swaps(x))
#define htonl(x) (endian()?(x):swapl(x))
+#define htonf(x) (endian()?(x):swapf(x))
+#define htond(x) (endian()?(x):swapd(x))
#define htovs(x) (endian()?swaps(x):(x))
#define htovl(x) (endian()?swapl(x):(x))
+#define htovf(x) (endian()?swapf(x):(x))
+#define htovd(x) (endian()?swapd(x):(x))
#define vtohs(x) (endian()?swaps(x):(x))
#define vtohl(x) (endian()?swapl(x):(x))
+#define vtohf(x) (endian()?swapf(x):(x))
+#define vtohd(x) (endian()?swapd(x):(x))
#else
#ifdef WORDS_BIGENDIAN
#ifndef ntohs
@@ -56,22 +194,94 @@ endian()
#define htons(x) (x)
#define htonl(x) (x)
#endif
+#define ntohf(x) (x)
+#define ntohd(x) (x)
+#define htonf(x) (x)
+#define htond(x) (x)
#define htovs(x) swaps(x)
#define htovl(x) swapl(x)
+#define htovf(x) swapf(x)
+#define htovd(x) swapd(x)
#define vtohs(x) swaps(x)
#define vtohl(x) swapl(x)
+#define vtohf(x) swapf(x)
+#define vtohd(x) swapd(x)
#else /* LITTLE ENDIAN */
#ifndef ntohs
+#undef ntohs
+#undef ntohl
+#undef htons
+#undef htonl
#define ntohs(x) swaps(x)
#define ntohl(x) swapl(x)
#define htons(x) swaps(x)
#define htonl(x) swapl(x)
#endif
+#define ntohf(x) swapf(x)
+#define ntohd(x) swapd(x)
+#define htonf(x) swapf(x)
+#define htond(x) swapd(x)
#define htovs(x) (x)
#define htovl(x) (x)
+#define htovf(x) (x)
+#define htovd(x) (x)
#define vtohs(x) (x)
#define vtohl(x) (x)
+#define vtohf(x) (x)
+#define vtohd(x) (x)
+#endif
#endif
+
+#ifdef FLOAT_SWAPPER
+#define FLOAT_CONVWITH(y) FLOAT_SWAPPER y;
+#define HTONF(x,y) (memcpy(&y,&x,sizeof(float)), \
+ y = htonf((FLOAT_SWAPPER)y), \
+ memcpy(&x,&y,sizeof(float)), \
+ x)
+#define HTOVF(x,y) (memcpy(&y,&x,sizeof(float)), \
+ y = htovf((FLOAT_SWAPPER)y), \
+ memcpy(&x,&y,sizeof(float)), \
+ x)
+#define NTOHF(x,y) (memcpy(&y,&x,sizeof(float)), \
+ y = ntohf((FLOAT_SWAPPER)y), \
+ memcpy(&x,&y,sizeof(float)), \
+ x)
+#define VTOHF(x,y) (memcpy(&y,&x,sizeof(float)), \
+ y = vtohf((FLOAT_SWAPPER)y), \
+ memcpy(&x,&y,sizeof(float)), \
+ x)
+#else
+#define FLOAT_CONVWITH(y)
+#define HTONF(x,y) htonf(x)
+#define HTOVF(x,y) htovf(x)
+#define NTOHF(x,y) ntohf(x)
+#define VTOHF(x,y) vtohf(x)
+#endif
+
+#ifdef DOUBLE_SWAPPER
+#define DOUBLE_CONVWITH(y) DOUBLE_SWAPPER y;
+#define HTOND(x,y) (memcpy(&y,&x,sizeof(double)), \
+ y = htond((DOUBLE_SWAPPER)y), \
+ memcpy(&x,&y,sizeof(double)), \
+ x)
+#define HTOVD(x,y) (memcpy(&y,&x,sizeof(double)), \
+ y = htovd((DOUBLE_SWAPPER)y), \
+ memcpy(&x,&y,sizeof(double)), \
+ x)
+#define NTOHD(x,y) (memcpy(&y,&x,sizeof(double)), \
+ y = ntohd((DOUBLE_SWAPPER)y), \
+ memcpy(&x,&y,sizeof(double)), \
+ x)
+#define VTOHD(x,y) (memcpy(&y,&x,sizeof(double)), \
+ y = vtohd((DOUBLE_SWAPPER)y), \
+ memcpy(&x,&y,sizeof(double)), \
+ x)
+#else
+#define DOUBLE_CONVWITH(y)
+#define HTOND(x,y) htond(x)
+#define HTOVD(x,y) htovd(x)
+#define NTOHD(x,y) ntohd(x)
+#define VTOHD(x,y) vtohd(x)
#endif
static char *toofew = "too few arguments";
@@ -79,6 +289,9 @@ static char *toofew = "too few arguments";
static void encodes _((VALUE,char*,int,int));
static void qpencode _((VALUE,VALUE,int));
+static int uv_to_utf8 _((char*,unsigned long));
+static unsigned long utf8_to_uv _((char*,int*));
+
static void
pack_add_ptr(str, add)
VALUE str, add;
@@ -103,9 +316,11 @@ pack_pack(ary, fmt)
int items, len, idx;
char *ptr;
int plen;
-
+#ifdef NATINT_PACK
+ int natint; /* native integer */
+#endif
- p = rb_str2cstr(fmt, &plen);
+ p = str2cstr(fmt, &plen);
pend = p + plen;
res = rb_str_new(0, 0);
@@ -116,7 +331,24 @@ pack_pack(ary, fmt)
while (p < pend) {
type = *p++; /* get data type */
+#ifdef NATINT_PACK
+ natint = 0;
+#endif
+
+ if (ISSPACE(type)) continue;
+ if (*p == '_') {
+ char *natstr = "sSiIlL";
+ if (strchr(natstr, type)) {
+#ifdef NATINT_PACK
+ natint = 1;
+#endif
+ p++;
+ }
+ else {
+ rb_raise(rb_eArgError, "'_' allowed only after types %s", natstr);
+ }
+ }
if (*p == '*') { /* set data length */
len = strchr("@Xxu", type) ? 0 : items;
p++;
@@ -129,7 +361,7 @@ pack_pack(ary, fmt)
}
switch (type) {
- case 'A': case 'a':
+ case 'A': case 'a': case 'Z':
case 'B': case 'b':
case 'H': case 'h':
from = NEXTFROM;
@@ -138,9 +370,7 @@ pack_pack(ary, fmt)
plen = 0;
}
else {
- from = rb_obj_as_string(from);
- ptr = RSTRING(from)->ptr;
- plen = RSTRING(from)->len;
+ ptr = str2cstr(from, &plen);
}
if (p[-1] == '*')
@@ -149,6 +379,7 @@ pack_pack(ary, fmt)
switch (type) {
case 'a':
case 'A':
+ case 'Z':
if (plen >= len)
rb_str_cat(res, ptr, len);
else {
@@ -165,8 +396,12 @@ pack_pack(ary, fmt)
case 'b':
{
int byte = 0;
- int i;
+ int i, j = 0;
+ if (len > plen) {
+ j = (len - plen + 1)/2;
+ len = plen;
+ }
for (i=0; i++ < len; ptr++) {
if (*ptr & 1)
byte |= 128;
@@ -184,14 +419,21 @@ pack_pack(ary, fmt)
c = byte & 0xff;
rb_str_cat(res, &c, 1);
}
+ len = RSTRING(res)->len;
+ rb_str_resize(res, len+j);
+ MEMZERO(RSTRING(res)->ptr+len, char, j);
}
break;
case 'B':
{
int byte = 0;
- int i;
+ int i, j = 0;
+ if (len > plen) {
+ j = (len - plen + 1)/2;
+ len = plen;
+ }
for (i=0; i++ < len; ptr++) {
byte |= *ptr & 1;
if (i & 7)
@@ -208,60 +450,73 @@ pack_pack(ary, fmt)
c = byte & 0xff;
rb_str_cat(res, &c, 1);
}
+ len = RSTRING(res)->len;
+ rb_str_resize(res, len+j);
+ MEMZERO(RSTRING(res)->ptr+len, char, j);
}
break;
case 'h':
{
int byte = 0;
- int i;
+ int i, j = 0;
+ if (len > plen) {
+ j = (len - plen + 1)/2;
+ len = plen;
+ }
for (i=0; i++ < len; ptr++) {
- if (ISXDIGIT(*ptr)) {
- if (ISALPHA(*ptr))
- byte |= (((*ptr & 15) + 9) & 15) << 4;
- else
- byte |= (*ptr & 15) << 4;
- if (i & 1)
- byte >>= 4;
- else {
- char c = byte & 0xff;
- rb_str_cat(res, &c, 1);
- byte = 0;
- }
+ if (ISALPHA(*ptr))
+ byte |= (((*ptr & 15) + 9) & 15) << 4;
+ else
+ byte |= (*ptr & 15) << 4;
+ if (i & 1)
+ byte >>= 4;
+ else {
+ char c = byte & 0xff;
+ rb_str_cat(res, &c, 1);
+ byte = 0;
}
}
if (len & 1) {
char c = byte & 0xff;
rb_str_cat(res, &c, 1);
}
+ len = RSTRING(res)->len;
+ rb_str_resize(res, len+j);
+ MEMZERO(RSTRING(res)->ptr+len, char, j);
}
break;
case 'H':
{
int byte = 0;
- int i;
+ int i, j = 0;
+ if (len > plen) {
+ j = (len - plen + 1)/2;
+ len = plen;
+ }
for (i=0; i++ < len; ptr++) {
- if (ISXDIGIT(*ptr)) {
- if (ISALPHA(*ptr))
- byte |= ((*ptr & 15) + 9) & 15;
- else
- byte |= *ptr & 15;
- if (i & 1)
- byte <<= 4;
- else {
- char c = byte & 0xff;
- rb_str_cat(res, &c, 1);
- byte = 0;
- }
+ if (ISALPHA(*ptr))
+ byte |= ((*ptr & 15) + 9) & 15;
+ else
+ byte |= *ptr & 15;
+ if (i & 1)
+ byte <<= 4;
+ else {
+ char c = byte & 0xff;
+ rb_str_cat(res, &c, 1);
+ byte = 0;
}
}
if (len & 1) {
char c = byte & 0xff;
rb_str_cat(res, &c, 1);
}
+ len = RSTRING(res)->len;
+ rb_str_resize(res, len+j);
+ MEMZERO(RSTRING(res)->ptr+len, char, j);
}
break;
}
@@ -291,7 +546,7 @@ pack_pack(ary, fmt)
else {
s = NUM2INT(from);
}
- rb_str_cat(res, (char*)&s, sizeof(short));
+ rb_str_cat(res, (char*)&s, NATINT_LEN(short,2));
}
break;
@@ -319,7 +574,7 @@ pack_pack(ary, fmt)
else {
l = NUM2ULONG(from);
}
- rb_str_cat(res, (char*)&l, sizeof(long));
+ rb_str_cat(res, (char*)&l, NATINT_LEN(long,4));
}
break;
@@ -333,7 +588,7 @@ pack_pack(ary, fmt)
s = NUM2INT(from);
}
s = htons(s);
- rb_str_cat(res, (char*)&s, sizeof(short));
+ rb_str_cat(res, (char*)&s, NATINT_LEN(short,2));
}
break;
@@ -347,7 +602,7 @@ pack_pack(ary, fmt)
l = NUM2ULONG(from);
}
l = htonl(l);
- rb_str_cat(res, (char*)&l, sizeof(long));
+ rb_str_cat(res, (char*)&l, NATINT_LEN(long,4));
}
break;
@@ -361,7 +616,7 @@ pack_pack(ary, fmt)
s = NUM2INT(from);
}
s = htovs(s);
- rb_str_cat(res, (char*)&s, sizeof(short));
+ rb_str_cat(res, (char*)&s, NATINT_LEN(short,2));
}
break;
@@ -375,7 +630,7 @@ pack_pack(ary, fmt)
l = NUM2ULONG(from);
}
l = htovl(l);
- rb_str_cat(res, (char*)&l, sizeof(long));
+ rb_str_cat(res, (char*)&l, NATINT_LEN(long,4));
}
break;
@@ -390,7 +645,7 @@ pack_pack(ary, fmt)
f = RFLOAT(from)->value;
break;
case T_STRING:
- f = atof(RSTRING(from)->ptr);
+ f = strtod(RSTRING(from)->ptr, 0);
default:
f = (float)NUM2INT(from);
break;
@@ -399,6 +654,48 @@ pack_pack(ary, fmt)
}
break;
+ case 'e':
+ while (len-- > 0) {
+ float f;
+ FLOAT_CONVWITH(ftmp);
+
+ from = NEXTFROM;
+ switch (TYPE(from)) {
+ case T_FLOAT:
+ f = RFLOAT(from)->value;
+ break;
+ case T_STRING:
+ f = strtod(RSTRING(from)->ptr, 0);
+ default:
+ f = (float)NUM2INT(from);
+ break;
+ }
+ f = HTOVF(f,ftmp);
+ rb_str_cat(res, (char*)&f, sizeof(float));
+ }
+ break;
+
+ case 'E':
+ while (len-- > 0) {
+ double d;
+ DOUBLE_CONVWITH(dtmp);
+
+ from = NEXTFROM;
+ switch (TYPE(from)) {
+ case T_FLOAT:
+ d = RFLOAT(from)->value;
+ break;
+ case T_STRING:
+ d = strtod(RSTRING(from)->ptr, 0);
+ default:
+ d = (double)NUM2INT(from);
+ break;
+ }
+ d = HTOVD(d,dtmp);
+ rb_str_cat(res, (char*)&d, sizeof(double));
+ }
+ break;
+
case 'd':
case 'D':
while (len-- > 0) {
@@ -410,11 +707,53 @@ pack_pack(ary, fmt)
d = RFLOAT(from)->value;
break;
case T_STRING:
- d = atof(RSTRING(from)->ptr);
+ d = strtod(RSTRING(from)->ptr, 0);
+ default:
+ d = (double)NUM2INT(from);
+ break;
+ }
+ rb_str_cat(res, (char*)&d, sizeof(double));
+ }
+ break;
+
+ case 'g':
+ while (len-- > 0) {
+ float f;
+ FLOAT_CONVWITH(ftmp);
+
+ from = NEXTFROM;
+ switch (TYPE(from)) {
+ case T_FLOAT:
+ f = RFLOAT(from)->value;
+ break;
+ case T_STRING:
+ f = strtod(RSTRING(from)->ptr, 0);
+ default:
+ f = (float)NUM2INT(from);
+ break;
+ }
+ f = HTONF(f,ftmp);
+ rb_str_cat(res, (char*)&f, sizeof(float));
+ }
+ break;
+
+ case 'G':
+ while (len-- > 0) {
+ double d;
+ DOUBLE_CONVWITH(dtmp);
+
+ from = NEXTFROM;
+ switch (TYPE(from)) {
+ case T_FLOAT:
+ d = RFLOAT(from)->value;
+ break;
+ case T_STRING:
+ d = strtod(RSTRING(from)->ptr, 0);
default:
d = (double)NUM2INT(from);
break;
}
+ d = HTOND(d,dtmp);
rb_str_cat(res, (char*)&d, sizeof(double));
}
break;
@@ -447,11 +786,25 @@ pack_pack(ary, fmt)
rb_raise(rb_eArgError, "% may only be used in unpack");
break;
+ case 'U':
+ while (len-- > 0) {
+ unsigned long l;
+ char buf[8];
+ int le;
+
+ from = NEXTFROM;
+ if (NIL_P(from)) l = 0;
+ else {
+ l = NUM2ULONG(from);
+ }
+ le = uv_to_utf8(buf, l);
+ rb_str_cat(res, (char*)&buf, le);
+ }
+ break;
+
case 'u':
case 'm':
- from = rb_obj_as_string(NEXTFROM);
- ptr = RSTRING(from)->ptr;
- plen = RSTRING(from)->len;
+ ptr = str2cstr(NEXTFROM, &plen);
if (len <= 1)
len = 45;
@@ -558,7 +911,7 @@ qpencode(str, from, len)
{
char buff[1024];
int i = 0, n = 0, prev = EOF;
- unsigned char *s = RSTRING(from)->ptr;
+ unsigned char *s = (unsigned char*)RSTRING(from)->ptr;
unsigned char *send = s + RSTRING(from)->len;
while (s < send) {
@@ -629,6 +982,31 @@ hex2num(c)
}
}
+#ifdef NATINT_PACK
+#define PACK_LENGTH_ADJUST(type,sz) do { \
+ int t__len = NATINT_LEN(type,(sz)); \
+ tmp = 0; \
+ if (len > (send-s)/t__len) { \
+ if (!star) { \
+ tmp = len-(send-s)/t__len; \
+ } \
+ len = (send-s)/t__len; \
+ } \
+} while (0)
+#else
+#define PACK_LENGTH_ADJUST(type,sz) do { \
+ tmp = 0; \
+ if (len > (send-s)/sizeof(type)) { \
+ if (!star) { \
+ tmp = len - (send-s)/sizeof(type); \
+ } \
+ len = (send-s)/sizeof(type); \
+ } \
+} while (0)
+#endif
+
+#define PACK_ITEM_ADJUST() while (tmp--) rb_ary_push(ary, Qnil);
+
static VALUE
pack_unpack(str, fmt)
VALUE str, fmt;
@@ -638,17 +1016,40 @@ pack_unpack(str, fmt)
char *p, *pend;
VALUE ary;
char type;
- int len;
+ int len, tmp, star;
+#ifdef NATINT_PACK
+ int natint; /* native integer */
+#endif
- s = rb_str2cstr(str, &len);
+ s = str2cstr(str, &len);
send = s + len;
- p = rb_str2cstr(fmt, &len);
+ p = str2cstr(fmt, &len);
pend = p + len;
ary = rb_ary_new();
while (p < pend) {
+#ifdef NATINT_PACK
+ natint = 0;
+#endif
+ star = 0;
type = *p++;
- if (*p == '*') {
+ if (*p == '_') {
+ char *natstr = "sSiIlL";
+
+ if (strchr(natstr, type)) {
+#ifdef NATINT_PACK
+ natint = 1;
+#endif
+ p++;
+ }
+ else {
+ rb_raise(rb_eArgError, "'_' allowed only after types %s", natstr);
+ }
+ }
+ if (p >= pend)
+ len = 1;
+ else if (*p == '*') {
+ star = 1;
len = send - s;
p++;
}
@@ -672,8 +1073,22 @@ pack_unpack(str, fmt)
while (t >= s) {
if (*t != ' ' && *t != '\0') break;
- t--;
- len--;
+ t--; len--;
+ }
+ rb_ary_push(ary, rb_str_new(s, len));
+ s += end;
+ }
+ break;
+
+ case 'Z':
+ if (len > send - s) len = send - s;
+ {
+ int end = len;
+ char *t = s + len - 1;
+
+ while (t >= s) {
+ if (*t) break;
+ t--; len--;
}
rb_ary_push(ary, rb_str_new(s, len));
s += end;
@@ -686,6 +1101,7 @@ pack_unpack(str, fmt)
s += len;
break;
+
case 'b':
{
VALUE bitstr;
@@ -767,160 +1183,228 @@ pack_unpack(str, fmt)
break;
case 'c':
- if (len > send - s)
- len = send - s;
+ PACK_LENGTH_ADJUST(char,sizeof(char));
while (len-- > 0) {
int c = *s++;
if (c > (char)127) c-=256;
rb_ary_push(ary, INT2FIX(c));
}
+ PACK_ITEM_ADJUST();
break;
case 'C':
- if (len > send - s)
- len = send - s;
+ PACK_LENGTH_ADJUST(unsigned char,sizeof(unsigned char));
while (len-- > 0) {
unsigned char c = *s++;
rb_ary_push(ary, INT2FIX(c));
}
+ PACK_ITEM_ADJUST();
break;
case 's':
- if (len >= (send - s) / sizeof(short))
- len = (send - s) / sizeof(short);
+ PACK_LENGTH_ADJUST(short,2);
while (len-- > 0) {
short tmp;
- memcpy(&tmp, s, sizeof(short));
- s += sizeof(short);
+ memcpy(&tmp, s, NATINT_LEN(short,2));
+ s += NATINT_LEN(short,2);
rb_ary_push(ary, INT2FIX(tmp));
}
+ PACK_ITEM_ADJUST();
break;
case 'S':
- if (len >= (send - s) / sizeof(short))
- len = (send - s) / sizeof(short);
+ PACK_LENGTH_ADJUST(unsigned short,2);
while (len-- > 0) {
unsigned short tmp;
- memcpy(&tmp, s, sizeof(short));
- s += sizeof(short);
+ memcpy(&tmp, s, NATINT_LEN(unsigned short,2));
+ s += NATINT_LEN(unsigned short,2);
rb_ary_push(ary, INT2FIX(tmp));
}
+ PACK_ITEM_ADJUST();
break;
case 'i':
- if (len >= (send - s) / sizeof(int))
- len = (send - s) / sizeof(int);
+ PACK_LENGTH_ADJUST(int,sizeof(int));
while (len-- > 0) {
int tmp;
memcpy(&tmp, s, sizeof(int));
s += sizeof(int);
rb_ary_push(ary, rb_int2inum(tmp));
}
+ PACK_ITEM_ADJUST();
break;
case 'I':
- if (len >= (send - s) / sizeof(int))
- len = (send - s) / sizeof(int);
+ PACK_LENGTH_ADJUST(unsigned int,sizeof(unsigned int));
while (len-- > 0) {
unsigned int tmp;
- memcpy(&tmp, s, sizeof(int));
- s += sizeof(int);
+ memcpy(&tmp, s, sizeof(unsigned int));
+ s += sizeof(unsigned int);
rb_ary_push(ary, rb_uint2inum(tmp));
}
+ PACK_ITEM_ADJUST();
break;
case 'l':
- if (len >= (send - s) / sizeof(long))
- len = (send - s) / sizeof(long);
+ PACK_LENGTH_ADJUST(long,4);
while (len-- > 0) {
long tmp;
- memcpy(&tmp, s, sizeof(long));
- s += sizeof(long);
+ memcpy(&tmp, s, NATINT_LEN(long,4));
+ s += NATINT_LEN(long,4);
rb_ary_push(ary, rb_int2inum(tmp));
}
+ PACK_ITEM_ADJUST();
break;
case 'L':
- if (len >= (send - s) / sizeof(long))
- len = (send - s) / sizeof(long);
+ PACK_LENGTH_ADJUST(unsigned long,4);
while (len-- > 0) {
unsigned long tmp;
- memcpy(&tmp, s, sizeof(long));
- s += sizeof(long);
+ memcpy(&tmp, s, NATINT_LEN(unsigned long,4));
+ s += NATINT_LEN(unsigned long,4);
rb_ary_push(ary, rb_uint2inum(tmp));
}
+ PACK_ITEM_ADJUST();
break;
case 'n':
- if (len >= (send - s) / sizeof(short))
- len = (send - s) / sizeof(short);
+ PACK_LENGTH_ADJUST(unsigned short,2);
while (len-- > 0) {
unsigned short tmp;
- memcpy(&tmp, s, sizeof(short));
- s += sizeof(short);
+ memcpy(&tmp, s, NATINT_LEN(unsigned short,2));
+ s += NATINT_LEN(unsigned short,2);
tmp = ntohs(tmp);
rb_ary_push(ary, rb_uint2inum(tmp));
}
+ PACK_ITEM_ADJUST();
break;
case 'N':
- if (len >= (send - s) / sizeof(long))
- len = (send - s) / sizeof(long);
+ PACK_LENGTH_ADJUST(unsigned long,4);
while (len-- > 0) {
unsigned long tmp;
- memcpy(&tmp, s, sizeof(long));
- s += sizeof(long);
+ memcpy(&tmp, s, NATINT_LEN(unsigned long,4));
+ s += NATINT_LEN(unsigned long,4);
tmp = ntohl(tmp);
rb_ary_push(ary, rb_uint2inum(tmp));
}
+ PACK_ITEM_ADJUST();
break;
case 'v':
- if (len >= (send - s) / sizeof(short))
- len = (send - s) / sizeof(short);
+ PACK_LENGTH_ADJUST(unsigned short,2);
while (len-- > 0) {
unsigned short tmp;
- memcpy(&tmp, s, sizeof(short));
- s += sizeof(short);
+ memcpy(&tmp, s, NATINT_LEN(unsigned short,2));
+ s += NATINT_LEN(unsigned short,2);
tmp = vtohs(tmp);
rb_ary_push(ary, rb_uint2inum(tmp));
}
+ PACK_ITEM_ADJUST();
break;
case 'V':
- if (len >= (send - s) / sizeof(long))
- len = (send - s) / sizeof(long);
+ PACK_LENGTH_ADJUST(unsigned long,4);
while (len-- > 0) {
unsigned long tmp;
- memcpy(&tmp, s, sizeof(long));
- s += sizeof(long);
+ memcpy(&tmp, s, NATINT_LEN(long,4));
+ s += NATINT_LEN(long,4);
tmp = vtohl(tmp);
rb_ary_push(ary, rb_uint2inum(tmp));
}
+ PACK_ITEM_ADJUST();
break;
case 'f':
case 'F':
- if (len >= (send - s) / sizeof(float))
- len = (send - s) / sizeof(float);
+ PACK_LENGTH_ADJUST(float,sizeof(float));
while (len-- > 0) {
float tmp;
memcpy(&tmp, s, sizeof(float));
s += sizeof(float);
rb_ary_push(ary, rb_float_new((double)tmp));
}
+ PACK_ITEM_ADJUST();
break;
+ case 'e':
+ PACK_LENGTH_ADJUST(float,sizeof(float));
+ while (len-- > 0) {
+ float tmp;
+ FLOAT_CONVWITH(ftmp);
+
+ memcpy(&tmp, s, sizeof(float));
+ s += sizeof(float);
+ tmp = VTOHF(tmp,ftmp);
+ rb_ary_push(ary, rb_float_new((double)tmp));
+ }
+ PACK_ITEM_ADJUST();
+ break;
+
+ case 'E':
+ PACK_LENGTH_ADJUST(double,sizeof(double));
+ while (len-- > 0) {
+ double tmp;
+ DOUBLE_CONVWITH(dtmp);
+
+ memcpy(&tmp, s, sizeof(double));
+ s += sizeof(double);
+ tmp = VTOHD(tmp,dtmp);
+ rb_ary_push(ary, rb_float_new(tmp));
+ }
+ PACK_ITEM_ADJUST();
+ break;
+
case 'D':
case 'd':
- if (len >= (send - s) / sizeof(double))
- len = (send - s) / sizeof(double);
+ PACK_LENGTH_ADJUST(double,sizeof(double));
+ while (len-- > 0) {
+ double tmp;
+ memcpy(&tmp, s, sizeof(double));
+ s += sizeof(double);
+ rb_ary_push(ary, rb_float_new(tmp));
+ }
+ PACK_ITEM_ADJUST();
+ break;
+
+ case 'g':
+ PACK_LENGTH_ADJUST(float,sizeof(float));
+ while (len-- > 0) {
+ float tmp;
+ FLOAT_CONVWITH(ftmp;)
+
+ memcpy(&tmp, s, sizeof(float));
+ s += sizeof(float);
+ tmp = NTOHF(tmp,ftmp);
+ rb_ary_push(ary, rb_float_new((double)tmp));
+ }
+ PACK_ITEM_ADJUST();
+ break;
+
+ case 'G':
+ PACK_LENGTH_ADJUST(double,sizeof(double));
while (len-- > 0) {
double tmp;
+ DOUBLE_CONVWITH(dtmp);
+
memcpy(&tmp, s, sizeof(double));
s += sizeof(double);
+ tmp = NTOHD(tmp,dtmp);
rb_ary_push(ary, rb_float_new(tmp));
}
+ PACK_ITEM_ADJUST();
+ break;
+
+ case 'U':
+ if (len > send - s) len = send - s;
+ while (len-- > 0 && s < send) {
+ int alen;
+ unsigned long l;
+
+ l = utf8_to_uv(s, &alen);
+ s += alen;
+ rb_ary_push(ary, rb_uint2inum(l));
+ }
break;
case 'u':
@@ -972,6 +1456,8 @@ pack_unpack(str, fmt)
else if (s < send && (s+1 == send || s[1] == '\n'))
s += 2; /* possible checksum byte */
}
+
+ RSTRING(str)->ptr[total] = '\0';
RSTRING(str)->len = total;
rb_ary_push(ary, str);
}
@@ -993,15 +1479,15 @@ pack_unpack(str, fmt)
b64_xtable[i] = -1;
}
for (i = 0; i < 64; i++) {
- b64_xtable[b64_table[i]] = i;
+ b64_xtable[(int)b64_table[i]] = i;
}
}
for (;;) {
while (s[0] == '\r' || s[0] == '\n') { s++; }
- if ((a = b64_xtable[s[0]]) == -1) break;
- if ((b = b64_xtable[s[1]]) == -1) break;
- if ((c = b64_xtable[s[2]]) == -1) break;
- if ((d = b64_xtable[s[3]]) == -1) break;
+ if ((a = b64_xtable[(int)s[0]]) == -1) break;
+ if ((b = b64_xtable[(int)s[1]]) == -1) break;
+ if ((c = b64_xtable[(int)s[2]]) == -1) break;
+ if ((d = b64_xtable[(int)s[3]]) == -1) break;
*ptr++ = a << 2 | b >> 4;
*ptr++ = b << 4 | c >> 2;
*ptr++ = c << 6 | d;
@@ -1014,6 +1500,7 @@ pack_unpack(str, fmt)
*ptr++ = a << 2 | b >> 4;
*ptr++ = b << 4 | c >> 2;
}
+ *ptr = '\0';
RSTRING(str)->len = ptr - RSTRING(str)->ptr;
rb_ary_push(ary, str);
}
@@ -1040,6 +1527,7 @@ pack_unpack(str, fmt)
}
s++;
}
+ *ptr = '\0';
RSTRING(str)->len = ptr - RSTRING(str)->ptr;
rb_ary_push(ary, str);
}
@@ -1099,6 +1587,97 @@ pack_unpack(str, fmt)
return ary;
}
+#define BYTEWIDTH 8
+
+static int
+uv_to_utf8(buf, uv)
+ char *buf;
+ unsigned long uv;
+{
+ if (uv <= 0x7f) {
+ buf[0] = (char)uv;
+ return 1;
+ }
+ if (uv <= 0x7ff) {
+ buf[0] = ((uv>>6)&0xff)|0xc0;
+ buf[1] = (uv&0x3f)|0x80;
+ return 2;
+ }
+ if (uv <= 0xffff) {
+ buf[0] = ((uv>>12)&0xff)|0xe0;
+ buf[1] = ((uv>>6)&0x3f)|0x80;
+ buf[2] = (uv&0x3f)|0x80;
+ return 3;
+ }
+ if (uv <= 0x1fffff) {
+ buf[0] = ((uv>>18)&0xff)|0xf0;
+ buf[1] = ((uv>>12)&0x3f)|0x80;
+ buf[2] = ((uv>>6)&0x3f)|0x80;
+ buf[3] = (uv&0x3f)|0x80;
+ return 4;
+ }
+ if (uv <= 0x3ffffff) {
+ buf[0] = ((uv>>24)&0xff)|0xf8;
+ buf[1] = ((uv>>18)&0x3f)|0x80;
+ buf[2] = ((uv>>12)&0x3f)|0x80;
+ buf[3] = ((uv>>6)&0x3f)|0x80;
+ buf[4] = (uv&0x3f)|0x80;
+ return 5;
+ }
+ if (uv <= 0x7fffffff) {
+ buf[0] = ((uv>>30)&0xff)|0xfc;
+ buf[1] = ((uv>>24)&0x3f)|0x80;
+ buf[2] = ((uv>>18)&0x3f)|0x80;
+ buf[3] = ((uv>>12)&0x3f)|0x80;
+ buf[4] = ((uv>>6)&0x3f)|0x80;
+ buf[5] = (uv&0x3f)|0x80;
+ return 6;
+ }
+#if SIZEOF_LONG > 4
+ if (uv <= 0xfffffffff) {
+#endif
+ buf[0] = 0xfe;
+ buf[1] = ((uv>>30)&0x3f)|0x80;
+ buf[2] = ((uv>>24)&0x3f)|0x80;
+ buf[3] = ((uv>>18)&0x3f)|0x80;
+ buf[4] = ((uv>>12)&0x3f)|0x80;
+ buf[5] = ((uv>>6)&0x3f)|0x80;
+ buf[6] = (uv&0x3f)|0x80;
+ return 7;
+#if SIZEOF_LONG > 4
+ }
+ rb_raise(rb_eArgError, "uv_to_utf8(); too big value");
+#endif
+}
+
+static unsigned long
+utf8_to_uv(p, lenp)
+ char *p;
+ int *lenp;
+{
+ int c = (*p++)&0xff;
+ unsigned long uv;
+ int n = 1;
+
+ if (c < 0xc0) n = 1;
+ else if (c < 0xe0) n = 2;
+ else if (c < 0xf0) n = 3;
+ else if (c < 0xf8) n = 4;
+ else if (c < 0xfc) n = 5;
+ else if (c < 0xfe) n = 6;
+ else if (c == 0xfe) n = 7;
+ *lenp = n--;
+
+ uv = c;
+ if (n != 0) {
+ uv &= (1<<(BYTEWIDTH-2-n)) - 1;
+ while (n--) {
+ uv = uv << 6 | *p++ & ((1<<6)-1);
+ }
+ }
+ return uv;
+}
+
void
Init_pack()
{
diff --git a/parse.c b/parse.c
deleted file mode 100644
index 8c3bcc545a..0000000000
--- a/parse.c
+++ /dev/null
@@ -1,7224 +0,0 @@
-
-/* A Bison parser, made from parse.y
- by GNU Bison version 1.25.90
- */
-
-#define YYBISON 1 /* Identify Bison output. */
-
-#define kCLASS 257
-#define kMODULE 258
-#define kDEF 259
-#define kUNDEF 260
-#define kBEGIN 261
-#define kRESCUE 262
-#define kENSURE 263
-#define kEND 264
-#define kIF 265
-#define kUNLESS 266
-#define kTHEN 267
-#define kELSIF 268
-#define kELSE 269
-#define kCASE 270
-#define kWHEN 271
-#define kWHILE 272
-#define kUNTIL 273
-#define kFOR 274
-#define kBREAK 275
-#define kNEXT 276
-#define kREDO 277
-#define kRETRY 278
-#define kIN 279
-#define kDO 280
-#define kRETURN 281
-#define kYIELD 282
-#define kSUPER 283
-#define kSELF 284
-#define kNIL 285
-#define kTRUE 286
-#define kFALSE 287
-#define kAND 288
-#define kOR 289
-#define kNOT 290
-#define kIF_MOD 291
-#define kUNLESS_MOD 292
-#define kWHILE_MOD 293
-#define kUNTIL_MOD 294
-#define kALIAS 295
-#define kDEFINED 296
-#define klBEGIN 297
-#define klEND 298
-#define k__LINE__ 299
-#define k__FILE__ 300
-#define tIDENTIFIER 301
-#define tFID 302
-#define tGVAR 303
-#define tIVAR 304
-#define tCONSTANT 305
-#define tINTEGER 306
-#define tFLOAT 307
-#define tSTRING 308
-#define tXSTRING 309
-#define tREGEXP 310
-#define tDSTRING 311
-#define tDXSTRING 312
-#define tDREGEXP 313
-#define tNTH_REF 314
-#define tBACK_REF 315
-#define tUPLUS 316
-#define tUMINUS 317
-#define tPOW 318
-#define tCMP 319
-#define tEQ 320
-#define tEQQ 321
-#define tNEQ 322
-#define tGEQ 323
-#define tLEQ 324
-#define tANDOP 325
-#define tOROP 326
-#define tMATCH 327
-#define tNMATCH 328
-#define tDOT2 329
-#define tDOT3 330
-#define tAREF 331
-#define tASET 332
-#define tLSHFT 333
-#define tRSHFT 334
-#define tCOLON2 335
-#define tCOLON3 336
-#define tOP_ASGN 337
-#define tASSOC 338
-#define tLPAREN 339
-#define tLBRACK 340
-#define tLBRACE 341
-#define tSTAR 342
-#define tAMPER 343
-#define tSYMBEG 344
-#define LAST_TOKEN 345
-
-#line 13 "parse.y"
-
-
-#define YYDEBUG 1
-#include "ruby.h"
-#include "env.h"
-#include "node.h"
-#include "st.h"
-#include <stdio.h>
-
-/* hack for bison */
-#ifdef const
-# undef const
-#endif
-
-#define ID_SCOPE_SHIFT 3
-#define ID_SCOPE_MASK 0x07
-#define ID_LOCAL 0x01
-#define ID_INSTANCE 0x02
-#define ID_GLOBAL 0x03
-#define ID_ATTRSET 0x04
-#define ID_CONST 0x05
-
-#define is_id_notop(id) ((id)>LAST_TOKEN)
-#define is_local_id(id) (is_id_notop(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
-#define is_global_id(id) (is_id_notop(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
-#define is_instance_id(id) (is_id_notop(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
-#define is_attrset_id(id) (is_id_notop(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
-#define is_const_id(id) (is_id_notop(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
-
-NODE *ruby_eval_tree_begin = 0;
-NODE *ruby_eval_tree = 0;
-
-char *ruby_sourcefile; /* current source file */
-int ruby_sourceline; /* current line no. */
-
-static int yylex();
-static int yyerror();
-
-static enum lex_state {
- EXPR_BEG, /* ignore newline, +/- is a sign. */
- EXPR_MID, /* newline significant, +/- is a sign. */
- EXPR_END, /* newline significant, +/- is a operator. */
- EXPR_ARG, /* newline significant, +/- is a operator. */
- EXPR_FNAME, /* ignore newline, +/- is a operator, no reserved words. */
- EXPR_DOT, /* immediate after `.', no reserved words. */
- EXPR_CLASS, /* immediate after `class', no here document. */
-} lex_state;
-
-static int class_nest = 0;
-static int in_single = 0;
-static ID cur_mid = 0;
-
-static int value_expr();
-static NODE *cond();
-static NODE *logop();
-
-static NODE *newline_node();
-static void fixpos();
-
-static NODE *block_append();
-static NODE *list_append();
-static NODE *list_concat();
-static NODE *arg_add();
-static NODE *call_op();
-static int in_defined = 0;
-
-static NODE *arg_blk_pass();
-static NODE *new_call();
-static NODE *new_fcall();
-
-static NODE *gettable();
-static NODE *assignable();
-static NODE *aryset();
-static NODE *attrset();
-static void rb_backref_error();
-
-static NODE *match_gen();
-static void local_push();
-static void local_pop();
-static int local_append();
-static int local_cnt();
-static int local_id();
-static ID *local_tbl();
-
-static struct RVarmap *dyna_push();
-static void dyna_pop();
-static int dyna_in_block();
-
-#define cref_push() NEW_CREF()
-static void cref_pop();
-static NODE *cur_cref;
-
-static void top_local_init();
-static void top_local_setup();
-
-#line 109 "parse.y"
-typedef union {
- NODE *node;
- VALUE val;
- ID id;
- int num;
- struct RVarmap *vars;
-} YYSTYPE;
-#include <stdio.h>
-
-#ifndef __cplusplus
-#ifndef __STDC__
-#define const
-#endif
-#endif
-
-
-
-#define YYFINAL 617
-#define YYFLAG -32768
-#define YYNTBASE 118
-
-#define YYTRANSLATE(x) ((unsigned)(x) <= 345 ? yytranslate[x] : 206)
-
-static const char yytranslate[] = { 0,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 116,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 104, 2, 2, 2, 103, 98, 2, 115,
- 110, 101, 99, 111, 100, 109, 102, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 93, 117, 95,
- 91, 94, 92, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 112, 2, 113, 97, 2, 114, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 107, 96, 108, 105, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 1, 3, 4, 5, 6,
- 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
- 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
- 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
- 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- 57, 58, 59, 60, 61, 62, 63, 64, 65, 66,
- 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
- 77, 78, 79, 80, 81, 82, 83, 84, 85, 86,
- 87, 88, 89, 90, 106
-};
-
-#if YYDEBUG != 0
-static const short yyprhs[] = { 0,
- 0, 1, 4, 7, 8, 10, 14, 17, 20, 21,
- 26, 30, 34, 38, 41, 45, 49, 53, 57, 58,
- 64, 69, 71, 75, 78, 81, 83, 87, 91, 94,
- 97, 99, 102, 107, 112, 115, 117, 121, 123, 127,
- 129, 133, 136, 142, 145, 147, 151, 154, 156, 160,
- 162, 167, 171, 173, 175, 177, 179, 181, 183, 185,
- 187, 189, 190, 195, 197, 199, 201, 203, 205, 207,
- 209, 211, 213, 215, 217, 219, 221, 223, 225, 227,
- 229, 231, 233, 235, 237, 239, 241, 243, 245, 247,
- 249, 251, 253, 255, 257, 259, 261, 263, 265, 267,
- 269, 271, 273, 275, 277, 279, 281, 283, 285, 287,
- 289, 291, 293, 295, 297, 299, 301, 303, 305, 307,
- 309, 311, 313, 315, 317, 319, 321, 323, 325, 327,
- 329, 330, 335, 342, 348, 354, 358, 359, 364, 371,
- 377, 383, 387, 391, 395, 399, 403, 407, 411, 415,
- 419, 422, 425, 429, 433, 437, 441, 445, 449, 453,
- 457, 461, 465, 469, 473, 477, 480, 483, 487, 491,
- 495, 499, 500, 505, 511, 513, 515, 516, 519, 521,
- 524, 530, 533, 539, 544, 552, 556, 558, 561, 564,
- 565, 567, 568, 570, 574, 576, 581, 584, 586, 587,
- 590, 592, 596, 600, 603, 605, 607, 609, 611, 613,
- 615, 617, 622, 626, 630, 635, 639, 641, 646, 650,
- 652, 653, 660, 662, 665, 667, 670, 677, 684, 690,
- 696, 701, 709, 716, 720, 721, 728, 729, 737, 738,
- 744, 745, 752, 753, 754, 764, 766, 768, 770, 772,
- 774, 776, 779, 781, 783, 785, 791, 792, 795, 797,
- 799, 800, 803, 805, 809, 810, 816, 817, 823, 825,
- 827, 829, 831, 833, 838, 845, 849, 856, 861, 863,
- 869, 871, 876, 879, 881, 883, 889, 890, 891, 894,
- 896, 899, 901, 903, 905, 907, 909, 911, 913, 915,
- 917, 919, 921, 923, 925, 927, 929, 931, 933, 935,
- 937, 939, 940, 945, 948, 953, 956, 963, 968, 973,
- 976, 981, 984, 987, 989, 990, 992, 996, 1000, 1002,
- 1006, 1009, 1012, 1015, 1016, 1018, 1023, 1024, 1027, 1030,
- 1032, 1036, 1040, 1042, 1044, 1046, 1048, 1050, 1051, 1053,
- 1054, 1056, 1057, 1059, 1061, 1063, 1065, 1067
-};
-
-static const short yyrhs[] = { -1,
- 119, 120, 0, 121, 201, 0, 0, 122, 0, 121,
- 205, 122, 0, 1, 122, 0, 172, 168, 0, 0,
- 41, 135, 123, 135, 0, 41, 49, 49, 0, 41,
- 49, 61, 0, 41, 49, 60, 0, 6, 136, 0,
- 122, 37, 125, 0, 122, 38, 125, 0, 122, 39,
- 125, 0, 122, 40, 125, 0, 0, 43, 124, 107,
- 120, 108, 0, 44, 107, 120, 108, 0, 125, 0,
- 127, 91, 151, 0, 27, 152, 0, 28, 152, 0,
- 126, 0, 125, 34, 125, 0, 125, 35, 125, 0,
- 36, 125, 0, 104, 126, 0, 140, 0, 199, 146,
- 0, 154, 109, 199, 146, 0, 154, 81, 199, 146,
- 0, 29, 146, 0, 129, 0, 85, 128, 110, 0,
- 129, 0, 85, 128, 110, 0, 131, 0, 131, 88,
- 133, 0, 131, 132, 0, 131, 132, 111, 88, 133,
- 0, 88, 133, 0, 133, 0, 85, 128, 110, 0,
- 130, 111, 0, 130, 0, 132, 111, 130, 0, 182,
- 0, 154, 112, 144, 113, 0, 154, 109, 47, 0,
- 184, 0, 47, 0, 51, 0, 47, 0, 51, 0,
- 48, 0, 138, 0, 139, 0, 135, 0, 0, 136,
- 111, 137, 135, 0, 75, 0, 96, 0, 97, 0,
- 98, 0, 65, 0, 66, 0, 67, 0, 73, 0,
- 94, 0, 69, 0, 95, 0, 70, 0, 79, 0,
- 80, 0, 99, 0, 100, 0, 101, 0, 88, 0,
- 102, 0, 103, 0, 64, 0, 105, 0, 62, 0,
- 63, 0, 77, 0, 78, 0, 114, 0, 45, 0,
- 46, 0, 43, 0, 44, 0, 41, 0, 34, 0,
- 7, 0, 21, 0, 16, 0, 3, 0, 5, 0,
- 42, 0, 26, 0, 15, 0, 14, 0, 10, 0,
- 9, 0, 33, 0, 20, 0, 37, 0, 25, 0,
- 4, 0, 22, 0, 31, 0, 36, 0, 35, 0,
- 23, 0, 8, 0, 24, 0, 27, 0, 30, 0,
- 29, 0, 13, 0, 32, 0, 6, 0, 38, 0,
- 40, 0, 17, 0, 39, 0, 28, 0, 0, 182,
- 91, 141, 140, 0, 154, 112, 144, 113, 91, 140,
- 0, 154, 109, 47, 91, 140, 0, 154, 109, 51,
- 91, 140, 0, 184, 91, 140, 0, 0, 182, 83,
- 142, 140, 0, 154, 112, 144, 113, 83, 140, 0,
- 154, 109, 47, 83, 140, 0, 154, 109, 51, 83,
- 140, 0, 184, 83, 140, 0, 140, 75, 140, 0,
- 140, 76, 140, 0, 140, 99, 140, 0, 140, 100,
- 140, 0, 140, 101, 140, 0, 140, 102, 140, 0,
- 140, 103, 140, 0, 140, 64, 140, 0, 62, 140,
- 0, 63, 140, 0, 140, 96, 140, 0, 140, 97,
- 140, 0, 140, 98, 140, 0, 140, 65, 140, 0,
- 140, 94, 140, 0, 140, 69, 140, 0, 140, 95,
- 140, 0, 140, 70, 140, 0, 140, 66, 140, 0,
- 140, 67, 140, 0, 140, 68, 140, 0, 140, 73,
- 140, 0, 140, 74, 140, 0, 104, 140, 0, 105,
- 140, 0, 140, 79, 140, 0, 140, 80, 140, 0,
- 140, 71, 140, 0, 140, 72, 140, 0, 0, 42,
- 202, 143, 140, 0, 140, 92, 140, 93, 140, 0,
- 154, 0, 145, 0, 0, 146, 202, 0, 126, 0,
- 150, 148, 0, 150, 111, 88, 140, 148, 0, 197,
- 148, 0, 197, 111, 88, 140, 148, 0, 150, 111,
- 197, 148, 0, 150, 111, 197, 111, 88, 140, 148,
- 0, 88, 140, 148, 0, 147, 0, 89, 140, 0,
- 111, 147, 0, 0, 150, 0, 0, 140, 0, 150,
- 111, 140, 0, 150, 0, 150, 111, 88, 140, 0,
- 88, 140, 0, 146, 0, 0, 150, 203, 0, 179,
- 0, 154, 81, 51, 0, 154, 81, 47, 0, 82,
- 134, 0, 54, 0, 57, 0, 55, 0, 58, 0,
- 59, 0, 183, 0, 184, 0, 154, 112, 144, 113,
- 0, 86, 153, 113, 0, 87, 196, 108, 0, 27,
- 115, 152, 110, 0, 27, 115, 110, 0, 27, 0,
- 28, 115, 152, 110, 0, 28, 115, 110, 0, 28,
- 0, 0, 42, 202, 115, 155, 125, 110, 0, 48,
- 0, 199, 170, 0, 173, 0, 173, 170, 0, 11,
- 125, 162, 120, 164, 10, 0, 12, 125, 162, 120,
- 165, 10, 0, 18, 125, 163, 120, 10, 0, 19,
- 125, 163, 120, 10, 0, 16, 120, 174, 10, 0,
- 20, 166, 25, 125, 163, 120, 10, 0, 7, 120,
- 177, 165, 178, 10, 0, 85, 120, 110, 0, 0,
- 3, 134, 185, 156, 120, 10, 0, 0, 3, 79,
- 125, 204, 157, 120, 10, 0, 0, 4, 134, 158,
- 120, 10, 0, 0, 5, 135, 159, 187, 120, 10,
- 0, 0, 0, 5, 195, 200, 160, 135, 161, 187,
- 120, 10, 0, 21, 0, 22, 0, 23, 0, 24,
- 0, 204, 0, 13, 0, 204, 13, 0, 204, 0,
- 26, 0, 165, 0, 14, 125, 162, 120, 164, 0,
- 0, 15, 120, 0, 133, 0, 127, 0, 0, 96,
- 96, 0, 72, 0, 96, 166, 96, 0, 0, 26,
- 169, 167, 120, 10, 0, 0, 107, 171, 167, 120,
- 108, 0, 47, 0, 51, 0, 48, 0, 173, 0,
- 126, 0, 199, 115, 145, 110, 0, 154, 109, 199,
- 115, 145, 110, 0, 154, 109, 199, 0, 154, 81,
- 199, 115, 145, 110, 0, 29, 115, 145, 110, 0,
- 29, 0, 17, 175, 162, 120, 176, 0, 150, 0,
- 150, 111, 88, 140, 0, 88, 140, 0, 165, 0,
- 174, 0, 8, 149, 163, 120, 177, 0, 0, 0,
- 9, 120, 0, 181, 0, 90, 180, 0, 56, 0,
- 135, 0, 50, 0, 49, 0, 52, 0, 53, 0,
- 47, 0, 50, 0, 49, 0, 51, 0, 31, 0,
- 30, 0, 32, 0, 33, 0, 46, 0, 45, 0,
- 182, 0, 60, 0, 61, 0, 204, 0, 0, 95,
- 186, 125, 204, 0, 1, 204, 0, 115, 188, 202,
- 110, 0, 188, 204, 0, 189, 111, 191, 111, 192,
- 194, 0, 189, 111, 191, 194, 0, 189, 111, 192,
- 194, 0, 189, 194, 0, 191, 111, 192, 194, 0,
- 191, 194, 0, 192, 194, 0, 193, 0, 0, 47,
- 0, 189, 111, 47, 0, 47, 91, 140, 0, 190,
- 0, 191, 111, 190, 0, 88, 47, 0, 89, 47,
- 0, 111, 193, 0, 0, 183, 0, 85, 125, 202,
- 110, 0, 0, 197, 203, 0, 150, 203, 0, 198,
- 0, 197, 111, 198, 0, 140, 84, 140, 0, 47,
- 0, 51, 0, 48, 0, 109, 0, 81, 0, 0,
- 205, 0, 0, 116, 0, 0, 116, 0, 111, 0,
- 117, 0, 116, 0, 204, 0, 205, 117, 0
-};
-
-#endif
-
-#if YYDEBUG != 0
-static const short yyrline[] = { 0,
- 231, 240, 248, 250, 254, 258, 262, 267, 276, 277,
- 282, 288, 297, 302, 308, 314, 320, 330, 340, 348,
- 355, 363, 365, 371, 378, 383, 384, 388, 392, 397,
- 402, 404, 409, 415, 421, 429, 430, 435, 436, 441,
- 445, 449, 453, 457, 462, 463, 468, 473, 477, 482,
- 486, 490, 494, 500, 504, 506, 507, 508, 509, 514,
- 520, 524, 525, 529, 530, 531, 532, 533, 534, 535,
- 536, 537, 538, 539, 540, 541, 542, 543, 544, 545,
- 546, 547, 548, 549, 550, 551, 552, 553, 554, 555,
- 557, 557, 557, 557, 558, 558, 558, 558, 558, 558,
- 558, 559, 559, 559, 559, 559, 559, 559, 560, 560,
- 560, 560, 560, 560, 560, 561, 561, 561, 561, 561,
- 561, 561, 562, 562, 562, 562, 562, 562, 563, 563,
- 565, 566, 573, 578, 583, 588, 594, 595, 610, 625,
- 636, 647, 652, 656, 660, 664, 668, 672, 676, 680,
- 684, 688, 692, 696, 700, 704, 708, 712, 716, 720,
- 724, 728, 732, 736, 740, 744, 749, 753, 757, 761,
- 765, 769, 770, 774, 780, 785, 793, 797, 799, 804,
- 808, 813, 818, 823, 828, 833, 838, 840, 846, 850,
- 855, 856, 861, 866, 872, 884, 889, 895, 909, 913,
- 915, 919, 924, 929, 933, 937, 938, 942, 943, 944,
- 945, 946, 951, 959, 963, 970, 976, 982, 987, 991,
- 995, 995, 1000, 1004, 1009, 1010, 1019, 1028, 1037, 1045,
- 1053, 1061, 1069, 1089, 1093, 1103, 1111, 1118, 1126, 1135,
- 1143, 1151, 1160, 1161, 1168, 1176, 1180, 1184, 1188, 1193,
- 1194, 1195, 1197, 1198, 1200, 1201, 1210, 1214, 1219, 1220,
- 1222, 1226, 1230, 1234, 1239, 1244, 1252, 1257, 1264, 1268,
- 1272, 1276, 1277, 1279, 1284, 1290, 1296, 1302, 1308, 1316,
- 1323, 1324, 1329, 1335, 1336, 1338, 1345, 1350, 1354, 1359,
- 1360, 1364, 1366, 1367, 1368, 1370, 1371, 1373, 1374, 1375,
- 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1384, 1389, 1390,
- 1392, 1396, 1400, 1404, 1406, 1411, 1416, 1420, 1424, 1428,
- 1432, 1436, 1440, 1444, 1448, 1453, 1460, 1468, 1475, 1480,
- 1485, 1492, 1497, 1501, 1506, 1519, 1537, 1541, 1545, 1553,
- 1554, 1559, 1564, 1565, 1566, 1568, 1569, 1571, 1572, 1574,
- 1575, 1577, 1578, 1579, 1581, 1582, 1584, 1585
-};
-#endif
-
-
-#if YYDEBUG != 0 || defined (YYERROR_VERBOSE)
-
-static const char * const yytname[] = { "$","error","$undefined.","kCLASS",
-"kMODULE","kDEF","kUNDEF","kBEGIN","kRESCUE","kENSURE","kEND","kIF","kUNLESS",
-"kTHEN","kELSIF","kELSE","kCASE","kWHEN","kWHILE","kUNTIL","kFOR","kBREAK","kNEXT",
-"kREDO","kRETRY","kIN","kDO","kRETURN","kYIELD","kSUPER","kSELF","kNIL","kTRUE",
-"kFALSE","kAND","kOR","kNOT","kIF_MOD","kUNLESS_MOD","kWHILE_MOD","kUNTIL_MOD",
-"kALIAS","kDEFINED","klBEGIN","klEND","k__LINE__","k__FILE__","tIDENTIFIER",
-"tFID","tGVAR","tIVAR","tCONSTANT","tINTEGER","tFLOAT","tSTRING","tXSTRING",
-"tREGEXP","tDSTRING","tDXSTRING","tDREGEXP","tNTH_REF","tBACK_REF","tUPLUS",
-"tUMINUS","tPOW","tCMP","tEQ","tEQQ","tNEQ","tGEQ","tLEQ","tANDOP","tOROP","tMATCH",
-"tNMATCH","tDOT2","tDOT3","tAREF","tASET","tLSHFT","tRSHFT","tCOLON2","tCOLON3",
-"tOP_ASGN","tASSOC","tLPAREN","tLBRACK","tLBRACE","tSTAR","tAMPER","tSYMBEG",
-"'='","'?'","':'","'>'","'<'","'|'","'^'","'&'","'+'","'-'","'*'","'/'","'%'",
-"'!'","'~'","LAST_TOKEN","'{'","'}'","'.'","')'","','","'['","']'","'`'","'('",
-"'\\n'","';'","program","@1","compstmt","stmts","stmt","@2","@3","expr","command_call",
-"mlhs","mlhs_entry","mlhs_basic","mlhs_item","mlhs_head","mlhs_tail","lhs","cname",
-"fname","undef_list","@4","op","reswords","arg","@5","@6","@7","aref_args","opt_call_args",
-"call_args","block_arg","opt_block_arg","opt_list","args","mrhs","ret_args",
-"array","primary","@8","@9","@10","@11","@12","@13","@14","then","do","if_tail",
-"opt_else","iter_var","opt_iter_var","iter_do_block","@15","iter_block","@16",
-"iterator","method_call","case_body","when_args","cases","rescue","ensure","literal",
-"symbol","numeric","variable","var_ref","backref","superclass","@17","f_arglist",
-"f_args","f_arg","f_opt","f_optarg","f_rest_arg","f_block_arg","opt_f_block_arg",
-"singleton","assoc_list","assocs","assoc","operation","dot_or_colon","opt_terms",
-"opt_nl","trailer","term","terms", NULL
-};
-#endif
-
-static const short yyr1[] = { 0,
- 119, 118, 120, 121, 121, 121, 121, 122, 123, 122,
- 122, 122, 122, 122, 122, 122, 122, 122, 124, 122,
- 122, 122, 125, 125, 125, 125, 125, 125, 125, 125,
- 125, 126, 126, 126, 126, 127, 127, 128, 128, 129,
- 129, 129, 129, 129, 130, 130, 131, 132, 132, 133,
- 133, 133, 133, 134, 134, 135, 135, 135, 135, 135,
- 136, 137, 136, 138, 138, 138, 138, 138, 138, 138,
- 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
- 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
- 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
- 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
- 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
- 139, 139, 139, 139, 139, 139, 139, 139, 139, 139,
- 141, 140, 140, 140, 140, 140, 142, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 140, 140, 140, 140, 140, 140, 140, 140, 140,
- 140, 143, 140, 140, 140, 144, 145, 145, 146, 146,
- 146, 146, 146, 146, 146, 146, 146, 147, 148, 148,
- 149, 149, 150, 150, 151, 151, 151, 152, 153, 153,
- 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
- 154, 154, 154, 154, 154, 154, 154, 154, 154, 154,
- 155, 154, 154, 154, 154, 154, 154, 154, 154, 154,
- 154, 154, 154, 154, 156, 154, 157, 154, 158, 154,
- 159, 154, 160, 161, 154, 154, 154, 154, 154, 162,
- 162, 162, 163, 163, 164, 164, 165, 165, 166, 166,
- 167, 167, 167, 167, 169, 168, 171, 170, 172, 172,
- 172, 172, 172, 173, 173, 173, 173, 173, 173, 174,
- 175, 175, 175, 176, 176, 177, 177, 178, 178, 179,
- 179, 179, 180, 180, 180, 181, 181, 182, 182, 182,
- 182, 182, 182, 182, 182, 182, 182, 183, 184, 184,
- 185, 186, 185, 185, 187, 187, 188, 188, 188, 188,
- 188, 188, 188, 188, 188, 189, 189, 190, 191, 191,
- 192, 193, 194, 194, 195, 195, 196, 196, 196, 197,
- 197, 198, 199, 199, 199, 200, 200, 201, 201, 202,
- 202, 203, 203, 203, 204, 204, 205, 205
-};
-
-static const short yyr2[] = { 0,
- 0, 2, 2, 0, 1, 3, 2, 2, 0, 4,
- 3, 3, 3, 2, 3, 3, 3, 3, 0, 5,
- 4, 1, 3, 2, 2, 1, 3, 3, 2, 2,
- 1, 2, 4, 4, 2, 1, 3, 1, 3, 1,
- 3, 2, 5, 2, 1, 3, 2, 1, 3, 1,
- 4, 3, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 0, 4, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 0, 4, 6, 5, 5, 3, 0, 4, 6, 5,
- 5, 3, 3, 3, 3, 3, 3, 3, 3, 3,
- 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
- 3, 3, 3, 3, 3, 2, 2, 3, 3, 3,
- 3, 0, 4, 5, 1, 1, 0, 2, 1, 2,
- 5, 2, 5, 4, 7, 3, 1, 2, 2, 0,
- 1, 0, 1, 3, 1, 4, 2, 1, 0, 2,
- 1, 3, 3, 2, 1, 1, 1, 1, 1, 1,
- 1, 4, 3, 3, 4, 3, 1, 4, 3, 1,
- 0, 6, 1, 2, 1, 2, 6, 6, 5, 5,
- 4, 7, 6, 3, 0, 6, 0, 7, 0, 5,
- 0, 6, 0, 0, 9, 1, 1, 1, 1, 1,
- 1, 2, 1, 1, 1, 5, 0, 2, 1, 1,
- 0, 2, 1, 3, 0, 5, 0, 5, 1, 1,
- 1, 1, 1, 4, 6, 3, 6, 4, 1, 5,
- 1, 4, 2, 1, 1, 5, 0, 0, 2, 1,
- 2, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 0, 4, 2, 4, 2, 6, 4, 4, 2,
- 4, 2, 2, 1, 0, 1, 3, 3, 1, 3,
- 2, 2, 2, 0, 1, 4, 0, 2, 2, 1,
- 3, 3, 1, 1, 1, 1, 1, 0, 1, 0,
- 1, 0, 1, 1, 1, 1, 1, 2
-};
-
-static const short yydefact[] = { 1,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 246, 247, 248, 249, 217, 220, 279,
- 303, 302, 304, 305, 0, 0, 350, 19, 0, 307,
- 306, 343, 345, 300, 299, 344, 296, 297, 205, 207,
- 292, 206, 208, 209, 309, 310, 0, 0, 0, 0,
- 199, 337, 0, 0, 0, 0, 2, 348, 5, 22,
- 26, 0, 36, 0, 40, 45, 31, 175, 0, 225,
- 201, 290, 308, 210, 211, 0, 7, 54, 55, 0,
- 0, 239, 100, 112, 101, 125, 97, 118, 107, 106,
- 123, 105, 104, 99, 128, 109, 98, 113, 117, 119,
- 111, 103, 120, 130, 122, 121, 114, 124, 108, 96,
- 116, 115, 110, 126, 129, 127, 95, 102, 93, 94,
- 91, 92, 56, 58, 57, 86, 87, 84, 68, 69,
- 70, 73, 75, 71, 64, 88, 89, 76, 77, 0,
- 81, 72, 74, 65, 66, 67, 78, 79, 80, 82,
- 83, 85, 90, 241, 59, 60, 308, 335, 0, 121,
- 114, 124, 108, 91, 92, 56, 57, 61, 14, 287,
- 298, 223, 301, 0, 26, 225, 0, 0, 0, 0,
- 217, 220, 279, 350, 260, 259, 0, 0, 50, 53,
- 0, 0, 0, 0, 0, 0, 179, 193, 198, 187,
- 190, 24, 175, 308, 211, 190, 340, 0, 25, 177,
- 35, 29, 0, 9, 351, 172, 0, 0, 151, 175,
- 152, 204, 0, 0, 0, 36, 193, 352, 0, 352,
- 0, 352, 44, 295, 294, 293, 291, 30, 166, 167,
- 356, 355, 3, 357, 349, 0, 0, 0, 0, 0,
- 0, 0, 47, 0, 0, 48, 42, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 177, 265, 8, 267, 226,
- 137, 131, 0, 0, 177, 32, 224, 0, 0, 312,
- 235, 311, 0, 350, 325, 347, 346, 243, 62, 192,
- 257, 251, 0, 250, 0, 0, 0, 254, 0, 253,
- 0, 0, 0, 0, 177, 0, 190, 188, 216, 0,
- 0, 0, 180, 0, 177, 0, 182, 219, 0, 0,
- 350, 11, 13, 12, 0, 221, 0, 0, 0, 0,
- 0, 234, 37, 354, 353, 200, 213, 339, 214, 354,
- 338, 358, 6, 15, 16, 17, 18, 27, 28, 0,
- 195, 23, 0, 41, 0, 150, 156, 161, 162, 163,
- 158, 160, 170, 171, 164, 165, 143, 144, 168, 169,
- 0, 157, 159, 153, 154, 155, 145, 146, 147, 148,
- 149, 203, 345, 202, 0, 343, 344, 276, 0, 176,
- 261, 261, 0, 0, 142, 136, 0, 237, 314, 0,
- 0, 0, 0, 326, 0, 0, 325, 0, 0, 334,
- 329, 334, 334, 324, 0, 0, 0, 191, 0, 288,
- 257, 252, 257, 0, 281, 0, 231, 0, 0, 0,
- 52, 344, 276, 0, 0, 0, 186, 215, 342, 0,
- 194, 189, 190, 343, 0, 0, 0, 341, 218, 278,
- 178, 10, 0, 173, 0, 21, 37, 194, 197, 0,
- 46, 0, 49, 0, 177, 34, 0, 0, 0, 0,
- 177, 33, 212, 263, 0, 0, 0, 138, 132, 274,
- 0, 0, 0, 240, 336, 0, 331, 332, 350, 0,
- 316, 0, 320, 0, 322, 0, 323, 244, 63, 0,
- 0, 258, 0, 0, 0, 0, 255, 0, 283, 0,
- 0, 229, 230, 51, 0, 190, 0, 184, 212, 190,
- 0, 20, 0, 43, 174, 0, 140, 134, 141, 135,
- 0, 0, 0, 262, 0, 0, 0, 0, 313, 236,
- 328, 0, 242, 327, 334, 334, 333, 0, 330, 334,
- 325, 287, 289, 233, 0, 227, 228, 0, 257, 0,
- 181, 0, 183, 222, 196, 277, 275, 139, 133, 264,
- 266, 268, 238, 315, 0, 318, 319, 321, 0, 286,
- 0, 282, 284, 285, 280, 232, 190, 334, 0, 257,
- 185, 317, 245, 256, 0, 0, 0
-};
-
-static const short yydefgoto[] = { 615,
- 1, 224, 58, 59, 345, 217, 60, 61, 62, 225,
- 63, 64, 65, 257, 66, 81, 154, 169, 436, 155,
- 156, 67, 414, 413, 347, 409, 410, 341, 200, 333,
- 437, 201, 372, 202, 229, 220, 473, 421, 501, 303,
- 305, 435, 571, 313, 319, 526, 527, 188, 496, 288,
- 411, 290, 412, 69, 176, 317, 446, 605, 311, 524,
- 71, 237, 72, 204, 74, 205, 301, 420, 428, 429,
- 430, 431, 432, 433, 567, 513, 159, 231, 206, 207,
- 191, 308, 243, 216, 356, 314, 245
-};
-
-static const short yypact[] = {-32768,
- 1581, 4673, 29, 135, 4070, 4379, 2015, 4763, 4763, 2487,
- 4763, 4763, 5841,-32768,-32768,-32768,-32768, 3427, 3517, 3607,
--32768,-32768,-32768,-32768, 4763, 4276, -45,-32768, 39,-32768,
--32768, 1679, 1898,-32768,-32768, 1793,-32768,-32768,-32768,-32768,
--32768,-32768,-32768,-32768,-32768,-32768, 5573, 5573, 135, 2578,
- 5573, 5573, 6105, 4173, 5663, 5573,-32768, -25, 338, 93,
- 136, 64,-32768, 59, 5929,-32768, 6104, 0, 147, 22,
--32768,-32768, 122,-32768, 168, 3067, 338,-32768,-32768, 4763,
- 41,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
--32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
--32768,-32768,-32768,-32768,-32768, -9, 1, 2, 12,-32768,
--32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
- 79, 85, 125,-32768, 130,-32768,-32768,-32768,-32768,-32768,
--32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 4763,
--32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,
--32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 175,-32768,
--32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 74, 212,
- 3157, 3247, 3337, 33,-32768, 118, 33, 221, 21, 21,
- 155, 172, 177, -45,-32768, 192, 62, 285, 71, 78,
- -17, 2686, 5573, 5573, 5573, 4483,-32768, 1089,-32768,-32768,
- 205,-32768, 80, 210, 222, 211,-32768, 4578,-32768, 4853,
--32768,-32768, 36,-32768,-32768, 215, 230, 2794, 284, 143,
- 284,-32768, 2578, 251, 257, 258, 6104, -22, 243, -22,
- 264, 92,-32768,-32768,-32768,-32768,-32768,-32768, 284, 284,
--32768,-32768,-32768,-32768, 2976, 4763, 4763, 4763, 4763, 4763,
- 4763, 5213,-32768, 2578, 6105,-32768, 268, 5573, 5573, 5573,
- 5573, 5573, 5573, 5573, 5573, 5573, 5573, 5573, 5573, 5573,
- 5573, 5573, 5573, 5573, 5573, 5573, 5573, 5573, 5573, 5573,
- 5573, 5573, 5573, 235, 280, 4853,-32768,-32768,-32768,-32768,
--32768,-32768, 5573, 5573, 4853,-32768,-32768, 31, -25,-32768,
--32768,-32768, 2885, 28, -2,-32768,-32768,-32768,-32768, 5573,
- 365,-32768, 2123, 382, 2305, 5303, 387,-32768, 2885,-32768,
- 2885, 215, 235, 306, 4853, 4763, 749, 6104,-32768, 288,
- 5573, 4943,-32768, 311, 4853, 5033,-32768,-32768, 290, 293,
- -45,-32768,-32768,-32768, 4379,-32768, 5573, 2794, 297, 311,
- 298,-32768, 299, 5573,-32768,-32768,-32768,-32768,-32768, 5573,
--32768,-32768, 338, 93, 93, 93, 93,-32768,-32768, 5573,
- 300,-32768, 302,-32768, 6017, 284, 670, 670, 670, 670,
- 286, 286, 1385, 6184, 670, 670, 6144, 6144, 129, 129,
- 1339, 286, 286, 99, 99, 291, 66, 66, 284, 284,
- 284, 3697,-32768, 3787, 3877, 197, 226, 3967, 296,-32768,
- 68, 68, 5573, 5573, 6104, 6104, 304,-32768,-32768, 4763,
- 2885, 391, 305, 326, 375, 376, 13, 2885, -25, 313,
--32768, 314, 315,-32768, 4379, 4379, 15, 318, 2396, 422,
- 246,-32768, 365, 5573, 321, 25,-32768, 423, 425, 322,
- 103,-32768, 324, 327, 21, 352,-32768,-32768, 6104, 5573,
- 1089,-32768, 333, 232, 332, 5573, 1089,-32768,-32768,-32768,
--32768,-32768, 4763, 6104, 339,-32768, 253, 6104, 6104, 5393,
--32768, 6105,-32768, 5573, 4853,-32768, 5573, 5573, 5573, 5573,
- 4853,-32768, 208,-32768, 5753, 2885, 2794, 6104, 6104,-32768,
- 2885, 31, 439,-32768,-32768, 5573,-32768,-32768, -45, 440,
--32768, 26,-32768, 30,-32768, 362,-32768,-32768,-32768, 2015,
- 5573,-32768, 2885, 443, 4763, 444,-32768, 445, 6104, 5483,
- 2214,-32768,-32768, 160, 2885, 749, 5123,-32768, 238, 749,
- 23,-32768, 5573,-32768, 6104, 346, 6104, 6104, 6104, 6104,
- 347, 5573, 5573,-32768, 363, 448, 353, 450,-32768,-32768,
- 6104, 355,-32768, 326, 351, 315,-32768, 326,-32768, 315,
- -2, 212,-32768,-32768, 33,-32768,-32768, 5573, 206, 457,
--32768, 5573,-32768,-32768, 6104,-32768,-32768, 6104, 6104,-32768,
--32768,-32768,-32768,-32768, 30,-32768,-32768,-32768, 2885,-32768,
- 2123, 6104,-32768,-32768,-32768,-32768, 749, 315, 458, 246,
--32768,-32768,-32768,-32768, 469, 470,-32768
-};
-
-static const short yypgoto[] = {-32768,
--32768, 479,-32768, 32,-32768,-32768, 95, 1321, -10, -149,
- -27, -49,-32768,-32768, 16, 46, 7,-32768,-32768,-32768,
--32768, 1012,-32768,-32768,-32768, -247, -196, 8, -300, -201,
--32768, -12,-32768, 18,-32768, -1,-32768,-32768,-32768,-32768,
--32768,-32768,-32768, -173, -159, -139, -289, -20, 61,-32768,
--32768, -46,-32768,-32768, 115, -103,-32768,-32768, -95,-32768,
--32768,-32768,-32768, 616, 473, 698,-32768,-32768, -89, 56,
--32768, -444, -24, -461, -274, -389,-32768,-32768, -32, -301,
- 256,-32768,-32768, -169, 119, -56,-32768
-};
-
-
-#define YYLAST 6287
-
-
-static const short yytable[] = { 68,
- 68, 244, 185, 315, 337, 68, 68, 68, 68, 68,
- 68, 187, 168, 340, 322, 256, 203, 203, 203, 232,
- 321, 440, 226, 68, 302, 199, 199, 211, 186, 297,
- 434, 462, 214, 77, 468, 462, 209, 312, 228, 230,
- 318, 299, 515, 517, 424, 312, 318, -272, 68, 82,
- 566, 187, 570, 203, 250, 251, 250, 251, 468, 424,
- 236, 250, 251, 187, 250, 251, 250, 251, 233, 569,
- 215, -303, 564, 351, 203, 78, 568, 454, 68, 79,
- 284, -302, -304, 296, 342, 425, 426, 465, 354, 289,
- 241, 242, -305, 355, 222, 343, 344, 295, 417, -303,
- 425, 426, 174, 177, 373, 179, 180, 80, 285, -302,
- -304, 286, 427, 425, 426, 70, 70, 425, 426, 212,
- -305, 70, 320, 320, 70, 457, 250, 251, 289, 258,
- 241, 242, 584, 608, 423, 300, 241, 242, 68, 494,
- 241, 242, 323, 215, 297, 218, 241, 242, 241, 242,
- 569, -308, 434, 528, 252, 462, 241, 242, -211, -307,
- 284, -273, 258, 495, 70, -306, 281, 282, 283, 253,
- 324, 471, 287, 325, 298, 596, 597, 271, 272, -308,
- 598, 78, -308, -343, 309, 79, -211, -307, 334, -211,
- 68, 335, 258, -306, 203, 226, 278, 279, 280, 281,
- 282, 283, 360, 199, 291, -298, 203, 355, 203, -343,
- -301, -343, 292, 330, -343, 199, 68, -343, 612, 310,
- 439, 68, 316, 323, 289, 339, 226, 279, 280, 281,
- 282, 283, -50, -298, 304, 468, 462, 316, -301, 371,
- -212, 418, 419, 68, 68, 68, 68, 68, 68, 68,
- 293, 350, 68, 187, 335, 306, 76, 76, 294, 525,
- 439, 538, 76, 76, 76, 76, 76, 76, -212, 196,
- 374, -212, 531, 76, 76, 76, 363, 520, -53, 487,
- 76, 402, 403, 307, 203, 404, 208, 488, 546, 603,
- 552, 210, 291, 203, 551, 535, 434, 438, 553, 463,
- 292, 68, -45, 445, 293, 76, 70, -52, 489, 326,
- 76, 68, 294, 68, 487, 332, 490, 68, -51, 68,
- 552, 336, 488, 203, 68, 483, 406, 403, 553, 346,
- 407, 76, 70, 203, 581, 76, 348, 70, 583, 562,
- 364, 365, 366, 367, 368, 369, 68, 258, 358, 258,
- 361, 472, 451, 403, 258, 357, 452, 464, 403, 70,
- 352, 407, -39, -46, 271, 272, 353, -38, 70, 271,
- 272, 359, 511, 187, 246, 247, 248, 249, 375, 439,
- 320, 276, 277, 278, 279, 280, 281, 282, 283, 279,
- 280, 281, 282, 283, 442, 76, 447, 458, 320, 469,
- 504, 601, 470, 203, 476, 611, 203, 477, 493, -46,
- 480, 481, 486, 500, 505, 492, 506, 70, 68, 68,
- 455, 507, 508, 512, 514, 516, 68, 70, 521, 70,
- 523, 530, 532, 70, 533, 70, 485, 68, 491, 534,
- 194, 518, 519, 537, 539, 559, 542, 76, 560, 563,
- 426, 76, 574, 576, 577, 586, 587, 591, 590, 593,
- 592, 595, 70, 76, 594, 76, 606, 613, 616, 617,
- 614, 68, 497, 76, 555, 604, 600, 158, 76, 57,
- 187, 599, 509, 203, 185, 170, 0, 565, 178, 203,
- 0, 0, 0, 187, 68, 68, 0, 544, 0, 68,
- 76, 76, 76, 76, 76, 76, 76, 0, 0, 76,
- 186, 0, 0, 0, 502, 0, 0, 0, 68, 0,
- 0, 68, 0, 68, 0, 0, 0, 0, 0, 68,
- 0, 0, 0, 68, 0, 70, 0, 0, 0, 405,
- 408, 76, 70, 0, 0, 0, 0, 0, 0, 0,
- 76, 0, 0, 70, 0, 0, 0, 0, 76, 0,
- 0, 0, 0, 0, 0, 0, 0, 541, 76, 0,
- 76, 0, 0, 0, 76, 0, 76, 0, 450, 453,
- 76, 76, 0, 0, 0, 0, 0, 0, 0, 408,
- 76, 0, 0, 0, 0, 0, 0, 68, 0, 68,
- 0, 0, 0, 76, 0, 453, 0, 0, 0, 0,
- 70, 70, 0, 0, 0, 70, 73, 73, 0, 575,
- 157, 0, 73, 73, 73, 73, 73, 73, 189, 0,
- 0, 0, 0, 0, 70, 0, 0, 70, 0, 0,
- 73, 0, 0, 0, 0, 70, 0, 0, 0, 70,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 76, 0, 0, 76, 0, 73, 0, 0, 189, 0,
- 0, 0, 0, 0, 0, 76, 76, 0, 0, 0,
- 189, 0, 0, 76, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 76, 73, 349, 0, 75, 75,
- 0, 0, 0, 0, 75, 75, 75, 75, 75, 75,
- 190, 0, 0, 70, 0, 70, 0, 0, 0, 0,
- 0, 0, 75, 0, 0, 0, 0, 0, 76, 0,
- 0, 0, 0, 258,-32768,-32768,-32768,-32768, 263, 264,
- 76, 0,-32768,-32768, 0, 0, 76, 75, 271, 272,
- 190, 76, 76, 0, 0, 73, 76, 0, 0, 0,
- 0, 0, 190, 274, 275, 276, 277, 278, 279, 280,
- 281, 282, 283, 0, 0, 76, 0, 75, 76, 0,
- 76, 422, 0, 0, 0, 0, 76, 0, 0, 0,
- 76, 441, 0, 443, 0, 0, 0, 448, 0, 449,
- 0, 0, 0, 0, 0, 0, 0, 73, 0, 0,
- 0, 0, 258, 259, 260, 261, 262, 263, 264, 265,
- 266, 267, 268, 269, 270, 0, 475, 271, 272, 0,
- 0, 0, 0, 73, 0, 0, 0, 75, 73, 0,
- 273, 0, 274, 275, 276, 277, 278, 279, 280, 281,
- 282, 283, 0, 0, 76, 0, 76, 0, 0, 456,
- 73, 73, 73, 73, 73, 73, 73, 0, 0, 73,
- 189, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 75,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 503,
- 0, 0, 0, 0, 0, 0, 510, 0, 0, 0,
- 0, 0, 0, 0, 0, 75, 0, 522, 73, 0,
- 75, 0, 0, 0, 0, 0, 0, 0, 73, 0,
- 73, 0, 0, 0, 73, 0, 73, 0, 0, 0,
- 0, 73, 75, 75, 75, 75, 75, 75, 75, 0,
- 0, 75, 190, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 73, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 556, 557, 0, 0, 0, 558,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 189, 0, 0, 0, 0, 0, 0, 0, 572, 0,
- 75, 573, 0, 0, 0, 0, 0, 0, 0, 579,
- 75, 0, 75, 580, 0, 0, 75, 0, 75, 0,
- 0, 0, 0, 75, 0, 0, 0, 0, 0, 198,
- 198, 198, 0, 0, 0, 73, 73, 0, 0, 0,
- 0, 0, 0, 73, 0, 75, 0, 0, 0, 0,
- 0, 0, 0, 0, 73, 0, 0, 0, 219, 221,
- 0, 0, 227, 198, 0, 0, 239, 240, 0, 0,
- 0, 0, 190, 0, 0, 0, 0, 609, 0, 610,
- 0, 0, 0, 0, 0, 0, 0, 198, 73, 0,
- 0, 0, 0, 0, 0, 0, 0, 189, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 189, 73, 73, 0, 0, 0, 73, 75, 75, 0,
- 0, 0, 0, 0, 0, 75, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 73, 75, 0, 73, 0,
- 73, 0, 0, 0, 0, 0, 73, 0, 0, 0,
- 73, 0, 258, 259, 260, 261, 262, 263, 264, 265,
- 266, 267, 268, 269, 270, 0, 0, 271, 272, 0,
- 75, 0, 331, 0, 0, 0, 0, 0, 0, 190,
- 273, 0, 274, 275, 276, 277, 278, 279, 280, 281,
- 282, 283, 190, 75, 75, 0, 0, 0, 75, 0,
- 0, 0, 0, 0, 327, 328, 239, 198, 0, 0,
- 0, 0, 0, 0, 73, 0, 73, 75, 0, 198,
- 75, 198, 75, 0, 0, 0, 0, 0, 75, 0,
- 0, 0, 75, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 227, 0, 0, 0, 0, 0, 376,
- 377, 378, 379, 380, 381, 382, 383, 384, 385, 386,
- 387, 388, 389, 390, 391, 392, 393, 394, 395, 396,
- 397, 398, 399, 400, 401, 0, 75, 198, 75, 0,
- 0, 0, 0, 0, 415, 416, 198, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 227, 0, 0, 0, 0, 0, 227, 175, 175,
- 0, 175, 175, 0, 0, 0, 198, 0, 197, 197,
- 197, 0, 459, 461, 0, 175, 198, 467, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 474, 0,
- 0, 0, 0, 0, 0, 478, 0, 0, 0, 0,
- 0, 467, 0, 0, 0, 238, 0, 0, 0, 0,
- 0, 479, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 197, 0, 0, 0,
- 175, 0, 258, 259, 260, 261, 262, 263, 264, 265,
- 266, 267, 268, 269, 270, 0, 198, 271, 272, 198,
- 0, 0, 0, 0, 498, 499, 0, 0, 0, 0,
- 273, 484, 274, 275, 276, 277, 278, 279, 280, 281,
- 282, 283, 0, 0, 0, 0, 0, 0, 258, 259,
- 260, 261, 262, 263, 264, 529, 0, 267, 268, 0,
- 175, 0, 0, 271, 272, 0, 0, 0, 0, 0,
- 0, 536, 0, 0, 0, 0, 0, 540, 274, 275,
- 276, 277, 278, 279, 280, 281, 282, 283, 0, 0,
- 0, 478, 0, 0, 0, 545, 198, 0, 547, 548,
- 549, 550, 198, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 197, 561, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 197, 0,
- 197, 0, 478, 0, 0, 0, 0, 0, 0, 0,
- 0, 478, 0, 0, 0, 0, 0, 0, 467, 0,
- 0, 0, 0, 0, 585, 0, 0, 0, 0, 0,
- 0, 0, 0, 588, 589, 0, 175, 175, 175, 175,
- 175, 175, 0, 0, 0, 0, 0, 0, 0, 0,
- -4, 2, 0, 3, 4, 5, 6, 7, 0, 602,
- 0, 8, 9, 607, 0, 0, 10, 0, 11, 12,
- 13, 14, 15, 16, 17, 0, 197, 18, 19, 20,
- 21, 22, 23, 24, 0, 197, 25, 0, 0, 0,
- 0, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
- 45, 46, 47, 48, 0, 197, 175, 0, 0, 0,
- 0, 0, 0, 0, 0, 197, 0, 0, 0, 0,
- 0, 0, 49, 0, 0, 50, 51, 52, 53, 0,
- 54, 0, 0, 0, 0, 0, 0, 0, -298, 0,
- 0, 0, 0, 0, 55, 56, -298, -298, -298, 0,
- 0, 0, -298, -298, 0, -298, -4, -4, 0, 0,
- 0, 0, 0, 0, -269, 0, 0, 0, 0, 0,
- 0, 0, -298, -298, 0, -298, -298, -298, -298, 0,
- 0, 0, 0, 0, 0, 197, 0, 0, 197, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 175, 0, -298, -298, -298, -298, -298, -298, -298, -298,
- -298, -298, -298, -298, -298, 0, 0, -298, -298, -298,
- 0, -298, 0, 0, 0, 0, 0, 0, 0, -298,
- -298, 0, -298, -298, -298, -298, -298, -298, -298, -298,
- -298, -298, 0, 0, 0, 0, -298, -298, -298, -298,
- -298, 0, -301, 175, -298, -298, 0, 0, 0, 0,
- -301, -301, -301, 0, 0, 197, -301, -301, 0, -301,
- 0, 197, 0, 0, 0, 0, 0, 0, -270, 0,
- 0, 0, 0, 0, 0, 0, -301, -301, 0, -301,
- -301, -301, -301, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 175, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, -301, -301, -301, -301,
- -301, -301, -301, -301, -301, -301, -301, -301, -301, 0,
- 0, -301, -301, -301, 0, -301, 0, 0, 0, 0,
- 0, 0, 0, -301, -301, 0, -301, -301, -301, -301,
- -301, -301, -301, -301, -301, -301, 0, -223, 0, 0,
- -301, -301, -301, -301, -301, -223, -223, -223, -301, -301,
- 0, -223, -223, 0, -223, 0, 0, 0, 0, 0,
- 0, 0, 0, -271, 0, 0, 0, 0, 0, 0,
- 0, -223, -223, 0, -223, -223, -223, -223, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, -223, -223, -223, -223, -223, -223, -223, -223, -223,
- -223, -223, -223, -223, 0, 0, -223, -223, -223, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, -223,
- 0, -223, -223, -223, -223, -223, -223, -223, -223, -223,
- -223, 0, 0, 0, 0, -223, -223, -223, 0, -223,
- 0, 0, 0, -223, -223, 2, 0, 3, 4, 5,
- 6, 7, -4, -4, -4, 8, 9, 0, 0, -4,
- 10, 0, 11, 12, 13, 14, 15, 16, 17, 0,
- 0, 18, 19, 20, 21, 22, 23, 24, 0, 0,
- 25, 0, 0, 0, 0, 26, 27, 28, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 49, 0, 0, 50,
- 51, 52, 53, 0, 54, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 55, 56,
- 0, 0, 0, 2, 0, 3, 4, 5, 6, 7,
- -4, -4, -4, 8, 9, 0, -4, -4, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 18,
- 19, 20, 21, 22, 23, 24, 0, 0, 25, 0,
- 0, 0, 0, 26, 27, 28, 29, 30, 31, 32,
- 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 50, 51, 52,
- 53, 0, 54, 0, 2, 0, 3, 4, 5, 6,
- 7, 0, 0, -4, 8, 9, 55, 56, -4, 10,
- -4, 11, 12, 13, 14, 15, 16, 17, -4, -4,
- 18, 19, 20, 21, 22, 23, 24, 0, 0, 25,
- 0, 0, 0, 0, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
- 42, 43, 44, 45, 46, 47, 48, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 49, 0, 0, 50, 51,
- 52, 53, 0, 54, 0, 2, 0, 3, 4, 5,
- 6, 7, 0, 0, -4, 8, 9, 55, 56, -4,
- 10, 0, 11, 12, 13, 14, 15, 16, 17, -4,
- -4, 18, 19, 20, 21, 22, 23, 24, 0, 0,
- 25, 0, 0, 0, 0, 26, 27, 28, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 49, 0, 0, 50,
- 51, 52, 53, 0, 54, 0, 2, 0, 3, 4,
- 5, 6, 7, 0, -4, -4, 8, 9, 55, 56,
- 0, 10, 0, 11, 12, 13, 14, 15, 16, 17,
- -4, -4, 18, 19, 20, 21, 22, 23, 24, 0,
- 0, 25, 0, 0, 0, 0, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47, 48, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 49, 0, 0,
- 50, 51, 52, 53, 0, 54, 0, 2, 0, 3,
- 4, 5, 6, 7, 0, 0, 0, 8, 9, 55,
- 56, 0, 10, -4, 11, 12, 13, 14, 15, 16,
- 17, -4, -4, 18, 19, 20, 21, 22, 23, 24,
- 0, 0, 25, 0, 0, 0, 0, 26, 27, 28,
- 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 49, 0,
- 0, 50, 51, 52, 53, 0, 54, 0, 2, 0,
- 3, 4, 5, 6, 7, 0, 0, 0, 8, 9,
- 55, 56, 0, 10, 0, 11, 12, 13, 14, 15,
- 16, 17, -4, -4, 18, 19, 20, 21, 22, 23,
- 24, 0, 0, 25, 0, 0, 0, 0, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 49,
- 0, 0, 223, 51, 52, 53, 0, 54, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 55, 56, 0, 0, 0, 2, -4, 3, 4,
- 5, 6, 7, -4, -4, 0, 8, 9, 0, 0,
- 0, 10, 0, 11, 12, 13, 14, 15, 16, 17,
- 0, 0, 18, 19, 20, 21, 22, 23, 24, 0,
- 0, 25, 0, 0, 0, 0, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47, 48, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 49, 0, 0,
- 50, 51, 52, 53, 0, 54, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 55,
- 56, 0, 0, 0, 2, -4, 3, 4, 5, 6,
- 7, -4, -4, 0, 8, 9, 0, 0, 0, 10,
- 0, 11, 12, 13, 14, 15, 16, 17, 0, 0,
- 18, 19, 20, 21, 22, 23, 24, 0, 0, 25,
- 0, 0, 0, 0, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
- 42, 43, 44, 45, 46, 47, 48, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 49, 0, 0, 50, 51,
- 52, 53, 0, 54, 0, 2, 0, 3, 4, 5,
- 6, 7, 0, 0, -4, 8, 9, 55, 56, 0,
- 10, -4, 11, 12, 13, 14, 15, 16, 17, -4,
- -4, 18, 19, 20, 21, 22, 23, 24, 0, 0,
- 25, 0, 0, 0, 0, 26, 27, 28, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 49, 0, 0, 50,
- 51, 52, 53, 0, 54, 0, 0, 0, 3, 4,
- 5, 6, 7, 0, 0, 0, 8, 9, 55, 56,
- 0, 10, 0, 11, 12, 13, 14, 15, 16, 17,
- -4, -4, 18, 19, 20, 21, 22, 23, 24, 0,
- 0, 25, 0, 0, 0, 0, 26, 27, 28, 29,
- 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
- 40, 41, 42, 43, 44, 45, 46, 47, 48, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 49, 0, 0,
- 50, 51, 52, 53, 0, 54, 0, 0, 0, 3,
- 4, 5, 0, 7, 0, 0, 0, 8, 9, 55,
- 56, 0, 10, 0, 11, 12, 13, 14, 15, 16,
- 17, 0, 362, 181, 182, 20, 21, 22, 23, 24,
- 0, 0, 0, 0, 0, 0, 0, 0, 27, 0,
- 0, 30, 31, 171, 172, 34, 35, 173, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 49, 0,
- 0, 192, 51, 52, 193, 194, 54, 0, 0, -343,
- -343, -343, 0, -343, 0, 0, 0, -343, -343, 0,
- 195, 56, -343, 289, -343, -343, -343, -343, -343, -343,
- -343, 295, 0, -343, -343, -343, -343, -343, -343, -343,
- 0, 0, 0, 0, 0, 0, 0, 0, -343, 0,
- 0, -343, -343, -343, -343, -343, -343, -343, -343, -343,
- -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, -343, 0,
- 0, -343, -343, -343, -343, -343, -343, 0, 0, -345,
- -345, -345, 0, -345, 0, 0, 0, -345, -345, 0,
- -343, -343, -345, -343, -345, -345, -345, -345, -345, -345,
- -345, -343, 0, -345, -345, -345, -345, -345, -345, -345,
- 0, 0, 0, 0, 0, 0, 0, 0, -345, 0,
- 0, -345, -345, -345, -345, -345, -345, -345, -345, -345,
- -345, -345, -345, -345, -345, -345, -345, -345, -345, -345,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, -345, 0,
- 0, -345, -345, -345, -345, -345, -345, 0, 0, -344,
- -344, -344, 0, -344, 0, 0, 0, -344, -344, 0,
- -345, -345, -344, -345, -344, -344, -344, -344, -344, -344,
- -344, -345, 0, -344, -344, -344, -344, -344, -344, -344,
- 0, 0, 0, 0, 0, 0, 0, 0, -344, 0,
- 0, -344, -344, -344, -344, -344, -344, -344, -344, -344,
- -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, -344, 0,
- 0, -344, -344, -344, -344, -344, -344, 0, 0, 3,
- 4, 5, 0, 7, 0, 0, 0, 8, 9, 0,
- -344, -344, 10, -344, 11, 12, 13, 14, 15, 16,
- 17, -344, 0, 181, 182, 20, 21, 22, 23, 24,
- 0, 0, 0, 0, 0, 0, 0, 0, 27, 0,
- 0, 30, 31, 171, 172, 34, 35, 173, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 49, 0,
- 0, 192, 51, 52, 193, 194, 54, 0, 0, 3,
- 4, 5, 0, 7, 0, 0, 0, 8, 9, 0,
- 195, 56, 10, 0, 11, 12, 13, 14, 15, 16,
- 17, 196, 0, 181, 182, 20, 21, 22, 23, 24,
- 0, 0, 0, 0, 0, 0, 0, 0, 27, 0,
- 0, 30, 31, 171, 172, 34, 35, 173, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 49, 0,
- 0, 192, 51, 52, 193, 194, 54, 0, 0, 3,
- 4, 5, 0, 7, 0, 0, 0, 8, 9, 0,
- 195, 56, 10, 0, 11, 12, 13, 14, 15, 16,
- 17, 208, 0, 181, 182, 20, 21, 22, 23, 24,
- 0, 0, 0, 0, 0, 0, 0, 0, 27, 0,
- 0, 30, 31, 171, 172, 34, 35, 173, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 49, 0,
- 0, 192, 51, 52, 193, 194, 54, 0, 0, -343,
- -343, -343, 0, -343, 0, 0, 0, -343, -343, 0,
- 195, 56, -343, 0, -343, -343, -343, -343, -343, -343,
- -343, 210, 0, -343, -343, -343, -343, -343, -343, -343,
- 0, 0, 0, 0, 0, 0, 0, 0, -343, 0,
- 0, -343, -343, -343, -343, -343, -343, -343, -343, -343,
- -343, -343, -343, -343, -343, -343, -343, -343, -343, -343,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, -343, 0,
- 0, -343, -343, -343, -343, -343, -343, 0, 0, -344,
- -344, -344, 0, -344, 0, 0, 0, -344, -344, 0,
- -343, -343, -344, 0, -344, -344, -344, -344, -344, -344,
- -344, -343, 0, -344, -344, -344, -344, -344, -344, -344,
- 0, 0, 0, 0, 0, 0, 0, 0, -344, 0,
- 0, -344, -344, -344, -344, -344, -344, -344, -344, -344,
- -344, -344, -344, -344, -344, -344, -344, -344, -344, -344,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, -344, 0,
- 0, -344, -344, -344, -344, -344, -344, 0, 0, 3,
- 4, 5, 0, 7, 0, 0, 0, 8, 9, 0,
- -344, -344, 10, 0, 11, 12, 13, 14, 15, 16,
- 17, -344, 0, 181, 182, 20, 21, 22, 23, 24,
- 0, 0, 0, 0, 0, 0, 0, 0, 27, 0,
- 0, 30, 31, 171, 172, 34, 35, 173, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 49, 0,
- 0, 192, 51, 52, 193, 194, 54, 0, 0, 3,
- 4, 5, 0, 7, 0, 0, 0, 8, 9, 0,
- 195, 56, 10, 0, 11, 12, 13, 14, 15, 16,
- 17, 485, 0, 181, 182, 20, 21, 22, 23, 24,
- 0, 0, 0, 0, 0, 0, 0, 0, 27, 0,
- 0, 30, 31, 171, 172, 34, 35, 173, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 49, 0,
- 0, 192, 51, 52, 193, 194, 54, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 195, 56, 83, 84, 85, 86, 87, 88, 89, 90,
- 0, 491, 91, 92, 93, 94, 95, 0, 0, 96,
- 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
- 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
- 117, 118, 119, 120, 121, 122, 123, 124, 34, 35,
- 125, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 126, 127, 128, 129, 130, 131, 0, 132, 133,
- 0, 0, 134, 0, 135, 0, 136, 137, 138, 139,
- 0, 0, 0, 0, 140, 0, 0, 141, 0, 0,
- 0, 0, 0, 142, 143, 144, 145, 146, 147, 148,
- 149, 150, 151, 0, 152, 83, 84, 85, 86, 87,
- 88, 89, 90, 153, 0, 91, 92, 93, 94, 95,
- 0, 0, 96, 97, 98, 99, 100, 101, 102, 103,
- 104, 105, 160, 161, 162, 163, 110, 111, 112, 113,
- 114, 115, 116, 117, 118, 119, 120, 164, 165, 166,
- 124, 234, 235, 167, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 126, 127, 128, 129, 130, 131,
- 0, 132, 133, 0, 0, 134, 0, 135, 0, 136,
- 137, 138, 139, 0, 0, 0, 0, 0, 0, 0,
- 141, 0, 0, 0, 0, 0, 142, 143, 144, 145,
- 146, 147, 148, 149, 150, 151, 0, 152, 83, 84,
- 85, 86, 87, 88, 89, 90, 153, 0, 91, 92,
- 93, 94, 95, 0, 0, 96, 97, 98, 99, 100,
- 101, 102, 103, 104, 105, 160, 161, 162, 163, 110,
- 111, 112, 113, 114, 115, 116, 117, 118, 119, 120,
- 164, 165, 166, 124, 213, 0, 167, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 126, 127, 128,
- 129, 130, 131, 0, 132, 133, 0, 0, 134, 0,
- 135, 0, 136, 137, 138, 139, 0, 0, 0, 0,
- 0, 0, 0, 141, 0, 0, 0, 0, 0, 142,
- 143, 144, 145, 146, 147, 148, 149, 150, 151, 0,
- 152, 83, 84, 85, 86, 87, 88, 89, 90, 153,
- 0, 91, 92, 93, 94, 95, 0, 0, 96, 97,
- 98, 99, 100, 101, 102, 103, 104, 105, 160, 161,
- 162, 163, 110, 111, 112, 113, 114, 115, 116, 117,
- 118, 119, 120, 164, 165, 166, 124, 0, 0, 167,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 126, 127, 128, 129, 130, 131, 0, 132, 133, 0,
- 0, 134, 0, 135, 0, 136, 137, 138, 139, 0,
- 0, 0, 0, 0, 0, 0, 141, 0, 0, 0,
- 0, 0, 142, 143, 144, 145, 146, 147, 148, 149,
- 150, 151, 0, 152, 0, 3, 4, 5, 0, 7,
- 0, 0, 153, 8, 9, 0, 0, 0, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 181,
- 182, 20, 21, 22, 23, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 27, 0, 0, 30, 31, 171,
- 172, 34, 35, 173, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 192, 51, 52,
- 193, 194, 54, 0, 0, 0, 0, 0, 0, 0,
- 3, 4, 5, 0, 7, 0, 195, 56, 8, 9,
- 0, 0, 329, 10, 0, 11, 12, 13, 14, 15,
- 16, 17, 0, 0, 181, 182, 20, 21, 22, 23,
- 24, 0, 0, 0, 0, 0, 0, 0, 0, 27,
- 0, 0, 30, 31, 171, 172, 34, 35, 173, 37,
- 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 49,
- 0, 0, 192, 51, 52, 193, 194, 54, 0, 0,
- 0, 0, 0, 0, 0, 3, 4, 5, 6, 7,
- 0, 195, 56, 8, 9, 0, 0, 338, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 18,
- 19, 20, 21, 22, 23, 24, 0, 0, 25, 0,
- 0, 0, 0, 26, 27, 28, 29, 30, 31, 32,
- 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 50, 51, 52,
- 53, 0, 54, 0, 0, 3, 4, 5, 0, 7,
- 0, 0, 0, 8, 9, 0, 55, 56, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 18,
- 19, 20, 21, 22, 23, 24, 0, 0, 25, 0,
- 0, 0, 0, 0, 27, 0, 0, 30, 31, 171,
- 172, 34, 35, 173, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 50, 51, 52,
- 53, 0, 54, 0, 0, 3, 4, 5, 0, 7,
- 0, 0, 0, 8, 9, 0, 55, 56, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 181,
- 182, 20, 21, 22, 23, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 27, 0, 0, 30, 31, 171,
- 172, 34, 35, 173, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 192, 51, 52,
- 193, 194, 54, 0, 0, 3, 4, 5, 0, 7,
- 0, 0, 0, 8, 9, 0, 195, 56, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 181,
- 182, 183, 21, 22, 23, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 27, 0, 0, 30, 31, 171,
- 172, 34, 35, 173, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 192, 51, 52,
- 460, 194, 54, 0, 0, 3, 4, 5, 0, 7,
- 0, 0, 0, 8, 9, 0, 195, 56, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 181,
- 182, 183, 21, 22, 23, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 27, 0, 0, 30, 31, 171,
- 172, 34, 35, 173, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 192, 51, 52,
- 466, 194, 54, 0, 0, 3, 4, 5, 0, 7,
- 0, 0, 0, 8, 9, 0, 195, 56, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 181,
- 182, 183, 21, 22, 23, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 27, 0, 0, 30, 31, 171,
- 172, 34, 35, 173, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 192, 51, 52,
- 582, 194, 54, 0, 0, 3, 4, 5, 0, 7,
- 0, 0, 0, 8, 9, 0, 195, 56, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 181,
- 182, 183, 21, 22, 23, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 27, 0, 0, 30, 31, 171,
- 172, 34, 35, 173, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 192, 51, 52,
- 370, 0, 54, 0, 0, 3, 4, 5, 0, 7,
- 0, 0, 0, 8, 9, 0, 195, 56, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 181,
- 182, 183, 21, 22, 23, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 27, 0, 0, 30, 31, 171,
- 172, 34, 35, 173, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 192, 51, 52,
- 444, 0, 54, 0, 0, 3, 4, 5, 0, 7,
- 0, 0, 0, 8, 9, 0, 195, 56, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 181,
- 182, 183, 21, 22, 23, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 27, 0, 0, 30, 31, 171,
- 172, 34, 35, 173, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 192, 51, 52,
- 543, 0, 54, 0, 0, 3, 4, 5, 0, 7,
- 0, 0, 0, 8, 9, 0, 195, 56, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 181,
- 182, 183, 21, 22, 23, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 27, 0, 0, 30, 31, 171,
- 172, 34, 35, 173, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 192, 51, 52,
- 578, 0, 54, 0, 0, 3, 4, 5, 0, 7,
- 0, 0, 0, 8, 9, 0, 195, 56, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 181,
- 182, 183, 21, 22, 23, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 27, 0, 0, 30, 31, 171,
- 172, 34, 35, 173, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 192, 51, 52,
- 0, 0, 54, 0, 0, 3, 4, 5, 0, 7,
- 0, 0, 0, 8, 9, 0, 195, 56, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 181,
- 182, 20, 21, 22, 23, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 27, 0, 0, 30, 31, 171,
- 172, 34, 35, 173, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 47, 48, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 192, 51, 52,
- 0, 0, 54, 0, 0, 3, 4, 5, 0, 7,
- 0, 0, 0, 8, 9, 0, 195, 56, 10, 0,
- 11, 12, 13, 14, 15, 16, 17, 0, 0, 181,
- 182, 183, 21, 22, 23, 24, 0, 0, 0, 0,
- 0, 0, 0, 0, 184, 0, 0, 30, 31, 171,
- 172, 34, 35, 173, 37, 38, 39, 40, 41, 42,
- 43, 44, 45, 46, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 49, 0, 0, 50, 51, 52,
- 53, 0, 54, 3, 4, 5, 0, 7, 554, 0,
- 0, 8, 9, 0, 0, 0, 10, 0, 11, 12,
- 13, 14, 15, 16, 17, 0, 0, 181, 182, 183,
- 21, 22, 23, 24, 0, 0, 0, 0, 0, 0,
- 0, 0, 184, 0, 0, 30, 31, 171, 172, 34,
- 35, 173, 37, 38, 39, 40, 41, 42, 43, 44,
- 45, 46, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 49, 0, 0, 50, 51, 52, 53, 0,
- 54, 3, 4, 5, 0, 7, 0, 0, 0, 8,
- 9, 0, 0, 0, 10, 0, 11, 12, 13, 14,
- 15, 16, 17, 0, 0, 181, 182, 183, 21, 22,
- 23, 24, 0, 0, 0, 0, 0, 0, 0, 0,
- 184, 0, 0, 30, 31, 171, 172, 34, 35, 173,
- 37, 38, 39, 40, 41, 42, 43, 44, 45, 46,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 49, 0, 0, 254, 51, 52, 255, 0, 54, 3,
- 4, 5, 0, 7, 0, 0, 0, 8, 9, 0,
- 0, 0, 10, 0, 11, 12, 13, 14, 15, 16,
- 17, 0, 0, 181, 182, 183, 21, 22, 23, 24,
- 0, 0, 0, 0, 0, 0, 0, 0, 184, 0,
- 0, 30, 31, 171, 172, 34, 35, 173, 37, 38,
- 39, 40, 41, 42, 43, 44, 45, 46, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 49, 0,
- 0, 254, 51, 52, 482, 0, 54, 3, 4, 5,
- 0, 7, 0, 0, 0, 8, 9, 0, 0, 0,
- 10, 0, 11, 12, 13, 14, 15, 16, 17, 0,
- 0, 181, 182, 183, 21, 22, 23, 24, 0, 0,
- 0, 0, 0, 0, 0, 0, 184, 0, 0, 30,
- 31, 171, 172, 34, 35, 173, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 0, 258, 259, 260,
- 261, 262, 263, 264, 265, 266, 267, 268, 269, 270,
- 0, 0, 271, 272, 0, 0, 49, 0, 0, 192,
- 51, 52, 0, 0, 54, 273, 0, 274, 275, 276,
- 277, 278, 279, 280, 281, 282, 283, 258, 259, 260,
- 261, 262, 263, 264, 265, 266, 267, 268,-32768,-32768,
- 0, 0, 271, 272, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 274, 275, 276,
- 277, 278, 279, 280, 281, 282, 283, 258, 259, 260,
- 261, 262, 263, 264, 265, 0, 267, 268, 0, 0,
- 0, 0, 271, 272, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 274, 275, 276,
- 277, 278, 279, 280, 281, 282, 283
-};
-
-static const short yycheck[] = { 1,
- 2, 58, 13, 177, 206, 7, 8, 9, 10, 11,
- 12, 13, 6, 210, 184, 65, 18, 19, 20, 52,
- 180, 311, 50, 25, 81, 18, 19, 20, 13, 76,
- 305, 332, 26, 2, 336, 336, 19, 13, 51, 52,
- 26, 1, 432, 433, 47, 13, 26, 26, 50, 4,
- 512, 53, 514, 55, 34, 35, 34, 35, 360, 47,
- 54, 34, 35, 65, 34, 35, 34, 35, 53, 514,
- 116, 81, 47, 223, 76, 47, 47, 325, 80, 51,
- 81, 81, 81, 76, 49, 88, 89, 335, 111, 107,
- 116, 117, 81, 116, 49, 60, 61, 115, 295, 109,
- 88, 89, 8, 9, 254, 11, 12, 79, 109, 109,
- 109, 112, 115, 88, 89, 1, 2, 88, 89, 25,
- 109, 7, 179, 180, 10, 327, 34, 35, 107, 64,
- 116, 117, 110, 595, 304, 95, 116, 117, 140, 72,
- 116, 117, 81, 116, 191, 107, 116, 117, 116, 117,
- 595, 81, 427, 443, 91, 456, 116, 117, 81, 81,
- 81, 26, 64, 96, 50, 81, 101, 102, 103, 111,
- 109, 341, 26, 112, 80, 565, 566, 79, 80, 109,
- 570, 47, 112, 81, 111, 51, 109, 109, 109, 112,
- 192, 112, 64, 109, 196, 223, 98, 99, 100, 101,
- 102, 103, 111, 196, 83, 81, 208, 116, 210, 107,
- 81, 109, 91, 196, 112, 208, 218, 115, 608, 8,
- 15, 223, 17, 81, 107, 208, 254, 99, 100, 101,
- 102, 103, 111, 109, 140, 537, 537, 17, 109, 252,
- 81, 298, 299, 245, 246, 247, 248, 249, 250, 251,
- 83, 109, 254, 255, 112, 81, 1, 2, 91, 14,
- 15, 463, 7, 8, 9, 10, 11, 12, 109, 115,
- 255, 112, 446, 18, 19, 20, 245, 437, 111, 83,
- 25, 47, 48, 109, 286, 51, 115, 91, 485, 579,
- 83, 115, 83, 295, 491, 455, 571, 310, 91, 332,
- 91, 303, 111, 316, 83, 50, 192, 111, 83, 25,
- 55, 313, 91, 315, 83, 111, 91, 319, 111, 321,
- 83, 111, 91, 325, 326, 375, 47, 48, 91, 115,
- 51, 76, 218, 335, 536, 80, 107, 223, 540, 509,
- 246, 247, 248, 249, 250, 251, 348, 64, 230, 64,
- 232, 345, 47, 48, 64, 113, 51, 47, 48, 245,
- 110, 51, 110, 111, 79, 80, 110, 110, 254, 79,
- 80, 108, 429, 375, 37, 38, 39, 40, 111, 15,
- 437, 96, 97, 98, 99, 100, 101, 102, 103, 99,
- 100, 101, 102, 103, 13, 140, 10, 110, 455, 110,
- 10, 575, 110, 405, 108, 607, 408, 110, 113, 111,
- 111, 110, 405, 110, 110, 408, 91, 303, 420, 421,
- 326, 47, 47, 111, 111, 111, 428, 313, 111, 315,
- 9, 111, 10, 319, 10, 321, 115, 439, 115, 113,
- 89, 435, 436, 111, 113, 502, 108, 192, 10, 10,
- 89, 196, 10, 10, 10, 110, 110, 10, 96, 10,
- 108, 111, 348, 208, 110, 210, 10, 10, 0, 0,
- 610, 473, 412, 218, 495, 579, 572, 5, 223, 1,
- 482, 571, 427, 485, 495, 7, -1, 512, 10, 491,
- -1, -1, -1, 495, 496, 497, -1, 482, -1, 501,
- 245, 246, 247, 248, 249, 250, 251, -1, -1, 254,
- 495, -1, -1, -1, 420, -1, -1, -1, 520, -1,
- -1, 523, -1, 525, -1, -1, -1, -1, -1, 531,
- -1, -1, -1, 535, -1, 421, -1, -1, -1, 284,
- 285, 286, 428, -1, -1, -1, -1, -1, -1, -1,
- 295, -1, -1, 439, -1, -1, -1, -1, 303, -1,
- -1, -1, -1, -1, -1, -1, -1, 473, 313, -1,
- 315, -1, -1, -1, 319, -1, 321, -1, 323, 324,
- 325, 326, -1, -1, -1, -1, -1, -1, -1, 334,
- 335, -1, -1, -1, -1, -1, -1, 599, -1, 601,
- -1, -1, -1, 348, -1, 350, -1, -1, -1, -1,
- 496, 497, -1, -1, -1, 501, 1, 2, -1, 525,
- 5, -1, 7, 8, 9, 10, 11, 12, 13, -1,
- -1, -1, -1, -1, 520, -1, -1, 523, -1, -1,
- 25, -1, -1, -1, -1, 531, -1, -1, -1, 535,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 405, -1, -1, 408, -1, 50, -1, -1, 53, -1,
- -1, -1, -1, -1, -1, 420, 421, -1, -1, -1,
- 65, -1, -1, 428, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 439, 80, 218, -1, 1, 2,
- -1, -1, -1, -1, 7, 8, 9, 10, 11, 12,
- 13, -1, -1, 599, -1, 601, -1, -1, -1, -1,
- -1, -1, 25, -1, -1, -1, -1, -1, 473, -1,
- -1, -1, -1, 64, 65, 66, 67, 68, 69, 70,
- 485, -1, 73, 74, -1, -1, 491, 50, 79, 80,
- 53, 496, 497, -1, -1, 140, 501, -1, -1, -1,
- -1, -1, 65, 94, 95, 96, 97, 98, 99, 100,
- 101, 102, 103, -1, -1, 520, -1, 80, 523, -1,
- 525, 303, -1, -1, -1, -1, 531, -1, -1, -1,
- 535, 313, -1, 315, -1, -1, -1, 319, -1, 321,
- -1, -1, -1, -1, -1, -1, -1, 192, -1, -1,
- -1, -1, 64, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, -1, 348, 79, 80, -1,
- -1, -1, -1, 218, -1, -1, -1, 140, 223, -1,
- 92, -1, 94, 95, 96, 97, 98, 99, 100, 101,
- 102, 103, -1, -1, 599, -1, 601, -1, -1, 111,
- 245, 246, 247, 248, 249, 250, 251, -1, -1, 254,
- 255, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 192,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 421,
- -1, -1, -1, -1, -1, -1, 428, -1, -1, -1,
- -1, -1, -1, -1, -1, 218, -1, 439, 303, -1,
- 223, -1, -1, -1, -1, -1, -1, -1, 313, -1,
- 315, -1, -1, -1, 319, -1, 321, -1, -1, -1,
- -1, 326, 245, 246, 247, 248, 249, 250, 251, -1,
- -1, 254, 255, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 348, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 496, 497, -1, -1, -1, 501,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 375, -1, -1, -1, -1, -1, -1, -1, 520, -1,
- 303, 523, -1, -1, -1, -1, -1, -1, -1, 531,
- 313, -1, 315, 535, -1, -1, 319, -1, 321, -1,
- -1, -1, -1, 326, -1, -1, -1, -1, -1, 18,
- 19, 20, -1, -1, -1, 420, 421, -1, -1, -1,
- -1, -1, -1, 428, -1, 348, -1, -1, -1, -1,
- -1, -1, -1, -1, 439, -1, -1, -1, 47, 48,
- -1, -1, 51, 52, -1, -1, 55, 56, -1, -1,
- -1, -1, 375, -1, -1, -1, -1, 599, -1, 601,
- -1, -1, -1, -1, -1, -1, -1, 76, 473, -1,
- -1, -1, -1, -1, -1, -1, -1, 482, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 495, 496, 497, -1, -1, -1, 501, 420, 421, -1,
- -1, -1, -1, -1, -1, 428, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 520, 439, -1, 523, -1,
- 525, -1, -1, -1, -1, -1, 531, -1, -1, -1,
- 535, -1, 64, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, -1, -1, 79, 80, -1,
- 473, -1, 84, -1, -1, -1, -1, -1, -1, 482,
- 92, -1, 94, 95, 96, 97, 98, 99, 100, 101,
- 102, 103, 495, 496, 497, -1, -1, -1, 501, -1,
- -1, -1, -1, -1, 193, 194, 195, 196, -1, -1,
- -1, -1, -1, -1, 599, -1, 601, 520, -1, 208,
- 523, 210, 525, -1, -1, -1, -1, -1, 531, -1,
- -1, -1, 535, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 252, -1, -1, -1, -1, -1, 258,
- 259, 260, 261, 262, 263, 264, 265, 266, 267, 268,
- 269, 270, 271, 272, 273, 274, 275, 276, 277, 278,
- 279, 280, 281, 282, 283, -1, 599, 286, 601, -1,
- -1, -1, -1, -1, 293, 294, 295, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 310, -1, -1, -1, -1, -1, 316, 8, 9,
- -1, 11, 12, -1, -1, -1, 325, -1, 18, 19,
- 20, -1, 331, 332, -1, 25, 335, 336, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 347, -1,
- -1, -1, -1, -1, -1, 354, -1, -1, -1, -1,
- -1, 360, -1, -1, -1, 55, -1, -1, -1, -1,
- -1, 370, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 76, -1, -1, -1,
- 80, -1, 64, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, -1, 405, 79, 80, 408,
- -1, -1, -1, -1, 413, 414, -1, -1, -1, -1,
- 92, 93, 94, 95, 96, 97, 98, 99, 100, 101,
- 102, 103, -1, -1, -1, -1, -1, -1, 64, 65,
- 66, 67, 68, 69, 70, 444, -1, 73, 74, -1,
- 140, -1, -1, 79, 80, -1, -1, -1, -1, -1,
- -1, 460, -1, -1, -1, -1, -1, 466, 94, 95,
- 96, 97, 98, 99, 100, 101, 102, 103, -1, -1,
- -1, 480, -1, -1, -1, 484, 485, -1, 487, 488,
- 489, 490, 491, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 196, 506, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 208, -1,
- 210, -1, 521, -1, -1, -1, -1, -1, -1, -1,
- -1, 530, -1, -1, -1, -1, -1, -1, 537, -1,
- -1, -1, -1, -1, 543, -1, -1, -1, -1, -1,
- -1, -1, -1, 552, 553, -1, 246, 247, 248, 249,
- 250, 251, -1, -1, -1, -1, -1, -1, -1, -1,
- 0, 1, -1, 3, 4, 5, 6, 7, -1, 578,
- -1, 11, 12, 582, -1, -1, 16, -1, 18, 19,
- 20, 21, 22, 23, 24, -1, 286, 27, 28, 29,
- 30, 31, 32, 33, -1, 295, 36, -1, -1, -1,
- -1, 41, 42, 43, 44, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
- 60, 61, 62, 63, -1, 325, 326, -1, -1, -1,
- -1, -1, -1, -1, -1, 335, -1, -1, -1, -1,
- -1, -1, 82, -1, -1, 85, 86, 87, 88, -1,
- 90, -1, -1, -1, -1, -1, -1, -1, 0, -1,
- -1, -1, -1, -1, 104, 105, 8, 9, 10, -1,
- -1, -1, 14, 15, -1, 17, 116, 117, -1, -1,
- -1, -1, -1, -1, 26, -1, -1, -1, -1, -1,
- -1, -1, 34, 35, -1, 37, 38, 39, 40, -1,
- -1, -1, -1, -1, -1, 405, -1, -1, 408, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 420, -1, 64, 65, 66, 67, 68, 69, 70, 71,
- 72, 73, 74, 75, 76, -1, -1, 79, 80, 81,
- -1, 83, -1, -1, -1, -1, -1, -1, -1, 91,
- 92, -1, 94, 95, 96, 97, 98, 99, 100, 101,
- 102, 103, -1, -1, -1, -1, 108, 109, 110, 111,
- 112, -1, 0, 473, 116, 117, -1, -1, -1, -1,
- 8, 9, 10, -1, -1, 485, 14, 15, -1, 17,
- -1, 491, -1, -1, -1, -1, -1, -1, 26, -1,
- -1, -1, -1, -1, -1, -1, 34, 35, -1, 37,
- 38, 39, 40, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 525, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 64, 65, 66, 67,
- 68, 69, 70, 71, 72, 73, 74, 75, 76, -1,
- -1, 79, 80, 81, -1, 83, -1, -1, -1, -1,
- -1, -1, -1, 91, 92, -1, 94, 95, 96, 97,
- 98, 99, 100, 101, 102, 103, -1, 0, -1, -1,
- 108, 109, 110, 111, 112, 8, 9, 10, 116, 117,
- -1, 14, 15, -1, 17, -1, -1, -1, -1, -1,
- -1, -1, -1, 26, -1, -1, -1, -1, -1, -1,
- -1, 34, 35, -1, 37, 38, 39, 40, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 64, 65, 66, 67, 68, 69, 70, 71, 72,
- 73, 74, 75, 76, -1, -1, 79, 80, 81, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 92,
- -1, 94, 95, 96, 97, 98, 99, 100, 101, 102,
- 103, -1, -1, -1, -1, 108, 109, 110, -1, 112,
- -1, -1, -1, 116, 117, 1, -1, 3, 4, 5,
- 6, 7, 8, 9, 10, 11, 12, -1, -1, 15,
- 16, -1, 18, 19, 20, 21, 22, 23, 24, -1,
- -1, 27, 28, 29, 30, 31, 32, 33, -1, -1,
- 36, -1, -1, -1, -1, 41, 42, 43, 44, 45,
- 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 82, -1, -1, 85,
- 86, 87, 88, -1, 90, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 104, 105,
- -1, -1, -1, 1, -1, 3, 4, 5, 6, 7,
- 116, 117, 10, 11, 12, -1, 14, 15, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, 36, -1,
- -1, -1, -1, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- 88, -1, 90, -1, 1, -1, 3, 4, 5, 6,
- 7, -1, -1, 10, 11, 12, 104, 105, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 116, 117,
- 27, 28, 29, 30, 31, 32, 33, -1, -1, 36,
- -1, -1, -1, -1, 41, 42, 43, 44, 45, 46,
- 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- 57, 58, 59, 60, 61, 62, 63, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 82, -1, -1, 85, 86,
- 87, 88, -1, 90, -1, 1, -1, 3, 4, 5,
- 6, 7, -1, -1, 10, 11, 12, 104, 105, 15,
- 16, -1, 18, 19, 20, 21, 22, 23, 24, 116,
- 117, 27, 28, 29, 30, 31, 32, 33, -1, -1,
- 36, -1, -1, -1, -1, 41, 42, 43, 44, 45,
- 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 82, -1, -1, 85,
- 86, 87, 88, -1, 90, -1, 1, -1, 3, 4,
- 5, 6, 7, -1, 9, 10, 11, 12, 104, 105,
- -1, 16, -1, 18, 19, 20, 21, 22, 23, 24,
- 116, 117, 27, 28, 29, 30, 31, 32, 33, -1,
- -1, 36, -1, -1, -1, -1, 41, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, 57, 58, 59, 60, 61, 62, 63, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 82, -1, -1,
- 85, 86, 87, 88, -1, 90, -1, 1, -1, 3,
- 4, 5, 6, 7, -1, -1, -1, 11, 12, 104,
- 105, -1, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 116, 117, 27, 28, 29, 30, 31, 32, 33,
- -1, -1, 36, -1, -1, -1, -1, 41, 42, 43,
- 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 82, -1,
- -1, 85, 86, 87, 88, -1, 90, -1, 1, -1,
- 3, 4, 5, 6, 7, -1, -1, -1, 11, 12,
- 104, 105, -1, 16, -1, 18, 19, 20, 21, 22,
- 23, 24, 116, 117, 27, 28, 29, 30, 31, 32,
- 33, -1, -1, 36, -1, -1, -1, -1, 41, 42,
- 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
- 63, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 82,
- -1, -1, 85, 86, 87, 88, -1, 90, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 104, 105, -1, -1, -1, 1, 110, 3, 4,
- 5, 6, 7, 116, 117, -1, 11, 12, -1, -1,
- -1, 16, -1, 18, 19, 20, 21, 22, 23, 24,
- -1, -1, 27, 28, 29, 30, 31, 32, 33, -1,
- -1, 36, -1, -1, -1, -1, 41, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, 57, 58, 59, 60, 61, 62, 63, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 82, -1, -1,
- 85, 86, 87, 88, -1, 90, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 104,
- 105, -1, -1, -1, 1, 110, 3, 4, 5, 6,
- 7, 116, 117, -1, 11, 12, -1, -1, -1, 16,
- -1, 18, 19, 20, 21, 22, 23, 24, -1, -1,
- 27, 28, 29, 30, 31, 32, 33, -1, -1, 36,
- -1, -1, -1, -1, 41, 42, 43, 44, 45, 46,
- 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
- 57, 58, 59, 60, 61, 62, 63, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 82, -1, -1, 85, 86,
- 87, 88, -1, 90, -1, 1, -1, 3, 4, 5,
- 6, 7, -1, -1, 10, 11, 12, 104, 105, -1,
- 16, 108, 18, 19, 20, 21, 22, 23, 24, 116,
- 117, 27, 28, 29, 30, 31, 32, 33, -1, -1,
- 36, -1, -1, -1, -1, 41, 42, 43, 44, 45,
- 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, 62, 63, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 82, -1, -1, 85,
- 86, 87, 88, -1, 90, -1, -1, -1, 3, 4,
- 5, 6, 7, -1, -1, -1, 11, 12, 104, 105,
- -1, 16, -1, 18, 19, 20, 21, 22, 23, 24,
- 116, 117, 27, 28, 29, 30, 31, 32, 33, -1,
- -1, 36, -1, -1, -1, -1, 41, 42, 43, 44,
- 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
- 55, 56, 57, 58, 59, 60, 61, 62, 63, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 82, -1, -1,
- 85, 86, 87, 88, -1, 90, -1, -1, -1, 3,
- 4, 5, -1, 7, -1, -1, -1, 11, 12, 104,
- 105, -1, 16, -1, 18, 19, 20, 21, 22, 23,
- 24, -1, 117, 27, 28, 29, 30, 31, 32, 33,
- -1, -1, -1, -1, -1, -1, -1, -1, 42, -1,
- -1, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 82, -1,
- -1, 85, 86, 87, 88, 89, 90, -1, -1, 3,
- 4, 5, -1, 7, -1, -1, -1, 11, 12, -1,
- 104, 105, 16, 107, 18, 19, 20, 21, 22, 23,
- 24, 115, -1, 27, 28, 29, 30, 31, 32, 33,
- -1, -1, -1, -1, -1, -1, -1, -1, 42, -1,
- -1, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 82, -1,
- -1, 85, 86, 87, 88, 89, 90, -1, -1, 3,
- 4, 5, -1, 7, -1, -1, -1, 11, 12, -1,
- 104, 105, 16, 107, 18, 19, 20, 21, 22, 23,
- 24, 115, -1, 27, 28, 29, 30, 31, 32, 33,
- -1, -1, -1, -1, -1, -1, -1, -1, 42, -1,
- -1, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 82, -1,
- -1, 85, 86, 87, 88, 89, 90, -1, -1, 3,
- 4, 5, -1, 7, -1, -1, -1, 11, 12, -1,
- 104, 105, 16, 107, 18, 19, 20, 21, 22, 23,
- 24, 115, -1, 27, 28, 29, 30, 31, 32, 33,
- -1, -1, -1, -1, -1, -1, -1, -1, 42, -1,
- -1, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 82, -1,
- -1, 85, 86, 87, 88, 89, 90, -1, -1, 3,
- 4, 5, -1, 7, -1, -1, -1, 11, 12, -1,
- 104, 105, 16, 107, 18, 19, 20, 21, 22, 23,
- 24, 115, -1, 27, 28, 29, 30, 31, 32, 33,
- -1, -1, -1, -1, -1, -1, -1, -1, 42, -1,
- -1, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 82, -1,
- -1, 85, 86, 87, 88, 89, 90, -1, -1, 3,
- 4, 5, -1, 7, -1, -1, -1, 11, 12, -1,
- 104, 105, 16, -1, 18, 19, 20, 21, 22, 23,
- 24, 115, -1, 27, 28, 29, 30, 31, 32, 33,
- -1, -1, -1, -1, -1, -1, -1, -1, 42, -1,
- -1, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 82, -1,
- -1, 85, 86, 87, 88, 89, 90, -1, -1, 3,
- 4, 5, -1, 7, -1, -1, -1, 11, 12, -1,
- 104, 105, 16, -1, 18, 19, 20, 21, 22, 23,
- 24, 115, -1, 27, 28, 29, 30, 31, 32, 33,
- -1, -1, -1, -1, -1, -1, -1, -1, 42, -1,
- -1, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 82, -1,
- -1, 85, 86, 87, 88, 89, 90, -1, -1, 3,
- 4, 5, -1, 7, -1, -1, -1, 11, 12, -1,
- 104, 105, 16, -1, 18, 19, 20, 21, 22, 23,
- 24, 115, -1, 27, 28, 29, 30, 31, 32, 33,
- -1, -1, -1, -1, -1, -1, -1, -1, 42, -1,
- -1, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 82, -1,
- -1, 85, 86, 87, 88, 89, 90, -1, -1, 3,
- 4, 5, -1, 7, -1, -1, -1, 11, 12, -1,
- 104, 105, 16, -1, 18, 19, 20, 21, 22, 23,
- 24, 115, -1, 27, 28, 29, 30, 31, 32, 33,
- -1, -1, -1, -1, -1, -1, -1, -1, 42, -1,
- -1, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 82, -1,
- -1, 85, 86, 87, 88, 89, 90, -1, -1, 3,
- 4, 5, -1, 7, -1, -1, -1, 11, 12, -1,
- 104, 105, 16, -1, 18, 19, 20, 21, 22, 23,
- 24, 115, -1, 27, 28, 29, 30, 31, 32, 33,
- -1, -1, -1, -1, -1, -1, -1, -1, 42, -1,
- -1, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 82, -1,
- -1, 85, 86, 87, 88, 89, 90, -1, -1, 3,
- 4, 5, -1, 7, -1, -1, -1, 11, 12, -1,
- 104, 105, 16, -1, 18, 19, 20, 21, 22, 23,
- 24, 115, -1, 27, 28, 29, 30, 31, 32, 33,
- -1, -1, -1, -1, -1, -1, -1, -1, 42, -1,
- -1, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 82, -1,
- -1, 85, 86, 87, 88, 89, 90, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 104, 105, 3, 4, 5, 6, 7, 8, 9, 10,
- -1, 115, 13, 14, 15, 16, 17, -1, -1, 20,
- 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
- 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
- 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
- 51, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, 62, 63, 64, 65, 66, 67, -1, 69, 70,
- -1, -1, 73, -1, 75, -1, 77, 78, 79, 80,
- -1, -1, -1, -1, 85, -1, -1, 88, -1, -1,
- -1, -1, -1, 94, 95, 96, 97, 98, 99, 100,
- 101, 102, 103, -1, 105, 3, 4, 5, 6, 7,
- 8, 9, 10, 114, -1, 13, 14, 15, 16, 17,
- -1, -1, 20, 21, 22, 23, 24, 25, 26, 27,
- 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 62, 63, 64, 65, 66, 67,
- -1, 69, 70, -1, -1, 73, -1, 75, -1, 77,
- 78, 79, 80, -1, -1, -1, -1, -1, -1, -1,
- 88, -1, -1, -1, -1, -1, 94, 95, 96, 97,
- 98, 99, 100, 101, 102, 103, -1, 105, 3, 4,
- 5, 6, 7, 8, 9, 10, 114, -1, 13, 14,
- 15, 16, 17, -1, -1, 20, 21, 22, 23, 24,
- 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 39, 40, 41, 42, 43, 44,
- 45, 46, 47, 48, 49, -1, 51, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 62, 63, 64,
- 65, 66, 67, -1, 69, 70, -1, -1, 73, -1,
- 75, -1, 77, 78, 79, 80, -1, -1, -1, -1,
- -1, -1, -1, 88, -1, -1, -1, -1, -1, 94,
- 95, 96, 97, 98, 99, 100, 101, 102, 103, -1,
- 105, 3, 4, 5, 6, 7, 8, 9, 10, 114,
- -1, 13, 14, 15, 16, 17, -1, -1, 20, 21,
- 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
- 42, 43, 44, 45, 46, 47, 48, -1, -1, 51,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 62, 63, 64, 65, 66, 67, -1, 69, 70, -1,
- -1, 73, -1, 75, -1, 77, 78, 79, 80, -1,
- -1, -1, -1, -1, -1, -1, 88, -1, -1, -1,
- -1, -1, 94, 95, 96, 97, 98, 99, 100, 101,
- 102, 103, -1, 105, -1, 3, 4, 5, -1, 7,
- -1, -1, 114, 11, 12, -1, -1, -1, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, -1, -1,
- -1, -1, -1, -1, 42, -1, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- 88, 89, 90, -1, -1, -1, -1, -1, -1, -1,
- 3, 4, 5, -1, 7, -1, 104, 105, 11, 12,
- -1, -1, 110, 16, -1, 18, 19, 20, 21, 22,
- 23, 24, -1, -1, 27, 28, 29, 30, 31, 32,
- 33, -1, -1, -1, -1, -1, -1, -1, -1, 42,
- -1, -1, 45, 46, 47, 48, 49, 50, 51, 52,
- 53, 54, 55, 56, 57, 58, 59, 60, 61, 62,
- 63, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, 82,
- -1, -1, 85, 86, 87, 88, 89, 90, -1, -1,
- -1, -1, -1, -1, -1, 3, 4, 5, 6, 7,
- -1, 104, 105, 11, 12, -1, -1, 110, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, 36, -1,
- -1, -1, -1, 41, 42, 43, 44, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- 88, -1, 90, -1, -1, 3, 4, 5, -1, 7,
- -1, -1, -1, 11, 12, -1, 104, 105, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, 36, -1,
- -1, -1, -1, -1, 42, -1, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- 88, -1, 90, -1, -1, 3, 4, 5, -1, 7,
- -1, -1, -1, 11, 12, -1, 104, 105, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, -1, -1,
- -1, -1, -1, -1, 42, -1, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- 88, 89, 90, -1, -1, 3, 4, 5, -1, 7,
- -1, -1, -1, 11, 12, -1, 104, 105, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, -1, -1,
- -1, -1, -1, -1, 42, -1, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- 88, 89, 90, -1, -1, 3, 4, 5, -1, 7,
- -1, -1, -1, 11, 12, -1, 104, 105, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, -1, -1,
- -1, -1, -1, -1, 42, -1, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- 88, 89, 90, -1, -1, 3, 4, 5, -1, 7,
- -1, -1, -1, 11, 12, -1, 104, 105, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, -1, -1,
- -1, -1, -1, -1, 42, -1, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- 88, 89, 90, -1, -1, 3, 4, 5, -1, 7,
- -1, -1, -1, 11, 12, -1, 104, 105, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, -1, -1,
- -1, -1, -1, -1, 42, -1, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- 88, -1, 90, -1, -1, 3, 4, 5, -1, 7,
- -1, -1, -1, 11, 12, -1, 104, 105, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, -1, -1,
- -1, -1, -1, -1, 42, -1, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- 88, -1, 90, -1, -1, 3, 4, 5, -1, 7,
- -1, -1, -1, 11, 12, -1, 104, 105, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, -1, -1,
- -1, -1, -1, -1, 42, -1, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- 88, -1, 90, -1, -1, 3, 4, 5, -1, 7,
- -1, -1, -1, 11, 12, -1, 104, 105, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, -1, -1,
- -1, -1, -1, -1, 42, -1, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- 88, -1, 90, -1, -1, 3, 4, 5, -1, 7,
- -1, -1, -1, 11, 12, -1, 104, 105, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, -1, -1,
- -1, -1, -1, -1, 42, -1, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- -1, -1, 90, -1, -1, 3, 4, 5, -1, 7,
- -1, -1, -1, 11, 12, -1, 104, 105, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, -1, -1,
- -1, -1, -1, -1, 42, -1, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, 62, 63, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- -1, -1, 90, -1, -1, 3, 4, 5, -1, 7,
- -1, -1, -1, 11, 12, -1, 104, 105, 16, -1,
- 18, 19, 20, 21, 22, 23, 24, -1, -1, 27,
- 28, 29, 30, 31, 32, 33, -1, -1, -1, -1,
- -1, -1, -1, -1, 42, -1, -1, 45, 46, 47,
- 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
- 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, 82, -1, -1, 85, 86, 87,
- 88, -1, 90, 3, 4, 5, -1, 7, 96, -1,
- -1, 11, 12, -1, -1, -1, 16, -1, 18, 19,
- 20, 21, 22, 23, 24, -1, -1, 27, 28, 29,
- 30, 31, 32, 33, -1, -1, -1, -1, -1, -1,
- -1, -1, 42, -1, -1, 45, 46, 47, 48, 49,
- 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
- 60, 61, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 82, -1, -1, 85, 86, 87, 88, -1,
- 90, 3, 4, 5, -1, 7, -1, -1, -1, 11,
- 12, -1, -1, -1, 16, -1, 18, 19, 20, 21,
- 22, 23, 24, -1, -1, 27, 28, 29, 30, 31,
- 32, 33, -1, -1, -1, -1, -1, -1, -1, -1,
- 42, -1, -1, 45, 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 82, -1, -1, 85, 86, 87, 88, -1, 90, 3,
- 4, 5, -1, 7, -1, -1, -1, 11, 12, -1,
- -1, -1, 16, -1, 18, 19, 20, 21, 22, 23,
- 24, -1, -1, 27, 28, 29, 30, 31, 32, 33,
- -1, -1, -1, -1, -1, -1, -1, -1, 42, -1,
- -1, 45, 46, 47, 48, 49, 50, 51, 52, 53,
- 54, 55, 56, 57, 58, 59, 60, 61, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 82, -1,
- -1, 85, 86, 87, 88, -1, 90, 3, 4, 5,
- -1, 7, -1, -1, -1, 11, 12, -1, -1, -1,
- 16, -1, 18, 19, 20, 21, 22, 23, 24, -1,
- -1, 27, 28, 29, 30, 31, 32, 33, -1, -1,
- -1, -1, -1, -1, -1, -1, 42, -1, -1, 45,
- 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
- 56, 57, 58, 59, 60, 61, -1, 64, 65, 66,
- 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
- -1, -1, 79, 80, -1, -1, 82, -1, -1, 85,
- 86, 87, -1, -1, 90, 92, -1, 94, 95, 96,
- 97, 98, 99, 100, 101, 102, 103, 64, 65, 66,
- 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,
- -1, -1, 79, 80, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 94, 95, 96,
- 97, 98, 99, 100, 101, 102, 103, 64, 65, 66,
- 67, 68, 69, 70, 71, -1, 73, 74, -1, -1,
- -1, -1, 79, 80, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, 94, 95, 96,
- 97, 98, 99, 100, 101, 102, 103
-};
-/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
-#line 3 "/usr/share/misc/bison.simple"
-/* This file comes from bison-1.25.90. */
-
-/* Skeleton output parser for bison,
- Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- 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. */
-
-/* As a special exception, when this file is copied by Bison into a
- Bison output file, you may use that output file without restriction.
- This special exception was added by the Free Software Foundation
- in version 1.24 of Bison. */
-
-/* This is the parser code that is written into each bison parser
- when the %semantic_parser declaration is not specified in the grammar.
- It was written by Richard Stallman by simplifying the hairy parser
- used when %semantic_parser is specified. */
-
-#ifndef YYSTACK_USE_ALLOCA
-#ifdef alloca
-#define YYSTACK_USE_ALLOCA
-#else /* alloca not defined */
-#ifdef __GNUC__
-#define YYSTACK_USE_ALLOCA
-#define alloca __builtin_alloca
-#else /* not GNU C. */
-#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386))
-#define YYSTACK_USE_ALLOCA
-#include <alloca.h>
-#else /* not sparc */
-/* We think this test detects Watcom and Microsoft C. */
-/* This used to test MSDOS, but that is a bad idea
- since that symbol is in the user namespace. */
-#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__)
-#if 0 /* No need for malloc.h, which pollutes the namespace;
- instead, just don't use alloca. */
-#include <malloc.h>
-#endif
-#else /* not MSDOS, or __TURBOC__ */
-#if defined(_AIX)
-/* I don't know what this was needed for, but it pollutes the namespace.
- So I turned it off. rms, 2 May 1997. */
-/* #include <malloc.h> */
- #pragma alloca
-#define YYSTACK_USE_ALLOCA
-#else /* not MSDOS, or __TURBOC__, or _AIX */
-#if 0
-#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up,
- and on HPUX 10. Eventually we can turn this on. */
-#define YYSTACK_USE_ALLOCA
-#define alloca __builtin_alloca
-#endif /* __hpux */
-#endif
-#endif /* not _AIX */
-#endif /* not MSDOS, or __TURBOC__ */
-#endif /* not sparc */
-#endif /* not GNU C */
-#endif /* alloca not defined */
-#endif /* YYSTACK_USE_ALLOCA not defined */
-
-#ifdef YYSTACK_USE_ALLOCA
-#define YYSTACK_ALLOC alloca
-#else
-#define YYSTACK_ALLOC malloc
-#endif
-
-/* Note: there must be only one dollar sign in this file.
- It is replaced by the list of actions, each action
- as one case of the switch. */
-
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY -2
-#define YYEOF 0
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrlab1
-/* Like YYERROR except do call yyerror.
- This remains here temporarily to ease the
- transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. */
-#define YYFAIL goto yyerrlab
-#define YYRECOVERING() (!!yyerrstatus)
-#define YYBACKUP(token, value) \
-do \
- if (yychar == YYEMPTY && yylen == 1) \
- { yychar = (token), yylval = (value); \
- yychar1 = YYTRANSLATE (yychar); \
- YYPOPSTACK; \
- goto yybackup; \
- } \
- else \
- { yyerror ("syntax error: cannot back up"); YYERROR; } \
-while (0)
-
-#define YYTERROR 1
-#define YYERRCODE 256
-
-#ifndef YYPURE
-#define YYLEX yylex()
-#endif
-
-#ifdef YYPURE
-#ifdef YYLSP_NEEDED
-#ifdef YYLEX_PARAM
-#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)
-#else
-#define YYLEX yylex(&yylval, &yylloc)
-#endif
-#else /* not YYLSP_NEEDED */
-#ifdef YYLEX_PARAM
-#define YYLEX yylex(&yylval, YYLEX_PARAM)
-#else
-#define YYLEX yylex(&yylval)
-#endif
-#endif /* not YYLSP_NEEDED */
-#endif
-
-/* If nonreentrant, generate the variables here */
-
-#ifndef YYPURE
-
-int yychar; /* the lookahead symbol */
-YYSTYPE yylval; /* the semantic value of the */
- /* lookahead symbol */
-
-#ifdef YYLSP_NEEDED
-YYLTYPE yylloc; /* location data for the lookahead */
- /* symbol */
-#endif
-
-int yynerrs; /* number of parse errors so far */
-#endif /* not YYPURE */
-
-#if YYDEBUG != 0
-int yydebug; /* nonzero means print parse trace */
-/* Since this is uninitialized, it does not stop multiple parsers
- from coexisting. */
-#endif
-
-/* YYINITDEPTH indicates the initial size of the parser's stacks */
-
-#ifndef YYINITDEPTH
-#define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH is the maximum size the stacks can grow to
- (effective only if the built-in stack extension method is used). */
-
-#if YYMAXDEPTH == 0
-#undef YYMAXDEPTH
-#endif
-
-#ifndef YYMAXDEPTH
-#define YYMAXDEPTH 10000
-#endif
-
-/* Define __yy_memcpy. Note that the size argument
- should be passed with type unsigned int, because that is what the non-GCC
- definitions require. With GCC, __builtin_memcpy takes an arg
- of type size_t, but it can handle unsigned int. */
-
-#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
-#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT)
-#else /* not GNU C or C++ */
-#ifndef __cplusplus
-
-/* This is the most reliable way to avoid incompatibilities
- in available built-in functions on various systems. */
-static void
-__yy_memcpy (to, from, count)
- char *to;
- char *from;
- unsigned int count;
-{
- register char *f = from;
- register char *t = to;
- register int i = count;
-
- while (i-- > 0)
- *t++ = *f++;
-}
-
-#else /* __cplusplus */
-
-/* This is the most reliable way to avoid incompatibilities
- in available built-in functions on various systems. */
-static void
-__yy_memcpy (char *to, char *from, unsigned int count)
-{
- register char *t = to;
- register char *f = from;
- register int i = count;
-
- while (i-- > 0)
- *t++ = *f++;
-}
-
-#endif
-#endif
-
-#line 216 "/usr/share/misc/bison.simple"
-
-/* The user can define YYPARSE_PARAM as the name of an argument to be passed
- into yyparse. The argument should have type void *.
- It should actually point to an object.
- Grammar actions can access the variable by casting it
- to the proper pointer type. */
-
-#ifdef YYPARSE_PARAM
-#ifdef __cplusplus
-#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM
-#define YYPARSE_PARAM_DECL
-#else /* not __cplusplus */
-#define YYPARSE_PARAM_ARG YYPARSE_PARAM
-#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM;
-#endif /* not __cplusplus */
-#else /* not YYPARSE_PARAM */
-#define YYPARSE_PARAM_ARG
-#define YYPARSE_PARAM_DECL
-#endif /* not YYPARSE_PARAM */
-
-/* Prevent warning if -Wstrict-prototypes. */
-#ifdef __GNUC__
-#ifdef YYPARSE_PARAM
-int yyparse (void *);
-#else
-int yyparse (void);
-#endif
-#endif
-
-int
-yyparse(YYPARSE_PARAM_ARG)
- YYPARSE_PARAM_DECL
-{
- register int yystate;
- register int yyn;
- register short *yyssp;
- register YYSTYPE *yyvsp;
- int yyerrstatus; /* number of tokens to shift before error messages enabled */
- int yychar1 = 0; /* lookahead token as an internal (translated) token number */
-
- short yyssa[YYINITDEPTH]; /* the state stack */
- YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
-
- short *yyss = yyssa; /* refer to the stacks thru separate pointers */
- YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
-
-#ifdef YYLSP_NEEDED
- YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
- YYLTYPE *yyls = yylsa;
- YYLTYPE *yylsp;
-
-#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--)
-#else
-#define YYPOPSTACK (yyvsp--, yyssp--)
-#endif
-
- int yystacksize = YYINITDEPTH;
- int yyfree_stacks = 0;
-
-#ifdef YYPURE
- int yychar;
- YYSTYPE yylval;
- int yynerrs;
-#ifdef YYLSP_NEEDED
- YYLTYPE yylloc;
-#endif
-#endif
-
- YYSTYPE yyval; /* the variable used to return */
- /* semantic values from the action */
- /* routines */
-
- int yylen;
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Starting parse\n");
-#endif
-
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
-
- yyssp = yyss - 1;
- yyvsp = yyvs;
-#ifdef YYLSP_NEEDED
- yylsp = yyls;
-#endif
-
-/* Push a new state, which is found in yystate . */
-/* In all cases, when you get here, the value and location stacks
- have just been pushed. so pushing a state here evens the stacks. */
-yynewstate:
-
- *++yyssp = yystate;
-
- if (yyssp >= yyss + yystacksize - 1)
- {
- /* Give user a chance to reallocate the stack */
- /* Use copies of these so that the &'s don't force the real ones into memory. */
- YYSTYPE *yyvs1 = yyvs;
- short *yyss1 = yyss;
-#ifdef YYLSP_NEEDED
- YYLTYPE *yyls1 = yyls;
-#endif
-
- /* Get the current used size of the three stacks, in elements. */
- int size = yyssp - yyss + 1;
-
-#ifdef yyoverflow
- /* Each stack pointer address is followed by the size of
- the data in use in that stack, in bytes. */
-#ifdef YYLSP_NEEDED
- /* This used to be a conditional around just the two extra args,
- but that might be undefined if yyoverflow is a macro. */
- yyoverflow("parser stack overflow",
- &yyss1, size * sizeof (*yyssp),
- &yyvs1, size * sizeof (*yyvsp),
- &yyls1, size * sizeof (*yylsp),
- &yystacksize);
-#else
- yyoverflow("parser stack overflow",
- &yyss1, size * sizeof (*yyssp),
- &yyvs1, size * sizeof (*yyvsp),
- &yystacksize);
-#endif
-
- yyss = yyss1; yyvs = yyvs1;
-#ifdef YYLSP_NEEDED
- yyls = yyls1;
-#endif
-#else /* no yyoverflow */
- /* Extend the stack our own way. */
- if (yystacksize >= YYMAXDEPTH)
- {
- yyerror("parser stack overflow");
- if (yyfree_stacks)
- {
- free (yyss);
- free (yyvs);
-#ifdef YYLSP_NEEDED
- free (yyls);
-#endif
- }
- return 2;
- }
- yystacksize *= 2;
- if (yystacksize > YYMAXDEPTH)
- yystacksize = YYMAXDEPTH;
-#ifndef YYSTACK_USE_ALLOCA
- yyfree_stacks = 1;
-#endif
- yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp));
- __yy_memcpy ((char *)yyss, (char *)yyss1,
- size * (unsigned int) sizeof (*yyssp));
- yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp));
- __yy_memcpy ((char *)yyvs, (char *)yyvs1,
- size * (unsigned int) sizeof (*yyvsp));
-#ifdef YYLSP_NEEDED
- yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp));
- __yy_memcpy ((char *)yyls, (char *)yyls1,
- size * (unsigned int) sizeof (*yylsp));
-#endif
-#endif /* no yyoverflow */
-
- yyssp = yyss + size - 1;
- yyvsp = yyvs + size - 1;
-#ifdef YYLSP_NEEDED
- yylsp = yyls + size - 1;
-#endif
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Stack size increased to %d\n", yystacksize);
-#endif
-
- if (yyssp >= yyss + yystacksize - 1)
- YYABORT;
- }
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Entering state %d\n", yystate);
-#endif
-
- goto yybackup;
- yybackup:
-
-/* Do appropriate processing given the current state. */
-/* Read a lookahead token if we need one and don't already have one. */
-/* yyresume: */
-
- /* First try to decide what to do without reference to lookahead token. */
-
- yyn = yypact[yystate];
- if (yyn == YYFLAG)
- goto yydefault;
-
- /* Not known => get a lookahead token if don't already have one. */
-
- /* yychar is either YYEMPTY or YYEOF
- or a valid token in external form. */
-
- if (yychar == YYEMPTY)
- {
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Reading a token: ");
-#endif
- yychar = YYLEX;
- }
-
- /* Convert token to internal form (in yychar1) for indexing tables with */
-
- if (yychar <= 0) /* This means end of input. */
- {
- yychar1 = 0;
- yychar = YYEOF; /* Don't call YYLEX any more */
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Now at end of input.\n");
-#endif
- }
- else
- {
- yychar1 = YYTRANSLATE(yychar);
-
-#if YYDEBUG != 0
- if (yydebug)
- {
- fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
- /* Give the individual parser a way to print the precise meaning
- of a token, for further debugging info. */
-#ifdef YYPRINT
- YYPRINT (stderr, yychar, yylval);
-#endif
- fprintf (stderr, ")\n");
- }
-#endif
- }
-
- yyn += yychar1;
- if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
- goto yydefault;
-
- yyn = yytable[yyn];
-
- /* yyn is what to do for this token type in this state.
- Negative => reduce, -yyn is rule number.
- Positive => shift, yyn is new state.
- New state is final state => don't bother to shift,
- just return success.
- 0, or most negative number => error. */
-
- if (yyn < 0)
- {
- if (yyn == YYFLAG)
- goto yyerrlab;
- yyn = -yyn;
- goto yyreduce;
- }
- else if (yyn == 0)
- goto yyerrlab;
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
- /* Shift the lookahead token. */
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
-#endif
-
- /* Discard the token being shifted unless it is eof. */
- if (yychar != YYEOF)
- yychar = YYEMPTY;
-
- *++yyvsp = yylval;
-#ifdef YYLSP_NEEDED
- *++yylsp = yylloc;
-#endif
-
- /* count tokens shifted since error; after three, turn off error status. */
- if (yyerrstatus) yyerrstatus--;
-
- yystate = yyn;
- goto yynewstate;
-
-/* Do the default action for the current state. */
-yydefault:
-
- yyn = yydefact[yystate];
- if (yyn == 0)
- goto yyerrlab;
-
-/* Do a reduction. yyn is the number of a rule to reduce with. */
-yyreduce:
- yylen = yyr2[yyn];
- if (yylen > 0)
- yyval = yyvsp[1-yylen]; /* implement default value of the action */
-
-#if YYDEBUG != 0
- if (yydebug)
- {
- int i;
-
- fprintf (stderr, "Reducing via rule %d (line %d), ",
- yyn, yyrline[yyn]);
-
- /* Print the symbols being reduced, and their result. */
- for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
- fprintf (stderr, "%s ", yytname[yyrhs[i]]);
- fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
- }
-#endif
-
-
- switch (yyn) {
-
-case 1:
-#line 231 "parse.y"
-{
- yyval.vars = ruby_dyna_vars;
- lex_state = EXPR_BEG;
- top_local_init();
- NEW_CREF0(); /* initialize constant c-ref */
- if ((VALUE)ruby_class == rb_cObject) class_nest = 0;
- else class_nest = 1;
- ;
- break;}
-case 2:
-#line 240 "parse.y"
-{
- ruby_eval_tree = block_append(ruby_eval_tree, yyvsp[0].node);
- top_local_setup();
- cur_cref = 0;
- class_nest = 0;
- ruby_dyna_vars = yyvsp[-1].vars;
- ;
- break;}
-case 4:
-#line 251 "parse.y"
-{
- yyval.node = 0;
- ;
- break;}
-case 5:
-#line 255 "parse.y"
-{
- yyval.node = newline_node(yyvsp[0].node);
- ;
- break;}
-case 6:
-#line 259 "parse.y"
-{
- yyval.node = block_append(yyvsp[-2].node, newline_node(yyvsp[0].node));
- ;
- break;}
-case 7:
-#line 263 "parse.y"
-{
- yyval.node = yyvsp[0].node;
- ;
- break;}
-case 8:
-#line 268 "parse.y"
-{
- if (yyvsp[-1].node && nd_type(yyvsp[-1].node) == NODE_BLOCK_PASS) {
- rb_compile_error("both block arg and actual block given");
- }
- yyvsp[0].node->nd_iter = yyvsp[-1].node;
- yyval.node = yyvsp[0].node;
- fixpos(yyval.node, yyvsp[0].node);
- ;
- break;}
-case 9:
-#line 276 "parse.y"
-{lex_state = EXPR_FNAME;;
- break;}
-case 10:
-#line 277 "parse.y"
-{
- if (cur_mid || in_single)
- yyerror("alias within method");
- yyval.node = NEW_ALIAS(yyvsp[-2].id, yyvsp[0].id);
- ;
- break;}
-case 11:
-#line 283 "parse.y"
-{
- if (cur_mid || in_single)
- yyerror("alias within method");
- yyval.node = NEW_VALIAS(yyvsp[-1].id, yyvsp[0].id);
- ;
- break;}
-case 12:
-#line 289 "parse.y"
-{
- char buf[3];
-
- if (cur_mid || in_single)
- yyerror("alias within method");
- sprintf(buf, "$%c", yyvsp[0].node->nd_nth);
- yyval.node = NEW_VALIAS(yyvsp[-1].id, rb_intern(buf));
- ;
- break;}
-case 13:
-#line 298 "parse.y"
-{
- yyerror("can't make alias for the number variables");
- yyval.node = 0;
- ;
- break;}
-case 14:
-#line 303 "parse.y"
-{
- if (cur_mid || in_single)
- yyerror("undef within method");
- yyval.node = yyvsp[0].node;
- ;
- break;}
-case 15:
-#line 309 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyval.node = NEW_IF(cond(yyvsp[0].node), yyvsp[-2].node, 0);
- fixpos(yyval.node, yyvsp[0].node);
- ;
- break;}
-case 16:
-#line 315 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyval.node = NEW_UNLESS(cond(yyvsp[0].node), yyvsp[-2].node, 0);
- fixpos(yyval.node, yyvsp[0].node);
- ;
- break;}
-case 17:
-#line 321 "parse.y"
-{
- value_expr(yyvsp[0].node);
- if (nd_type(yyvsp[-2].node) == NODE_BEGIN) {
- yyval.node = NEW_WHILE(cond(yyvsp[0].node), yyvsp[-2].node->nd_body, 0);
- }
- else {
- yyval.node = NEW_WHILE(cond(yyvsp[0].node), yyvsp[-2].node, 1);
- }
- ;
- break;}
-case 18:
-#line 331 "parse.y"
-{
- value_expr(yyvsp[0].node);
- if (nd_type(yyvsp[-2].node) == NODE_BEGIN) {
- yyval.node = NEW_UNTIL(cond(yyvsp[0].node), yyvsp[-2].node->nd_body, 0);
- }
- else {
- yyval.node = NEW_UNTIL(cond(yyvsp[0].node), yyvsp[-2].node, 1);
- }
- ;
- break;}
-case 19:
-#line 341 "parse.y"
-{
- if (cur_mid || in_single) {
- yyerror("BEGIN in method");
- }
-
- local_push();
- ;
- break;}
-case 20:
-#line 349 "parse.y"
-{
- ruby_eval_tree_begin = block_append(ruby_eval_tree_begin,
- NEW_PREEXE(yyvsp[-1].node));
- local_pop();
- yyval.node = 0;
- ;
- break;}
-case 21:
-#line 356 "parse.y"
-{
- if (cur_mid || in_single) {
- yyerror("END in method; use at_exit");
- }
-
- yyval.node = NEW_ITER(0, NEW_POSTEXE(), yyvsp[-1].node);
- ;
- break;}
-case 23:
-#line 366 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyvsp[-2].node->nd_value = yyvsp[0].node;
- yyval.node = yyvsp[-2].node;
- ;
- break;}
-case 24:
-#line 372 "parse.y"
-{
- value_expr(yyvsp[0].node);
- if (!cur_mid && !in_single)
- yyerror("return appeared outside of method");
- yyval.node = NEW_RETURN(yyvsp[0].node);
- ;
- break;}
-case 25:
-#line 379 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyval.node = NEW_YIELD(yyvsp[0].node);
- ;
- break;}
-case 27:
-#line 385 "parse.y"
-{
- yyval.node = logop(NODE_AND, yyvsp[-2].node, yyvsp[0].node);
- ;
- break;}
-case 28:
-#line 389 "parse.y"
-{
- yyval.node = logop(NODE_OR, yyvsp[-2].node, yyvsp[0].node);
- ;
- break;}
-case 29:
-#line 393 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyval.node = NEW_NOT(cond(yyvsp[0].node));
- ;
- break;}
-case 30:
-#line 398 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyval.node = NEW_NOT(cond(yyvsp[0].node));
- ;
- break;}
-case 32:
-#line 405 "parse.y"
-{
- yyval.node = new_fcall(yyvsp[-1].id, yyvsp[0].node);
- fixpos(yyval.node, yyvsp[0].node);
- ;
- break;}
-case 33:
-#line 410 "parse.y"
-{
- value_expr(yyvsp[-3].node);
- yyval.node = new_call(yyvsp[-3].node, yyvsp[-1].id, yyvsp[0].node);
- fixpos(yyval.node, yyvsp[-3].node);
- ;
- break;}
-case 34:
-#line 416 "parse.y"
-{
- value_expr(yyvsp[-3].node);
- yyval.node = new_call(yyvsp[-3].node, yyvsp[-1].id, yyvsp[0].node);
- fixpos(yyval.node, yyvsp[-3].node);
- ;
- break;}
-case 35:
-#line 422 "parse.y"
-{
- if (!cur_mid && !in_single && !in_defined)
- yyerror("super called outside of method");
- yyval.node = NEW_SUPER(yyvsp[0].node);
- fixpos(yyval.node, yyvsp[0].node);
- ;
- break;}
-case 37:
-#line 431 "parse.y"
-{
- yyval.node = yyvsp[-1].node;
- ;
- break;}
-case 39:
-#line 437 "parse.y"
-{
- yyval.node = NEW_MASGN(NEW_LIST(yyvsp[-1].node), 0);
- ;
- break;}
-case 40:
-#line 442 "parse.y"
-{
- yyval.node = NEW_MASGN(NEW_LIST(yyvsp[0].node), 0);
- ;
- break;}
-case 41:
-#line 446 "parse.y"
-{
- yyval.node = NEW_MASGN(NEW_LIST(yyvsp[-2].node), yyvsp[0].node);
- ;
- break;}
-case 42:
-#line 450 "parse.y"
-{
- yyval.node = NEW_MASGN(list_concat(NEW_LIST(yyvsp[-1].node),yyvsp[0].node), 0);
- ;
- break;}
-case 43:
-#line 454 "parse.y"
-{
- yyval.node = NEW_MASGN(list_concat(NEW_LIST(yyvsp[-4].node),yyvsp[-3].node),yyvsp[0].node);
- ;
- break;}
-case 44:
-#line 458 "parse.y"
-{
- yyval.node = NEW_MASGN(0, yyvsp[0].node);
- ;
- break;}
-case 46:
-#line 464 "parse.y"
-{
- yyval.node = yyvsp[-1].node;
- ;
- break;}
-case 47:
-#line 469 "parse.y"
-{
- yyval.node = yyvsp[-1].node;
- ;
- break;}
-case 48:
-#line 474 "parse.y"
-{
- yyval.node = NEW_LIST(yyvsp[0].node);
- ;
- break;}
-case 49:
-#line 478 "parse.y"
-{
- yyval.node = list_append(yyvsp[-2].node, yyvsp[0].node);
- ;
- break;}
-case 50:
-#line 483 "parse.y"
-{
- yyval.node = assignable(yyvsp[0].id, 0);
- ;
- break;}
-case 51:
-#line 487 "parse.y"
-{
- yyval.node = aryset(yyvsp[-3].node, yyvsp[-1].node, 0);
- ;
- break;}
-case 52:
-#line 491 "parse.y"
-{
- yyval.node = attrset(yyvsp[-2].node, yyvsp[0].id, 0);
- ;
- break;}
-case 53:
-#line 495 "parse.y"
-{
- rb_backref_error(yyvsp[0].node);
- yyval.node = 0;
- ;
- break;}
-case 54:
-#line 501 "parse.y"
-{
- yyerror("class/module name must be CONSTANT");
- ;
- break;}
-case 59:
-#line 510 "parse.y"
-{
- lex_state = EXPR_END;
- yyval.id = yyvsp[0].id;
- ;
- break;}
-case 60:
-#line 515 "parse.y"
-{
- lex_state = EXPR_END;
- yyval.id = yyvsp[0].id;
- ;
- break;}
-case 61:
-#line 521 "parse.y"
-{
- yyval.node = NEW_UNDEF(yyvsp[0].id);
- ;
- break;}
-case 62:
-#line 524 "parse.y"
-{lex_state = EXPR_FNAME;;
- break;}
-case 63:
-#line 525 "parse.y"
-{
- yyval.node = block_append(yyvsp[-3].node, NEW_UNDEF(yyvsp[0].id));
- ;
- break;}
-case 64:
-#line 529 "parse.y"
-{ yyval.id = tDOT2; ;
- break;}
-case 65:
-#line 530 "parse.y"
-{ yyval.id = '|'; ;
- break;}
-case 66:
-#line 531 "parse.y"
-{ yyval.id = '^'; ;
- break;}
-case 67:
-#line 532 "parse.y"
-{ yyval.id = '&'; ;
- break;}
-case 68:
-#line 533 "parse.y"
-{ yyval.id = tCMP; ;
- break;}
-case 69:
-#line 534 "parse.y"
-{ yyval.id = tEQ; ;
- break;}
-case 70:
-#line 535 "parse.y"
-{ yyval.id = tEQQ; ;
- break;}
-case 71:
-#line 536 "parse.y"
-{ yyval.id = tMATCH; ;
- break;}
-case 72:
-#line 537 "parse.y"
-{ yyval.id = '>'; ;
- break;}
-case 73:
-#line 538 "parse.y"
-{ yyval.id = tGEQ; ;
- break;}
-case 74:
-#line 539 "parse.y"
-{ yyval.id = '<'; ;
- break;}
-case 75:
-#line 540 "parse.y"
-{ yyval.id = tLEQ; ;
- break;}
-case 76:
-#line 541 "parse.y"
-{ yyval.id = tLSHFT; ;
- break;}
-case 77:
-#line 542 "parse.y"
-{ yyval.id = tRSHFT; ;
- break;}
-case 78:
-#line 543 "parse.y"
-{ yyval.id = '+'; ;
- break;}
-case 79:
-#line 544 "parse.y"
-{ yyval.id = '-'; ;
- break;}
-case 80:
-#line 545 "parse.y"
-{ yyval.id = '*'; ;
- break;}
-case 81:
-#line 546 "parse.y"
-{ yyval.id = '*'; ;
- break;}
-case 82:
-#line 547 "parse.y"
-{ yyval.id = '/'; ;
- break;}
-case 83:
-#line 548 "parse.y"
-{ yyval.id = '%'; ;
- break;}
-case 84:
-#line 549 "parse.y"
-{ yyval.id = tPOW; ;
- break;}
-case 85:
-#line 550 "parse.y"
-{ yyval.id = '~'; ;
- break;}
-case 86:
-#line 551 "parse.y"
-{ yyval.id = tUPLUS; ;
- break;}
-case 87:
-#line 552 "parse.y"
-{ yyval.id = tUMINUS; ;
- break;}
-case 88:
-#line 553 "parse.y"
-{ yyval.id = tAREF; ;
- break;}
-case 89:
-#line 554 "parse.y"
-{ yyval.id = tASET; ;
- break;}
-case 90:
-#line 555 "parse.y"
-{ yyval.id = '`'; ;
- break;}
-case 131:
-#line 565 "parse.y"
-{yyval.node = assignable(yyvsp[-1].id, 0);;
- break;}
-case 132:
-#line 566 "parse.y"
-{
- yyval.node = yyvsp[-1].node;
- if (yyval.node) {
- yyval.node->nd_value = yyvsp[0].node;
- fixpos(yyval.node, yyvsp[0].node);
- }
- ;
- break;}
-case 133:
-#line 574 "parse.y"
-{
- yyval.node = aryset(yyvsp[-5].node, yyvsp[-3].node, yyvsp[0].node);
- fixpos(yyval.node, yyvsp[-5].node);
- ;
- break;}
-case 134:
-#line 579 "parse.y"
-{
- yyval.node = attrset(yyvsp[-4].node, yyvsp[-2].id, yyvsp[0].node);
- fixpos(yyval.node, yyvsp[0].node);
- ;
- break;}
-case 135:
-#line 584 "parse.y"
-{
- yyval.node = attrset(yyvsp[-4].node, yyvsp[-2].id, yyvsp[0].node);
- fixpos(yyval.node, yyvsp[0].node);
- ;
- break;}
-case 136:
-#line 589 "parse.y"
-{
- value_expr(yyvsp[0].node);
- rb_backref_error(yyvsp[-2].node);
- yyval.node = 0;
- ;
- break;}
-case 137:
-#line 594 "parse.y"
-{yyval.node = assignable(yyvsp[-1].id, 0);;
- break;}
-case 138:
-#line 595 "parse.y"
-{
- if (yyvsp[-2].id == tOROP) {
- yyvsp[-1].node->nd_value = yyvsp[0].node;
- yyval.node = NEW_OP_ASGN_OR(gettable(yyvsp[-3].id), yyvsp[-1].node);
- }
- else if (yyvsp[-2].id == tANDOP) {
- yyvsp[-1].node->nd_value = yyvsp[0].node;
- yyval.node = NEW_OP_ASGN_AND(gettable(yyvsp[-3].id), yyvsp[-1].node);
- }
- else {
- yyval.node = yyvsp[-1].node;
- yyval.node->nd_value = call_op(gettable(yyvsp[-3].id), yyvsp[-2].id, 1, yyvsp[0].node);
- }
- fixpos(yyval.node, yyvsp[0].node);
- ;
- break;}
-case 139:
-#line 611 "parse.y"
-{
- NODE *args = NEW_LIST(yyvsp[0].node);
-
- list_append(yyvsp[-3].node, NEW_NIL());
- list_concat(args, yyvsp[-3].node);
- if (yyvsp[-1].id == tOROP) {
- yyvsp[-1].id = 0;
- }
- else if (yyvsp[-1].id == tANDOP) {
- yyvsp[-1].id = 1;
- }
- yyval.node = NEW_OP_ASGN1(yyvsp[-5].node, yyvsp[-1].id, args);
- fixpos(yyval.node, yyvsp[-5].node);
- ;
- break;}
-case 140:
-#line 626 "parse.y"
-{
- if (yyvsp[-1].id == tOROP) {
- yyvsp[-1].id = 0;
- }
- else if (yyvsp[-1].id == tANDOP) {
- yyvsp[-1].id = 1;
- }
- yyval.node = NEW_OP_ASGN2(yyvsp[-4].node, yyvsp[-2].id, yyvsp[-1].id, yyvsp[0].node);
- fixpos(yyval.node, yyvsp[-4].node);
- ;
- break;}
-case 141:
-#line 637 "parse.y"
-{
- if (yyvsp[-1].id == tOROP) {
- yyvsp[-1].id = 0;
- }
- else if (yyvsp[-1].id == tANDOP) {
- yyvsp[-1].id = 1;
- }
- yyval.node = NEW_OP_ASGN2(yyvsp[-4].node, yyvsp[-2].id, yyvsp[-1].id, yyvsp[0].node);
- fixpos(yyval.node, yyvsp[-4].node);
- ;
- break;}
-case 142:
-#line 648 "parse.y"
-{
- rb_backref_error(yyvsp[-2].node);
- yyval.node = 0;
- ;
- break;}
-case 143:
-#line 653 "parse.y"
-{
- yyval.node = NEW_DOT2(yyvsp[-2].node, yyvsp[0].node);
- ;
- break;}
-case 144:
-#line 657 "parse.y"
-{
- yyval.node = NEW_DOT3(yyvsp[-2].node, yyvsp[0].node);
- ;
- break;}
-case 145:
-#line 661 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, '+', 1, yyvsp[0].node);
- ;
- break;}
-case 146:
-#line 665 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, '-', 1, yyvsp[0].node);
- ;
- break;}
-case 147:
-#line 669 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, '*', 1, yyvsp[0].node);
- ;
- break;}
-case 148:
-#line 673 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, '/', 1, yyvsp[0].node);
- ;
- break;}
-case 149:
-#line 677 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, '%', 1, yyvsp[0].node);
- ;
- break;}
-case 150:
-#line 681 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, tPOW, 1, yyvsp[0].node);
- ;
- break;}
-case 151:
-#line 685 "parse.y"
-{
- yyval.node = call_op(yyvsp[0].node, tUPLUS, 0);
- ;
- break;}
-case 152:
-#line 689 "parse.y"
-{
- yyval.node = call_op(yyvsp[0].node, tUMINUS, 0);
- ;
- break;}
-case 153:
-#line 693 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, '|', 1, yyvsp[0].node);
- ;
- break;}
-case 154:
-#line 697 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, '^', 1, yyvsp[0].node);
- ;
- break;}
-case 155:
-#line 701 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, '&', 1, yyvsp[0].node);
- ;
- break;}
-case 156:
-#line 705 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, tCMP, 1, yyvsp[0].node);
- ;
- break;}
-case 157:
-#line 709 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, '>', 1, yyvsp[0].node);
- ;
- break;}
-case 158:
-#line 713 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, tGEQ, 1, yyvsp[0].node);
- ;
- break;}
-case 159:
-#line 717 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, '<', 1, yyvsp[0].node);
- ;
- break;}
-case 160:
-#line 721 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, tLEQ, 1, yyvsp[0].node);
- ;
- break;}
-case 161:
-#line 725 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, tEQ, 1, yyvsp[0].node);
- ;
- break;}
-case 162:
-#line 729 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, tEQQ, 1, yyvsp[0].node);
- ;
- break;}
-case 163:
-#line 733 "parse.y"
-{
- yyval.node = NEW_NOT(call_op(yyvsp[-2].node, tEQ, 1, yyvsp[0].node));
- ;
- break;}
-case 164:
-#line 737 "parse.y"
-{
- yyval.node = match_gen(yyvsp[-2].node, yyvsp[0].node);
- ;
- break;}
-case 165:
-#line 741 "parse.y"
-{
- yyval.node = NEW_NOT(match_gen(yyvsp[-2].node, yyvsp[0].node));
- ;
- break;}
-case 166:
-#line 745 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyval.node = NEW_NOT(cond(yyvsp[0].node));
- ;
- break;}
-case 167:
-#line 750 "parse.y"
-{
- yyval.node = call_op(yyvsp[0].node, '~', 0);
- ;
- break;}
-case 168:
-#line 754 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, tLSHFT, 1, yyvsp[0].node);
- ;
- break;}
-case 169:
-#line 758 "parse.y"
-{
- yyval.node = call_op(yyvsp[-2].node, tRSHFT, 1, yyvsp[0].node);
- ;
- break;}
-case 170:
-#line 762 "parse.y"
-{
- yyval.node = logop(NODE_AND, yyvsp[-2].node, yyvsp[0].node);
- ;
- break;}
-case 171:
-#line 766 "parse.y"
-{
- yyval.node = logop(NODE_OR, yyvsp[-2].node, yyvsp[0].node);
- ;
- break;}
-case 172:
-#line 769 "parse.y"
-{in_defined = 1;;
- break;}
-case 173:
-#line 770 "parse.y"
-{
- in_defined = 0;
- yyval.node = NEW_DEFINED(yyvsp[0].node);
- ;
- break;}
-case 174:
-#line 775 "parse.y"
-{
- value_expr(yyvsp[-4].node);
- yyval.node = NEW_IF(cond(yyvsp[-4].node), yyvsp[-2].node, yyvsp[0].node);
- fixpos(yyval.node, yyvsp[-4].node);
- ;
- break;}
-case 175:
-#line 781 "parse.y"
-{
- yyval.node = yyvsp[0].node;
- ;
- break;}
-case 176:
-#line 786 "parse.y"
-{
- if (yyvsp[0].node && nd_type(yyvsp[0].node) == NODE_BLOCK_PASS) {
- rb_compile_error("block argument should not be given");
- }
- yyval.node = yyvsp[0].node;
- ;
- break;}
-case 177:
-#line 794 "parse.y"
-{
- yyval.node = 0;
- ;
- break;}
-case 179:
-#line 800 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyval.node = NEW_LIST(yyvsp[0].node);
- ;
- break;}
-case 180:
-#line 805 "parse.y"
-{
- yyval.node = arg_blk_pass(yyvsp[-1].node, yyvsp[0].node);
- ;
- break;}
-case 181:
-#line 809 "parse.y"
-{
- yyval.node = arg_add(yyvsp[-4].node, yyvsp[-1].node);
- yyval.node = arg_blk_pass(yyval.node, yyvsp[0].node);
- ;
- break;}
-case 182:
-#line 814 "parse.y"
-{
- yyval.node = NEW_LIST(NEW_HASH(yyvsp[-1].node));
- yyval.node = arg_blk_pass(yyval.node, yyvsp[0].node);
- ;
- break;}
-case 183:
-#line 819 "parse.y"
-{
- yyval.node = arg_add(NEW_LIST(NEW_HASH(yyvsp[-4].node)), yyvsp[-1].node);
- yyval.node = arg_blk_pass(yyval.node, yyvsp[0].node);
- ;
- break;}
-case 184:
-#line 824 "parse.y"
-{
- yyval.node = list_append(yyvsp[-3].node, NEW_HASH(yyvsp[-1].node));
- yyval.node = arg_blk_pass(yyval.node, yyvsp[0].node);
- ;
- break;}
-case 185:
-#line 829 "parse.y"
-{
- yyval.node = arg_add(list_append(yyvsp[-6].node, NEW_HASH(yyvsp[-4].node)), yyvsp[-1].node);
- yyval.node = arg_blk_pass(yyval.node, yyvsp[0].node);
- ;
- break;}
-case 186:
-#line 834 "parse.y"
-{
- value_expr(yyvsp[-1].node);
- yyval.node = arg_blk_pass(NEW_RESTARGS(yyvsp[-1].node), yyvsp[0].node);
- ;
- break;}
-case 188:
-#line 841 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyval.node = NEW_BLOCK_PASS(yyvsp[0].node);
- ;
- break;}
-case 189:
-#line 847 "parse.y"
-{
- yyval.node = yyvsp[0].node;
- ;
- break;}
-case 190:
-#line 851 "parse.y"
-{
- yyval.node = 0;
- ;
- break;}
-case 192:
-#line 857 "parse.y"
-{
- yyval.node = 0;
- ;
- break;}
-case 193:
-#line 862 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyval.node = NEW_LIST(yyvsp[0].node);
- ;
- break;}
-case 194:
-#line 867 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyval.node = list_append(yyvsp[-2].node, yyvsp[0].node);
- ;
- break;}
-case 195:
-#line 873 "parse.y"
-{
- if (yyvsp[0].node &&
- nd_type(yyvsp[0].node) == NODE_ARRAY &&
- yyvsp[0].node->nd_next == 0)
- {
- yyval.node = yyvsp[0].node->nd_head;
- }
- else {
- yyval.node = yyvsp[0].node;
- }
- ;
- break;}
-case 196:
-#line 885 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyval.node = arg_add(yyvsp[-3].node, yyvsp[0].node);
- ;
- break;}
-case 197:
-#line 890 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyval.node = yyvsp[0].node;
- ;
- break;}
-case 198:
-#line 896 "parse.y"
-{
- yyval.node = yyvsp[0].node;
- if (yyvsp[0].node) {
- if (nd_type(yyvsp[0].node) == NODE_ARRAY &&
- yyvsp[0].node->nd_next == 0) {
- yyval.node = yyvsp[0].node->nd_head;
- }
- else if (nd_type(yyvsp[0].node) == NODE_BLOCK_PASS) {
- rb_compile_error("block argument should not be given");
- }
- }
- ;
- break;}
-case 199:
-#line 910 "parse.y"
-{
- yyval.node = 0;
- ;
- break;}
-case 201:
-#line 916 "parse.y"
-{
- yyval.node = NEW_LIT(yyvsp[0].val);
- ;
- break;}
-case 202:
-#line 920 "parse.y"
-{
- value_expr(yyvsp[-2].node);
- yyval.node = NEW_COLON2(yyvsp[-2].node, yyvsp[0].id);
- ;
- break;}
-case 203:
-#line 925 "parse.y"
-{
- value_expr(yyvsp[-2].node);
- yyval.node = new_call(yyvsp[-2].node, yyvsp[0].id, 0);
- ;
- break;}
-case 204:
-#line 930 "parse.y"
-{
- yyval.node = NEW_COLON3(yyvsp[0].id);
- ;
- break;}
-case 205:
-#line 934 "parse.y"
-{
- yyval.node = NEW_STR(yyvsp[0].val);
- ;
- break;}
-case 207:
-#line 939 "parse.y"
-{
- yyval.node = NEW_XSTR(yyvsp[0].val);
- ;
- break;}
-case 212:
-#line 947 "parse.y"
-{
- value_expr(yyvsp[-3].node);
- yyval.node = NEW_CALL(yyvsp[-3].node, tAREF, yyvsp[-1].node);
- ;
- break;}
-case 213:
-#line 952 "parse.y"
-{
- if (yyvsp[-1].node == 0)
- yyval.node = NEW_ZARRAY(); /* zero length array*/
- else {
- yyval.node = yyvsp[-1].node;
- }
- ;
- break;}
-case 214:
-#line 960 "parse.y"
-{
- yyval.node = NEW_HASH(yyvsp[-1].node);
- ;
- break;}
-case 215:
-#line 964 "parse.y"
-{
- if (!cur_mid && !in_single)
- yyerror("return appeared outside of method");
- value_expr(yyvsp[-1].node);
- yyval.node = NEW_RETURN(yyvsp[-1].node);
- ;
- break;}
-case 216:
-#line 971 "parse.y"
-{
- if (!cur_mid && !in_single)
- yyerror("return appeared outside of method");
- yyval.node = NEW_RETURN(0);
- ;
- break;}
-case 217:
-#line 977 "parse.y"
-{
- if (!cur_mid && !in_single)
- yyerror("return appeared outside of method");
- yyval.node = NEW_RETURN(0);
- ;
- break;}
-case 218:
-#line 983 "parse.y"
-{
- value_expr(yyvsp[-1].node);
- yyval.node = NEW_YIELD(yyvsp[-1].node);
- ;
- break;}
-case 219:
-#line 988 "parse.y"
-{
- yyval.node = NEW_YIELD(0);
- ;
- break;}
-case 220:
-#line 992 "parse.y"
-{
- yyval.node = NEW_YIELD(0);
- ;
- break;}
-case 221:
-#line 995 "parse.y"
-{in_defined = 1;;
- break;}
-case 222:
-#line 996 "parse.y"
-{
- in_defined = 0;
- yyval.node = NEW_DEFINED(yyvsp[-1].node);
- ;
- break;}
-case 223:
-#line 1001 "parse.y"
-{
- yyval.node = NEW_VCALL(yyvsp[0].id);
- ;
- break;}
-case 224:
-#line 1005 "parse.y"
-{
- yyvsp[0].node->nd_iter = NEW_FCALL(yyvsp[-1].id, 0);
- yyval.node = yyvsp[0].node;
- ;
- break;}
-case 226:
-#line 1011 "parse.y"
-{
- if (yyvsp[-1].node && nd_type(yyvsp[-1].node) == NODE_BLOCK_PASS) {
- rb_compile_error("both block arg and actual block given");
- }
- yyvsp[0].node->nd_iter = yyvsp[-1].node;
- yyval.node = yyvsp[0].node;
- fixpos(yyval.node, yyvsp[-1].node);
- ;
- break;}
-case 227:
-#line 1023 "parse.y"
-{
- value_expr(yyvsp[-4].node);
- yyval.node = NEW_IF(cond(yyvsp[-4].node), yyvsp[-2].node, yyvsp[-1].node);
- fixpos(yyval.node, yyvsp[-4].node);
- ;
- break;}
-case 228:
-#line 1032 "parse.y"
-{
- value_expr(yyvsp[-4].node);
- yyval.node = NEW_UNLESS(cond(yyvsp[-4].node), yyvsp[-2].node, yyvsp[-1].node);
- fixpos(yyval.node, yyvsp[-4].node);
- ;
- break;}
-case 229:
-#line 1040 "parse.y"
-{
- value_expr(yyvsp[-3].node);
- yyval.node = NEW_WHILE(cond(yyvsp[-3].node), yyvsp[-1].node, 1);
- fixpos(yyval.node, yyvsp[-3].node);
- ;
- break;}
-case 230:
-#line 1048 "parse.y"
-{
- value_expr(yyvsp[-3].node);
- yyval.node = NEW_UNTIL(cond(yyvsp[-3].node), yyvsp[-1].node, 1);
- fixpos(yyval.node, yyvsp[-3].node);
- ;
- break;}
-case 231:
-#line 1056 "parse.y"
-{
- value_expr(yyvsp[-2].node);
- yyval.node = NEW_CASE(yyvsp[-2].node, yyvsp[-1].node);
- fixpos(yyval.node, yyvsp[-2].node);
- ;
- break;}
-case 232:
-#line 1064 "parse.y"
-{
- value_expr(yyvsp[-5].node);
- yyval.node = NEW_FOR(yyvsp[-5].node, yyvsp[-3].node, yyvsp[-1].node);
- fixpos(yyval.node, yyvsp[-5].node);
- ;
- break;}
-case 233:
-#line 1075 "parse.y"
-{
- if (!yyvsp[-3].node && !yyvsp[-2].node && !yyvsp[-1].node)
- yyval.node = NEW_BEGIN(yyvsp[-4].node);
- else {
- if (yyvsp[-3].node) yyvsp[-4].node = NEW_RESCUE(yyvsp[-4].node, yyvsp[-3].node, yyvsp[-2].node);
- else if (yyvsp[-2].node) {
- rb_warn("else without rescue is useless");
- yyvsp[-4].node = block_append(yyvsp[-4].node, yyvsp[-2].node);
- }
- if (yyvsp[-1].node) yyvsp[-4].node = NEW_ENSURE(yyvsp[-4].node, yyvsp[-1].node);
- yyval.node = yyvsp[-4].node;
- }
- fixpos(yyval.node, yyvsp[-4].node);
- ;
- break;}
-case 234:
-#line 1090 "parse.y"
-{
- yyval.node = yyvsp[-1].node;
- ;
- break;}
-case 235:
-#line 1094 "parse.y"
-{
- if (cur_mid || in_single)
- yyerror("class definition in method body");
-
- class_nest++;
- cref_push();
- local_push();
- ;
- break;}
-case 236:
-#line 1104 "parse.y"
-{
- yyval.node = NEW_CLASS(yyvsp[-4].id, yyvsp[-1].node, yyvsp[-3].node);
- fixpos(yyval.node, yyvsp[-3].node);
- local_pop();
- cref_pop();
- class_nest--;
- ;
- break;}
-case 237:
-#line 1112 "parse.y"
-{
- class_nest++;
- cref_push();
- local_push();
- ;
- break;}
-case 238:
-#line 1119 "parse.y"
-{
- yyval.node = NEW_SCLASS(yyvsp[-4].node, yyvsp[-1].node);
- fixpos(yyval.node, yyvsp[-4].node);
- local_pop();
- cref_pop();
- class_nest--;
- ;
- break;}
-case 239:
-#line 1127 "parse.y"
-{
- if (cur_mid || in_single)
- yyerror("module definition in method body");
- class_nest++;
- cref_push();
- local_push();
- ;
- break;}
-case 240:
-#line 1136 "parse.y"
-{
- yyval.node = NEW_MODULE(yyvsp[-3].id, yyvsp[-1].node);
- fixpos(yyval.node, yyvsp[-1].node);
- local_pop();
- cref_pop();
- class_nest--;
- ;
- break;}
-case 241:
-#line 1144 "parse.y"
-{
- if (cur_mid || in_single)
- yyerror("nested method definition");
- cur_mid = yyvsp[0].id;
- local_push();
- ;
- break;}
-case 242:
-#line 1153 "parse.y"
-{
- /* NOEX_PRIVATE for toplevel */
- yyval.node = NEW_DEFN(yyvsp[-4].id, yyvsp[-2].node, yyvsp[-1].node, class_nest?0:1);
- fixpos(yyval.node, yyvsp[-2].node);
- local_pop();
- cur_mid = 0;
- ;
- break;}
-case 243:
-#line 1160 "parse.y"
-{lex_state = EXPR_FNAME;;
- break;}
-case 244:
-#line 1161 "parse.y"
-{
- value_expr(yyvsp[-3].node);
- in_single++;
- local_push();
- lex_state = EXPR_END; /* force for args */
- ;
- break;}
-case 245:
-#line 1170 "parse.y"
-{
- yyval.node = NEW_DEFS(yyvsp[-7].node, yyvsp[-4].id, yyvsp[-2].node, yyvsp[-1].node);
- fixpos(yyval.node, yyvsp[-7].node);
- local_pop();
- in_single--;
- ;
- break;}
-case 246:
-#line 1177 "parse.y"
-{
- yyval.node = NEW_BREAK();
- ;
- break;}
-case 247:
-#line 1181 "parse.y"
-{
- yyval.node = NEW_NEXT();
- ;
- break;}
-case 248:
-#line 1185 "parse.y"
-{
- yyval.node = NEW_REDO();
- ;
- break;}
-case 249:
-#line 1189 "parse.y"
-{
- yyval.node = NEW_RETRY();
- ;
- break;}
-case 256:
-#line 1204 "parse.y"
-{
- value_expr(yyvsp[-3].node);
- yyval.node = NEW_IF(cond(yyvsp[-3].node), yyvsp[-1].node, yyvsp[0].node);
- fixpos(yyval.node, yyvsp[-3].node);
- ;
- break;}
-case 257:
-#line 1211 "parse.y"
-{
- yyval.node = 0;
- ;
- break;}
-case 258:
-#line 1215 "parse.y"
-{
- yyval.node = yyvsp[0].node;
- ;
- break;}
-case 261:
-#line 1223 "parse.y"
-{
- yyval.node = 0;
- ;
- break;}
-case 262:
-#line 1227 "parse.y"
-{
- yyval.node = 0;
- ;
- break;}
-case 263:
-#line 1231 "parse.y"
-{
- yyval.node = 0;
- ;
- break;}
-case 264:
-#line 1235 "parse.y"
-{
- yyval.node = yyvsp[-1].node;
- ;
- break;}
-case 265:
-#line 1240 "parse.y"
-{
- yyval.vars = dyna_push();
- ;
- break;}
-case 266:
-#line 1246 "parse.y"
-{
- yyval.node = NEW_ITER(yyvsp[-2].node, 0, yyvsp[-1].node);
- fixpos(yyval.node, yyvsp[-2].node?yyvsp[-2].node:yyvsp[-1].node);
- dyna_pop(yyvsp[-3].vars);
- ;
- break;}
-case 267:
-#line 1253 "parse.y"
-{
- yyval.vars = dyna_push();
- ;
- break;}
-case 268:
-#line 1258 "parse.y"
-{
- yyval.node = NEW_ITER(yyvsp[-2].node, 0, yyvsp[-1].node);
- fixpos(yyval.node, yyvsp[-2].node?yyvsp[-2].node:yyvsp[-1].node);
- dyna_pop(yyvsp[-3].vars);
- ;
- break;}
-case 269:
-#line 1265 "parse.y"
-{
- yyval.node = NEW_VCALL(yyvsp[0].id);
- ;
- break;}
-case 270:
-#line 1269 "parse.y"
-{
- yyval.node = NEW_VCALL(yyvsp[0].id);
- ;
- break;}
-case 271:
-#line 1273 "parse.y"
-{
- yyval.node = NEW_VCALL(yyvsp[0].id);
- ;
- break;}
-case 274:
-#line 1280 "parse.y"
-{
- yyval.node = new_fcall(yyvsp[-3].id, yyvsp[-1].node);
- fixpos(yyval.node, yyvsp[-1].node);
- ;
- break;}
-case 275:
-#line 1285 "parse.y"
-{
- value_expr(yyvsp[-5].node);
- yyval.node = new_call(yyvsp[-5].node, yyvsp[-3].id, yyvsp[-1].node);
- fixpos(yyval.node, yyvsp[-5].node);
- ;
- break;}
-case 276:
-#line 1291 "parse.y"
-{
- value_expr(yyvsp[-2].node);
- yyval.node = new_call(yyvsp[-2].node, yyvsp[0].id, 0);
- fixpos(yyval.node, yyvsp[-2].node);
- ;
- break;}
-case 277:
-#line 1297 "parse.y"
-{
- value_expr(yyvsp[-5].node);
- yyval.node = new_call(yyvsp[-5].node, yyvsp[-3].id, yyvsp[-1].node);
- fixpos(yyval.node, yyvsp[-5].node);
- ;
- break;}
-case 278:
-#line 1303 "parse.y"
-{
- if (!cur_mid && !in_single && !in_defined)
- yyerror("super called outside of method");
- yyval.node = NEW_SUPER(yyvsp[-1].node);
- ;
- break;}
-case 279:
-#line 1309 "parse.y"
-{
- if (!cur_mid && !in_single && !in_defined)
- yyerror("super called outside of method");
- yyval.node = NEW_ZSUPER();
- ;
- break;}
-case 280:
-#line 1319 "parse.y"
-{
- yyval.node = NEW_WHEN(yyvsp[-3].node, yyvsp[-1].node, yyvsp[0].node);
- ;
- break;}
-case 282:
-#line 1325 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyval.node = list_append(yyvsp[-3].node, NEW_WHEN(yyvsp[0].node, 0, 0));
- ;
- break;}
-case 283:
-#line 1330 "parse.y"
-{
- value_expr(yyvsp[0].node);
- yyval.node = NEW_LIST(NEW_WHEN(yyvsp[0].node, 0, 0));
- ;
- break;}
-case 286:
-#line 1341 "parse.y"
-{
- yyval.node = NEW_RESBODY(yyvsp[-3].node, yyvsp[-1].node, yyvsp[0].node);
- fixpos(yyval.node, yyvsp[-3].node?yyvsp[-3].node:yyvsp[-1].node);
- ;
- break;}
-case 287:
-#line 1346 "parse.y"
-{
- yyval.node = 0;
- ;
- break;}
-case 288:
-#line 1351 "parse.y"
-{
- yyval.node = 0;
- ;
- break;}
-case 289:
-#line 1355 "parse.y"
-{
- yyval.node = yyvsp[0].node;
- ;
- break;}
-case 291:
-#line 1361 "parse.y"
-{
- yyval.val = INT2FIX(yyvsp[0].id);
- ;
- break;}
-case 302:
-#line 1377 "parse.y"
-{yyval.id = kNIL;;
- break;}
-case 303:
-#line 1378 "parse.y"
-{yyval.id = kSELF;;
- break;}
-case 304:
-#line 1379 "parse.y"
-{yyval.id = kTRUE;;
- break;}
-case 305:
-#line 1380 "parse.y"
-{yyval.id = kFALSE;;
- break;}
-case 306:
-#line 1381 "parse.y"
-{yyval.id = k__FILE__;;
- break;}
-case 307:
-#line 1382 "parse.y"
-{yyval.id = k__LINE__;;
- break;}
-case 308:
-#line 1385 "parse.y"
-{
- yyval.node = gettable(yyvsp[0].id);
- ;
- break;}
-case 311:
-#line 1393 "parse.y"
-{
- yyval.node = 0;
- ;
- break;}
-case 312:
-#line 1397 "parse.y"
-{
- lex_state = EXPR_BEG;
- ;
- break;}
-case 313:
-#line 1401 "parse.y"
-{
- yyval.node = yyvsp[-1].node;
- ;
- break;}
-case 314:
-#line 1404 "parse.y"
-{yyerrok; yyval.node = 0;;
- break;}
-case 315:
-#line 1407 "parse.y"
-{
- yyval.node = yyvsp[-2].node;
- lex_state = EXPR_BEG;
- ;
- break;}
-case 316:
-#line 1412 "parse.y"
-{
- yyval.node = yyvsp[-1].node;
- ;
- break;}
-case 317:
-#line 1417 "parse.y"
-{
- yyval.node = block_append(NEW_ARGS(yyvsp[-5].num, yyvsp[-3].node, yyvsp[-1].id), yyvsp[0].node);
- ;
- break;}
-case 318:
-#line 1421 "parse.y"
-{
- yyval.node = block_append(NEW_ARGS(yyvsp[-3].num, yyvsp[-1].node, -1), yyvsp[0].node);
- ;
- break;}
-case 319:
-#line 1425 "parse.y"
-{
- yyval.node = block_append(NEW_ARGS(yyvsp[-3].num, 0, yyvsp[-1].id), yyvsp[0].node);
- ;
- break;}
-case 320:
-#line 1429 "parse.y"
-{
- yyval.node = block_append(NEW_ARGS(yyvsp[-1].num, 0, -1), yyvsp[0].node);
- ;
- break;}
-case 321:
-#line 1433 "parse.y"
-{
- yyval.node = block_append(NEW_ARGS(0, yyvsp[-3].node, yyvsp[-1].id), yyvsp[0].node);
- ;
- break;}
-case 322:
-#line 1437 "parse.y"
-{
- yyval.node = block_append(NEW_ARGS(0, yyvsp[-1].node, -1), yyvsp[0].node);
- ;
- break;}
-case 323:
-#line 1441 "parse.y"
-{
- yyval.node = block_append(NEW_ARGS(0, 0, yyvsp[-1].id), yyvsp[0].node);
- ;
- break;}
-case 324:
-#line 1445 "parse.y"
-{
- yyval.node = block_append(NEW_ARGS(0, 0, -1), yyvsp[0].node);
- ;
- break;}
-case 325:
-#line 1449 "parse.y"
-{
- yyval.node = NEW_ARGS(0, 0, -1);
- ;
- break;}
-case 326:
-#line 1454 "parse.y"
-{
- if (!is_local_id(yyvsp[0].id))
- yyerror("formal argument must be local variable");
- local_cnt(yyvsp[0].id);
- yyval.num = 1;
- ;
- break;}
-case 327:
-#line 1461 "parse.y"
-{
- if (!is_local_id(yyvsp[0].id))
- yyerror("formal argument must be local variable");
- local_cnt(yyvsp[0].id);
- yyval.num += 1;
- ;
- break;}
-case 328:
-#line 1469 "parse.y"
-{
- if (!is_local_id(yyvsp[-2].id))
- yyerror("formal argument must be local variable");
- yyval.node = assignable(yyvsp[-2].id, yyvsp[0].node);
- ;
- break;}
-case 329:
-#line 1476 "parse.y"
-{
- yyval.node = NEW_BLOCK(yyvsp[0].node);
- yyval.node->nd_end = yyval.node;
- ;
- break;}
-case 330:
-#line 1481 "parse.y"
-{
- yyval.node = block_append(yyvsp[-2].node, yyvsp[0].node);
- ;
- break;}
-case 331:
-#line 1486 "parse.y"
-{
- if (!is_local_id(yyvsp[0].id))
- yyerror("rest argument must be local variable");
- yyval.id = local_cnt(yyvsp[0].id);
- ;
- break;}
-case 332:
-#line 1493 "parse.y"
-{
- yyval.node = NEW_BLOCK_ARG(yyvsp[0].id);
- ;
- break;}
-case 333:
-#line 1498 "parse.y"
-{
- yyval.node = yyvsp[0].node;
- ;
- break;}
-case 334:
-#line 1502 "parse.y"
-{
- yyval.node = 0;
- ;
- break;}
-case 335:
-#line 1507 "parse.y"
-{
- if (nd_type(yyvsp[0].node) == NODE_SELF) {
- yyval.node = NEW_SELF();
- }
- else if (nd_type(yyvsp[0].node) == NODE_NIL) {
- yyerror("Can't define single method for nil.");
- yyval.node = 0;
- }
- else {
- yyval.node = yyvsp[0].node;
- }
- ;
- break;}
-case 336:
-#line 1520 "parse.y"
-{
- switch (nd_type(yyvsp[-2].node)) {
- case NODE_STR:
- case NODE_DSTR:
- case NODE_XSTR:
- case NODE_DXSTR:
- case NODE_DREGX:
- case NODE_LIT:
- case NODE_ARRAY:
- case NODE_ZARRAY:
- yyerror("Can't define single method for literals.");
- default:
- break;
- }
- yyval.node = yyvsp[-2].node;
- ;
- break;}
-case 337:
-#line 1538 "parse.y"
-{
- yyval.node = 0;
- ;
- break;}
-case 338:
-#line 1542 "parse.y"
-{
- yyval.node = yyvsp[-1].node;
- ;
- break;}
-case 339:
-#line 1546 "parse.y"
-{
- if (yyvsp[-1].node->nd_alen%2 != 0) {
- yyerror("odd number list for Hash");
- }
- yyval.node = yyvsp[-1].node;
- ;
- break;}
-case 341:
-#line 1555 "parse.y"
-{
- yyval.node = list_concat(yyvsp[-2].node, yyvsp[0].node);
- ;
- break;}
-case 342:
-#line 1560 "parse.y"
-{
- yyval.node = list_append(NEW_LIST(yyvsp[-2].node), yyvsp[0].node);
- ;
- break;}
-case 355:
-#line 1581 "parse.y"
-{yyerrok;;
- break;}
-case 358:
-#line 1585 "parse.y"
-{yyerrok;;
- break;}
-}
- /* the action file gets copied in in place of this dollarsign */
-#line 542 "/usr/share/misc/bison.simple"
-
- yyvsp -= yylen;
- yyssp -= yylen;
-#ifdef YYLSP_NEEDED
- yylsp -= yylen;
-#endif
-
-#if YYDEBUG != 0
- if (yydebug)
- {
- short *ssp1 = yyss - 1;
- fprintf (stderr, "state stack now");
- while (ssp1 != yyssp)
- fprintf (stderr, " %d", *++ssp1);
- fprintf (stderr, "\n");
- }
-#endif
-
- *++yyvsp = yyval;
-
-#ifdef YYLSP_NEEDED
- yylsp++;
- if (yylen == 0)
- {
- yylsp->first_line = yylloc.first_line;
- yylsp->first_column = yylloc.first_column;
- yylsp->last_line = (yylsp-1)->last_line;
- yylsp->last_column = (yylsp-1)->last_column;
- yylsp->text = 0;
- }
- else
- {
- yylsp->last_line = (yylsp+yylen-1)->last_line;
- yylsp->last_column = (yylsp+yylen-1)->last_column;
- }
-#endif
-
- /* Now "shift" the result of the reduction.
- Determine what state that goes to,
- based on the state we popped back to
- and the rule number reduced by. */
-
- yyn = yyr1[yyn];
-
- yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
- if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
- yystate = yytable[yystate];
- else
- yystate = yydefgoto[yyn - YYNTBASE];
-
- goto yynewstate;
-
-yyerrlab: /* here on detecting error */
-
- if (! yyerrstatus)
- /* If not already recovering from an error, report this error. */
- {
- ++yynerrs;
-
-#ifdef YYERROR_VERBOSE
- yyn = yypact[yystate];
-
- if (yyn > YYFLAG && yyn < YYLAST)
- {
- int size = 0;
- char *msg;
- int x, count;
-
- count = 0;
- /* Start X at -yyn if nec to avoid negative indexes in yycheck. */
- for (x = (yyn < 0 ? -yyn : 0);
- x < (sizeof(yytname) / sizeof(char *)); x++)
- if (yycheck[x + yyn] == x)
- size += strlen(yytname[x]) + 15, count++;
- msg = (char *) malloc(size + 15);
- if (msg != 0)
- {
- strcpy(msg, "parse error");
-
- if (count < 5)
- {
- count = 0;
- for (x = (yyn < 0 ? -yyn : 0);
- x < (sizeof(yytname) / sizeof(char *)); x++)
- if (yycheck[x + yyn] == x)
- {
- strcat(msg, count == 0 ? ", expecting `" : " or `");
- strcat(msg, yytname[x]);
- strcat(msg, "'");
- count++;
- }
- }
- yyerror(msg);
- free(msg);
- }
- else
- yyerror ("parse error; also virtual memory exceeded");
- }
- else
-#endif /* YYERROR_VERBOSE */
- yyerror("parse error");
- }
-
- goto yyerrlab1;
-yyerrlab1: /* here on error raised explicitly by an action */
-
- if (yyerrstatus == 3)
- {
- /* if just tried and failed to reuse lookahead token after an error, discard it. */
-
- /* return failure if at end of input */
- if (yychar == YYEOF)
- YYABORT;
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
-#endif
-
- yychar = YYEMPTY;
- }
-
- /* Else will try to reuse lookahead token
- after shifting the error token. */
-
- yyerrstatus = 3; /* Each real token shifted decrements this */
-
- goto yyerrhandle;
-
-yyerrdefault: /* current state does not do anything special for the error token. */
-
-#if 0
- /* This is wrong; only states that explicitly want error tokens
- should shift them. */
- yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
- if (yyn) goto yydefault;
-#endif
-
-yyerrpop: /* pop the current state because it cannot handle the error token */
-
- if (yyssp == yyss) YYABORT;
- yyvsp--;
- yystate = *--yyssp;
-#ifdef YYLSP_NEEDED
- yylsp--;
-#endif
-
-#if YYDEBUG != 0
- if (yydebug)
- {
- short *ssp1 = yyss - 1;
- fprintf (stderr, "Error: state stack now");
- while (ssp1 != yyssp)
- fprintf (stderr, " %d", *++ssp1);
- fprintf (stderr, "\n");
- }
-#endif
-
-yyerrhandle:
-
- yyn = yypact[yystate];
- if (yyn == YYFLAG)
- goto yyerrdefault;
-
- yyn += YYTERROR;
- if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
- goto yyerrdefault;
-
- yyn = yytable[yyn];
- if (yyn < 0)
- {
- if (yyn == YYFLAG)
- goto yyerrpop;
- yyn = -yyn;
- goto yyreduce;
- }
- else if (yyn == 0)
- goto yyerrpop;
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
-#if YYDEBUG != 0
- if (yydebug)
- fprintf(stderr, "Shifting error token, ");
-#endif
-
- *++yyvsp = yylval;
-#ifdef YYLSP_NEEDED
- *++yylsp = yylloc;
-#endif
-
- yystate = yyn;
- goto yynewstate;
-
- yyacceptlab:
- /* YYACCEPT comes here. */
- if (yyfree_stacks)
- {
- free (yyss);
- free (yyvs);
-#ifdef YYLSP_NEEDED
- free (yyls);
-#endif
- }
- return 0;
-
- yyabortlab:
- /* YYABORT comes here. */
- if (yyfree_stacks)
- {
- free (yyss);
- free (yyvs);
-#ifdef YYLSP_NEEDED
- free (yyls);
-#endif
- }
- return 1;
-}
-#line 1586 "parse.y"
-
-#include <ctype.h>
-#include <sys/types.h>
-#include "regex.h"
-#include "util.h"
-
-#define is_identchar(c) ((c)!=-1&&(ISALNUM(c) || (c) == '_' || ismbchar(c)))
-
-static char *tokenbuf = NULL;
-static int tokidx, toksiz = 0;
-
-char *strdup();
-
-static NODE *rb_str_extend();
-
-#define LEAVE_BS 1
-
-static VALUE (*lex_gets)(); /* gets function */
-static VALUE lex_input; /* non-nil if File */
-static VALUE lex_lastline; /* gc protect */
-static char *lex_pbeg;
-static char *lex_p;
-static char *lex_pend;
-
-static int
-yyerror(msg)
- char *msg;
-{
- char *p, *pe, *buf;
- int len, i;
-
- rb_compile_error("%s", msg);
- p = lex_p;
- while (lex_pbeg <= p) {
- if (*p == '\n') break;
- p--;
- }
- p++;
-
- pe = lex_p;
- while (pe < lex_pend) {
- if (*pe == '\n') break;
- pe++;
- }
-
- len = pe - p;
- if (len > 4) {
- buf = ALLOCA_N(char, len+2);
- MEMCPY(buf, p, char, len);
- buf[len] = '\0';
- rb_compile_error_append("%s", buf);
-
- i = lex_p - p;
- p = buf; pe = p + len;
-
- while (p < pe) {
- if (*p != '\t') *p = ' ';
- p++;
- }
- buf[i] = '^';
- buf[i+1] = '\0';
- rb_compile_error_append("%s", buf);
- }
-
- return 0;
-}
-
-static int newline_seen;
-static int heredoc_end;
-
-int ruby_in_compile = 0;
-int ruby__end__seen;
-
-static NODE*
-yycompile(f)
- char *f;
-{
- int n;
-
- ruby__end__seen = 0;
- ruby_eval_tree = 0;
- newline_seen = 0;
- ruby_sourcefile = f;
- ruby_in_compile = 1;
- n = yyparse();
- ruby_in_compile = 0;
- if (n == 0) return ruby_eval_tree;
-
- return 0;
-}
-
-static int lex_gets_ptr;
-
-static VALUE
-lex_get_str(s)
- VALUE s;
-{
- char *beg, *end, *pend;
-
- beg = RSTRING(s)->ptr;
- if (lex_gets_ptr) {
- if (RSTRING(s)->len == lex_gets_ptr) return Qnil;
- beg += lex_gets_ptr;
- }
- pend = RSTRING(s)->ptr + RSTRING(s)->len;
- end = beg;
- while (end < pend) {
- if (*end++ == '\n') break;
- }
- lex_gets_ptr = end - RSTRING(s)->ptr;
- return rb_str_new(beg, end - beg);
-}
-
-NODE*
-rb_compile_string(f, s)
- char *f;
- VALUE s;
-{
- lex_gets = lex_get_str;
- lex_gets_ptr = 0;
- lex_input = s;
- lex_pbeg = lex_p = lex_pend = 0;
- if (!ruby_sourcefile || strcmp(f, ruby_sourcefile)) /* not in eval() */
- ruby_sourceline = 1;
-
- return yycompile(f);
-}
-
-NODE*
-rb_compile_cstr(f, s, len)
- char *f, *s;
- int len;
-{
- return rb_compile_string(f, rb_str_new(s, len));
-}
-
-NODE*
-rb_compile_file(f, file, start)
- char *f;
- VALUE file;
- int start;
-{
- lex_gets = rb_io_gets;
- lex_input = file;
- lex_pbeg = lex_p = lex_pend = 0;
- ruby_sourceline = start;
-
- return yycompile(strdup(f));
-}
-
-
-static void
-normalize_newline(line)
- VALUE line;
-{
- if (RSTRING(line)->len >= 2 &&
- RSTRING(line)->ptr[RSTRING(line)->len-1] == '\n' &&
- RSTRING(line)->ptr[RSTRING(line)->len-2] == '\r')
- {
- RSTRING(line)->ptr[RSTRING(line)->len-2] = '\n';
- RSTRING(line)->len--;
- }
-}
-
-static int
-nextc()
-{
- int c;
-
- if (lex_p == lex_pend) {
- if (lex_input) {
- VALUE v = (*lex_gets)(lex_input);
-
- if (NIL_P(v)) return -1;
- if (heredoc_end > 0) {
- ruby_sourceline = heredoc_end+1;
- heredoc_end = 0;
- }
- normalize_newline(v);
- while (RSTRING(v)->len >= 2 &&
- RSTRING(v)->ptr[RSTRING(v)->len-1] == '\n' &&
- RSTRING(v)->ptr[RSTRING(v)->len-2] == '\\') {
- VALUE v2 = (*lex_gets)(lex_input);
-
- if (!NIL_P(v2)) {
- normalize_newline(v2);
- rb_str_cat(v, RSTRING(v2)->ptr, RSTRING(v2)->len);
- }
- }
- lex_pbeg = lex_p = RSTRING(v)->ptr;
- lex_pend = lex_p + RSTRING(v)->len;
- if (strncmp(lex_pbeg, "__END__", 7) == 0 && lex_pbeg[7] == '\n') {
- ruby__end__seen = 1;
- lex_lastline = 0;
- return -1;
- }
- lex_lastline = v;
- }
- else {
- lex_lastline = 0;
- return -1;
- }
- }
- c = (unsigned char)*lex_p++;
-
- return c;
-}
-
-static void
-pushback(c)
- int c;
-{
- if (c == -1) return;
- lex_p--;
-}
-
-#define tokfix() (tokenbuf[tokidx]='\0')
-#define tok() tokenbuf
-#define toklen() tokidx
-#define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
-
-static char*
-newtok()
-{
- tokidx = 0;
- if (!tokenbuf) {
- toksiz = 60;
- tokenbuf = ALLOC_N(char, 60);
- }
- if (toksiz > 4096) {
- toksiz = 60;
- REALLOC_N(tokenbuf, char, 60);
- }
- return tokenbuf;
-}
-
-static void
-tokadd(c)
- char c;
-{
- tokenbuf[tokidx++] = c;
- if (tokidx >= toksiz) {
- toksiz *= 2;
- REALLOC_N(tokenbuf, char, toksiz);
- }
-}
-
-static int
-read_escape()
-{
- int c;
-
- switch (c = nextc()) {
- case '\\': /* Backslash */
- return c;
-
- case 'n': /* newline */
- return '\n';
-
- case 't': /* horizontal tab */
- return '\t';
-
- case 'r': /* carriage-return */
- return '\r';
-
- case 'f': /* form-feed */
- return '\f';
-
- case 'v': /* vertical tab */
- return '\13';
-
- case 'a': /* alarm(bell) */
- return '\007';
-
- case 'e': /* escape */
- return 033;
-
- case '0': case '1': case '2': case '3': /* octal constant */
- case '4': case '5': case '6': case '7':
- {
- char buf[3];
- int i;
-
- pushback(c);
- for (i=0; i<3; i++) {
- c = nextc();
- if (c == -1) goto eof;
- if (c < '0' || '7' < c) {
- pushback(c);
- break;
- }
- buf[i] = c;
- }
- c = scan_oct(buf, i+1, &i);
- }
- return c;
-
- case 'x': /* hex constant */
- {
- char buf[2];
- int i;
-
- for (i=0; i<2; i++) {
- buf[i] = nextc();
- if (buf[i] == -1) goto eof;
- if (!ISXDIGIT(buf[i])) {
- pushback(buf[i]);
- break;
- }
- }
- c = scan_hex(buf, i+1, &i);
- }
- return c;
-
- case 'b': /* backspace */
- return '\b';
-
- case 's': /* space */
- return ' ';
-
- case 'M':
- if ((c = nextc()) != '-') {
- yyerror("Invalid escape character syntax");
- pushback(c);
- return '\0';
- }
- if ((c = nextc()) == '\\') {
- return read_escape() | 0x80;
- }
- else if (c == -1) goto eof;
- else {
- return ((c & 0xff) | 0x80);
- }
-
- case 'C':
- if ((c = nextc()) != '-') {
- yyerror("Invalid escape character syntax");
- pushback(c);
- return '\0';
- }
- case 'c':
- if ((c = nextc())== '\\') {
- c = read_escape();
- }
- else if (c == '?')
- return 0177;
- else if (c == -1) goto eof;
- return c & 0x9f;
-
- eof:
- case -1:
- yyerror("Invalid escape character syntax");
- return '\0';
-
- default:
- return c;
- }
-}
-
-static int
-parse_regx(term, paren)
- int term;
-{
- register int c;
- char kcode = 0;
- int once = 0;
- int nest = 0;
- int options = 0;
- int in_brack = 0;
- int re_start = ruby_sourceline;
- NODE *list = 0;
-
- newtok();
- while ((c = nextc()) != -1) {
- if ((!in_brack && c == term) || nest > 0) {
- goto regx_end;
- }
-
- switch (c) {
- case '\n':
- ruby_sourceline++;
- break;
- case '[':
- in_brack = 1;
- break;
- case ']':
- in_brack = 0;
- break;
-
- case '#':
- list = rb_str_extend(list, term);
- if (list == (NODE*)-1) return 0;
- continue;
-
- case '\\':
- switch (c = nextc()) {
- case -1:
- ruby_sourceline = re_start;
- rb_compile_error("unterminated regexp meets end of file");
- return 0;
-
- case '\n':
- ruby_sourceline++;
- break;
-
- case '\\':
- case '^':
- case 's':
- tokadd('\\');
- tokadd(c);
- break;
-
- case '1': case '2': case '3':
- case '4': case '5': case '6':
- case '7': case '8': case '9':
- case '0': case 'x':
- tokadd('\\');
- tokadd(c);
- break;
-
- case 'b':
- if (!in_brack) {
- tokadd('\\');
- tokadd('b');
- break;
- }
- /* fall through */
- default:
- if (c == paren) nest++;
- if (c == term) nest--;
- if (c == '\n') {
- ruby_sourceline++;
- }
- else if (c == term) {
- tokadd(c);
- }
- else {
- pushback(c);
- tokadd('\\');
- tokadd(read_escape());
- }
- }
- continue;
-
- case -1:
- rb_compile_error("unterminated regexp");
- return 0;
-
- default:
- if (ismbchar(c)) {
- int i, len = mbclen(c)-1;
-
- for (i = 0; i < len; i++) {
- tokadd(c);
- c = nextc();
- }
- }
- break;
-
- regx_end:
- for (;;) {
- switch (c = nextc()) {
- case 'i':
- options |= RE_OPTION_IGNORECASE;
- break;
- case 'x':
- options |= RE_OPTION_EXTENDED;
- break;
- case 'o':
- once = 1;
- break;
- case 'n':
- kcode = 4;
- break;
- case 'e':
- kcode = 8;
- break;
- case 's':
- kcode = 12;
- break;
- case 'u':
- kcode = 16;
- break;
- default:
- pushback(c);
- goto end_options;
- }
- }
-
- end_options:
- tokfix();
- lex_state = EXPR_END;
- if (list) {
- if (toklen() > 0) {
- VALUE ss = rb_str_new(tok(), toklen());
- list_append(list, NEW_STR(ss));
- }
- nd_set_type(list, once?NODE_DREGX_ONCE:NODE_DREGX);
- list->nd_cflag = options | kcode;
- yylval.node = list;
- return tDREGEXP;
- }
- else {
- yylval.val = rb_reg_new(tok(), toklen(), options | kcode);
- return tREGEXP;
- }
- }
- tokadd(c);
- }
- rb_compile_error("unterminated regexp");
- return 0;
-}
-
-static int parse_qstring _((int,int));
-
-static int
-parse_string(func, term, paren)
- int func, term, paren;
-{
- int c;
- NODE *list = 0;
- int strstart;
- int nest = 0;
-
- if (func == '\'') {
- return parse_qstring(term, paren);
- }
- if (func == 0) { /* read 1 line for heredoc */
- ruby_sourceline++;
- /* -1 for chomp */
- yylval.val = rb_str_new(lex_pbeg, lex_pend - lex_pbeg - 1);
- return tSTRING;
- }
- strstart = ruby_sourceline;
- newtok();
- while ((c = nextc()) != term || nest > 0) {
- if (c == -1) {
- unterm_str:
- ruby_sourceline = strstart;
- rb_compile_error("unterminated string meets end of file");
- return 0;
- }
- if (ismbchar(c)) {
- int i, len = mbclen(c)-1;
-
- for (i = 0; i < len; i++) {
- tokadd(c);
- c = nextc();
- }
- }
- else if (c == '\n') {
- ruby_sourceline++;
- }
- else if (c == '#') {
- list = rb_str_extend(list, term);
- if (list == (NODE*)-1) goto unterm_str;
- continue;
- }
- else if (c == '\\') {
- c = nextc();
- if (c == '\n') {
- ruby_sourceline++;
- }
- else if (c == term) {
- tokadd(c);
- }
- else {
- pushback(c);
- if (func != '"') tokadd('\\');
- tokadd(read_escape());
- }
- continue;
- }
- if (c == paren) nest++;
- if (c == term) {
- nest--;
- if (nest == 0) break;
- }
- tokadd(c);
- }
-
- tokfix();
- lex_state = EXPR_END;
- if (list) {
- if (toklen() > 0) {
- VALUE ss = rb_str_new(tok(), toklen());
- list_append(list, NEW_STR(ss));
- }
- yylval.node = list;
- if (func == '`') {
- nd_set_type(list, NODE_DXSTR);
- return tDXSTRING;
- }
- else {
- return tDSTRING;
- }
- }
- else {
- yylval.val = rb_str_new(tok(), toklen());
- return (func == '`') ? tXSTRING : tSTRING;
- }
-}
-
-static int
-parse_qstring(term, paren)
- int term, paren;
-{
- int strstart;
- int c;
- int nest = 0;
-
- strstart = ruby_sourceline;
- newtok();
- while ((c = nextc()) != term || nest > 0) {
- if (c == -1) {
- ruby_sourceline = strstart;
- rb_compile_error("unterminated string meets end of file");
- return 0;
- }
- if (ismbchar(c)) {
- int i, len = mbclen(c)-1;
-
- for (i = 0; i < len; i++) {
- tokadd(c);
- c = nextc();
- }
- }
- else if (c == '\n') {
- ruby_sourceline++;
- }
- else if (c == '\\') {
- c = nextc();
- switch (c) {
- case '\n':
- ruby_sourceline++;
- continue;
-
- case '\\':
- c = '\\';
- break;
-
- case '\'':
- if (term == '\'') {
- c = '\'';
- break;
- }
- /* fall through */
- default:
- tokadd('\\');
- }
- }
- if (c == paren) nest++;
- if (c == term) {
- nest--;
- if (nest == 0) break;
- }
- tokadd(c);
- }
-
- tokfix();
- yylval.val = rb_str_new(tok(), toklen());
- lex_state = EXPR_END;
- return tSTRING;
-}
-
-static int
-parse_quotedword(term, paren)
- int term, paren;
-{
- if (parse_qstring(term, paren) == 0) return 0;
- yylval.node = NEW_CALL(NEW_STR(yylval.val), rb_intern("split"), 0);
- return tDSTRING;
-}
-
-char *strdup();
-
-static int
-here_document(term, indent)
- char term;
- int indent;
-{
- int c;
- char *eos, *p;
- int len;
- VALUE str;
- volatile VALUE line;
- VALUE lastline_save;
- int offset_save;
- NODE *list = 0;
- int linesave = ruby_sourceline;
-
- newtok();
- switch (term) {
- case '\'':
- case '"':
- case '`':
- while ((c = nextc()) != term) {
- tokadd(c);
- }
- if (term == '\'') term = 0;
- break;
-
- default:
- c = term;
- term = '"';
- if (!is_identchar(c)) {
- rb_warn("Use of bare << to mean <<\"\" is deprecated");
- break;
- }
- while (is_identchar(c)) {
- tokadd(c);
- c = nextc();
- }
- pushback(c);
- break;
- }
- tokfix();
- lastline_save = lex_lastline;
- offset_save = lex_p - lex_pbeg;
- eos = strdup(tok());
- len = strlen(eos);
-
- str = rb_str_new(0,0);
- for (;;) {
- line = (*lex_gets)(lex_input);
- if (NIL_P(line)) {
- error:
- ruby_sourceline = linesave;
- rb_compile_error("can't find string \"%s\" anywhere before EOF", eos);
- free(eos);
- return 0;
- }
- normalize_newline(line);
- ruby_sourceline++;
- p = RSTRING(line)->ptr;
- if (indent) {
- while (*p && (*p == ' ' || *p == '\t')) {
- p++;
- }
- }
- if (strncmp(eos, p, len) == 0 && p[len] == '\n') {
- break;
- }
-
- lex_pbeg = lex_p = RSTRING(line)->ptr;
- lex_pend = lex_p + RSTRING(line)->len;
-#if 0
- if (indent) {
- while (*lex_p && *lex_p == '\t') {
- lex_p++;
- }
- }
-#endif
- switch (parse_string(term, '\n', '\n')) {
- case tSTRING:
- case tXSTRING:
- rb_str_cat(yylval.val, "\n", 1);
- if (!list) {
- rb_str_cat(str, RSTRING(yylval.val)->ptr, RSTRING(yylval.val)->len);
- }
- else {
- list_append(list, NEW_STR(yylval.val));
- }
- break;
- case tDSTRING:
- case tDXSTRING:
- list_append(yylval.node, NEW_STR(rb_str_new2("\n")));
- nd_set_type(yylval.node, NODE_STR);
- if (!list) list = NEW_DSTR(str);
- yylval.node = NEW_LIST(yylval.node);
- yylval.node->nd_next = yylval.node->nd_head->nd_next;
- list_concat(list, yylval.node);
- break;
-
- case 0:
- goto error;
- }
- }
- free(eos);
- lex_lastline = lastline_save;
- lex_pbeg = RSTRING(lex_lastline)->ptr;
- lex_pend = lex_pbeg + RSTRING(lex_lastline)->len;
- lex_p = lex_pbeg + offset_save;
-
- lex_state = EXPR_END;
- heredoc_end = ruby_sourceline;
- ruby_sourceline = linesave;
-
- if (list) {
- yylval.node = list;
- }
- switch (term) {
- case '\0':
- case '\'':
- case '"':
- if (list) return tDSTRING;
- yylval.val = str;
- return tSTRING;
- case '`':
- if (list) return tDXSTRING;
- return tXSTRING;
- }
- return 0;
-}
-
-#include "lex.c"
-
-static void
-arg_ambiguous()
-{
- rb_warning("ambiguous first argument; make sure");
-}
-
-#ifndef atof
-double atof();
-#endif
-
-static int
-yylex()
-{
- register int c;
- int space_seen = 0;
- struct kwtable *kw;
-
- if (newline_seen) {
- ruby_sourceline += newline_seen;
- newline_seen = 0;
- }
-
-retry:
- switch (c = nextc()) {
- case '\0': /* NUL */
- case '\004': /* ^D */
- case '\032': /* ^Z */
- case -1: /* end of script. */
- return 0;
-
- /* white spaces */
- case ' ': case '\t': case '\f': case '\r':
- case '\13': /* '\v' */
- space_seen = 1;
- goto retry;
-
- case '#': /* it's a comment */
- while ((c = nextc()) != '\n') {
- if (c == -1)
- return 0;
- if (c == '\\') { /* skip a char */
- c = nextc();
- if (c == '\n') ruby_sourceline++;
- }
- if (ismbchar(c)) {
- int i, len = mbclen(c)-1;
-
- for (i = 0; i < len; i++) {
- c = nextc();
- if (c == '\n') {
- ruby_sourceline++;
- break;
- }
- }
- }
- }
- /* fall through */
- case '\n':
- switch (lex_state) {
- case EXPR_BEG:
- case EXPR_FNAME:
- case EXPR_DOT:
- ruby_sourceline++;
- goto retry;
- default:
- break;
- }
- newline_seen++;
- lex_state = EXPR_BEG;
- return '\n';
-
- case '*':
- if ((c = nextc()) == '*') {
- lex_state = EXPR_BEG;
- if (nextc() == '=') {
- yylval.id = tPOW;
- return tOP_ASGN;
- }
- pushback(c);
- return tPOW;
- }
- if (c == '=') {
- yylval.id = '*';
- lex_state = EXPR_BEG;
- return tOP_ASGN;
- }
- pushback(c);
- if (lex_state == EXPR_ARG && space_seen && !ISSPACE(c)){
- arg_ambiguous();
- lex_state = EXPR_BEG;
- return tSTAR;
- }
- if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
- lex_state = EXPR_BEG;
- return tSTAR;
- }
- lex_state = EXPR_BEG;
- return '*';
-
- case '!':
- lex_state = EXPR_BEG;
- if ((c = nextc()) == '=') {
- return tNEQ;
- }
- if (c == '~') {
- return tNMATCH;
- }
- pushback(c);
- return '!';
-
- case '=':
- if (lex_p == lex_pbeg + 1) {
- /* skip embedded rd document */
- if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) {
- for (;;) {
- ruby_sourceline++;
- lex_p = lex_pend;
- c = nextc();
- if (c == -1) {
- rb_compile_error("embedded document meets end of file");
- return 0;
- }
- if (c != '=') continue;
- if (strncmp(lex_p, "end", 3) == 0 && ISSPACE(lex_p[3])) {
- break;
- }
- }
- ruby_sourceline++;
- lex_p = lex_pend;
- goto retry;
- }
- }
-
- lex_state = EXPR_BEG;
- if ((c = nextc()) == '=') {
- if ((c = nextc()) == '=') {
- return tEQQ;
- }
- pushback(c);
- return tEQ;
- }
- if (c == '~') {
- return tMATCH;
- }
- else if (c == '>') {
- return tASSOC;
- }
- pushback(c);
- return '=';
-
- case '<':
- c = nextc();
- if (c == '<' &&
- lex_state != EXPR_END && lex_state != EXPR_CLASS &&
- (lex_state != EXPR_ARG || space_seen)) {
- int c2 = nextc();
- int indent = 0;
- if (c2 == '-') {
- indent = 1;
- c2 = nextc();
- }
- if (!ISSPACE(c2) && (strchr("\"'`", c2) || is_identchar(c2))) {
- return here_document(c2, indent);
- }
- pushback(c2);
- }
- lex_state = EXPR_BEG;
- if (c == '=') {
- if ((c = nextc()) == '>') {
- return tCMP;
- }
- pushback(c);
- return tLEQ;
- }
- if (c == '<') {
- if (nextc() == '=') {
- yylval.id = tLSHFT;
- return tOP_ASGN;
- }
- pushback(c);
- return tLSHFT;
- }
- pushback(c);
- return '<';
-
- case '>':
- lex_state = EXPR_BEG;
- if ((c = nextc()) == '=') {
- return tGEQ;
- }
- if (c == '>') {
- if ((c = nextc()) == '=') {
- yylval.id = tRSHFT;
- return tOP_ASGN;
- }
- pushback(c);
- return tRSHFT;
- }
- pushback(c);
- return '>';
-
- case '"':
- return parse_string(c,c,c);
- case '`':
- if (lex_state == EXPR_FNAME) return c;
- return parse_string(c,c,c);
-
- case '\'':
- return parse_qstring(c,c);
-
- case '?':
- if (lex_state == EXPR_END) {
- lex_state = EXPR_BEG;
- return '?';
- }
- c = nextc();
- if (lex_state == EXPR_ARG && ISSPACE(c)){
- pushback(c);
- arg_ambiguous();
- lex_state = EXPR_BEG;
- return '?';
- }
- if (c == '\\') {
- c = read_escape();
- }
- c &= 0xff;
- yylval.val = INT2FIX(c);
- lex_state = EXPR_END;
- return tINTEGER;
-
- case '&':
- if ((c = nextc()) == '&') {
- lex_state = EXPR_BEG;
- if ((c = nextc()) == '=') {
- yylval.id = tANDOP;
- return tOP_ASGN;
- }
- pushback(c);
- return tANDOP;
- }
- else if (c == '=') {
- yylval.id = '&';
- lex_state = EXPR_BEG;
- return tOP_ASGN;
- }
- pushback(c);
- if (lex_state == EXPR_ARG && space_seen && !ISSPACE(c)){
- arg_ambiguous();
- lex_state = EXPR_BEG;
- return tAMPER;
- }
- if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
- lex_state = EXPR_BEG;
- return tAMPER;
- }
- lex_state = EXPR_BEG;
- return '&';
-
- case '|':
- lex_state = EXPR_BEG;
- if ((c = nextc()) == '|') {
- if ((c = nextc()) == '=') {
- yylval.id = tOROP;
- return tOP_ASGN;
- }
- pushback(c);
- return tOROP;
- }
- else if (c == '=') {
- yylval.id = '|';
- return tOP_ASGN;
- }
- pushback(c);
- return '|';
-
- case '+':
- c = nextc();
- if (lex_state == EXPR_FNAME) {
- if (c == '@') {
- return tUPLUS;
- }
- pushback(c);
- return '+';
- }
- if (c == '=') {
- lex_state = EXPR_BEG;
- yylval.id = '+';
- return tOP_ASGN;
- }
- if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
- if (ISDIGIT(c)) {
- goto start_num;
- }
- pushback(c);
- lex_state = EXPR_BEG;
- return tUPLUS;
- }
- lex_state = EXPR_BEG;
- pushback(c);
- return '+';
-
- case '-':
- c = nextc();
- if (lex_state == EXPR_FNAME) {
- if (c == '@') {
- return tUMINUS;
- }
- pushback(c);
- return '-';
- }
- if (c == '=') {
- lex_state = EXPR_BEG;
- yylval.id = '-';
- return tOP_ASGN;
- }
- if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
- if (ISDIGIT(c)) {
- pushback(c);
- c = '-';
- goto start_num;
- }
- lex_state = EXPR_BEG;
- pushback(c);
- return tUMINUS;
- }
- lex_state = EXPR_BEG;
- pushback(c);
- return '-';
-
- case '.':
- lex_state = EXPR_BEG;
- if ((c = nextc()) == '.') {
- if ((c = nextc()) == '.') {
- return tDOT3;
- }
- pushback(c);
- return tDOT2;
- }
- pushback(c);
- if (!ISDIGIT(c)) {
- lex_state = EXPR_DOT;
- return '.';
- }
- c = '.';
- /* fall through */
-
- start_num:
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- {
- int is_float, seen_point, seen_e;
-
- is_float = seen_point = seen_e = 0;
- lex_state = EXPR_END;
- newtok();
- if (c == '-' || c == '+') {
- tokadd(c);
- c = nextc();
- }
- if (c == '0') {
- c = nextc();
- if (c == 'x' || c == 'X') {
- /* hexadecimal */
- while (c = nextc()) {
- if (c == '_') continue;
- if (!ISXDIGIT(c)) break;
- tokadd(c);
- }
- pushback(c);
- tokfix();
- yylval.val = rb_str2inum(tok(), 16);
- return tINTEGER;
- }
- else if (c >= '0' && c <= '7') {
- /* octal */
- do {
- tokadd(c);
- while ((c = nextc()) == '_')
- ;
- } while (c >= '0' && c <= '9');
- pushback(c);
- tokfix();
- yylval.val = rb_str2inum(tok(), 8);
- return tINTEGER;
- }
- else if (c > '7' && c <= '9') {
- yyerror("Illegal octal digit");
- }
- else if (c == '.') {
- tokadd('0');
- }
- else {
- pushback(c);
- yylval.val = INT2FIX(0);
- return tINTEGER;
- }
- }
-
- for (;;) {
- switch (c) {
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- tokadd(c);
- break;
-
- case '.':
- if (seen_point || seen_e) {
- goto decode_num;
- }
- else {
- int c0 = nextc();
- if (!ISDIGIT(c0)) {
- pushback(c0);
- goto decode_num;
- }
- c = c0;
- }
- tokadd('.');
- tokadd(c);
- is_float++;
- seen_point++;
- break;
-
- case 'e':
- case 'E':
- if (seen_e) {
- goto decode_num;
- }
- tokadd(c);
- seen_e++;
- is_float++;
- if ((c = nextc()) == '-' || c == '+')
- tokadd(c);
- else
- continue;
- break;
-
- case '_': /* `_' in decimal just ignored */
- break;
-
- default:
- goto decode_num;
- }
- c = nextc();
- }
-
- decode_num:
- pushback(c);
- tokfix();
- if (is_float) {
- yylval.val = rb_float_new(atof(tok()));
- return tFLOAT;
- }
- yylval.val = rb_str2inum(tok(), 10);
- return tINTEGER;
- }
-
- case ']':
- case '}':
- case ')':
- lex_state = EXPR_END;
- return c;
-
- case ':':
- c = nextc();
- if (c == ':') {
- if (lex_state == EXPR_BEG) {
- lex_state = EXPR_BEG;
- return tCOLON3;
- }
- if (lex_state == EXPR_ARG && space_seen) {
- arg_ambiguous();
- lex_state = EXPR_BEG;
- return tCOLON3;
- }
- lex_state = EXPR_DOT;
- return tCOLON2;
- }
- pushback(c);
- if (lex_state == EXPR_END || ISSPACE(c)) {
- lex_state = EXPR_BEG;
- return ':';
- }
- lex_state = EXPR_FNAME;
- return tSYMBEG;
-
- case '/':
- if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
- return parse_regx('/', '/');
- }
- if ((c = nextc()) == '=') {
- lex_state = EXPR_BEG;
- yylval.id = '/';
- return tOP_ASGN;
- }
- if (lex_state == EXPR_ARG) {
- if (space_seen && !ISSPACE(c)) {
- pushback(c);
- arg_ambiguous();
- return parse_regx('/', '/');
- }
- }
- lex_state = EXPR_BEG;
- pushback(c);
- return '/';
-
- case '^':
- lex_state = EXPR_BEG;
- if (nextc() == '=') {
- yylval.id = '^';
- return tOP_ASGN;
- }
- pushback(c);
- return c;
-
- case ',':
- case ';':
- lex_state = EXPR_BEG;
- return c;
-
- case '~':
- if (lex_state == EXPR_FNAME) {
- if ((c = nextc()) != '@') {
- pushback(c);
- }
- }
- lex_state = EXPR_BEG;
- return '~';
-
- case '(':
- if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
- c = tLPAREN;
- lex_state = EXPR_BEG;
- }
- else {
- lex_state = EXPR_BEG;
- }
- return c;
-
- case '[':
- if (lex_state == EXPR_FNAME) {
- if ((c = nextc()) == ']') {
- if ((c = nextc()) == '=') {
- return tASET;
- }
- pushback(c);
- return tAREF;
- }
- pushback(c);
- return '[';
- }
- else if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
- c = tLBRACK;
- }
- else if (lex_state == EXPR_ARG && space_seen) {
- arg_ambiguous();
- c = tLBRACK;
- }
- lex_state = EXPR_BEG;
- return c;
-
- case '{':
- if (lex_state != EXPR_END && lex_state != EXPR_ARG)
- c = tLBRACE;
- lex_state = EXPR_BEG;
- return c;
-
- case '\\':
- c = nextc();
- if (c == '\n') {
- ruby_sourceline++;
- space_seen = 1;
- goto retry; /* skip \\n */
- }
- pushback(c);
- return '\\';
-
- case '%':
- if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
- int term;
- int paren;
-
- c = nextc();
- quotation:
- if (!ISALNUM(c)) {
- term = c;
- c = 'Q';
- }
- else {
- term = nextc();
- }
- if (c == -1 || term == -1) {
- rb_compile_error("unterminated quoted string meets end of file");
- return 0;
- }
- paren = term;
- if (term == '(') term = ')';
- else if (term == '[') term = ']';
- else if (term == '{') term = '}';
- else if (term == '<') term = '>';
-
- switch (c) {
- case 'Q':
- return parse_string('"', term, paren);
-
- case 'q':
- return parse_qstring(term, paren);
-
- case 'w':
- return parse_quotedword(term, paren);
-
- case 'x':
- return parse_string('`', term, paren);
-
- case 'r':
- return parse_regx(term, paren);
-
- default:
- yyerror("unknown type of %string");
- return 0;
- }
- }
- if ((c = nextc()) == '=') {
- yylval.id = '%';
- return tOP_ASGN;
- }
- if (lex_state == EXPR_ARG) {
- if (space_seen && !ISSPACE(c)) {
- arg_ambiguous();
- goto quotation;
- }
- }
- lex_state = EXPR_BEG;
- pushback(c);
- return '%';
-
- case '$':
- lex_state = EXPR_END;
- newtok();
- c = nextc();
- switch (c) {
- case '~': /* $~: match-data */
- /* fall through */
- case '_': /* $_: last read line string */
- local_cnt(c);
- /* fall through */
- case '*': /* $*: argv */
- case '$': /* $$: pid */
- case '?': /* $?: last status */
- case '!': /* $!: error string */
- case '@': /* $@: error position */
- case '/': /* $/: input record separator */
- case '\\': /* $\: output record separator */
- case ';': /* $;: field separator */
- case ',': /* $,: output field separator */
- case '.': /* $.: last read line number */
- case '=': /* $=: ignorecase */
- case ':': /* $:: load path */
- case '<': /* $<: reading filename */
- case '>': /* $>: default output handle */
- case '\"': /* $": already loaded files */
- tokadd('$');
- tokadd(c);
- tokfix();
- yylval.id = rb_intern(tok());
- return tGVAR;
-
- case '-':
- tokadd('$');
- tokadd(c);
- c = nextc();
- tokadd(c);
- tokfix();
- yylval.id = rb_intern(tok());
- return tGVAR;
-
- case '&': /* $&: last match */
- case '`': /* $`: string before last match */
- case '\'': /* $': string after last match */
- case '+': /* $+: string matches last paren. */
- yylval.node = NEW_BACK_REF(c);
- return tBACK_REF;
-
- case '1': case '2': case '3':
- case '4': case '5': case '6':
- case '7': case '8': case '9':
- while (ISDIGIT(c)) {
- tokadd(c);
- c = nextc();
- }
- pushback(c);
- tokfix();
- yylval.node = NEW_NTH_REF(atoi(tok()));
- return tNTH_REF;
-
- default:
- if (!is_identchar(c)) {
- pushback(c);
- return '$';
- }
- case '0':
- tokadd('$');
- }
- break;
-
- case '@':
- c = nextc();
- if (!is_identchar(c)) {
- pushback(c);
- return '@';
- }
- newtok();
- tokadd('@');
- break;
-
- default:
- if (c != '_' && !ISALPHA(c) && !ismbchar(c)) {
- rb_compile_error("Invalid char '%c' in expression", c);
- goto retry;
- }
-
- newtok();
- break;
- }
-
- while (is_identchar(c)) {
- tokadd(c);
- if (ismbchar(c)) {
- int i, len = mbclen(c)-1;
-
- tokadd(c);
- for (i = 0; i < len; i++) {
- c = nextc();
- tokadd(c);
- }
- }
- c = nextc();
- }
- if ((c == '!' || c == '?') && is_identchar(tok()[0])) {
- tokadd(c);
- }
- else {
- pushback(c);
- }
- tokfix();
-
- {
- int result;
-
- switch (tok()[0]) {
- case '$':
- lex_state = EXPR_END;
- result = tGVAR;
- break;
- case '@':
- lex_state = EXPR_END;
- result = tIVAR;
- break;
- default:
- if (lex_state != EXPR_DOT) {
- /* See if it is a reserved word. */
- kw = rb_reserved_word(tok(), toklen());
- if (kw) {
- enum lex_state state = lex_state;
- if (lex_state == EXPR_FNAME) {
- yylval.id = rb_intern(kw->name);
- }
- lex_state = kw->state;
- return kw->id[state != EXPR_BEG];
- }
- }
-
- if (ISUPPER(tok()[0])) {
- result = tCONSTANT;
- }
- else if (toklast() == '!' || toklast() == '?') {
- result = tFID;
- } else {
- result = tIDENTIFIER;
- if (lex_state == EXPR_FNAME) {
- lex_state = EXPR_END;
- if ((c = nextc()) == '=') {
- tokadd(c);
- }
- else {
- pushback(c);
- }
- }
- }
- if (lex_state == EXPR_BEG ||
- lex_state == EXPR_DOT ||
- lex_state == EXPR_ARG){
- lex_state = EXPR_ARG;
- }
- else {
- lex_state = EXPR_END;
- }
- }
- tokfix();
- yylval.id = rb_intern(tok());
- return result;
- }
-}
-
-static NODE*
-rb_str_extend(list, term)
- NODE *list;
- char term;
-{
- int c;
- int brace = -1;
- VALUE ss;
- NODE *node;
- int nest;
-
- c = nextc();
- switch (c) {
- case '$':
- case '@':
- case '{':
- break;
- default:
- tokadd('#');
- pushback(c);
- return list;
- }
-
- ss = rb_str_new(tok(), toklen());
- if (list == 0) {
- list = NEW_DSTR(ss);
- }
- else if (toklen() > 0) {
- list_append(list, NEW_STR(ss));
- }
- newtok();
-
- switch (c) {
- case '$':
- tokadd('$');
- c = nextc();
- if (c == -1) return (NODE*)-1;
- switch (c) {
- case '1': case '2': case '3':
- case '4': case '5': case '6':
- case '7': case '8': case '9':
- while (ISDIGIT(c)) {
- tokadd(c);
- c = nextc();
- }
- pushback(c);
- goto fetch_id;
-
- case '&': case '+':
- case '_': case '~':
- case '*': case '$': case '?':
- case '!': case '@': case ',':
- case '.': case '=': case ':':
- case '<': case '>': case '\\':
- refetch:
- tokadd(c);
- goto fetch_id;
-
- default:
- if (c == term) {
- list_append(list, NEW_STR(rb_str_new2("#$")));
- pushback(c);
- newtok();
- return list;
- }
- switch (c) {
- case '\"':
- case '/':
- case '\'':
- case '`':
- goto refetch;
- }
- if (!is_identchar(c)) {
- yyerror("bad global variable in string");
- newtok();
- return list;
- }
- }
- /* through */
-
- case '@':
- tokadd(c);
- c = nextc();
- while (is_identchar(c)) {
- tokadd(c);
- if (ismbchar(c)) {
- int i, len = mbclen(c)-1;
-
- tokadd(c);
- for (i = 0; i < len; i++) {
- c = nextc();
- tokadd(c);
- }
- }
- c = nextc();
- }
- pushback(c);
- break;
-
- case '{':
- if (c == '{') brace = '}';
- nest = 0;
- do {
- loop_again:
- c = nextc();
- switch (c) {
- case -1:
- if (nest > 0) {
- yyerror("bad substitution in string");
- newtok();
- return list;
- }
- return (NODE*)-1;
- case '}':
- if (c == brace) {
- if (nest == 0) break;
- nest--;
- }
- tokadd(c);
- goto loop_again;
- case '\\':
- c = read_escape();
- tokadd(c);
- goto loop_again;
- case '{':
- if (brace != -1) nest++;
- case '\"':
- case '/':
- case '`':
- if (c == term) {
- pushback(c);
- list_append(list, NEW_STR(rb_str_new2("#")));
- rb_warning("bad substitution in string");
- tokfix();
- list_append(list, NEW_STR(rb_str_new(tok(), toklen())));
- newtok();
- return list;
- }
- default:
- tokadd(c);
- break;
- }
- } while (c != brace);
- }
-
- fetch_id:
- tokfix();
- node = NEW_EVSTR(tok(),toklen());
- list_append(list, node);
- newtok();
-
- return list;
-}
-
-NODE*
-rb_node_newnode(type, a0, a1, a2)
- enum node_type type;
- NODE *a0, *a1, *a2;
-{
- NODE *n = (NODE*)rb_newobj();
-
- n->flags |= T_NODE;
- nd_set_type(n, type);
- nd_set_line(n, ruby_sourceline);
- n->nd_file = ruby_sourcefile;
-
- n->u1.node = a0;
- n->u2.node = a1;
- n->u3.node = a2;
-
- return n;
-}
-
-static enum node_type
-nodetype(node) /* for debug */
- NODE *node;
-{
- return (enum node_type)nd_type(node);
-}
-
-static int
-nodeline(node)
- NODE *node;
-{
- return nd_line(node);
-}
-
-static NODE*
-newline_node(node)
- NODE *node;
-{
- NODE *nl = 0;
- if (node) {
- nl = NEW_NEWLINE(node);
- fixpos(nl, node);
- nl->nd_nth = nd_line(node);
- }
- return nl;
-}
-
-static void
-fixpos(node, orig)
- NODE *node, *orig;
-{
- if (!node) return;
- if (!orig) return;
- node->nd_file = orig->nd_file;
- nd_set_line(node, nd_line(orig));
-}
-
-static NODE*
-block_append(head, tail)
- NODE *head, *tail;
-{
- NODE *end;
-
- if (tail == 0) return head;
- if (head == 0) return tail;
-
- if (nd_type(head) != NODE_BLOCK) {
- end = NEW_BLOCK(head);
- end->nd_end = end;
- fixpos(end, head);
- head = end;
- }
- else {
- end = head->nd_end;
- }
-
- if (RTEST(rb_verbose)) {
- NODE *nd = end->nd_head;
- newline:
- switch (nd_type(nd)) {
- case NODE_RETURN:
- case NODE_BREAK:
- case NODE_NEXT:
- case NODE_REDO:
- case NODE_RETRY:
- rb_warning("statement not reached");
- break;
-
- case NODE_NEWLINE:
- nd = nd->nd_next;
- goto newline;
-
- default:
- break;
- }
- }
-
- if (nd_type(tail) != NODE_BLOCK) {
- tail = NEW_BLOCK(tail);
- tail->nd_end = tail;
- }
- end->nd_next = tail;
- head->nd_end = tail->nd_end;
- return head;
-}
-
-static NODE*
-list_append(head, tail)
- NODE *head, *tail;
-{
- NODE *last;
-
- if (head == 0) return NEW_LIST(tail);
-
- last = head;
- while (last->nd_next) {
- last = last->nd_next;
- }
-
- last->nd_next = NEW_LIST(tail);
- head->nd_alen += 1;
- return head;
-}
-
-static NODE*
-list_concat(head, tail)
- NODE *head, *tail;
-{
- NODE *last;
-
- last = head;
- while (last->nd_next) {
- last = last->nd_next;
- }
-
- last->nd_next = tail;
- head->nd_alen += tail->nd_alen;
-
- return head;
-}
-
-static NODE *
-call_op(recv, id, narg, arg1)
- NODE *recv;
- ID id;
- int narg;
- NODE *arg1;
-{
- value_expr(recv);
- if (narg == 1) {
- value_expr(arg1);
- }
-
- return NEW_CALL(recv, id, narg==1?NEW_LIST(arg1):0);
-}
-
-static NODE*
-match_gen(node1, node2)
- NODE *node1;
- NODE *node2;
-{
- local_cnt('~');
-
- switch (nd_type(node1)) {
- case NODE_DREGX:
- case NODE_DREGX_ONCE:
- return NEW_MATCH2(node1, node2);
-
- case NODE_LIT:
- if (TYPE(node1->nd_lit) == T_REGEXP) {
- return NEW_MATCH2(node1, node2);
- }
- }
-
- switch (nd_type(node2)) {
- case NODE_DREGX:
- case NODE_DREGX_ONCE:
- return NEW_MATCH3(node2, node1);
-
- case NODE_LIT:
- if (TYPE(node2->nd_lit) == T_REGEXP) {
- return NEW_MATCH3(node2, node1);
- }
- }
-
- return NEW_CALL(node1, tMATCH, NEW_LIST(node2));
-}
-
-static NODE*
-gettable(id)
- ID id;
-{
- if (id == kSELF) {
- return NEW_SELF();
- }
- else if (id == kNIL) {
- return NEW_NIL();
- }
- else if (id == kTRUE) {
- return NEW_TRUE();
- }
- else if (id == kFALSE) {
- return NEW_FALSE();
- }
- else if (id == k__FILE__) {
- return NEW_STR(rb_str_new2(ruby_sourcefile));
- }
- else if (id == k__LINE__) {
- return NEW_LIT(INT2FIX(ruby_sourceline));
- }
- else if (is_local_id(id)) {
- if (dyna_in_block() && rb_dvar_defined(id)) return NEW_DVAR(id);
- if (local_id(id)) return NEW_LVAR(id);
- /* method call without arguments */
- return NEW_VCALL(id);
- }
- else if (is_global_id(id)) {
- return NEW_GVAR(id);
- }
- else if (is_instance_id(id)) {
- return NEW_IVAR(id);
- }
- else if (is_const_id(id)) {
- return NEW_CVAR(id);
- }
- rb_bug("invalid id for gettable");
- return 0;
-}
-
-static NODE*
-assignable(id, val)
- ID id;
- NODE *val;
-{
- NODE *lhs = 0;
-
- value_expr(val);
- if (id == kSELF) {
- yyerror("Can't change the value of self");
- }
- else if (id == kNIL) {
- yyerror("Can't assign to nil");
- }
- else if (id == kTRUE) {
- yyerror("Can't assign to true");
- }
- else if (id == kFALSE) {
- yyerror("Can't assign to false");
- }
- else if (id == k__FILE__) {
- yyerror("Can't assign to __FILE__");
- }
- else if (id == k__LINE__) {
- yyerror("Can't assign to __LINE__");
- }
- else if (is_local_id(id)) {
- if (rb_dvar_defined(id)) {
- lhs = NEW_DASGN(id, val);
- }
- else if (local_id(id) || !dyna_in_block()) {
- lhs = NEW_LASGN(id, val);
- }
- else{
- rb_dvar_push(id, 0);
- lhs = NEW_DASGN_PUSH(id, val);
- }
- }
- else if (is_global_id(id)) {
- lhs = NEW_GASGN(id, val);
- }
- else if (is_instance_id(id)) {
- lhs = NEW_IASGN(id, val);
- }
- else if (is_const_id(id)) {
- if (cur_mid || in_single)
- yyerror("dynamic constant assignment");
- lhs = NEW_CASGN(id, val);
- }
- else {
- rb_bug("bad id for variable");
- }
- return lhs;
-}
-
-static NODE *
-arg_add(node1, node2)
- NODE *node1;
- NODE *node2;
-{
- return NEW_ARGSCAT(node1, node2);
-}
-
-static NODE *
-aryset(recv, idx, val)
- NODE *recv, *idx, *val;
-{
- value_expr(recv);
- value_expr(val);
- if (idx) {
- if (nd_type(idx) == NODE_ARRAY) {
- idx = list_append(idx, val);
- }
- else {
- idx = arg_add(idx, val);
- }
- }
- return NEW_CALL(recv, tASET, idx);
-}
-
-ID
-rb_id_attrset(id)
- ID id;
-{
- id &= ~ID_SCOPE_MASK;
- id |= ID_ATTRSET;
- return id;
-}
-
-static NODE *
-attrset(recv, id, val)
- NODE *recv, *val;
- ID id;
-{
- value_expr(recv);
- value_expr(val);
-
- return NEW_CALL(recv, rb_id_attrset(id), NEW_LIST(val));
-}
-
-static void
-rb_backref_error(node)
- NODE *node;
-{
- switch (nd_type(node)) {
- case NODE_NTH_REF:
- rb_compile_error("Can't set variable $%d", node->nd_nth);
- break;
- case NODE_BACK_REF:
- rb_compile_error("Can't set variable $%c", node->nd_nth);
- break;
- }
-}
-
-static int
-value_expr(node)
- NODE *node;
-{
- if (node == 0) return Qtrue;
-
- switch (nd_type(node)) {
- case NODE_RETURN:
- case NODE_BREAK:
- case NODE_NEXT:
- case NODE_REDO:
- case NODE_RETRY:
- case NODE_WHILE:
- case NODE_UNTIL:
- case NODE_CLASS:
- case NODE_MODULE:
- case NODE_DEFN:
- case NODE_DEFS:
- yyerror("void value expression");
- return Qfalse;
- break;
-
- case NODE_BLOCK:
- while (node->nd_next) {
- node = node->nd_next;
- }
- return value_expr(node->nd_head);
-
- case NODE_IF:
- return value_expr(node->nd_body) && value_expr(node->nd_else);
-
- case NODE_NEWLINE:
- return value_expr(node->nd_next);
-
- default:
- return Qtrue;
- }
-}
-
-static NODE *cond2();
-
-static int
-assign_in_cond(node)
- NODE *node;
-{
- switch (nd_type(node)) {
- case NODE_MASGN:
- yyerror("multiple assignment in conditional");
- return 1;
-
- case NODE_LASGN:
- case NODE_DASGN:
- case NODE_GASGN:
- case NODE_IASGN:
- case NODE_CASGN:
- break;
-
- case NODE_NEWLINE:
- default:
- return 0;
- }
-
- switch (nd_type(node->nd_value)) {
- case NODE_LIT:
- case NODE_STR:
- case NODE_DSTR:
- case NODE_XSTR:
- case NODE_DXSTR:
- case NODE_EVSTR:
- case NODE_DREGX:
- case NODE_NIL:
- case NODE_TRUE:
- case NODE_FALSE:
- /* reports always */
- rb_warn("found = in conditional, should be ==");
- return 1;
-
- default:
- break;
- }
- if (assign_in_cond(node->nd_value) == 0) {
- rb_warning("assignment in condition");
- }
- return 1;
-}
-
-static NODE*
-cond0(node)
- NODE *node;
-{
- enum node_type type = nd_type(node);
-
- assign_in_cond(node);
- switch (type) {
- case NODE_DREGX:
- case NODE_DREGX_ONCE:
- local_cnt('_');
- local_cnt('~');
- return NEW_MATCH2(node, NEW_GVAR(rb_intern("$_")));
-
- case NODE_DOT2:
- case NODE_DOT3:
- node->nd_beg = cond2(node->nd_beg);
- node->nd_end = cond2(node->nd_end);
- if (type == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
- else if (type == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
- node->nd_cnt = local_append(0);
- return node;
-
- case NODE_LIT:
- if (TYPE(node->nd_lit) == T_REGEXP) {
- local_cnt('_');
- local_cnt('~');
- return NEW_MATCH(node);
- }
- if (TYPE(node->nd_lit) == T_STRING) {
- local_cnt('_');
- local_cnt('~');
- return NEW_MATCH(rb_reg_new(RSTRING(node)->ptr,RSTRING(node)->len,0));
- }
- default:
- return node;
- }
-}
-
-static NODE*
-cond(node)
- NODE *node;
-{
- if (node == 0) return 0;
- if (nd_type(node) == NODE_NEWLINE){
- node->nd_next = cond0(node->nd_next);
- return node;
- }
- return cond0(node);
-}
-
-static NODE*
-cond2(node)
- NODE *node;
-{
- enum node_type type;
-
- node = cond(node);
- type = nd_type(node);
- if (type == NODE_NEWLINE) node = node->nd_next;
- if (type == NODE_LIT && FIXNUM_P(node->nd_lit)) {
- return call_op(node,tEQ,1,NEW_GVAR(rb_intern("$.")));
- }
- return node;
-}
-
-static NODE*
-logop(type, left, right)
- enum node_type type;
- NODE *left, *right;
-{
- value_expr(left);
- return rb_node_newnode(type, cond(left), cond(right), 0);
-}
-
-static NODE *
-arg_blk_pass(node1, node2)
- NODE *node1;
- NODE *node2;
-{
- if (node2) {
- node2->nd_head = node1;
- return node2;
- }
- return node1;
-}
-
-static NODE*
-new_call(r,m,a)
- NODE *r;
- ID m;
- NODE *a;
-{
- if (a && nd_type(a) == NODE_BLOCK_PASS) {
- a->nd_iter = NEW_CALL(r,m,a->nd_head);
- return a;
- }
- return NEW_CALL(r,m,a);
-}
-
-static NODE*
-new_fcall(m,a)
- ID m;
- NODE *a;
-{
- if (a && nd_type(a) == NODE_BLOCK_PASS) {
- a->nd_iter = NEW_FCALL(m,a->nd_head);
- return a;
- }
- return NEW_FCALL(m,a);
-}
-
-static struct local_vars {
- ID *tbl;
- int nofree;
- int cnt;
- int dlev;
- struct local_vars *prev;
-} *lvtbl;
-
-static void
-local_push()
-{
- struct local_vars *local;
-
- local = ALLOC(struct local_vars);
- local->prev = lvtbl;
- local->nofree = 0;
- local->cnt = 0;
- local->tbl = 0;
- local->dlev = 0;
- lvtbl = local;
-}
-
-static void
-local_pop()
-{
- struct local_vars *local = lvtbl->prev;
-
- if (lvtbl->tbl) {
- if (!lvtbl->nofree) free(lvtbl->tbl);
- else lvtbl->tbl[0] = lvtbl->cnt;
- }
- free(lvtbl);
- lvtbl = local;
-}
-
-static ID*
-local_tbl()
-{
- lvtbl->nofree = 1;
- return lvtbl->tbl;
-}
-
-static int
-local_append(id)
- ID id;
-{
- if (lvtbl->tbl == 0) {
- lvtbl->tbl = ALLOC_N(ID, 4);
- lvtbl->tbl[0] = 0;
- lvtbl->tbl[1] = '_';
- lvtbl->tbl[2] = '~';
- lvtbl->cnt = 2;
- if (id == '_') return 0;
- if (id == '~') return 1;
- }
- else {
- REALLOC_N(lvtbl->tbl, ID, lvtbl->cnt+2);
- }
-
- lvtbl->tbl[lvtbl->cnt+1] = id;
- return lvtbl->cnt++;
-}
-
-static int
-local_cnt(id)
- ID id;
-{
- int cnt, max;
-
- if (id == 0) return lvtbl->cnt;
-
- for (cnt=1, max=lvtbl->cnt+1; cnt<max ;cnt++) {
- if (lvtbl->tbl[cnt] == id) return cnt-1;
- }
- return local_append(id);
-}
-
-static int
-local_id(id)
- ID id;
-{
- int i, max;
-
- if (lvtbl == 0) return Qfalse;
- for (i=3, max=lvtbl->cnt+1; i<max; i++) {
- if (lvtbl->tbl[i] == id) return Qtrue;
- }
- return Qfalse;
-}
-
-static void
-top_local_init()
-{
- local_push();
- lvtbl->cnt = ruby_scope->local_tbl?ruby_scope->local_tbl[0]:0;
- if (lvtbl->cnt > 0) {
- lvtbl->tbl = ALLOC_N(ID, lvtbl->cnt+3);
- MEMCPY(lvtbl->tbl, ruby_scope->local_tbl, ID, lvtbl->cnt+1);
- }
- else {
- lvtbl->tbl = 0;
- }
- if (ruby_dyna_vars)
- lvtbl->dlev = 1;
- else
- lvtbl->dlev = 0;
-}
-
-static void
-top_local_setup()
-{
- int len = lvtbl->cnt;
- int i;
-
- if (len > 0) {
- i = lvtbl->tbl[0];
-
- if (i < len) {
- if (i == 0 || ruby_scope->flag == SCOPE_ALLOCA) {
- VALUE *vars = ALLOC_N(VALUE, len+1);
- if (ruby_scope->local_vars) {
- *vars++ = ruby_scope->local_vars[-1];
- MEMCPY(vars, ruby_scope->local_vars, VALUE, i);
- rb_mem_clear(vars+i, len-i);
- }
- else {
- *vars++ = 0;
- rb_mem_clear(vars, len);
- }
- ruby_scope->local_vars = vars;
- ruby_scope->flag |= SCOPE_MALLOC;
- }
- else {
- VALUE *vars = ruby_scope->local_vars-1;
- REALLOC_N(vars, VALUE, len+1);
- ruby_scope->local_vars = vars+1;
- rb_mem_clear(ruby_scope->local_vars+i, len-i);
- }
- if (ruby_scope->local_tbl && ruby_scope->local_vars[-1] == 0) {
- free(ruby_scope->local_tbl);
- }
- ruby_scope->local_vars[-1] = 0;
- ruby_scope->local_tbl = local_tbl();
- }
- }
- local_pop();
-}
-
-static struct RVarmap*
-dyna_push()
-{
- lvtbl->dlev++;
- return ruby_dyna_vars;
-}
-
-static void
-dyna_pop(vars)
- struct RVarmap* vars;
-{
- lvtbl->dlev--;
- ruby_dyna_vars = vars;
-}
-
-static int
-dyna_in_block()
-{
- return (lvtbl->dlev > 0);
-}
-
-static void
-cref_pop()
-{
- cur_cref = cur_cref->nd_next;
-}
-
-void
-rb_parser_append_print()
-{
- ruby_eval_tree =
- block_append(ruby_eval_tree,
- NEW_FCALL(rb_intern("print"),
- NEW_ARRAY(NEW_GVAR(rb_intern("$_")))));
-}
-
-void
-rb_parser_while_loop(chop, split)
- int chop, split;
-{
- if (split) {
- ruby_eval_tree =
- block_append(NEW_GASGN(rb_intern("$F"),
- NEW_CALL(NEW_GVAR(rb_intern("$_")),
- rb_intern("split"), 0)),
- ruby_eval_tree);
- }
- if (chop) {
- ruby_eval_tree =
- block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
- rb_intern("chop!"), 0), ruby_eval_tree);
- }
- ruby_eval_tree = NEW_OPT_N(ruby_eval_tree);
-}
-
-static struct {
- ID token;
- char *name;
-} op_tbl[] = {
- tDOT2, "..",
- '+', "+",
- '-', "-",
- '+', "+(binary)",
- '-', "-(binary)",
- '*', "*",
- '/', "/",
- '%', "%",
- tPOW, "**",
- tUPLUS, "+@",
- tUMINUS, "-@",
- tUPLUS, "+(unary)",
- tUMINUS, "-(unary)",
- '|', "|",
- '^', "^",
- '&', "&",
- tCMP, "<=>",
- '>', ">",
- tGEQ, ">=",
- '<', "<",
- tLEQ, "<=",
- tEQ, "==",
- tEQQ, "===",
- tNEQ, "!=",
- tMATCH, "=~",
- tNMATCH, "!~",
- '!', "!",
- '~', "~",
- '!', "!(unary)",
- '~', "~(unary)",
- '!', "!@",
- '~', "~@",
- tAREF, "[]",
- tASET, "[]=",
- tLSHFT, "<<",
- tRSHFT, ">>",
- tCOLON2, "::",
- tCOLON3, "::",
- '`', "`",
- 0, 0,
-};
-
-char *rb_id2name();
-char *rb_class2name();
-
-static st_table *sym_tbl;
-static st_table *sym_rev_tbl;
-
-void
-Init_sym()
-{
- sym_tbl = st_init_strtable_with_size(200);
- sym_rev_tbl = st_init_numtable_with_size(200);
- rb_global_variable((VALUE*)&cur_cref);
- rb_global_variable((VALUE*)&lex_lastline);
-}
-
-ID
-rb_intern(name)
- char *name;
-{
- static ID last_id = LAST_TOKEN;
- int id;
- int last;
-
- if (st_lookup(sym_tbl, name, &id))
- return id;
-
- id = 0;
- switch (name[0]) {
- case '$':
- id |= ID_GLOBAL;
- break;
- case '@':
- id |= ID_INSTANCE;
- break;
- default:
- if (name[0] != '_' && !ISALPHA(name[0]) && !ismbchar(name[0])) {
- /* operator */
- int i;
-
- for (i=0; op_tbl[i].token; i++) {
- if (*op_tbl[i].name == *name &&
- strcmp(op_tbl[i].name, name) == 0) {
- id = op_tbl[i].token;
- goto id_regist;
- }
- }
- }
-
- last = strlen(name)-1;
- if (name[last] == '=') {
- /* attribute assignment */
- char *buf = ALLOCA_N(char,last+1);
-
- strncpy(buf, name, last);
- buf[last] = '\0';
- id = rb_intern(buf);
- if (id > LAST_TOKEN) {
- id = rb_id_attrset(id);
- goto id_regist;
- }
- id |= ID_ATTRSET;
- }
- else if (ISUPPER(name[0])) {
- id = ID_CONST;
- }
- else {
- id = ID_LOCAL;
- }
- break;
- }
- id |= ++last_id << ID_SCOPE_SHIFT;
- id_regist:
- name = strdup(name);
- st_add_direct(sym_tbl, name, id);
- st_add_direct(sym_rev_tbl, id, name);
- return id;
-}
-
-char *
-rb_id2name(id)
- ID id;
-{
- char *name;
-
- if (id < LAST_TOKEN) {
- int i = 0;
-
- for (i=0; op_tbl[i].token; i++) {
- if (op_tbl[i].token == id)
- return op_tbl[i].name;
- }
- }
-
- if (st_lookup(sym_rev_tbl, id, &name))
- return name;
-
- if (is_attrset_id(id)) {
- char *res;
- ID id2;
-
- id2 = (id & ~ID_SCOPE_MASK) | ID_LOCAL;
- res = rb_id2name(id2);
-
- if (res) {
- char *buf = ALLOCA_N(char, strlen(res)+2);
-
- strcpy(buf, res);
- strcat(buf, "=");
- rb_intern(buf);
- return rb_id2name(id);
- }
- }
- return 0;
-}
-
-int
-rb_is_const_id(id)
- ID id;
-{
- if (is_const_id(id)) return Qtrue;
- return Qfalse;
-}
-
-int
-rb_is_instance_id(id)
- ID id;
-{
- if (is_instance_id(id)) return Qtrue;
- return Qfalse;
-}
-
-static void
-special_local_set(c, val)
- char c;
- VALUE val;
-{
- int cnt;
-
- top_local_init();
- cnt = local_cnt(c);
- top_local_setup();
- ruby_scope->local_vars[cnt] = val;
-}
-
-VALUE
-rb_backref_get()
-{
- if (ruby_scope->local_vars) {
- return ruby_scope->local_vars[1];
- }
- return Qnil;
-}
-
-void
-rb_backref_set(val)
- VALUE val;
-{
- if (ruby_scope->local_vars) {
- ruby_scope->local_vars[1] = val;
- }
- else {
- special_local_set('~', val);
- }
-}
-
-VALUE
-rb_lastline_get()
-{
- if (ruby_scope->local_vars) {
- return ruby_scope->local_vars[0];
- }
- return Qnil;
-}
-
-void
-rb_lastline_set(val)
- VALUE val;
-{
- if (ruby_scope->local_vars) {
- ruby_scope->local_vars[0] = val;
- }
- else {
- special_local_set('_', val);
- }
-}
diff --git a/parse.y b/parse.y
index a4142bbe20..103d01bbf7 100644
--- a/parse.y
+++ b/parse.y
@@ -6,7 +6,7 @@
$Date$
created at: Fri May 28 18:02:42 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -18,11 +18,7 @@
#include "node.h"
#include "st.h"
#include <stdio.h>
-
-/* hack for bison */
-#ifdef const
-# undef const
-#endif
+#include <errno.h>
#define ID_SCOPE_SHIFT 3
#define ID_SCOPE_MASK 0x07
@@ -52,27 +48,33 @@ static enum lex_state {
EXPR_BEG, /* ignore newline, +/- is a sign. */
EXPR_MID, /* newline significant, +/- is a sign. */
EXPR_END, /* newline significant, +/- is a operator. */
+ EXPR_PAREN, /* almost like EXPR_END, `do' works as `{'. */
EXPR_ARG, /* newline significant, +/- is a operator. */
- EXPR_FNAME, /* ignore newline, +/- is a operator, no reserved words. */
- EXPR_DOT, /* immediate after `.', no reserved words. */
+ EXPR_FNAME, /* ignore newline, no reserved words. */
+ EXPR_DOT, /* right after `.' or `::', no reserved words. */
EXPR_CLASS, /* immediate after `class', no here document. */
} lex_state;
+static int cond_nest = 0;
static int class_nest = 0;
static int in_single = 0;
+static int compile_for_eval = 0;
static ID cur_mid = 0;
-static int value_expr();
static NODE *cond();
static NODE *logop();
static NODE *newline_node();
static void fixpos();
+static int value_expr();
+static void void_expr();
+static void void_stmts();
+
static NODE *block_append();
static NODE *list_append();
static NODE *list_concat();
-static NODE *arg_add();
+static NODE *arg_concat();
static NODE *call_op();
static int in_defined = 0;
@@ -85,6 +87,7 @@ static NODE *assignable();
static NODE *aryset();
static NODE *attrset();
static void rb_backref_error();
+static NODE *node_assign();
static NODE *match_gen();
static void local_push();
@@ -138,6 +141,7 @@ static void top_local_setup();
kRETRY
kIN
kDO
+ kDO2
kRETURN
kYIELD
kSUPER
@@ -168,15 +172,15 @@ static void top_local_setup();
%type <node> compstmt stmts stmt expr arg primary command_call method_call
%type <node> if_tail opt_else case_body cases rescue ensure
%type <node> opt_call_args call_args ret_args args when_args
-%type <node> aref_args opt_block_arg block_arg
-%type <node> mrhs opt_list superclass iterator var_ref
+%type <node> aref_args opt_block_arg block_arg stmt_rhs
+%type <node> mrhs opt_list superclass generic_call block_call var_ref
%type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
%type <node> array assoc_list assocs assoc undef_list backref
-%type <node> iter_var opt_iter_var iter_block iter_do_block
-%type <node> mlhs mlhs_head mlhs_tail mlhs_basic mlhs_entry mlhs_item lhs
-%type <id> variable symbol operation
+%type <node> block_var opt_block_var brace_block do_block lhs none
+%type <node> mlhs mlhs_head mlhs_tail mlhs_basic mlhs_entry mlhs_item mlhs_node
+%type <id> fitem variable sym symbol operation operation2 operation3
%type <id> cname fname op f_rest_arg
-%type <num> f_arg
+%type <num> f_norm_arg f_arg
%token tUPLUS /* unary+ */
%token tUMINUS /* unary- */
%token tPOW /* ** */
@@ -206,6 +210,8 @@ static void top_local_setup();
* precedence table
*/
+%nonassoc kDO
+%nonassoc kDO2
%left kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD
%left kOR kAND
%right kNOT
@@ -238,6 +244,17 @@ program : {
}
compstmt
{
+ if ($2 && !compile_for_eval) {
+ /* last expression should not be void */
+ if (nd_type($2) != NODE_BLOCK) void_expr($2);
+ else {
+ NODE *node = $2;
+ while (node->nd_next) {
+ node = node->nd_next;
+ }
+ void_expr(node->nd_head);
+ }
+ }
ruby_eval_tree = block_append(ruby_eval_tree, $2);
top_local_setup();
cur_cref = 0;
@@ -246,11 +263,12 @@ program : {
}
compstmt : stmts opt_terms
-
-stmts : /* none */
{
- $$ = 0;
+ void_stmts($1);
+ $$ = $1;
}
+
+stmts : none
| stmt
{
$$ = newline_node($1);
@@ -264,16 +282,8 @@ stmts : /* none */
$$ = $2;
}
-stmt : iterator iter_do_block
- {
- if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
- rb_compile_error("both block arg and actual block given");
- }
- $2->nd_iter = $1;
- $$ = $2;
- fixpos($$, $2);
- }
- | kALIAS fname {lex_state = EXPR_FNAME;} fname
+stmt : block_call
+ | kALIAS fitem {lex_state = EXPR_FNAME;} fitem
{
if (cur_mid || in_single)
yyerror("alias within method");
@@ -342,24 +352,28 @@ stmt : iterator iter_do_block
if (cur_mid || in_single) {
yyerror("BEGIN in method");
}
-
local_push();
}
'{' compstmt '}'
{
ruby_eval_tree_begin = block_append(ruby_eval_tree_begin,
- NEW_PREEXE($4));
+ NEW_PREEXE($4));
local_pop();
$$ = 0;
}
| klEND '{' compstmt '}'
{
- if (cur_mid || in_single) {
+ if (compile_for_eval && (cur_mid || in_single)) {
yyerror("END in method; use at_exit");
}
$$ = NEW_ITER(0, NEW_POSTEXE(), $3);
}
+ | lhs '=' stmt_rhs
+ {
+ value_expr($3);
+ $$ = node_assign($1, $3);
+ }
| expr
expr : mlhs '=' mrhs
@@ -371,7 +385,7 @@ expr : mlhs '=' mrhs
| kRETURN ret_args
{
value_expr($2);
- if (!cur_mid && !in_single)
+ if (!compile_for_eval && !cur_mid && !in_single)
yyerror("return appeared outside of method");
$$ = NEW_RETURN($2);
}
@@ -406,13 +420,13 @@ command_call : operation call_args
$$ = new_fcall($1, $2);
fixpos($$, $2);
}
- | primary '.' operation call_args
+ | primary '.' operation2 call_args
{
value_expr($1);
$$ = new_call($1, $3, $4);
fixpos($$, $1);
}
- | primary tCOLON2 operation call_args
+ | primary tCOLON2 operation2 call_args
{
value_expr($1);
$$ = new_call($1, $3, $4);
@@ -420,7 +434,7 @@ command_call : operation call_args
}
| kSUPER call_args
{
- if (!cur_mid && !in_single && !in_defined)
+ if (!compile_for_eval && !cur_mid && !in_single)
yyerror("super called outside of method");
$$ = NEW_SUPER($2);
fixpos($$, $2);
@@ -446,6 +460,10 @@ mlhs_basic : mlhs_head
{
$$ = NEW_MASGN(NEW_LIST($1), $3);
}
+ | mlhs_head tSTAR
+ {
+ $$ = NEW_MASGN(NEW_LIST($1), -1);
+ }
| mlhs_head mlhs_tail
{
$$ = NEW_MASGN(list_concat(NEW_LIST($1),$2), 0);
@@ -454,12 +472,20 @@ mlhs_basic : mlhs_head
{
$$ = NEW_MASGN(list_concat(NEW_LIST($1),$2),$5);
}
- | tSTAR lhs
+ | mlhs_head mlhs_tail ',' tSTAR
+ {
+ $$ = NEW_MASGN(list_concat(NEW_LIST($1),$2),-1);
+ }
+ | tSTAR mlhs_node
{
$$ = NEW_MASGN(0, $2);
}
+ | tSTAR
+ {
+ $$ = NEW_MASGN(0, -1);
+ }
-mlhs_item : lhs
+mlhs_item : mlhs_node
| tLPAREN mlhs_entry ')'
{
$$ = $2;
@@ -479,17 +505,35 @@ mlhs_tail : mlhs_item
$$ = list_append($1, $3);
}
+mlhs_node : variable
+ {
+ $$ = assignable($1, 0);
+ }
+ | primary '[' aref_args ']'
+ {
+ $$ = aryset($1, $3);
+ }
+ | primary '.' tIDENTIFIER
+ {
+ $$ = attrset($1, $3);
+ }
+ | backref
+ {
+ rb_backref_error($1);
+ $$ = 0;
+ }
+
lhs : variable
{
$$ = assignable($1, 0);
}
| primary '[' aref_args ']'
{
- $$ = aryset($1, $3, 0);
+ $$ = aryset($1, $3);
}
| primary '.' tIDENTIFIER
{
- $$ = attrset($1, $3, 0);
+ $$ = attrset($1, $3);
}
| backref
{
@@ -517,11 +561,14 @@ fname : tIDENTIFIER
$$ = $<id>1;
}
-undef_list : fname
+fitem : fname
+ | symbol
+
+undef_list : fitem
{
$$ = NEW_UNDEF($1);
}
- | undef_list ',' {lex_state = EXPR_FNAME;} fname
+ | undef_list ',' {lex_state = EXPR_FNAME;} fitem
{
$$ = block_append($1, NEW_UNDEF($4));
}
@@ -562,34 +609,10 @@ reswords : k__LINE__ | k__FILE__ | klBEGIN | klEND
| kTHEN | kTRUE | kUNDEF | kUNLESS_MOD | kUNTIL_MOD | kWHEN
| kWHILE_MOD | kYIELD
-arg : variable '=' {$$ = assignable($1, 0);} arg
- {
- $$ = $<node>3;
- if ($$) {
- $$->nd_value = $4;
- fixpos($$, $4);
- }
- }
- | primary '[' aref_args ']' '=' arg
- {
- $$ = aryset($1, $3, $6);
- fixpos($$, $1);
- }
- | primary '.' tIDENTIFIER '=' arg
- {
- $$ = attrset($1, $3, $5);
- fixpos($$, $5);
- }
- | primary '.' tCONSTANT '=' arg
- {
- $$ = attrset($1, $3, $5);
- fixpos($$, $5);
- }
- | backref '=' arg
+arg : lhs '=' arg
{
value_expr($3);
- rb_backref_error($1);
- $$ = 0;
+ $$ = node_assign($1, $3);
}
| variable tOP_ASGN {$$ = assignable($1, 0);} arg
{
@@ -683,11 +706,24 @@ arg : variable '=' {$$ = assignable($1, 0);} arg
}
| tUPLUS arg
{
- $$ = call_op($2, tUPLUS, 0);
+ if (nd_type($2) == NODE_LIT) {
+ $$ = $2;
+ }
+ else {
+ $$ = call_op($2, tUPLUS, 0);
+ }
}
| tUMINUS arg
{
- $$ = call_op($2, tUMINUS, 0);
+ if (nd_type($2) == NODE_LIT && FIXNUM_P($2->nd_lit)) {
+ long i = FIX2LONG($2->nd_lit);
+
+ $2->nd_lit = INT2FIX(-i);
+ $$ = $2;
+ }
+ else {
+ $$ = call_op($2, tUMINUS, 0);
+ }
}
| arg '|' arg
{
@@ -790,10 +826,7 @@ aref_args : opt_call_args
$$ = $1;
}
-opt_call_args : /* none */
- {
- $$ = 0;
- }
+opt_call_args : none
| call_args opt_nl
call_args : command_call
@@ -801,15 +834,23 @@ call_args : command_call
value_expr($1);
$$ = NEW_LIST($1);
}
+ | args ','
+ {
+ $$ = $1;
+ }
| args opt_block_arg
{
$$ = arg_blk_pass($1, $2);
}
| args ',' tSTAR arg opt_block_arg
{
- $$ = arg_add($1, $4);
+ $$ = arg_concat($1, $4);
$$ = arg_blk_pass($$, $5);
}
+ | assocs ','
+ {
+ $$ = NEW_LIST(NEW_HASH($1));
+ }
| assocs opt_block_arg
{
$$ = NEW_LIST(NEW_HASH($1));
@@ -817,7 +858,7 @@ call_args : command_call
}
| assocs ',' tSTAR arg opt_block_arg
{
- $$ = arg_add(NEW_LIST(NEW_HASH($1)), $4);
+ $$ = arg_concat(NEW_LIST(NEW_HASH($1)), $4);
$$ = arg_blk_pass($$, $5);
}
| args ',' assocs opt_block_arg
@@ -825,9 +866,13 @@ call_args : command_call
$$ = list_append($1, NEW_HASH($3));
$$ = arg_blk_pass($$, $4);
}
+ | args ',' assocs ','
+ {
+ $$ = list_append($1, NEW_HASH($3));
+ }
| args ',' assocs ',' tSTAR arg opt_block_arg
{
- $$ = arg_add(list_append($1, NEW_HASH($3)), $6);
+ $$ = arg_concat(list_append($1, NEW_HASH($3)), $6);
$$ = arg_blk_pass($$, $7);
}
| tSTAR arg opt_block_arg
@@ -847,16 +892,10 @@ opt_block_arg : ',' block_arg
{
$$ = $2;
}
- | /* none */
- {
- $$ = 0;
- }
+ | none
opt_list : args
- | /* none */
- {
- $$ = 0;
- }
+ | none
args : arg
{
@@ -884,7 +923,7 @@ mrhs : args
| args ',' tSTAR arg
{
value_expr($4);
- $$ = arg_add($1, $4);
+ $$ = arg_concat($1, $4);
}
| tSTAR arg
{
@@ -906,10 +945,7 @@ ret_args : call_args
}
}
-array : /* none */
- {
- $$ = 0;
- }
+array : none
| args trailer
primary : literal
@@ -921,11 +957,6 @@ primary : literal
value_expr($1);
$$ = NEW_COLON2($1, $3);
}
- | primary tCOLON2 tIDENTIFIER
- {
- value_expr($1);
- $$ = new_call($1, $3, 0);
- }
| tCOLON3 cname
{
$$ = NEW_COLON3($2);
@@ -962,20 +993,20 @@ primary : literal
}
| kRETURN '(' ret_args ')'
{
- if (!cur_mid && !in_single)
+ if (!compile_for_eval && !cur_mid && !in_single)
yyerror("return appeared outside of method");
value_expr($3);
$$ = NEW_RETURN($3);
}
| kRETURN '(' ')'
{
- if (!cur_mid && !in_single)
+ if (!compile_for_eval && !cur_mid && !in_single)
yyerror("return appeared outside of method");
$$ = NEW_RETURN(0);
}
| kRETURN
{
- if (!cur_mid && !in_single)
+ if (!compile_for_eval && !cur_mid && !in_single)
yyerror("return appeared outside of method");
$$ = NEW_RETURN(0);
}
@@ -1001,13 +1032,13 @@ primary : literal
{
$$ = NEW_VCALL($1);
}
- | operation iter_block
+ | operation brace_block
{
$2->nd_iter = NEW_FCALL($1, 0);
$$ = $2;
}
| method_call
- | method_call iter_block
+ | method_call brace_block
{
if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
rb_compile_error("both block arg and actual block given");
@@ -1034,21 +1065,21 @@ primary : literal
$$ = NEW_UNLESS(cond($2), $4, $5);
fixpos($$, $2);
}
- | kWHILE expr do
+ | kWHILE {cond_nest++;} expr do {cond_nest--;}
compstmt
kEND
{
- value_expr($2);
- $$ = NEW_WHILE(cond($2), $4, 1);
- fixpos($$, $2);
+ value_expr($3);
+ $$ = NEW_WHILE(cond($3), $6, 1);
+ fixpos($$, $3);
}
- | kUNTIL expr do
+ | kUNTIL {cond_nest++;} expr do {cond_nest--;}
compstmt
kEND
{
- value_expr($2);
- $$ = NEW_UNTIL(cond($2), $4, 1);
- fixpos($$, $2);
+ value_expr($3);
+ $$ = NEW_UNTIL(cond($3), $6, 1);
+ fixpos($$, $3);
}
| kCASE compstmt
case_body
@@ -1058,12 +1089,12 @@ primary : literal
$$ = NEW_CASE($2, $3);
fixpos($$, $2);
}
- | kFOR iter_var kIN expr do
+ | kFOR block_var kIN {cond_nest++;} expr do {cond_nest--;}
compstmt
kEND
{
value_expr($2);
- $$ = NEW_FOR($2, $4, $6);
+ $$ = NEW_FOR($2, $5, $8);
fixpos($$, $2);
}
| kBEGIN
@@ -1207,22 +1238,16 @@ if_tail : opt_else
fixpos($$, $2);
}
-opt_else : /* none */
- {
- $$ = 0;
- }
+opt_else : none
| kELSE compstmt
{
$$ = $2;
}
-iter_var : lhs
+block_var : lhs
| mlhs
-opt_iter_var : /* node */
- {
- $$ = 0;
- }
+opt_block_var : none
| '|' /* none */ '|'
{
$$ = 0;
@@ -1231,16 +1256,16 @@ opt_iter_var : /* node */
{
$$ = 0;
}
- | '|' iter_var '|'
+ | '|' block_var '|'
{
$$ = $2;
}
-iter_do_block : kDO
+do_block : kDO
{
$<vars>$ = dyna_push();
}
- opt_iter_var
+ opt_block_var
compstmt
kEND
{
@@ -1249,19 +1274,32 @@ iter_do_block : kDO
dyna_pop($<vars>2);
}
-iter_block : '{'
+brace_block : '{'
{
$<vars>$ = dyna_push();
}
- opt_iter_var
+ opt_block_var
compstmt '}'
{
$$ = NEW_ITER($3, 0, $4);
fixpos($$, $3?$3:$4);
dyna_pop($<vars>2);
}
+ | kDO2
+ {
+ $<vars>$ = dyna_push();
+ }
+ opt_block_var
+ compstmt
+ kEND
+ {
+ $$ = NEW_ITER($3, 0, $4);
+ fixpos($$, $3?$3:$4);
+ dyna_pop($<vars>2);
+ }
-iterator : tIDENTIFIER
+
+generic_call : tIDENTIFIER
{
$$ = NEW_VCALL($1);
}
@@ -1276,42 +1314,67 @@ iterator : tIDENTIFIER
| method_call
| command_call
-method_call : operation '(' opt_call_args ')'
+block_call : generic_call do_block
+ {
+ if ($1 && nd_type($1) == NODE_BLOCK_PASS) {
+ rb_compile_error("both block arg and actual block given");
+ }
+ $2->nd_iter = $1;
+ $$ = $2;
+ fixpos($$, $2);
+ }
+
+method_call : operation '(' opt_call_args close_paren
{
$$ = new_fcall($1, $3);
fixpos($$, $3);
}
- | primary '.' operation '(' opt_call_args ')'
+ | primary '.' operation2 '(' opt_call_args close_paren
{
value_expr($1);
$$ = new_call($1, $3, $5);
fixpos($$, $1);
}
- | primary '.' operation
+ | primary '.' operation2
{
value_expr($1);
$$ = new_call($1, $3, 0);
fixpos($$, $1);
}
- | primary tCOLON2 operation '(' opt_call_args ')'
+ | primary tCOLON2 operation2 '(' opt_call_args close_paren
{
value_expr($1);
$$ = new_call($1, $3, $5);
fixpos($$, $1);
}
- | kSUPER '(' opt_call_args ')'
+ | primary tCOLON2 operation3
+ {
+ value_expr($1);
+ $$ = new_call($1, $3, 0);
+ }
+ | kSUPER '(' opt_call_args close_paren
{
- if (!cur_mid && !in_single && !in_defined)
+ if (!compile_for_eval && !cur_mid &&
+ !in_single && !in_defined)
yyerror("super called outside of method");
$$ = NEW_SUPER($3);
}
| kSUPER
{
- if (!cur_mid && !in_single && !in_defined)
+ if (!compile_for_eval && !cur_mid &&
+ !in_single && !in_defined)
yyerror("super called outside of method");
$$ = NEW_ZSUPER();
}
+close_paren : ')'
+ {
+ if (cond_nest == 0)
+ lex_state = EXPR_PAREN;
+ }
+
+stmt_rhs : block_call
+ | command_call
case_body : kWHEN when_args then
compstmt
@@ -1342,31 +1405,32 @@ rescue : kRESCUE opt_list do
$$ = NEW_RESBODY($2, $4, $5);
fixpos($$, $2?$2:$4);
}
- | /* none */
- {
- $$ = 0;
- }
+ | none
-ensure : /* none */
- {
- $$ = 0;
- }
+ensure : none
| kENSURE compstmt
{
$$ = $2;
}
literal : numeric
- | tSYMBEG symbol
+ | symbol
{
- $$ = INT2FIX($2);
+ $$ = INT2FIX($1);
}
| tREGEXP
-symbol : fname
+symbol : tSYMBEG sym
+ {
+ lex_state = EXPR_END;
+ $$ = $2;
+ }
+
+sym : fname
| tIVAR
| tGVAR
+
numeric : tINTEGER
| tFLOAT
@@ -1450,18 +1514,19 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
$$ = NEW_ARGS(0, 0, -1);
}
-f_arg : tIDENTIFIER
+f_norm_arg : tIDENTIFIER
{
if (!is_local_id($1))
yyerror("formal argument must be local variable");
+ else if (local_id($1))
+ yyerror("duplicate argument name");
local_cnt($1);
$$ = 1;
}
- | f_arg ',' tIDENTIFIER
+
+f_arg : f_norm_arg
+ | f_arg ',' f_norm_arg
{
- if (!is_local_id($3))
- yyerror("formal argument must be local variable");
- local_cnt($3);
$$ += 1;
}
@@ -1469,6 +1534,8 @@ f_opt : tIDENTIFIER '=' arg
{
if (!is_local_id($1))
yyerror("formal argument must be local variable");
+ else if (local_id($1))
+ yyerror("duplicate optional argument name");
$$ = assignable($1, $3);
}
@@ -1486,8 +1553,14 @@ f_rest_arg : tSTAR tIDENTIFIER
{
if (!is_local_id($2))
yyerror("rest argument must be local variable");
+ else if (local_id($2))
+ yyerror("duplicate rest argument name");
$$ = local_cnt($2);
}
+ | tSTAR
+ {
+ $$ = -2;
+ }
f_block_arg : tAMPER tIDENTIFIER
{
@@ -1498,10 +1571,7 @@ opt_f_block_arg : ',' f_block_arg
{
$$ = $2;
}
- | /* none */
- {
- $$ = 0;
- }
+ | none
singleton : var_ref
{
@@ -1516,9 +1586,9 @@ singleton : var_ref
$$ = $1;
}
}
- | tLPAREN expr opt_nl ')'
+ | '(' {lex_state = EXPR_BEG;} expr opt_nl ')'
{
- switch (nd_type($2)) {
+ switch (nd_type($3)) {
case NODE_STR:
case NODE_DSTR:
case NODE_XSTR:
@@ -1527,17 +1597,14 @@ singleton : var_ref
case NODE_LIT:
case NODE_ARRAY:
case NODE_ZARRAY:
- yyerror("Can't define single method for literals.");
+ yyerror("can't define single method for literals.");
default:
break;
}
- $$ = $2;
+ $$ = $3;
}
-assoc_list : /* none */
- {
- $$ = 0;
- }
+assoc_list : none
| assocs trailer
{
$$ = $1;
@@ -1565,6 +1632,15 @@ operation : tIDENTIFIER
| tCONSTANT
| tFID
+operation2 : tIDENTIFIER
+ | tCONSTANT
+ | tFID
+ | op
+
+operation3 : tIDENTIFIER
+ | tFID
+ | op
+
dot_or_colon : '.'
| tCOLON2
@@ -1583,19 +1659,25 @@ term : ';' {yyerrok;}
terms : term
| terms ';' {yyerrok;}
+
+none : /* none */
+ {
+ $$ = 0;
+ }
%%
#include <ctype.h>
#include <sys/types.h>
#include "regex.h"
#include "util.h"
+#ifndef strdup
+char *strdup();
+#endif
-#define is_identchar(c) ((c)!=-1&&(ISALNUM(c) || (c) == '_' || ismbchar(c)))
+#define is_identchar(c) (((int)(c))!=-1&&(ISALNUM(c) || (c) == '_' || ismbchar(c)))
static char *tokenbuf = NULL;
static int tokidx, toksiz = 0;
-char *strdup();
-
static NODE *rb_str_extend();
#define LEAVE_BS 1
@@ -1650,7 +1732,6 @@ yyerror(msg)
return 0;
}
-static int newline_seen;
static int heredoc_end;
int ruby_in_compile = 0;
@@ -1664,11 +1745,16 @@ yycompile(f)
ruby__end__seen = 0;
ruby_eval_tree = 0;
- newline_seen = 0;
+ heredoc_end = 0;
ruby_sourcefile = f;
ruby_in_compile = 1;
n = yyparse();
+ compile_for_eval = 0;
ruby_in_compile = 0;
+ cond_nest = 0;
+ class_nest = 0;
+ in_single = 0;
+ cur_mid = 0;
if (n == 0) return ruby_eval_tree;
return 0;
@@ -1697,56 +1783,46 @@ lex_get_str(s)
}
NODE*
-rb_compile_string(f, s)
- char *f;
+rb_compile_string(f, s, line)
+ const char *f;
VALUE s;
+ int line;
{
lex_gets = lex_get_str;
lex_gets_ptr = 0;
lex_input = s;
lex_pbeg = lex_p = lex_pend = 0;
- if (!ruby_sourcefile || strcmp(f, ruby_sourcefile)) /* not in eval() */
- ruby_sourceline = 1;
+ ruby_sourceline = line - 1;
+ compile_for_eval = 1;
return yycompile(f);
}
NODE*
-rb_compile_cstr(f, s, len)
- char *f, *s;
- int len;
+rb_compile_cstr(f, s, len, line)
+ const char *f, *s;
+ int len, line;
{
- return rb_compile_string(f, rb_str_new(s, len));
+ return rb_compile_string(f, rb_str_new(s, len), line);
}
NODE*
rb_compile_file(f, file, start)
- char *f;
+ const char *f;
VALUE file;
int start;
{
lex_gets = rb_io_gets;
lex_input = file;
lex_pbeg = lex_p = lex_pend = 0;
- ruby_sourceline = start;
+ ruby_sourceline = start - 1;
return yycompile(strdup(f));
}
-
-static void
-normalize_newline(line)
- VALUE line;
-{
- if (RSTRING(line)->len >= 2 &&
- RSTRING(line)->ptr[RSTRING(line)->len-1] == '\n' &&
- RSTRING(line)->ptr[RSTRING(line)->len-2] == '\r')
- {
- RSTRING(line)->ptr[RSTRING(line)->len-2] = '\n';
- RSTRING(line)->len--;
- }
-}
-
+#if defined(__GNUC__) && __GNUC__ >= 2
+__inline__
+#endif
static int
nextc()
{
@@ -1758,20 +1834,10 @@ nextc()
if (NIL_P(v)) return -1;
if (heredoc_end > 0) {
- ruby_sourceline = heredoc_end+1;
+ ruby_sourceline = heredoc_end;
heredoc_end = 0;
}
- normalize_newline(v);
- while (RSTRING(v)->len >= 2 &&
- RSTRING(v)->ptr[RSTRING(v)->len-1] == '\n' &&
- RSTRING(v)->ptr[RSTRING(v)->len-2] == '\\') {
- VALUE v2 = (*lex_gets)(lex_input);
-
- if (!NIL_P(v2)) {
- normalize_newline(v2);
- rb_str_cat(v, RSTRING(v2)->ptr, RSTRING(v2)->len);
- }
- }
+ ruby_sourceline++;
lex_pbeg = lex_p = RSTRING(v)->ptr;
lex_pend = lex_p + RSTRING(v)->len;
if (strncmp(lex_pbeg, "__END__", 7) == 0 && lex_pbeg[7] == '\n') {
@@ -1799,6 +1865,8 @@ pushback(c)
lex_p--;
}
+#define peek(c) (lex_p != lex_pend && (c) == *lex_p)
+
#define tokfix() (tokenbuf[tokidx]='\0')
#define tok() tokenbuf
#define toklen() tokidx
@@ -1876,7 +1944,7 @@ read_escape()
}
buf[i] = c;
}
- c = scan_oct(buf, i+1, &i);
+ c = scan_oct(buf, i, &i);
}
return c;
@@ -1886,19 +1954,21 @@ read_escape()
int i;
for (i=0; i<2; i++) {
- buf[i] = nextc();
- if (buf[i] == -1) goto eof;
+ int cc = nextc();
+
+ if (cc == -1) goto eof;
+ buf[i] = cc;
if (!ISXDIGIT(buf[i])) {
pushback(buf[i]);
break;
}
}
- c = scan_hex(buf, i+1, &i);
+ c = scan_hex(buf, i, &i);
}
return c;
case 'b': /* backspace */
- return '\b';
+ return '\010';
case 's': /* space */
return ' ';
@@ -1944,7 +2014,7 @@ read_escape()
static int
parse_regx(term, paren)
- int term;
+ int term, paren;
{
register int c;
char kcode = 0;
@@ -1957,14 +2027,11 @@ parse_regx(term, paren)
newtok();
while ((c = nextc()) != -1) {
- if ((!in_brack && c == term) || nest > 0) {
+ if (!in_brack && c == term && nest == 0) {
goto regx_end;
}
switch (c) {
- case '\n':
- ruby_sourceline++;
- break;
case '[':
in_brack = 1;
break;
@@ -1985,7 +2052,6 @@ parse_regx(term, paren)
return 0;
case '\n':
- ruby_sourceline++;
break;
case '\\':
@@ -2011,18 +2077,12 @@ parse_regx(term, paren)
}
/* fall through */
default:
- if (c == paren) nest++;
- if (c == term) nest--;
- if (c == '\n') {
- ruby_sourceline++;
- }
- else if (c == term) {
+ if (c == term) {
tokadd(c);
}
else {
- pushback(c);
tokadd('\\');
- tokadd(read_escape());
+ tokadd(c);
}
}
continue;
@@ -2032,6 +2092,10 @@ parse_regx(term, paren)
return 0;
default:
+ if (paren && !in_brack) {
+ if (c == paren) nest++;
+ if (c == term) nest--;
+ }
if (ismbchar(c)) {
int i, len = mbclen(c)-1;
@@ -2051,20 +2115,23 @@ parse_regx(term, paren)
case 'x':
options |= RE_OPTION_EXTENDED;
break;
+ case 'p':
+ options |= RE_OPTION_POSIXLINE;
+ break;
case 'o':
once = 1;
break;
case 'n':
- kcode = 4;
+ kcode = 8;
break;
case 'e':
- kcode = 8;
+ kcode = 16;
break;
case 's':
- kcode = 12;
+ kcode = 24;
break;
case 'u':
- kcode = 16;
+ kcode = 32;
break;
default:
pushback(c);
@@ -2076,6 +2143,7 @@ parse_regx(term, paren)
tokfix();
lex_state = EXPR_END;
if (list) {
+ nd_set_line(list, re_start);
if (toklen() > 0) {
VALUE ss = rb_str_new(tok(), toklen());
list_append(list, NEW_STR(ss));
@@ -2111,9 +2179,9 @@ parse_string(func, term, paren)
return parse_qstring(term, paren);
}
if (func == 0) { /* read 1 line for heredoc */
- ruby_sourceline++;
/* -1 for chomp */
yylval.val = rb_str_new(lex_pbeg, lex_pend - lex_pbeg - 1);
+ lex_p = lex_pend;
return tSTRING;
}
strstart = ruby_sourceline;
@@ -2133,9 +2201,6 @@ parse_string(func, term, paren)
c = nextc();
}
}
- else if (c == '\n') {
- ruby_sourceline++;
- }
else if (c == '#') {
list = rb_str_extend(list, term);
if (list == (NODE*)-1) goto unterm_str;
@@ -2143,10 +2208,9 @@ parse_string(func, term, paren)
}
else if (c == '\\') {
c = nextc();
- if (c == '\n') {
- ruby_sourceline++;
- }
- else if (c == term) {
+ if (c == '\n')
+ continue;
+ if (c == term) {
tokadd(c);
}
else {
@@ -2156,17 +2220,18 @@ parse_string(func, term, paren)
}
continue;
}
- if (c == paren) nest++;
- if (c == term) {
- nest--;
- if (nest == 0) break;
+ if (paren) {
+ if (c == paren) nest++;
+ if (c == term && nest-- == 0) break;
}
tokadd(c);
}
tokfix();
lex_state = EXPR_END;
+
if (list) {
+ nd_set_line(list, strstart);
if (toklen() > 0) {
VALUE ss = rb_str_new(tok(), toklen());
list_append(list, NEW_STR(ss));
@@ -2210,14 +2275,10 @@ parse_qstring(term, paren)
c = nextc();
}
}
- else if (c == '\n') {
- ruby_sourceline++;
- }
else if (c == '\\') {
c = nextc();
switch (c) {
case '\n':
- ruby_sourceline++;
continue;
case '\\':
@@ -2234,10 +2295,9 @@ parse_qstring(term, paren)
tokadd('\\');
}
}
- if (c == paren) nest++;
- if (c == term) {
- nest--;
- if (nest == 0) break;
+ if (paren) {
+ if (c == paren) nest++;
+ if (c == term && nest-- == 0) break;
}
tokadd(c);
}
@@ -2257,8 +2317,6 @@ parse_quotedword(term, paren)
return tDSTRING;
}
-char *strdup();
-
static int
here_document(term, indent)
char term;
@@ -2268,7 +2326,7 @@ here_document(term, indent)
char *eos, *p;
int len;
VALUE str;
- volatile VALUE line;
+ volatile VALUE line = 0;
VALUE lastline_save;
int offset_save;
NODE *list = 0;
@@ -2289,7 +2347,7 @@ here_document(term, indent)
c = term;
term = '"';
if (!is_identchar(c)) {
- rb_warn("Use of bare << to mean <<\"\" is deprecated");
+ rb_warn("use of bare << to mean <<\"\" is deprecated");
break;
}
while (is_identchar(c)) {
@@ -2307,15 +2365,14 @@ here_document(term, indent)
str = rb_str_new(0,0);
for (;;) {
- line = (*lex_gets)(lex_input);
+ lex_lastline = line = (*lex_gets)(lex_input);
if (NIL_P(line)) {
error:
ruby_sourceline = linesave;
rb_compile_error("can't find string \"%s\" anywhere before EOF", eos);
- free(eos);
- return 0;
+ free(eos);
+ return 0;
}
- normalize_newline(line);
ruby_sourceline++;
p = RSTRING(line)->ptr;
if (indent) {
@@ -2336,6 +2393,7 @@ here_document(term, indent)
}
}
#endif
+ retry:
switch (parse_string(term, '\n', '\n')) {
case tSTRING:
case tXSTRING:
@@ -2348,10 +2406,13 @@ here_document(term, indent)
}
break;
case tDSTRING:
+ if (!list) list = NEW_DSTR(str);
+ /* fall through */
case tDXSTRING:
+ if (!list) list = NEW_DXSTR(str);
+
list_append(yylval.node, NEW_STR(rb_str_new2("\n")));
nd_set_type(yylval.node, NODE_STR);
- if (!list) list = NEW_DSTR(str);
yylval.node = NEW_LIST(yylval.node);
yylval.node->nd_next = yylval.node->nd_head->nd_next;
list_concat(list, yylval.node);
@@ -2360,6 +2421,9 @@ here_document(term, indent)
case 0:
goto error;
}
+ if (lex_p != lex_pend) {
+ goto retry;
+ }
}
free(eos);
lex_lastline = lastline_save;
@@ -2372,6 +2436,7 @@ here_document(term, indent)
ruby_sourceline = linesave;
if (list) {
+ nd_set_line(list, linesave+1);
yylval.node = list;
}
switch (term) {
@@ -2383,6 +2448,7 @@ here_document(term, indent)
return tSTRING;
case '`':
if (list) return tDXSTRING;
+ yylval.val = str;
return tXSTRING;
}
return 0;
@@ -2396,8 +2462,8 @@ arg_ambiguous()
rb_warning("ambiguous first argument; make sure");
}
-#ifndef atof
-double atof();
+#ifndef strtod
+double strtod ();
#endif
static int
@@ -2407,12 +2473,7 @@ yylex()
int space_seen = 0;
struct kwtable *kw;
- if (newline_seen) {
- ruby_sourceline += newline_seen;
- newline_seen = 0;
- }
-
-retry:
+ retry:
switch (c = nextc()) {
case '\0': /* NUL */
case '\004': /* ^D */
@@ -2430,21 +2491,6 @@ retry:
while ((c = nextc()) != '\n') {
if (c == -1)
return 0;
- if (c == '\\') { /* skip a char */
- c = nextc();
- if (c == '\n') ruby_sourceline++;
- }
- if (ismbchar(c)) {
- int i, len = mbclen(c)-1;
-
- for (i = 0; i < len; i++) {
- c = nextc();
- if (c == '\n') {
- ruby_sourceline++;
- break;
- }
- }
- }
}
/* fall through */
case '\n':
@@ -2452,12 +2498,10 @@ retry:
case EXPR_BEG:
case EXPR_FNAME:
case EXPR_DOT:
- ruby_sourceline++;
goto retry;
default:
break;
}
- newline_seen++;
lex_state = EXPR_BEG;
return '\n';
@@ -2478,7 +2522,6 @@ retry:
}
pushback(c);
if (lex_state == EXPR_ARG && space_seen && !ISSPACE(c)){
- arg_ambiguous();
lex_state = EXPR_BEG;
return tSTAR;
}
@@ -2505,7 +2548,6 @@ retry:
/* skip embedded rd document */
if (strncmp(lex_p, "begin", 5) == 0 && ISSPACE(lex_p[5])) {
for (;;) {
- ruby_sourceline++;
lex_p = lex_pend;
c = nextc();
if (c == -1) {
@@ -2517,7 +2559,6 @@ retry:
break;
}
}
- ruby_sourceline++;
lex_p = lex_pend;
goto retry;
}
@@ -2543,7 +2584,8 @@ retry:
case '<':
c = nextc();
if (c == '<' &&
- lex_state != EXPR_END && lex_state != EXPR_CLASS &&
+ lex_state != EXPR_END && lex_state != EXPR_PAREN &&
+ lex_state != EXPR_CLASS &&
(lex_state != EXPR_ARG || space_seen)) {
int c2 = nextc();
int indent = 0;
@@ -2595,20 +2637,20 @@ retry:
return parse_string(c,c,c);
case '`':
if (lex_state == EXPR_FNAME) return c;
+ if (lex_state == EXPR_DOT) return c;
return parse_string(c,c,c);
case '\'':
- return parse_qstring(c,c);
+ return parse_qstring(c,0);
case '?':
- if (lex_state == EXPR_END) {
+ if (lex_state == EXPR_END || lex_state == EXPR_PAREN) {
lex_state = EXPR_BEG;
return '?';
}
c = nextc();
if (lex_state == EXPR_ARG && ISSPACE(c)){
pushback(c);
- arg_ambiguous();
lex_state = EXPR_BEG;
return '?';
}
@@ -2637,7 +2679,6 @@ retry:
}
pushback(c);
if (lex_state == EXPR_ARG && space_seen && !ISSPACE(c)){
- arg_ambiguous();
lex_state = EXPR_BEG;
return tAMPER;
}
@@ -2667,7 +2708,7 @@ retry:
case '+':
c = nextc();
- if (lex_state == EXPR_FNAME) {
+ if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
if (c == '@') {
return tUPLUS;
}
@@ -2679,10 +2720,8 @@ retry:
yylval.id = '+';
return tOP_ASGN;
}
- if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
- if (ISDIGIT(c)) {
- goto start_num;
- }
+ if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
+ (lex_state == EXPR_ARG && space_seen && !ISSPACE(c))) {
pushback(c);
lex_state = EXPR_BEG;
return tUPLUS;
@@ -2693,7 +2732,7 @@ retry:
case '-':
c = nextc();
- if (lex_state == EXPR_FNAME) {
+ if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
if (c == '@') {
return tUMINUS;
}
@@ -2705,12 +2744,8 @@ retry:
yylval.id = '-';
return tOP_ASGN;
}
- if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
- if (ISDIGIT(c)) {
- pushback(c);
- c = '-';
- goto start_num;
- }
+ if (lex_state == EXPR_BEG || lex_state == EXPR_MID ||
+ (lex_state == EXPR_ARG && space_seen && !ISSPACE(c))) {
lex_state = EXPR_BEG;
pushback(c);
return tUMINUS;
@@ -2753,29 +2788,49 @@ retry:
c = nextc();
if (c == 'x' || c == 'X') {
/* hexadecimal */
- while (c = nextc()) {
+ c = nextc();
+ if (!ISXDIGIT(c)) {
+ yyerror("hexadecimal number without hex-digits");
+ }
+ do {
if (c == '_') continue;
if (!ISXDIGIT(c)) break;
tokadd(c);
- }
+ } while (c = nextc());
pushback(c);
tokfix();
yylval.val = rb_str2inum(tok(), 16);
return tINTEGER;
}
- else if (c >= '0' && c <= '7') {
- /* octal */
+ if (c == 'b' || c == 'B') {
+ /* binary */
+ c = nextc();
+ if (c != '0' && c != '1') {
+ yyerror("numeric constant with no digits");
+ }
do {
+ if (c == '_') continue;
+ if (c != '0'&& c != '1') break;
tokadd(c);
- while ((c = nextc()) == '_')
- ;
- } while (c >= '0' && c <= '9');
+ } while (c = nextc());
+ pushback(c);
+ tokfix();
+ yylval.val = rb_str2inum(tok(), 2);
+ return tINTEGER;
+ }
+ if (c >= '0' && c <= '7' || c == '_') {
+ /* octal */
+ do {
+ if (c == '_') continue;
+ if (c < '0' || c > '7') break;
+ tokadd(c);
+ } while (c = nextc());
pushback(c);
tokfix();
yylval.val = rb_str2inum(tok(), 8);
return tINTEGER;
}
- else if (c > '7' && c <= '9') {
+ if (c > '7' && c <= '9') {
yyerror("Illegal octal digit");
}
else if (c == '.') {
@@ -2840,7 +2895,12 @@ retry:
pushback(c);
tokfix();
if (is_float) {
- yylval.val = rb_float_new(atof(tok()));
+ double d = strtod(tok(), 0);
+ if (errno == ERANGE) {
+ rb_warn("Float %s out of range", tok());
+ errno = 0;
+ }
+ yylval.val = rb_float_new(d);
return tFLOAT;
}
yylval.val = rb_str2inum(tok(), 10);
@@ -2861,7 +2921,6 @@ retry:
return tCOLON3;
}
if (lex_state == EXPR_ARG && space_seen) {
- arg_ambiguous();
lex_state = EXPR_BEG;
return tCOLON3;
}
@@ -2869,7 +2928,7 @@ retry:
return tCOLON2;
}
pushback(c);
- if (lex_state == EXPR_END || ISSPACE(c)) {
+ if (lex_state == EXPR_END || lex_state == EXPR_PAREN || ISSPACE(c)) {
lex_state = EXPR_BEG;
return ':';
}
@@ -2911,7 +2970,7 @@ retry:
return c;
case '~':
- if (lex_state == EXPR_FNAME) {
+ if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
if ((c = nextc()) != '@') {
pushback(c);
}
@@ -2930,7 +2989,7 @@ retry:
return c;
case '[':
- if (lex_state == EXPR_FNAME) {
+ if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
if ((c = nextc()) == ']') {
if ((c = nextc()) == '=') {
return tASET;
@@ -2945,22 +3004,26 @@ retry:
c = tLBRACK;
}
else if (lex_state == EXPR_ARG && space_seen) {
- arg_ambiguous();
c = tLBRACK;
}
lex_state = EXPR_BEG;
return c;
case '{':
- if (lex_state != EXPR_END && lex_state != EXPR_ARG)
+ if (lex_state != EXPR_END &&
+ lex_state != EXPR_PAREN &&
+ lex_state != EXPR_ARG)
c = tLBRACE;
lex_state = EXPR_BEG;
return c;
case '\\':
c = nextc();
+ if (c == '\r') {
+ c = nextc();
+ if (c != '\n') pushback(c);
+ }
if (c == '\n') {
- ruby_sourceline++;
space_seen = 1;
goto retry; /* skip \\n */
}
@@ -2990,6 +3053,7 @@ retry:
else if (term == '[') term = ']';
else if (term == '{') term = '}';
else if (term == '<') term = '>';
+ else paren = 0;
switch (c) {
case 'Q':
@@ -3016,11 +3080,8 @@ retry:
yylval.id = '%';
return tOP_ASGN;
}
- if (lex_state == EXPR_ARG) {
- if (space_seen && !ISSPACE(c)) {
- arg_ambiguous();
- goto quotation;
- }
+ if (lex_state == EXPR_ARG && space_seen && !ISSPACE(c)) {
+ goto quotation;
}
lex_state = EXPR_BEG;
pushback(c);
@@ -3120,7 +3181,6 @@ retry:
if (ismbchar(c)) {
int i, len = mbclen(c)-1;
- tokadd(c);
for (i = 0; i < len; i++) {
c = nextc();
tokadd(c);
@@ -3128,7 +3188,7 @@ retry:
}
c = nextc();
}
- if ((c == '!' || c == '?') && is_identchar(tok()[0])) {
+ if ((c == '!' || c == '?') && is_identchar(tok()[0]) && !peek('=')) {
tokadd(c);
}
else {
@@ -3154,10 +3214,13 @@ retry:
kw = rb_reserved_word(tok(), toklen());
if (kw) {
enum lex_state state = lex_state;
- if (lex_state == EXPR_FNAME) {
+ lex_state = kw->state;
+ if (state == EXPR_FNAME) {
yylval.id = rb_intern(kw->name);
}
- lex_state = kw->state;
+ if (state == EXPR_PAREN && kw->id[0] == kDO) {
+ return kDO2;
+ }
return kw->id[state != EXPR_BEG];
}
}
@@ -3169,9 +3232,8 @@ retry:
result = tFID;
} else {
result = tIDENTIFIER;
- if (lex_state == EXPR_FNAME) {
- lex_state = EXPR_END;
- if ((c = nextc()) == '=') {
+ if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
+ if ((c = nextc()) == '=' && !peek('=')) {
tokadd(c);
}
else {
@@ -3272,7 +3334,21 @@ rb_str_extend(list, term)
return list;
}
}
- /* through */
+
+ while (is_identchar(c)) {
+ tokadd(c);
+ if (ismbchar(c)) {
+ int i, len = mbclen(c)-1;
+
+ for (i = 0; i < len; i++) {
+ c = nextc();
+ tokadd(c);
+ }
+ }
+ c = nextc();
+ }
+ pushback(c);
+ break;
case '@':
tokadd(c);
@@ -3282,7 +3358,6 @@ rb_str_extend(list, term)
if (ismbchar(c)) {
int i, len = mbclen(c)-1;
- tokadd(c);
for (i = 0; i < len; i++) {
c = nextc();
tokadd(c);
@@ -3423,7 +3498,7 @@ block_append(head, tail)
end = head->nd_end;
}
- if (RTEST(rb_verbose)) {
+ if (RTEST(ruby_verbose)) {
NODE *nd = end->nd_head;
newline:
switch (nd_type(nd)) {
@@ -3632,27 +3707,11 @@ assignable(id, val)
}
static NODE *
-arg_add(node1, node2)
- NODE *node1;
- NODE *node2;
-{
- return NEW_ARGSCAT(node1, node2);
-}
-
-static NODE *
-aryset(recv, idx, val)
- NODE *recv, *idx, *val;
+aryset(recv, idx)
+ NODE *recv, *idx;
{
value_expr(recv);
- value_expr(val);
- if (idx) {
- if (nd_type(idx) == NODE_ARRAY) {
- idx = list_append(idx, val);
- }
- else {
- idx = arg_add(idx, val);
- }
- }
+
return NEW_CALL(recv, tASET, idx);
}
@@ -3666,14 +3725,13 @@ rb_id_attrset(id)
}
static NODE *
-attrset(recv, id, val)
- NODE *recv, *val;
+attrset(recv, id)
+ NODE *recv;
ID id;
{
value_expr(recv);
- value_expr(val);
- return NEW_CALL(recv, rb_id_attrset(id), NEW_LIST(val));
+ return NEW_CALL(recv, rb_id_attrset(id), 0);
}
static void
@@ -3690,6 +3748,59 @@ rb_backref_error(node)
}
}
+static NODE *
+arg_concat(node1, node2)
+ NODE *node1;
+ NODE *node2;
+{
+ return NEW_ARGSCAT(node1, node2);
+}
+
+static NODE *
+arg_add(node1, node2)
+ NODE *node1;
+ NODE *node2;
+{
+ if (!node1) return NEW_LIST(node2);
+ if (nd_type(node1) == NODE_ARRAY) {
+ return list_append(node1, node2);
+ }
+ else {
+ return NEW_ARGSCAT(node1, node2);
+ }
+}
+
+static NODE*
+node_assign(lhs, rhs)
+ NODE *lhs, *rhs;
+{
+ if (!lhs) return 0;
+
+ value_expr(rhs);
+ switch (nd_type(lhs)) {
+ case NODE_GASGN:
+ case NODE_IASGN:
+ case NODE_LASGN:
+ case NODE_DASGN:
+ case NODE_DASGN_PUSH:
+ case NODE_CASGN:
+ case NODE_MASGN:
+ lhs->nd_value = rhs;
+ break;
+
+ case NODE_CALL:
+ lhs->nd_args = arg_add(lhs->nd_args, rhs);
+ break;
+
+ default:
+ /* should not happen */
+ break;
+ }
+
+ if (rhs) fixpos(lhs, rhs);
+ return lhs;
+}
+
static int
value_expr(node)
NODE *node;
@@ -3729,6 +3840,120 @@ value_expr(node)
}
}
+static void
+void_expr(node)
+ NODE *node;
+{
+ char *useless = 0;
+
+ if (!ruby_verbose) return;
+ if (!node) return;
+
+ again:
+ switch (nd_type(node)) {
+ case NODE_NEWLINE:
+ node = node->nd_next;
+ goto again;
+
+ case NODE_CALL:
+ switch (node->nd_mid) {
+ case '+':
+ case '-':
+ case '*':
+ case '/':
+ case '%':
+ case tPOW:
+ case tUPLUS:
+ case tUMINUS:
+ case '|':
+ case '^':
+ case '&':
+ case tCMP:
+ case '>':
+ case tGEQ:
+ case '<':
+ case tLEQ:
+ case tEQ:
+ case tNEQ:
+ case tAREF:
+ case tRSHFT:
+ case tCOLON2:
+ case tCOLON3:
+ useless = rb_id2name(node->nd_mid);
+ break;
+ }
+ break;
+
+ case NODE_LVAR:
+ case NODE_DVAR:
+ case NODE_GVAR:
+ case NODE_IVAR:
+ case NODE_NTH_REF:
+ case NODE_BACK_REF:
+ useless = "a variable";
+ break;
+ case NODE_CVAR:
+ case NODE_CREF:
+ useless = "a constant";
+ break;
+ case NODE_LIT:
+ case NODE_STR:
+ case NODE_DSTR:
+ case NODE_DREGX:
+ case NODE_DREGX_ONCE:
+ useless = "a literal";
+ break;
+ case NODE_COLON2:
+ case NODE_COLON3:
+ useless = "::";
+ break;
+ case NODE_DOT2:
+ useless = "..";
+ break;
+ case NODE_DOT3:
+ useless = "...";
+ break;
+ case NODE_SELF:
+ useless = "self";
+ break;
+ case NODE_NIL:
+ useless = "nil";
+ break;
+ case NODE_TRUE:
+ useless = "true";
+ break;
+ case NODE_FALSE:
+ useless = "false";
+ break;
+ case NODE_DEFINED:
+ useless = "defined?";
+ break;
+ }
+
+ if (useless) {
+ int line = ruby_sourceline;
+
+ ruby_sourceline = nd_line(node);
+ rb_warn("useless use of %s in void context", useless);
+ ruby_sourceline = line;
+ }
+}
+
+static void
+void_stmts(node)
+ NODE *node;
+{
+ if (!ruby_verbose) return;
+ if (!node) return;
+ if (nd_type(node) != NODE_BLOCK) return;
+
+ for (;;) {
+ if (!node->nd_next) return;
+ void_expr(node->nd_head);
+ node = node->nd_next;
+ }
+}
+
static NODE *cond2();
static int
@@ -3959,7 +4184,7 @@ local_cnt(id)
if (id == 0) return lvtbl->cnt;
- for (cnt=1, max=lvtbl->cnt+1; cnt<max ;cnt++) {
+ for (cnt=1, max=lvtbl->cnt+1; cnt<max;cnt++) {
if (lvtbl->tbl[cnt] == id) return cnt-1;
}
return local_append(id);
@@ -4003,7 +4228,7 @@ top_local_setup()
int i;
if (len > 0) {
- i = lvtbl->tbl[0];
+ i = ruby_scope->local_tbl?ruby_scope->local_tbl[0]:0;
if (i < len) {
if (i == 0 || ruby_scope->flag == SCOPE_ALLOCA) {
@@ -4096,6 +4321,7 @@ static struct {
char *name;
} op_tbl[] = {
tDOT2, "..",
+ tDOT3, "...",
'+', "+",
'-', "-",
'+', "+(binary)",
@@ -4137,9 +4363,6 @@ static struct {
0, 0,
};
-char *rb_id2name();
-char *rb_class2name();
-
static st_table *sym_tbl;
static st_table *sym_rev_tbl;
@@ -4154,7 +4377,7 @@ Init_sym()
ID
rb_intern(name)
- char *name;
+ const char *name;
{
static ID last_id = LAST_TOKEN;
int id;
diff --git a/prec.c b/prec.c
new file mode 100644
index 0000000000..693b81ba4c
--- /dev/null
+++ b/prec.c
@@ -0,0 +1,81 @@
+/************************************************
+
+ ruby.h -
+
+ $Author$
+ $Date$
+ created at: Tue Jan 26 02:40:41 1999
+
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
+
+*************************************************/
+
+#include "ruby.h"
+
+VALUE rb_mPrecision;
+
+static ID prc_pr, prc_if;
+
+static VALUE
+prec_prec(x, klass)
+ VALUE x, klass;
+{
+ return rb_funcall(klass, prc_if, 1, x);
+}
+
+static VALUE
+prec_prec_i(x)
+ VALUE x;
+{
+ VALUE klass = rb_cInteger;
+
+ return rb_funcall(x, prc_pr, 1, klass);
+}
+
+static VALUE
+prec_prec_f(x)
+ VALUE x;
+{
+ VALUE klass = rb_cFloat;
+
+ return rb_funcall(x, prc_pr, 1, klass);
+}
+
+static VALUE
+prec_induced_from(module, x)
+
+{
+ rb_raise(rb_eTypeError, "undefined conversion from %s into %s",
+ rb_class2name(CLASS_OF(x)), rb_class2name(module));
+}
+
+static VALUE
+prec_append_features(module, include)
+ VALUE module, include;
+{
+ switch (TYPE(include)) {
+ case T_CLASS:
+ case T_MODULE:
+ break;
+ default:
+ Check_Type(include, T_CLASS);
+ break;
+ }
+ rb_include_module(include, module);
+ rb_define_singleton_method(include, "induced_from", prec_induced_from, 1);
+ return module;
+}
+
+
+void
+Init_Precision()
+{
+ rb_mPrecision = rb_define_module("Precision");
+ rb_define_singleton_method(rb_mPrecision, "append_features", prec_append_features, 1);
+ rb_define_method(rb_mPrecision, "prec", prec_prec, 1);
+ rb_define_method(rb_mPrecision, "prec_i", prec_prec_i, 0);
+ rb_define_method(rb_mPrecision, "prec_f", prec_prec_f, 0);
+
+ prc_pr = rb_intern("prec");
+ prc_if = rb_intern("induced_from");
+}
diff --git a/process.c b/process.c
index d3e6559ca3..d5c2d5eb8a 100644
--- a/process.c
+++ b/process.c
@@ -6,7 +6,7 @@
$Date$
created at: Tue Aug 10 14:30:50 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -30,7 +30,7 @@ struct timeval {
#endif /* NT */
#include <ctype.h>
-struct timeval rb_time_timeval _((VALUE));
+struct timeval rb_time_interval _((VALUE));
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
@@ -48,6 +48,10 @@ struct timeval rb_time_timeval _((VALUE));
# include "macruby_missing.h"
#endif
+#ifdef __EMX__
+#undef HAVE_GETPGRP
+#endif
+
static VALUE
get_pid()
{
@@ -79,12 +83,10 @@ rb_waitpid(pid, flags, st)
{
int result;
#ifndef NO_WAITPID
-#if defined(USE_THREAD)
int oflags = flags;
if (!rb_thread_alone()) { /* there're other threads to run */
flags |= WNOHANG;
}
-#endif
retry:
#ifdef HAVE_WAITPID
@@ -94,21 +96,17 @@ rb_waitpid(pid, flags, st)
#endif
if (result < 0) {
if (errno == EINTR) {
-#ifdef USE_THREAD
rb_thread_schedule();
-#endif
goto retry;
}
return -1;
}
-#ifdef USE_THREAD
if (result == 0) {
if (oflags & WNOHANG) return 0;
rb_thread_schedule();
if (rb_thread_alone()) flags = oflags;
goto retry;
}
-#endif
#else /* NO_WAITPID */
if (pid_tbl && st_lookup(pid_tbl, pid, st)) {
rb_last_status = INT2FIX(*st);
@@ -117,16 +115,14 @@ rb_waitpid(pid, flags, st)
}
if (flags) {
- rb_raise(rb_eArgError, "Can't do waitpid with flags");
+ rb_raise(rb_eArgError, "can't do waitpid with flags");
}
for (;;) {
result = wait(st);
if (result < 0) {
if (errno == EINTR) {
-#ifdef USE_THREAD
rb_thread_schedule();
-#endif
continue;
}
return -1;
@@ -137,9 +133,7 @@ rb_waitpid(pid, flags, st)
if (!pid_tbl)
pid_tbl = st_init_numtable();
st_insert(pid_tbl, pid, st);
-#ifdef USE_THREAD
- if (!thread_alone()) rb_thread_schedule();
-#endif
+ if (!rb_thread_alone()) rb_thread_schedule();
}
#endif
rb_last_status = INT2FIX(*st);
@@ -181,9 +175,7 @@ rb_f_wait()
while ((pid = wait(&state)) < 0) {
if (errno == EINTR) {
-#ifdef USE_THREAD
rb_thread_schedule();
-#endif
continue;
}
rb_sys_fail(0);
@@ -212,7 +204,7 @@ rb_f_waitpid(obj, vpid, vflags)
char *strtok();
-#if defined(USE_THREAD) && defined(HAVE_SETITIMER)
+#ifdef HAVE_SETITIMER
#define before_exec() rb_thread_stop_timer()
#define after_exec() rb_thread_start_timer()
#else
@@ -252,11 +244,15 @@ proc_exec_v(argv, prog)
return -1;
}
}
-#if (defined(MSDOS) && !defined(DJGPP)) || defined(__human68k__)
+#if (defined(MSDOS) && !defined(DJGPP)) || defined(__human68k__) || defined(__EMX__) || defined(OS2)
{
#if defined(__human68k__)
#define COMMAND "command.x"
-#else
+#endif
+#if defined(__EMX__) || defined(OS2) /* OS/2 emx */
+#define COMMAND "cmd.exe"
+#endif
+#if (defined(MSDOS) && !defined(DJGPP))
#define COMMAND "command.com"
#endif
char *extension;
@@ -284,7 +280,7 @@ proc_exec_v(argv, prog)
}
}
}
-#endif /* MSDOS or __human68k__ */
+#endif /* MSDOS or __human68k__ or __EMX__ */
before_exec();
execv(prog, argv);
after_exec();
@@ -320,10 +316,11 @@ proc_exec_n(argc, argv, progv)
int
rb_proc_exec(str)
- char *str;
+ const char *str;
{
#ifndef USE_CWGUSI
- char *s = str, *t;
+ const char *s = str;
+ char *ss, *t;
char **argv, **a;
security(str);
@@ -337,7 +334,7 @@ rb_proc_exec(str)
if (state != -1)
exit(state);
#else
-#if defined(__human68k__) || defined(__CYGWIN32__)
+#if defined(__human68k__) || defined(__CYGWIN32__) || defined(__EMX__)
char *shell = dln_find_exe("sh", 0);
int state = -1;
before_exec();
@@ -358,9 +355,9 @@ rb_proc_exec(str)
}
}
a = argv = ALLOCA_N(char*, (s-str)/2+2);
- s = ALLOCA_N(char, s-str+1);
- strcpy(s, str);
- if (*a++ = strtok(s, " \t")) {
+ ss = ALLOCA_N(char, s-str+1);
+ strcpy(ss, str);
+ if (*a++ = strtok(ss, " \t")) {
while (t = strtok(NULL, " \t")) {
*a++ = t;
}
@@ -459,7 +456,7 @@ proc_spawn(sv)
if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) {
char *shell = dln_find_exe("sh", 0);
before_exec();
- state = shell ? spawnl(P_WAIT, shell, "sh", "-c", str, (char *) NULL) : system(str) ;
+ state = shell?spawnl(P_WAIT,shell,"sh","-c",str,(char*)NULL):system(str);
after_exec();
return state;
}
@@ -472,7 +469,7 @@ proc_spawn(sv)
*a++ = t;
*a = NULL;
}
- return argv[0] ? proc_spawn_v(argv, 0) : -1 ;
+ return argv[0] ? proc_spawn_v(argv, 0) : -1;
}
#endif /* __human68k__ */
@@ -487,13 +484,6 @@ rb_f_exec(argc, argv)
if (argc == 0) {
rb_raise(rb_eArgError, "wrong # of arguments");
}
- if (TYPE(argv[0]) == T_ARRAY) {
- if (RARRAY(argv[0])->len != 2) {
- rb_raise(rb_eArgError, "wrong first argument");
- }
- prog = RARRAY(argv[0])->ptr[0];
- argv[0] = RARRAY(argv[0])->ptr[1];
- }
if (TYPE(argv[0]) == T_ARRAY) {
if (RARRAY(argv[0])->len != 2) {
@@ -521,7 +511,7 @@ static VALUE
rb_f_fork(obj)
VALUE obj;
{
-#if !defined(__human68k__)
+#if !defined(__human68k__) && !defined(NT) && !defined(__MACOS__) && !defined(__EMX__)
int pid;
rb_secure(2);
@@ -549,23 +539,27 @@ rb_f_fork(obj)
}
static VALUE
-rb_f_exit_bang(obj, status)
- VALUE obj, status;
+rb_f_exit_bang(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
{
- int code = -1;
+ VALUE status;
+ int istatus;
rb_secure(4);
- if (FIXNUM_P(status)) {
- code = INT2FIX(status);
+ if (rb_scan_args(argc, argv, "01", &status) == 1) {
+ istatus = NUM2INT(status);
+ }
+ else {
+ istatus = -1;
}
-
#ifdef USE_CWGUSI
- exit(code);
+ exit(istatus);
#else
- _exit(code);
+ _exit(istatus);
#endif
-
- /* not reached */
+ return Qnil; /* not reached */
}
void
@@ -602,7 +596,7 @@ rb_f_system(argc, argv)
int argc;
VALUE *argv;
{
-#ifdef NT
+#if defined(NT) || defined(__EMX__)
VALUE cmd;
int state;
@@ -621,7 +615,7 @@ rb_f_system(argc, argv)
if (state == 0) return Qtrue;
return Qfalse;
#else
-#if defined(DJGPP)
+#ifdef DJGPP
VALUE cmd;
int state;
@@ -668,9 +662,12 @@ rb_f_system(argc, argv)
state = proc_spawn_n(argc, argv, prog);
}
rb_last_status = state == -1 ? INT2FIX(127) : INT2FIX(state);
- return state == 0 ? Qtrue : Qfalse ;
+ return state == 0 ? Qtrue : Qfalse;
+#else
+#if defined(USE_CWGUSI)
+ rb_notimplement();
#else
- volatile VALUE prog = 0;
+ volatile VALUE prog = 0;
int pid;
int i;
@@ -709,11 +706,7 @@ rb_f_system(argc, argv)
case -1:
if (errno == EAGAIN) {
-#ifdef USE_THREAD
rb_thread_sleep(1);
-#else
- sleep(1);
-#endif
goto retry;
}
rb_sys_fail(0);
@@ -725,9 +718,10 @@ rb_f_system(argc, argv)
if (rb_last_status == INT2FIX(0)) return Qtrue;
return Qfalse;
-#endif
-#endif
-#endif
+#endif /* USE_CWGUSI */
+#endif /* __human68k__ */
+#endif /* DJGPP */
+#endif /* NT */
}
static VALUE
@@ -738,30 +732,12 @@ rb_f_sleep(argc, argv)
int beg, end;
beg = time(0);
-#ifdef USE_THREAD
if (argc == 0) {
rb_thread_sleep_forever();
}
else if (argc == 1) {
- rb_thread_wait_for(rb_time_timeval(argv[0]));
- }
-#else
- if (argc == 0) {
- TRAP_BEG;
- sleep((32767<<16)+32767);
- TRAP_END;
+ rb_thread_wait_for(rb_time_interval(argv[0]));
}
- else if (argc == 1) {
- struct timeval tv;
- int n;
-
- tv = rb_time_timeval(argv[0]);
- TRAP_BEG;
- n = select(0, 0, 0, 0, &tv);
- TRAP_END;
- if (n<0) rb_sys_fail(0);
- }
-#endif
else {
rb_raise(rb_eArgError, "wrong # of arguments");
}
@@ -771,26 +747,29 @@ rb_f_sleep(argc, argv)
return INT2FIX(end);
}
-#if !defined(NT) && !defined(DJGPP) && !defined(__human68k__) && !defined(USE_CWGUSI)
static VALUE
proc_getpgrp(argc, argv)
int argc;
VALUE *argv;
{
+#ifdef HAVE_GETPGRP
int pgrp;
-#ifdef BSD_GETPGRP
+#ifndef GETPGRP_VOID
VALUE vpid;
int pid;
rb_scan_args(argc, argv, "01", &vpid);
pid = NIL_P(vpid)?0:NUM2INT(vpid);
- pgrp = BSD_GETPGRP(pid);
+ pgrp = getpgrp(pid);
#else
rb_scan_args(argc, argv, "0");
pgrp = getpgrp();
#endif
if (pgrp < 0) rb_sys_fail(0);
return INT2FIX(pgrp);
+#else
+ rb_notimplement();
+#endif
}
static VALUE
@@ -799,7 +778,7 @@ proc_setpgrp(argc, argv)
VALUE *argv;
{
#ifdef HAVE_SETPGRP
-#ifdef BSD_SETPGRP
+#ifndef SETPGRP_VOID
VALUE pid, pgrp;
int ipid, ipgrp;
@@ -807,7 +786,7 @@ proc_setpgrp(argc, argv)
ipid = NIL_P(pid)?0:NUM2INT(pid);
ipgrp = NIL_P(pgrp)?0:NUM2INT(pgrp);
- if (BSD_SETPGRP(ipid, ipgrp) < 0) rb_sys_fail(0);
+ if (setpgrp(ipid, ipgrp) < 0) rb_sys_fail(0);
#else
rb_scan_args(argc, argv, "0");
if (setpgrp() < 0) rb_sys_fail(0);
@@ -898,7 +877,6 @@ proc_setpriority(obj, which, who, prio)
rb_notimplement();
#endif
}
-#endif
static VALUE
proc_getuid(obj)
@@ -1032,13 +1010,9 @@ Init_process()
#ifndef USE_CWGUSI
rb_define_global_function("exec", rb_f_exec, -1);
#endif
-#if !defined(NT) && !defined(USE_CWGUSI)
rb_define_global_function("fork", rb_f_fork, 0);
-#endif
- rb_define_global_function("exit!", rb_f_exit_bang, 1);
-#ifndef USE_CWGUSI
+ rb_define_global_function("exit!", rb_f_exit_bang, -1);
rb_define_global_function("system", rb_f_system, -1);
-#endif
rb_define_global_function("sleep", rb_f_sleep, -1);
rb_mProcess = rb_define_module("Process");
@@ -1056,10 +1030,10 @@ Init_process()
#endif
#endif
-#if !defined(NT) && !defined(USE_CWGUSI)
+#if !defined(NT)
rb_define_singleton_method(rb_mProcess, "fork", rb_f_fork, 0);
#endif
- rb_define_singleton_method(rb_mProcess, "exit!", rb_f_exit_bang, 1);
+ rb_define_singleton_method(rb_mProcess, "exit!", rb_f_exit_bang, -1);
#ifndef USE_CWGUSI
rb_define_module_function(rb_mProcess, "kill", rb_f_kill, -1);
#endif
@@ -1073,7 +1047,6 @@ Init_process()
#endif /* ifndef USE_CWGUSI */
#endif /* ifndef NT */
-#if !defined(NT) && !defined(DJGPP) && !defined(__human68k__) && !defined(USE_CWGUSI)
rb_define_module_function(rb_mProcess, "getpgrp", proc_getpgrp, -1);
rb_define_module_function(rb_mProcess, "setpgrp", proc_setpgrp, -1);
rb_define_module_function(rb_mProcess, "getpgid", proc_getpgid, 1);
@@ -1098,5 +1071,4 @@ Init_process()
rb_define_module_function(rb_mProcess, "euid=", proc_seteuid, 1);
rb_define_module_function(rb_mProcess, "egid", proc_getegid, 0);
rb_define_module_function(rb_mProcess, "egid=", proc_setegid, 1);
-#endif
}
diff --git a/random.c b/random.c
index 7b57d472cd..8dfa6729f4 100644
--- a/random.c
+++ b/random.c
@@ -6,7 +6,7 @@
$Date$
created at: Fri Dec 24 16:39:21 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -69,7 +69,7 @@ void srand48 _((long));
#endif /* HAVE_RANDOM */
/* 0 <= RANDOM_NUMBER <= 1 */
-#define RANDOM_NUMBER (((double)RANDOM())/(double)RANDOM_MAX)
+#define RANDOM_NUMBER (((double)RANDOM())/((double)RANDOM_MAX+1))
#endif /* not HAVE_DRAND48 */
diff --git a/range.c b/range.c
index 9fc363e2a8..d37dfaa21f 100644
--- a/range.c
+++ b/range.c
@@ -6,15 +6,17 @@
$Date$
created at: Thu Aug 19 17:46:47 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
VALUE rb_cRange;
-static ID id_upto, id_cmp;
-static ID id_beg, id_end;
+static ID id_cmp, id_beg, id_end;
+
+#define EXCL(r) FL_TEST((r), FL_USER1)
+#define SET_EXCL(r) FL_SET((r), FL_USER1)
static VALUE
range_check(args)
@@ -31,92 +33,119 @@ range_failed()
}
static VALUE
-range_s_new(klass, beg, end)
+range_new(klass, beg, end, exclude_end)
VALUE klass, beg, end;
+ int exclude_end;
{
VALUE obj;
+ VALUE args[2];
+ args[0] = beg; args[1] = end;
if (!FIXNUM_P(beg) || !FIXNUM_P(end)) {
- VALUE args[2];
-
- args[0] = beg; args[1] = end;
rb_rescue(range_check, (VALUE)args, range_failed, 0);
}
obj = rb_obj_alloc(klass);
+ if (exclude_end) {
+ SET_EXCL(obj);
+ }
rb_ivar_set(obj, id_beg, beg);
rb_ivar_set(obj, id_end, end);
- rb_obj_call_init(obj);
return obj;
}
VALUE
-rb_range_new(beg, end)
+rb_range_new(beg, end, exclude_end)
VALUE beg, end;
+ int exclude_end;
+{
+ return range_new(rb_cRange, beg, end, exclude_end);
+}
+
+static VALUE
+range_s_new(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE beg, end, flag;
+
+ rb_scan_args(argc, argv, "21", &beg, &end, &flag);
+ return range_new(klass, beg, end, RTEST(flag));
+}
+
+static VALUE
+range_exclude_end_p(range)
+ VALUE range;
{
- return range_s_new(rb_cRange, beg, end);
+ return EXCL(range)?Qtrue:Qfalse;
}
static VALUE
-range_eqq(rng, obj)
- VALUE rng, obj;
+range_eqq(range, obj)
+ VALUE range, obj;
{
VALUE beg, end;
- beg = rb_ivar_get(rng, id_beg);
- end = rb_ivar_get(rng, id_end);
+ beg = rb_ivar_get(range, id_beg);
+ end = rb_ivar_get(range, id_end);
if (FIXNUM_P(beg) && FIXNUM_P(obj) && FIXNUM_P(end)) {
- if (FIX2INT(beg) <= FIX2INT(obj) && FIX2INT(obj) <= FIX2INT(end)) {
- return Qtrue;
+ if (NUM2LONG(beg) <= NUM2LONG(obj)) {
+ if (EXCL(range)) {
+ if (NUM2LONG(obj) < NUM2LONG(end)) return Qtrue;
+ }
+ else {
+ if (NUM2LONG(obj) <= NUM2LONG(end)) return Qtrue;
+ }
}
return Qfalse;
}
- else {
- if (RTEST(rb_funcall(beg, rb_intern("<="), 1, obj)) &&
- RTEST(rb_funcall(end, rb_intern(">="), 1, obj))) {
- return Qtrue;
+ else if (RTEST(rb_funcall(beg, rb_intern("<="), 1, obj))) {
+ if (EXCL(range)) {
+ if (RTEST(rb_funcall(end, rb_intern(">"), 1, obj)))
+ return Qtrue;
+ }
+ else {
+ if (RTEST(rb_funcall(end, rb_intern(">="), 1, obj)))
+ return Qtrue;
}
- return Qfalse;
}
+ return Qfalse;
}
-struct upto_data {
- VALUE beg;
- VALUE end;
-};
-
static VALUE
-range_upto(data)
- struct upto_data *data;
-{
- return rb_funcall(data->beg, id_upto, 1, data->end);
-}
-
-static VALUE
-range_each(obj)
- VALUE obj;
+range_each(range)
+ VALUE range;
{
VALUE b, e;
- b = rb_ivar_get(obj, id_beg);
- e = rb_ivar_get(obj, id_end);
-
- if (FIXNUM_P(b)) { /* fixnum is a special case(for performance) */
- rb_fix_upto(b, e);
- }
- else {
- struct upto_data data;
+ b = rb_ivar_get(range, id_beg);
+ e = rb_ivar_get(range, id_end);
- data.beg = b;
- data.end = e;
+ if (FIXNUM_P(b) && FIXNUM_P(e)) { /* fixnums are special */
+ long end = FIX2LONG(e);
+ long i;
- rb_iterate(range_upto, (VALUE)&data, rb_yield, 0);
+ if (!EXCL(range)) end += 1;
+ for (i=FIX2LONG(b); i<end; i++) {
+ rb_yield(INT2NUM(i));
+ }
+ }
+ else { /* generic each */
+ VALUE v = b;
+ ID le = EXCL(range)?'<':rb_intern("<=");
+ ID succ = rb_intern("succ");
+
+ while (rb_funcall(v, le, 1, e)) {
+ rb_yield(v);
+ v = rb_funcall(v, succ, 0, 0);
+ }
}
- return Qnil;
+ return range;
}
static VALUE
@@ -140,17 +169,54 @@ range_last(obj)
}
VALUE
-rb_range_beg_end(range, begp, endp)
+rb_range_beg_len(range, begp, lenp, len, err)
VALUE range;
- int *begp, *endp;
+ long *begp, *lenp;
+ long len;
+ int err;
{
- VALUE beg, end;
+ long beg, end, b, e;
if (!rb_obj_is_kind_of(range, rb_cRange)) return Qfalse;
- beg = rb_ivar_get(range, id_beg); *begp = NUM2INT(beg);
- end = rb_ivar_get(range, id_end); *endp = NUM2INT(end);
+ beg = b = NUM2LONG(rb_ivar_get(range, id_beg));
+ end = e = NUM2LONG(rb_ivar_get(range, id_end));
+
+ if (beg < 0) {
+ beg += len;
+ if (beg < 0) goto out_of_range;
+ }
+ if (err == 0 || err == 2) {
+ if (beg > len) goto out_of_range;
+ if (end > len || (!EXCL(range) && end == len))
+ end = len;
+ }
+ if (end < 0) {
+ end += len;
+ if (end < 0) {
+ if (beg == 0 && end == -1 && !EXCL(range)) {
+ len = 0;
+ goto length_set;
+ }
+ goto out_of_range;
+ }
+ }
+ len = end - beg;
+ if (!EXCL(range)) len++; /* include end point */
+ if (len < 0) goto out_of_range;
+
+ length_set:
+ *begp = beg;
+ *lenp = len;
+
return Qtrue;
+
+ out_of_range:
+ if (err) {
+ rb_raise(rb_eIndexError, "%d..%s%d out of range",
+ b, EXCL(range)?".":"", e);
+ }
+ return Qnil;
}
static VALUE
@@ -161,7 +227,7 @@ range_to_s(range)
str = rb_obj_as_string(rb_ivar_get(range, id_beg));
str2 = rb_obj_as_string(rb_ivar_get(range, id_end));
- rb_str_cat(str, "..", 2);
+ rb_str_cat(str, "...", EXCL(range)?3:2);
rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
return str;
@@ -175,30 +241,40 @@ range_inspect(range)
str = rb_inspect(rb_ivar_get(range, id_beg));
str2 = rb_inspect(rb_ivar_get(range, id_end));
- rb_str_cat(str, "..", 2);
+ rb_str_cat(str, "...", EXCL(range)?3:2);
rb_str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len);
return str;
}
static VALUE
-range_length(rng)
- VALUE rng;
+range_length(range)
+ VALUE range;
{
VALUE beg, end;
VALUE size;
- beg = rb_ivar_get(rng, id_beg);
- end = rb_ivar_get(rng, id_end);
+ beg = rb_ivar_get(range, id_beg);
+ end = rb_ivar_get(range, id_end);
if (RTEST(rb_funcall(beg, '>', 1, end))) {
return INT2FIX(0);
}
+ if (FIXNUM_P(beg) && FIXNUM_P(end)) {
+ if (EXCL(range)) {
+ return INT2NUM(NUM2LONG(end) - NUM2LONG(beg));
+ }
+ else {
+ return INT2NUM(NUM2LONG(end) - NUM2LONG(beg) + 1);
+ }
+ }
if (!rb_obj_is_kind_of(beg, rb_cNumeric)) {
- return rb_enum_length(rng);
+ return rb_enum_length(range);
}
size = rb_funcall(end, '-', 1, beg);
- size = rb_funcall(size, '+', 1, INT2FIX(1));
+ if (!EXCL(range)) {
+ size = rb_funcall(size, '+', 1, INT2FIX(1));
+ }
return size;
}
@@ -208,7 +284,7 @@ Init_Range()
{
rb_cRange = rb_define_class("Range", rb_cObject);
rb_include_module(rb_cRange, rb_mEnumerable);
- rb_define_singleton_method(rb_cRange, "new", range_s_new, 2);
+ rb_define_singleton_method(rb_cRange, "new", range_s_new, -1);
rb_define_method(rb_cRange, "===", range_eqq, 1);
rb_define_method(rb_cRange, "each", range_each, 0);
rb_define_method(rb_cRange, "first", range_first, 0);
@@ -218,10 +294,11 @@ Init_Range()
rb_define_method(rb_cRange, "to_s", range_to_s, 0);
rb_define_method(rb_cRange, "inspect", range_inspect, 0);
+ rb_define_method(rb_cRange, "exclude_end?", range_exclude_end_p, 0);
+
rb_define_method(rb_cRange, "length", range_length, 0);
rb_define_method(rb_cRange, "size", range_length, 0);
- id_upto = rb_intern("upto");
id_cmp = rb_intern("<=>");
id_beg = rb_intern("begin");
id_end = rb_intern("end");
diff --git a/re.c b/re.c
index 287c6c1bd4..4ecc46eee5 100644
--- a/re.c
+++ b/re.c
@@ -5,7 +5,7 @@
$Author$
created at: Mon Aug 9 18:24:49 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -18,7 +18,7 @@ static VALUE rb_eRegxpError;
#define END(no) regs->end[no]
#if 'a' == 97 /* it's ascii */
-static char casetable[] = {
+static const char casetable[] = {
'\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
'\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
'\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
@@ -87,30 +87,19 @@ rb_str_cicmp(str1, str2)
return RSTRING(str1)->len - RSTRING(str2)->len;
}
-#define REG_IGNORECASE FL_USER0
-#define REG_CASESTATE FL_USER1
+#define REG_CASESTATE FL_USER0
+#define REG_IGNORECASE FL_USER1
+#define REG_EXTENDED FL_USER2
+#define REG_POSIXLINE FL_USER3
#define KCODE_NONE 0
-#define KCODE_EUC FL_USER2
-#define KCODE_SJIS FL_USER3
-#define KCODE_UTF8 FL_USER4
-#define KCODE_FIXED FL_USER5
+#define KCODE_EUC FL_USER4
+#define KCODE_SJIS FL_USER5
+#define KCODE_UTF8 FL_USER6
+#define KCODE_FIXED FL_USER7
#define KCODE_MASK (KCODE_EUC|KCODE_SJIS|KCODE_UTF8)
-static int reg_kcode =
-#ifdef RUBY_USE_EUC
- KCODE_EUC;
-#else
-# ifdef RUBY_USE_SJIS
- KCODE_SJIS;
-# else
-# ifdef RUBY_USE_UTF8
- KCODE_UTF8
-# else
- KCODE_NONE;
-# endif
-# endif
-#endif
+static int reg_kcode = DEFAULT_KCODE;
static void
kcode_euc(reg)
@@ -198,10 +187,10 @@ extern int ruby_in_compile;
static void
rb_reg_expr_str(str, s, len)
VALUE str;
- char *s;
+ const char *s;
int len;
{
- char *p, *pend;
+ const char *p, *pend;
int slash = 0;
p = s; pend = p + len;
@@ -233,7 +222,7 @@ rb_reg_expr_str(str, s, len)
static VALUE
rb_reg_desc(s, len, re)
- char *s;
+ const char *s;
int len;
VALUE re;
{
@@ -243,6 +232,10 @@ rb_reg_desc(s, len, re)
if (re) {
if (FL_TEST(re, REG_IGNORECASE))
rb_str_cat(str, "i", 1);
+ if (FL_TEST(re, REG_EXTENDED))
+ rb_str_cat(str, "x", 1);
+ if (FL_TEST(re, REG_POSIXLINE))
+ rb_str_cat(str, "p", 1);
if (FL_TEST(re, KCODE_FIXED)) {
switch ((RBASIC(re)->flags & KCODE_MASK)) {
case KCODE_NONE:
@@ -282,9 +275,9 @@ rb_reg_inspect(re)
static void
rb_reg_raise(s, len, err, re)
- char *s;
+ const char *s;
int len;
- char *err;
+ const char *err;
VALUE re;
{
VALUE desc = rb_reg_desc(s, len, re);
@@ -329,8 +322,8 @@ rb_reg_kcode_method(re)
static Regexp*
make_regexp(s, len, flag)
- char *s;
- size_t len, flag;
+ const char *s;
+ int len, flag;
{
Regexp *rp;
char *err;
@@ -392,6 +385,74 @@ match_clone(orig)
return (VALUE)match;
}
+static VALUE
+match_size(match)
+ VALUE match;
+{
+ return INT2FIX(RMATCH(match)->regs->num_regs);
+}
+
+static VALUE
+match_offset(match, n)
+ VALUE match, n;
+{
+ int i = NUM2INT(n);
+
+ if (i < 0 || RMATCH(match)->regs->num_regs <= i)
+ rb_raise(rb_eIndexError, "index %d out of matches", i);
+
+ if (RMATCH(match)->regs->beg[i] < 0)
+ return rb_assoc_new(Qnil, Qnil);
+
+ return rb_assoc_new(INT2FIX(RMATCH(match)->regs->beg[i]),
+ INT2FIX(RMATCH(match)->regs->end[i]));
+}
+
+static VALUE
+match_begin(match, n)
+ VALUE match, n;
+{
+ int i = NUM2INT(n);
+
+ if (i < 0 || RMATCH(match)->regs->num_regs <= i)
+ rb_raise(rb_eIndexError, "index %d out of matches", i);
+
+ if (RMATCH(match)->regs->beg[i] < 0)
+ return Qnil;
+
+ return INT2FIX(RMATCH(match)->regs->beg[i]);
+}
+
+static VALUE
+match_end(match, n)
+ VALUE match, n;
+{
+ int i = NUM2INT(n);
+
+ if (i < 0 || RMATCH(match)->regs->num_regs <= i)
+ rb_raise(rb_eIndexError, "index %d out of matches", i);
+
+ if (RMATCH(match)->regs->beg[i] < 0)
+ return Qnil;
+
+ return INT2FIX(RMATCH(match)->regs->end[i]);
+}
+
+#define MATCH_BUSY FL_USER2
+
+void
+rb_match_busy(match, busy)
+ VALUE match;
+ int busy;
+{
+ if (busy) {
+ FL_SET(match, MATCH_BUSY);
+ }
+ else {
+ FL_UNSET(match, MATCH_BUSY);
+ }
+}
+
int ruby_ignorecase;
static int may_need_recompile;
static VALUE matchcache;
@@ -433,16 +494,16 @@ rb_reg_prepare_re(reg)
}
int
-rb_reg_search(reg, str, start, reverse)
+rb_reg_search(reg, str, pos, reverse)
VALUE reg, str;
- int start, reverse;
+ int pos, reverse;
{
int result;
VALUE match;
struct re_registers *regs = 0;
int range;
- if (start > RSTRING(str)->len) return -1;
+ if (pos > RSTRING(str)->len) return -1;
if (may_need_recompile)
rb_reg_prepare_re(reg);
@@ -452,17 +513,13 @@ rb_reg_search(reg, str, start, reverse)
else if (reg_kcode != curr_kcode)
kcode_reset_option();
-#ifdef USE_THREAD
if (rb_thread_scope_shared_p()) {
match = Qnil;
}
else {
match = rb_backref_get();
}
-#else
- match = rb_backref_get();
-#endif
- if (NIL_P(match)) {
+ if (NIL_P(match) || FL_TEST(match, MATCH_BUSY)) {
if (matchcache) {
match = matchcache;
matchcache = 0;
@@ -474,13 +531,15 @@ rb_reg_search(reg, str, start, reverse)
regs = RMATCH(match)->regs;
if (reverse) {
- range = -start;
+ range = -pos;
}
else {
- range = RSTRING(str)->len - start;
+ range = RSTRING(str)->len - pos;
}
result = re_search(RREGEXP(reg)->ptr,RSTRING(str)->ptr,RSTRING(str)->len,
- start, range, regs);
+ pos, range, regs);
+ if (FL_TEST(reg, KCODE_FIXED))
+ kcode_reset_option();
if (result == -2) {
rb_reg_raise(RREGEXP(reg)->str, RREGEXP(reg)->len,
@@ -552,7 +611,7 @@ rb_reg_match_post(match)
if (NIL_P(match)) return Qnil;
if (RMATCH(match)->BEG(0) == -1) return Qnil;
return rb_str_new(RSTRING(RMATCH(match)->str)->ptr+RMATCH(match)->END(0),
- RSTRING(RMATCH(match)->str)->len-RMATCH(match)->END(0));
+ RSTRING(RMATCH(match)->str)->len-RMATCH(match)->END(0));
}
VALUE
@@ -631,7 +690,7 @@ match_aref(argc, argv, match)
regs = RMATCH(match)->regs;
i = FIX2INT(idx);
- if (i>=regs->num_regs) return Qnil;
+ if (i >= regs->num_regs) return Qnil;
ptr = RSTRING(RMATCH(match)->str)->ptr;
return rb_str_new(ptr+regs->beg[i], regs->end[i]-regs->beg[i]);
@@ -647,19 +706,27 @@ match_to_s(match)
return str;
}
+static VALUE
+match_string(match)
+ VALUE match;
+{
+ return rb_str_dup(RMATCH(match)->str);
+}
+
VALUE rb_cRegexp;
static VALUE
rb_reg_new_1(klass, s, len, options)
VALUE klass;
- char *s;
- size_t len;
+ const char *s;
+ int len;
int options; /* CASEFOLD = 1 */
/* EXTENDED = 2 */
- /* CODE_NONE = 4 */
- /* CODE_EUC = 8 */
- /* CODE_SJIS = 12 */
- /* CODE_UTF8 = 16 */
+ /* POSIXLINE = 4 */
+ /* CODE_NONE = 8 */
+ /* CODE_EUC = 16 */
+ /* CODE_SJIS = 24 */
+ /* CODE_UTF8 = 32 */
{
NEWOBJ(re, struct RRegexp);
OBJSETUP(re, klass, T_REGEXP);
@@ -669,49 +736,54 @@ rb_reg_new_1(klass, s, len, options)
if (options & RE_OPTION_IGNORECASE) {
FL_SET(re, REG_IGNORECASE);
}
- switch (options & ~0x3) {
+ if (options & RE_OPTION_EXTENDED) {
+ FL_SET(re, REG_EXTENDED);
+ }
+ if (options & RE_OPTION_POSIXLINE) {
+ FL_SET(re, REG_POSIXLINE);
+ }
+ switch (options & ~0x7) {
case 0:
default:
FL_SET(re, reg_kcode);
break;
- case 4:
+ case 8:
kcode_none(re);
break;
- case 8:
+ case 16:
kcode_euc(re);
break;
- case 12:
+ case 24:
kcode_sjis(re);
break;
- case 16:
+ case 32:
kcode_utf8(re);
break;
}
- if (options & ~0x3) {
+ if (options & ~0x7) {
kcode_set_option((VALUE)re);
}
if (ruby_ignorecase) {
options |= RE_OPTION_IGNORECASE;
FL_SET(re, REG_CASESTATE);
}
- re->ptr = make_regexp(s, len, options & 0x3);
+ re->ptr = make_regexp(s, len, options & 0x7);
re->str = ALLOC_N(char, len+1);
memcpy(re->str, s, len);
re->str[len] = '\0';
re->len = len;
- if (options & ~0x3) {
+ if (options & ~0x7) {
kcode_reset_option();
}
- rb_obj_call_init((VALUE)re);
return (VALUE)re;
}
VALUE
rb_reg_new(s, len, options)
- char *s;
- size_t len;
+ const char *s;
+ long len;
int options;
{
return rb_reg_new_1(rb_cRegexp, s, len, options);
@@ -799,6 +871,16 @@ rb_reg_match2(re)
}
static VALUE
+rb_reg_match_method(re, str)
+ VALUE re, str;
+{
+ VALUE result = rb_reg_match(re, str);
+
+ if (NIL_P(result)) return Qnil;
+ return rb_backref_get();
+}
+
+static VALUE
rb_reg_s_new(argc, argv, self)
int argc;
VALUE *argv;
@@ -810,21 +892,25 @@ rb_reg_s_new(argc, argv, self)
if (argc == 0 || argc > 3) {
rb_raise(rb_eArgError, "wrong # of argument");
}
- if (argc >= 2 && RTEST(argv[1])) {
- flag = RE_OPTION_IGNORECASE;
+ if (argc >= 2) {
+ if (FIXNUM_P(argv[1])) flag = FIX2INT(argv[1]);
+ else if (RTEST(argv[1])) flag = RE_OPTION_IGNORECASE;
}
if (argc == 3) {
char *kcode = STR2CSTR(argv[2]);
switch (kcode[0]) {
case 'n': case 'N':
- flag |= 4;
+ flag |= 8;
break;
case 'e': case 'E':
- flag |= 8;
+ flag |= 16;
break;
case 's': case 'S':
- flag |= 12;
+ flag |= 24;
+ break;
+ case 'u': case 'U':
+ flag |= 32;
break;
default:
break;
@@ -837,7 +923,7 @@ rb_reg_s_new(argc, argv, self)
}
else {
char *p;
- size_t len;
+ int len;
p = str2cstr(src, &len);
return rb_reg_new_1(self, p, len, flag);
@@ -845,37 +931,50 @@ rb_reg_s_new(argc, argv, self)
}
static VALUE
-rb_reg_s_quote(re, str)
- VALUE re, str;
+rb_reg_s_quote(argc, argv)
+ int argc;
+ VALUE *argv;
{
- char *s, *send, *t;
- char *tmp;
- int len;
-
- s = str2cstr(str, &len);
- send = s + len;
- tmp = ALLOCA_N(char, len*2);
- t = tmp;
-
- for (; s != send; s++) {
- if (ismbchar(*s)) {
- *t++ = *s++;
- *t++ = *s;
- continue;
- }
- if (*s == '[' || *s == ']'
- || *s == '{' || *s == '}'
- || *s == '(' || *s == ')'
- || *s == '|'
- || *s == '*' || *s == '.' || *s == '\\'
- || *s == '?' || *s == '+'
- || *s == '^' || *s == '$') {
- *t++ = '\\';
- }
- *t++ = *s;
+ VALUE str, kcode;
+ int kcode_saved = reg_kcode;
+ char *s, *send, *t;
+ char *tmp;
+ int len;
+
+ rb_scan_args(argc, argv, "11", &str, &kcode);
+ if (!NIL_P(kcode)) {
+ rb_set_kcode(STR2CSTR(kcode));
+ curr_kcode = reg_kcode;
+ reg_kcode = kcode_saved;
}
+ s = str2cstr(str, &len);
+ send = s + len;
+ tmp = ALLOCA_N(char, len*2);
+ t = tmp;
+
+ for (; s != send; s++) {
+ if (ismbchar(*s)) {
+ size_t n = mbclen(*s);
+
+ while (n--)
+ *t++ = *s++;
+ s--;
+ continue;
+ }
+ if (*s == '[' || *s == ']'
+ || *s == '{' || *s == '}'
+ || *s == '(' || *s == ')'
+ || *s == '|'
+ || *s == '*' || *s == '.' || *s == '\\'
+ || *s == '?' || *s == '+'
+ || *s == '^' || *s == '$') {
+ *t++ = '\\';
+ }
+ *t++ = *s;
+ }
+ kcode_reset_option();
- return rb_str_new(tmp, t - tmp);
+ return rb_str_new(tmp, t - tmp);
}
int
@@ -886,6 +985,8 @@ rb_kcode()
return MBCTYPE_EUC;
case KCODE_SJIS:
return MBCTYPE_SJIS;
+ case KCODE_UTF8:
+ return MBCTYPE_UTF8;
case KCODE_NONE:
return MBCTYPE_ASCII;
}
@@ -905,6 +1006,8 @@ rb_reg_get_kcode(re)
kcode |= 8; break;
case KCODE_SJIS:
kcode |= 12; break;
+ case KCODE_UTF8:
+ kcode |= 16; break;
default:
break;
}
@@ -955,7 +1058,7 @@ rb_reg_regsub(str, src, regs)
c = *s++;
if (ismbchar(c)) {
- s++;
+ s += mbclen(c) - 1;
continue;
}
if (c != '\\' || s == e) continue;
@@ -1012,7 +1115,7 @@ rb_reg_regsub(str, src, regs)
return val;
}
-char*
+const char*
rb_get_kcode()
{
switch (reg_kcode) {
@@ -1035,7 +1138,7 @@ kcode_getter()
void
rb_set_kcode(code)
- char *code;
+ const char *code;
{
if (code == 0) goto set_no_conversion;
@@ -1092,7 +1195,10 @@ ignorecase_setter(val)
static VALUE
match_getter()
{
- return match_clone(rb_backref_get());
+ VALUE match = rb_backref_get();
+
+ if (NIL_P(match)) return Qnil;
+ return match_clone(match);
}
static void
@@ -1109,13 +1215,13 @@ Init_Regexp()
rb_eRegxpError = rb_define_class("RegxpError", rb_eStandardError);
re_set_casetable(casetable);
-#ifdef RUBY_USE_EUC
+#if DEFAULT_KCODE == KCODE_EUC
re_mbcinit(MBCTYPE_EUC);
#else
-#ifdef RUBY_USE_SJIS
+#if DEFAULT_KCODE == KCODE_SJIS
re_mbcinit(MBCTYPE_SJIS);
#else
-#ifdef RUBY_USE_UTF8
+#if DEFAULT_KCODE == KCODE_UTF8
re_mbcinit(MBCTYPE_UTF8);
#else
re_mbcinit(MBCTYPE_ASCII);
@@ -1136,25 +1242,39 @@ Init_Regexp()
rb_cRegexp = rb_define_class("Regexp", rb_cObject);
rb_define_singleton_method(rb_cRegexp, "new", rb_reg_s_new, -1);
rb_define_singleton_method(rb_cRegexp, "compile", rb_reg_s_new, -1);
- rb_define_singleton_method(rb_cRegexp, "quote", rb_reg_s_quote, 1);
+ rb_define_singleton_method(rb_cRegexp, "quote", rb_reg_s_quote, -1);
+ rb_define_singleton_method(rb_cRegexp, "escape", rb_reg_s_quote, -1);
rb_define_method(rb_cRegexp, "clone", rb_reg_clone, 0);
rb_define_method(rb_cRegexp, "==", rb_reg_equal, 1);
rb_define_method(rb_cRegexp, "=~", rb_reg_match, 1);
rb_define_method(rb_cRegexp, "===", rb_reg_match, 1);
rb_define_method(rb_cRegexp, "~", rb_reg_match2, 0);
+ rb_define_method(rb_cRegexp, "match", rb_reg_match_method, 1);
rb_define_method(rb_cRegexp, "inspect", rb_reg_inspect, 0);
rb_define_method(rb_cRegexp, "source", rb_reg_source, 0);
rb_define_method(rb_cRegexp, "casefold?", rb_reg_casefold_p, 0);
rb_define_method(rb_cRegexp, "kcode", rb_reg_kcode_method, 0);
+ rb_define_const(rb_cRegexp, "IGNORECASE", INT2FIX(RE_OPTION_IGNORECASE));
+ rb_define_const(rb_cRegexp, "EXTENDED", INT2FIX(RE_OPTION_EXTENDED));
+ rb_define_const(rb_cRegexp, "POSIXLINE", INT2FIX(RE_OPTION_POSIXLINE));
+
rb_global_variable(&reg_cache);
rb_global_variable(&matchcache);
rb_cMatch = rb_define_class("MatchingData", rb_cData);
rb_define_method(rb_cMatch, "clone", match_clone, 0);
+ rb_define_method(rb_cMatch, "size", match_size, 0);
+ rb_define_method(rb_cMatch, "length", match_size, 0);
+ rb_define_method(rb_cMatch, "offset", match_offset, 1);
+ rb_define_method(rb_cMatch, "begin", match_begin, 1);
+ rb_define_method(rb_cMatch, "end", match_end, 1);
rb_define_method(rb_cMatch, "to_a", match_to_a, 0);
rb_define_method(rb_cMatch, "[]", match_aref, -1);
+ rb_define_method(rb_cMatch, "pre_match", rb_reg_match_pre, 0);
+ rb_define_method(rb_cMatch, "post_match", rb_reg_match_post, 0);
rb_define_method(rb_cMatch, "to_s", match_to_s, 0);
+ rb_define_method(rb_cMatch, "string", match_string, 0);
rb_define_method(rb_cMatch, "inspect", rb_any_to_s, 0);
}
diff --git a/re.h b/re.h
index 4d7220b5e6..dc4cd17354 100644
--- a/re.h
+++ b/re.h
@@ -6,7 +6,7 @@
$Date$
created at: Thu Sep 30 14:18:32 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
diff --git a/regex.c b/regex.c
index 924f32b836..aa0b61300f 100644
--- a/regex.c
+++ b/regex.c
@@ -1,29 +1,30 @@
/* Extended regular expression matching and search library.
- Copyright (C) 1985, 1989-90 Free Software Foundation, Inc.
+ Copyright (C) 1993, 94, 95, 96, 97, 98 Free Software Foundation, Inc.
- 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 GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
/* Multi-byte extension added May, 1993 by t^2 (Takahiro Tanimoto)
Last change: May 21, 1993 by t^2 */
+/* removed gapped buffer support, multiple syntax support by matz <matz@nts.co.jp> */
+/* Perl5 extension added by matz <matz@caelum.co.jp> */
+/* UTF-8 extension added Jan 16 1999 by Yoshida Masato <yoshidam@tau.bekkoame.ne.jp> */
-
-/* To test, compile with -Dtest. This Dtestable feature turns this into
- a self-contained program which reads a pattern, describes how it
- compiles, then reads a string and searches for it.
-
- On the other hand, if you compile with both -Dtest and -Dcanned you
- can run some tests we've already thought of. */
+#include "config.h"
+#ifdef RUBY_PLATFORM
+# define RUBY
+#endif
/* We write fatal error messages on standard error. */
#include <stdio.h>
@@ -32,24 +33,46 @@
#include <ctype.h>
#include <sys/types.h>
-#ifdef __STDC__
-#define P(s) s
-#define MALLOC_ARG_T size_t
+#ifndef PARAMS
+# if defined __GNUC__ || (defined __STDC__ && __STDC__)
+# define PARAMS(args) args
+# else
+# define PARAMS(args) ()
+# endif /* GCC. */
+#endif /* Not PARAMS. */
+
+#if defined(STDC_HEADERS)
+# include <stddef.h>
#else
-#define P(s) ()
-#define MALLOC_ARG_T unsigned
-#define volatile
-#define const
+/* We need this for `regex.h', and perhaps for the Emacs include files. */
+# include <sys/types.h>
#endif
-#include "config.h"
+#if defined(STDC_HEADERS)
+# include <stddef.h>
+#else
+/* We need this for `regex.h', and perhaps for the Emacs include files. */
+# include <sys/types.h>
+#endif
+
+#ifndef __STDC__
+# define volatile
+#endif
+
+#ifdef HAVE_PROTOTYPES
+# define _(args) args
+#else
+# define _(args) ()
+#endif
-void *xmalloc P((unsigned long));
-void *xcalloc P((unsigned long,unsigned long));
-void *xrealloc P((void*,unsigned long));
-void free P((void*));
+#ifndef xmalloc
+void *xmalloc _((unsigned long));
+void *xcalloc _((unsigned long,unsigned long));
+void *xrealloc _((void*,unsigned long));
+void free _((void*));
+#endif
-/* #define NO_ALLOCA /* try it out for now */
+/* #define NO_ALLOCA */ /* try it out for now */
#ifndef NO_ALLOCA
/* Make alloca work the best possible way. */
#ifdef __GNUC__
@@ -85,7 +108,7 @@ char *alloca();
#define FREE_AND_RETURN_VOID(stackb) return
#define FREE_AND_RETURN(stackb,val) return(val)
-#define DOUBLE_STACK(stackx,stackb,len,type) \
+#define DOUBLE_STACK(stackx,stackb,len,type) \
(stackx = (type*)alloca(2 * len * sizeof(type)), \
/* Only copy what is in use. */ \
(type*)memcpy(stackx, stackb, len * sizeof (type)))
@@ -94,16 +117,7 @@ char *alloca();
#define RE_ALLOCATE xmalloc
#define FREE_VAR(var) if (var) free(var); var = NULL
-#define FREE_VARIABLES() \
- do { \
- FREE_VAR(regstart); \
- FREE_VAR(regend); \
- FREE_VAR(old_regstart) \
- FREE_VAR(old_regend); \
- FREE_VAR(best_regstart); \
- FREE_VAR(best_regend); \
- FREE_VAR(reg_info); \
- } while (0)
+#define FREE_VARIABLES()
#define FREE_AND_RETURN_VOID(stackb) free(stackb);return
#define FREE_AND_RETURN(stackb,val) free(stackb);return(val)
@@ -115,8 +129,8 @@ char *alloca();
#define TMALLOC(n,t) ((t*)xmalloc((n)*sizeof(t)))
#define TREALLOC(s,n,t) (s=((t*)xrealloc(s,(n)*sizeof(t))))
-#define EXPAND_FAIL_STACK(stackx,stackb,len) \
- do {\
+#define EXPAND_FAIL_STACK(stackx,stackb,len) \
+ do { \
/* Roughly double the size of the stack. */ \
stackx = DOUBLE_STACK(stackx,stackb,len,unsigned char*); \
/* Rearrange the pointers. */ \
@@ -129,16 +143,13 @@ char *alloca();
#include "regex.h"
/* Subroutines for re_compile_pattern. */
-static void store_jump P((char*, int, char*));
-static void insert_jump P((int, char*, char*, char*));
-static void store_jump_n P((char*, int, char*, unsigned));
-static void insert_jump_n P((int, char*, char*, char*, unsigned));
-static void insert_op P((int, char*, char*));
-static void insert_op_2 P((int, char*, char*, int, int));
-static int memcmp_translate P((unsigned char*, unsigned char*, int));
-static int alt_match_null_string_p ();
-static int common_op_match_null_string_p ();
-static int group_match_null_string_p ();
+static void store_jump _((char*, int, char*));
+static void insert_jump _((int, char*, char*, char*));
+static void store_jump_n _((char*, int, char*, unsigned));
+static void insert_jump_n _((int, char*, char*, char*, unsigned));
+static void insert_op _((int, char*, char*));
+static void insert_op_2 _((int, char*, char*, int, int));
+static int memcmp_translate _((unsigned char*, unsigned char*, int));
/* Define the syntax stuff, so we can do the \<, \>, etc. */
@@ -150,15 +161,17 @@ static int group_match_null_string_p ();
#define SYNTAX(c) re_syntax_table[c]
static char re_syntax_table[256];
-static void init_syntax_once P((void));
-static unsigned char *translate = 0;
-static void init_regs P((struct re_registers*, unsigned int));
-static void bm_init_skip P((int *, unsigned char*, int, char*));
+static void init_syntax_once _((void));
+static const unsigned char *translate = 0;
+static void init_regs _((struct re_registers*, unsigned int));
+static void bm_init_skip _((int *, unsigned char*, int, const char*));
static int current_mbctype = MBCTYPE_ASCII;
#undef P
+#ifdef RUBY
#include "util.h"
+#endif
static void
init_syntax_once()
@@ -171,7 +184,7 @@ init_syntax_once()
memset(re_syntax_table, 0, sizeof re_syntax_table);
- for (c=0; c<0x7f; c++)
+ for (c=0; c<=0x7f; c++)
if (isalnum(c))
re_syntax_table[c] = Sword;
re_syntax_table['_'] = Sword;
@@ -184,9 +197,9 @@ init_syntax_once()
void
re_set_casetable(table)
- char *table;
+ const char *table;
{
- translate = (unsigned char*)table;
+ translate = (const unsigned char*)table;
}
/* Jim Meyering writes:
@@ -198,28 +211,54 @@ re_set_casetable(table)
STDC_HEADERS is defined, then autoconf has verified that the ctype
macros don't need to be guarded with references to isascii. ...
Defining isascii to 1 should let any compiler worth its salt
- eliminate the && through constant folding." */
+ eliminate the && through constant folding."
+ Solaris defines some of these symbols so we must undefine them first. */
+
+#undef ISASCII
+#if defined STDC_HEADERS || (!defined isascii && !defined HAVE_ISASCII)
+# define ISASCII(c) 1
+#else
+# define ISASCII(c) isascii(c)
+#endif
+
#ifdef isblank
-#define ISBLANK(c) isblank ((unsigned char)c)
+# define ISBLANK(c) (ISASCII (c) && isblank (c))
#else
-#define ISBLANK(c) ((c) == ' ' || (c) == '\t')
+# define ISBLANK(c) ((c) == ' ' || (c) == '\t')
#endif
#ifdef isgraph
-#define ISGRAPH(c) isgraph ((unsigned char)c)
+# define ISGRAPH(c) (ISASCII (c) && isgraph (c))
#else
-#define ISGRAPH(c) (isprint ((unsigned char)c) && !isspace ((unsigned char)c))
+# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c))
#endif
-#define ISPRINT(c) isprint ((unsigned char)c)
-#define ISDIGIT(c) isdigit ((unsigned char)c)
-#define ISALNUM(c) isalnum ((unsigned char)c)
-#define ISALPHA(c) isalpha ((unsigned char)c)
-#define ISCNTRL(c) iscntrl ((unsigned char)c)
-#define ISLOWER(c) islower ((unsigned char)c)
-#define ISPUNCT(c) ispunct ((unsigned char)c)
-#define ISSPACE(c) isspace ((unsigned char)c)
-#define ISUPPER(c) isupper ((unsigned char)c)
-#define ISXDIGIT(c) isxdigit ((unsigned char)c)
+#undef ISPRINT
+#define ISPRINT(c) (ISASCII (c) && isprint (c))
+#define ISDIGIT(c) (ISASCII (c) && isdigit (c))
+#define ISALNUM(c) (ISASCII (c) && isalnum (c))
+#define ISALPHA(c) (ISASCII (c) && isalpha (c))
+#define ISCNTRL(c) (ISASCII (c) && iscntrl (c))
+#define ISLOWER(c) (ISASCII (c) && islower (c))
+#define ISPUNCT(c) (ISASCII (c) && ispunct (c))
+#define ISSPACE(c) (ISASCII (c) && isspace (c))
+#define ISUPPER(c) (ISASCII (c) && isupper (c))
+#define ISXDIGIT(c) (ISASCII (c) && isxdigit (c))
+
+#ifndef NULL
+# define NULL (void *)0
+#endif
+
+/* We remove any previous definition of `SIGN_EXTEND_CHAR',
+ since ours (we hope) works properly with all combinations of
+ machines, compilers, `char' and `unsigned char' argument types.
+ (Per Bothner suggested the basic approach.) */
+#undef SIGN_EXTEND_CHAR
+#if __STDC__
+# define SIGN_EXTEND_CHAR(c) ((signed char) (c))
+#else /* not __STDC__ */
+/* As in Harbison and Steele. */
+# define SIGN_EXTEND_CHAR(c) ((((unsigned char) (c)) ^ 128) - 128)
+#endif
/* These are the command codes that appear in compiled regular
expressions, one per byte. Some command codes are followed by
@@ -277,7 +316,8 @@ enum regexpcode
finalize_push_n, /* Similar to finalize_push, buf finalize n time only */
set_number_at, /* Set the following relative location to the
subsequent number. */
- anychar, /* Matches any (more or less) one character. */
+ anychar, /* Matches any (more or less) one character excluding newlines. */
+ anychar_repeat, /* Matches sequence of characters excluding newlines. */
charset, /* Matches any one char belonging to specified set.
First following byte is number of bitmap bytes.
Then come bytes for a bitmap saying which chars are in.
@@ -295,9 +335,12 @@ enum regexpcode
and store it in a memory register. Followed by
one byte containing the register number. Register
numbers must be in the range 0 through RE_NREGS. */
+ start_paren, /* Place holder at the start of (?:..). */
stop_paren, /* Place holder at the end of (?:..). */
casefold_on, /* Turn on casefold flag. */
casefold_off, /* Turn off casefold flag. */
+ posix_on, /* Turn on POSIXified line match (match with newlines). */
+ posix_off, /* Turn off POSIXified line match. */
start_nowidth, /* Save string point to the stack. */
stop_nowidth, /* Restore string place at the point start_nowidth. */
pop_and_fail, /* Fail after popping nowidth entry from stack. */
@@ -321,14 +364,6 @@ enum regexpcode
#define NFAILURES 80
#endif
-#if defined(CHAR_UNSIGNED) || defined(__CHAR_UNSIGNED__)
-#define SIGN_EXTEND_CHAR(c) ((c)>(char)127?(c)-256:(c)) /* for IBM RT */
-#endif
-#ifndef SIGN_EXTEND_CHAR
-#define SIGN_EXTEND_CHAR(x) (x)
-#endif
-
-
/* Store NUMBER in two contiguous bytes starting at DESTINATION. */
#define STORE_NUMBER(destination, number) \
do { (destination)[0] = (number) & 0377; \
@@ -353,7 +388,7 @@ enum regexpcode
such as p, not, e.g., p + 1. */
#define EXTRACT_NUMBER_AND_INCR(destination, source) \
do { EXTRACT_NUMBER(destination, source); \
- (source) += 2; } while (0)
+ (source) += 2; } while (0)
/* Specify the precise syntax of regexps for compilation. This provides
@@ -395,60 +430,64 @@ re_set_syntax(syntax)
/* Go backwards one character in the pattern. */
#define PATUNFETCH p--
-#define MBC2WC(c, p)\
- do {\
- if (current_mbctype == MBCTYPE_UTF8) {\
- int n = ismbchar(c);\
- int c1;\
- c &= 1<<(BYTEWIDTH-2-n);\
- while (n--) {\
- c = c << 6 | *p++;\
- }\
- }\
- else {\
- c <<= 8;\
- c |= (unsigned char)*(p)++;\
- }\
+#define MBC2WC(c, p) \
+ do { \
+ if (current_mbctype == MBCTYPE_UTF8) { \
+ int n = mbclen(c) - 1; \
+ c &= (1<<(BYTEWIDTH-2-n)) - 1; \
+ while (n--) { \
+ c = c << 6 | *p++ & ((1<<6)-1); \
+ } \
+ } \
+ else { \
+ c <<= 8; \
+ c |= (unsigned char)*(p)++; \
+ } \
} while (0)
-#define PATFETCH_MBC(c) \
- do {\
- if (p + ismbchar(c) == pend) goto end_of_pattern;\
- MBC2WC(c, p);\
+#define PATFETCH_MBC(c) \
+ do { \
+ if (p + mbclen(c) - 1 >= pend) goto end_of_pattern; \
+ MBC2WC(c, p); \
} while(0)
-#define WC2MBC1ST(c) \
+#define WC2MBC1ST(c) \
((current_mbctype != MBCTYPE_UTF8)?(((c)>>8)&0xff):utf8_firstbyte(c))
static unsigned int
utf8_firstbyte(c)
- unsigned int c;
+ unsigned long c;
{
if (c < 0x80) return c;
- if (c < 0x7ff) return ((c>>6)&0xff)|0xc0;
- if (c < 0xffff) return ((c>>12)&0xff)|0xe0;
- if (c < 0x1fffff) return ((c>>18)&0xff)|0xf0;
- if (c < 0x3ffffff) return ((c>>24)&0xff)|0xf8;
- if (c < 0x7fffffff) return ((c>>30)&0xff)|0xfc;
+ if (c <= 0x7ff) return ((c>>6)&0xff)|0xc0;
+ if (c <= 0xffff) return ((c>>12)&0xff)|0xe0;
+ if (c <= 0x1fffff) return ((c>>18)&0xff)|0xf0;
+ if (c <= 0x3ffffff) return ((c>>24)&0xff)|0xf8;
+ if (c <= 0x7fffffff) return ((c>>30)&0xff)|0xfc;
+#if SIZEOF_INT > 4
+ if (c <= 0xfffffffff) return 0xfe;
+#else
+ return 0xfe;
+#endif
}
static void
print_mbc(c)
- unsigned int c;
+ unsigned long c;
{
if (current_mbctype == MBCTYPE_UTF8) {
if (c < 0x80)
printf("%c", c);
- else if (c < 0x7ff)
+ else if (c <= 0x7ff)
printf("%c%c", utf8_firstbyte(c), c&0x3f);
- else if (c < 0xffff)
+ else if (c <= 0xffff)
printf("%c%c%c", utf8_firstbyte(c), (c>>6)&0x3f, c&0x3f);
- else if (c < 0x1fffff)
+ else if (c <= 0x1fffff)
printf("%c%c%c%c", utf8_firstbyte(c), (c>>12)&0x3f, (c>>6)&0x3f, c&0x3f);
- else if (c < 0x3ffffff)
+ else if (c <= 0x3ffffff)
printf("%c%c%c%c%c", utf8_firstbyte(c), (c>>18)&0x3f, (c>>12)&0x3f, (c>>6)&0x3f, c&0x3f);
- else if (c < 0x7fffffff)
- printf("%c%c%c%c%c", utf8_firstbyte(c), (c>>24)&0x3f, (c>>18)&0x3f, (c>>12)&0x3f, (c>>6)&0x3f, c&0x3f);
+ else if (c <= 0x7fffffff)
+ printf("%c%c%c%c%c%c", utf8_firstbyte(c), (c>>24)&0x3f, (c>>18)&0x3f, (c>>12)&0x3f, (c>>6)&0x3f, c&0x3f);
}
else {
printf("%c%c", c>>BYTEWIDTH, c&0xff);
@@ -502,19 +541,17 @@ print_mbc(c)
/* Get the next unsigned number in the uncompiled pattern. */
#define GET_UNSIGNED_NUMBER(num) \
- do { if (p != pend) \
- { \
+ do { if (p != pend) { \
PATFETCH(c); \
- while (ISDIGIT(c)) \
- { \
- if (num < 0) \
- num = 0; \
- num = num * 10 + c - '0'; \
- if (p == pend) \
- break; \
- PATFETCH(c); \
- } \
- } \
+ while (ISDIGIT(c)) { \
+ if (num < 0) \
+ num = 0; \
+ num = num * 10 + c - '0'; \
+ if (p == pend) \
+ break; \
+ PATFETCH(c); \
+ } \
+ } \
} while (0)
#define STREQ(s1, s2) ((strcmp (s1, s2) == 0))
@@ -546,13 +583,13 @@ print_mbc(c)
} while (0)
#define EXTRACT_MBC(p) \
- ((unsigned short)((unsigned char)(p)[0] << 24 | \
+ ((unsigned long)((unsigned char)(p)[0] << 24 | \
(unsigned char)(p)[1] << 16 | \
(unsigned char)(p)[2] << 8 | \
(unsigned char)(p)[3]))
#define EXTRACT_MBC_AND_INCR(p) \
- ((unsigned short)((p) += 4, \
+ ((unsigned long)((p) += 4, \
(unsigned char)(p)[-4] << 24 | \
(unsigned char)(p)[-3] << 16 | \
(unsigned char)(p)[-2] << 8 | \
@@ -573,14 +610,14 @@ print_mbc(c)
unsigned char sbc_map[sbc_size]; same as charset(_not)? up to here.
unsigned short mbc_size; number of intervals.
struct {
- unsigned int beg; beginning of interval.
- unsigned int end; end of interval.
+ unsigned long beg; beginning of interval.
+ unsigned long end; end of interval.
} intervals[mbc_size];
}; */
static void
set_list_bits(c1, c2, b)
- unsigned int c1, c2;
+ unsigned long c1, c2;
unsigned char *b;
{
unsigned char sbc_size = b[-1];
@@ -626,33 +663,32 @@ set_list_bits(c1, c2, b)
static int
is_in_list(c, b)
- unsigned int c;
+ unsigned long c;
const unsigned char *b;
{
- unsigned short size;
- unsigned short i, j;
- int result = 0;
+ unsigned short size;
+ unsigned short i, j;
- size = *b++;
- if ((int)c / BYTEWIDTH < (int)size && b[c / BYTEWIDTH] & 1 << c % BYTEWIDTH) {
- return 2;
- }
- b += size + 2;
- size = EXTRACT_UNSIGNED(&b[-2]);
- if (size == 0) return 0;
+ size = *b++;
+ if ((int)c / BYTEWIDTH < (int)size && b[c / BYTEWIDTH] & 1 << c % BYTEWIDTH) {
+ return 1;
+ }
+ b += size + 2;
+ size = EXTRACT_UNSIGNED(&b[-2]);
+ if (size == 0) return 0;
- for (i = 0, j = size; i < j; ) {
- unsigned short k = (unsigned short)(i + j) >> 1;
+ for (i = 0, j = size; i < j; ) {
+ unsigned short k = (unsigned short)(i + j) >> 1;
- if (c > EXTRACT_MBC(&b[k*8+4]))
- i = k + 1;
- else
- j = k;
- }
- if (i < size && EXTRACT_MBC(&b[i*8]) <= c
- && ((unsigned char)c != '\n' && (unsigned char)c != '\0'))
- return 1;
- return result;
+ if (c > EXTRACT_MBC(&b[k*8+4]))
+ i = k + 1;
+ else
+ j = k;
+ }
+ if (i < size && EXTRACT_MBC(&b[i*8]) <= c
+ && ((unsigned char)c != '\n' && (unsigned char)c != '\0'))
+ return 1;
+ return 0;
}
static void
@@ -664,230 +700,241 @@ print_partial_compiled_pattern(start, end)
unsigned char *p = start;
unsigned char *pend = end;
- if (start == NULL)
- {
- printf ("(null)\n");
- return;
- }
-
+ if (start == NULL) {
+ printf("(null)\n");
+ return;
+ }
+
/* Loop over pattern commands. */
- while (p < pend)
- {
- switch ((enum regexpcode)*p++)
- {
- case unused:
- printf ("/unused");
- break;
+ while (p < pend) {
+ switch ((enum regexpcode)*p++) {
+ case unused:
+ printf("/unused");
+ break;
- case exactn:
- mcnt = *p++;
- printf ("/exactn/%d", mcnt);
- do
- {
- putchar('/');
- printf("%c", *p++);
- }
- while (--mcnt);
- break;
-
- case start_memory:
- mcnt = *p++;
- printf ("/start_memory/%d/%d", mcnt, *p++);
- break;
-
- case stop_memory:
- mcnt = *p++;
- printf ("/stop_memory/%d/%d", mcnt, *p++);
- break;
-
- case stop_paren:
- printf ("/stop_paren");
- break;
+ case exactn:
+ mcnt = *p++;
+ printf("/exactn/%d", mcnt);
+ do {
+ putchar('/');
+ printf("%c", *p++);
+ }
+ while (--mcnt);
+ break;
- case casefold_on:
- printf ("/casefold_on");
- break;
+ case start_memory:
+ mcnt = *p++;
+ printf("/start_memory/%d/%d", mcnt, *p++);
+ break;
- case casefold_off:
- printf ("/casefold_off");
- break;
+ case stop_memory:
+ mcnt = *p++;
+ printf("/stop_memory/%d/%d", mcnt, *p++);
+ break;
- case start_nowidth:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- printf ("/start_nowidth//%d", mcnt);
- break;
+ case start_paren:
+ printf("/start_paren");
+ break;
- case stop_nowidth:
- printf ("/stop_nowidth//");
- p += 2;
- break;
+ case stop_paren:
+ printf("/stop_paren");
+ break;
- case pop_and_fail:
- printf ("/pop_and_fail");
- break;
+ case casefold_on:
+ printf("/casefold_on");
+ break;
- case duplicate:
- printf ("/duplicate/%d", *p++);
- break;
+ case casefold_off:
+ printf("/casefold_off");
+ break;
- case anychar:
- printf ("/anychar");
- break;
+ case posix_on:
+ printf("/posix_on");
+ break;
- case charset:
- case charset_not:
- {
- register int c;
-
- printf ("/charset%s",
- (enum regexpcode)*(p - 1) == charset_not ? "_not" : "");
-
- mcnt = *p++;
- printf("/%d", mcnt);
- for (c = 0; c < mcnt; c++)
- {
- unsigned bit;
- unsigned char map_byte = p[c];
-
- putchar ('/');
-
- for (bit = 0; bit < BYTEWIDTH; bit++)
- if (map_byte & (1 << bit))
- printf("%c", c * BYTEWIDTH + bit);
- }
- p += mcnt;
- mcnt = EXTRACT_UNSIGNED_AND_INCR(p);
- printf("/");
- while (mcnt--) {
- print_mbc(EXTRACT_MBC_AND_INCR(p));
- printf("-");
- print_mbc(EXTRACT_MBC_AND_INCR(p));
- }
- break;
- }
+ case posix_off:
+ printf("/posix_off");
+ break;
- case begline:
- printf ("/begline");
- break;
+ case start_nowidth:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ printf("/start_nowidth//%d", mcnt);
+ break;
- case endline:
- printf ("/endline");
- break;
+ case stop_nowidth:
+ printf("/stop_nowidth//");
+ p += 2;
+ break;
- case on_failure_jump:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- printf ("/on_failure_jump//%d", mcnt);
- break;
+ case pop_and_fail:
+ printf("/pop_and_fail");
+ break;
- case dummy_failure_jump:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- printf ("/dummy_failure_jump//%d", mcnt);
- break;
-
- case push_dummy_failure:
- printf ("/push_dummy_failure");
- break;
-
- case finalize_jump:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- printf ("/finalize_jump//%d", mcnt);
- break;
+ case duplicate:
+ printf("/duplicate/%d", *p++);
+ break;
- case maybe_finalize_jump:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- printf ("/maybe_finalize_jump//%d", mcnt);
- break;
+ case anychar:
+ printf("/anychar");
+ break;
- case jump_past_alt:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- printf ("/jump_past_alt//%d", mcnt);
- break;
+ case anychar_repeat:
+ printf("/anychar_repeat");
+ break;
- case jump:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- printf ("/jump//%d", mcnt);
- break;
+ case charset:
+ case charset_not:
+ {
+ register int c;
- case succeed_n:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- EXTRACT_NUMBER_AND_INCR (mcnt2, p);
- printf ("/succeed_n//%d//%d", mcnt, mcnt2);
- break;
-
- case jump_n:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- EXTRACT_NUMBER_AND_INCR (mcnt2, p);
- printf ("/jump_n//%d//%d", mcnt, mcnt2);
- break;
-
- case set_number_at:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- EXTRACT_NUMBER_AND_INCR (mcnt2, p);
- printf ("/set_number_at//%d//%d", mcnt, mcnt2);
- break;
-
- case try_next:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- printf ("/try_next//%d", mcnt);
- break;
+ printf("/charset%s",
+ (enum regexpcode)*(p - 1) == charset_not ? "_not" : "");
- case finalize_push:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- printf ("/finalize_push//%d", mcnt);
- break;
+ mcnt = *p++;
+ printf("/%d", mcnt);
+ for (c = 0; c < mcnt; c++) {
+ unsigned bit;
+ unsigned char map_byte = p[c];
- case finalize_push_n:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- EXTRACT_NUMBER_AND_INCR (mcnt2, p);
- printf ("/finalize_push_n//%d//%d", mcnt, mcnt2);
- break;
+ putchar ('/');
- case wordbound:
- printf ("/wordbound");
- break;
+ for (bit = 0; bit < BYTEWIDTH; bit++)
+ if (map_byte & (1 << bit))
+ printf("%c", c * BYTEWIDTH + bit);
+ }
+ p += mcnt;
+ mcnt = EXTRACT_UNSIGNED_AND_INCR(p);
+ printf("/");
+ while (mcnt--) {
+ print_mbc(EXTRACT_MBC_AND_INCR(p));
+ printf("-");
+ print_mbc(EXTRACT_MBC_AND_INCR(p));
+ }
+ break;
+ }
- case notwordbound:
- printf ("/notwordbound");
- break;
+ case begline:
+ printf("/begline");
+ break;
- case wordbeg:
- printf ("/wordbeg");
- break;
-
- case wordend:
- printf ("/wordend");
-
- case wordchar:
- printf ("/wordchar");
- break;
+ case endline:
+ printf("/endline");
+ break;
+
+ case on_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ printf("/on_failure_jump//%d", mcnt);
+ break;
+
+ case dummy_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ printf("/dummy_failure_jump//%d", mcnt);
+ break;
+
+ case push_dummy_failure:
+ printf("/push_dummy_failure");
+ break;
+
+ case finalize_jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ printf("/finalize_jump//%d", mcnt);
+ break;
+
+ case maybe_finalize_jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ printf("/maybe_finalize_jump//%d", mcnt);
+ break;
+
+ case jump_past_alt:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ printf("/jump_past_alt//%d", mcnt);
+ break;
+
+ case jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ printf("/jump//%d", mcnt);
+ break;
+
+ case succeed_n:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ EXTRACT_NUMBER_AND_INCR (mcnt2, p);
+ printf("/succeed_n//%d//%d", mcnt, mcnt2);
+ break;
+
+ case jump_n:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ EXTRACT_NUMBER_AND_INCR (mcnt2, p);
+ printf("/jump_n//%d//%d", mcnt, mcnt2);
+ break;
+
+ case set_number_at:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ EXTRACT_NUMBER_AND_INCR (mcnt2, p);
+ printf("/set_number_at//%d//%d", mcnt, mcnt2);
+ break;
+
+ case try_next:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ printf("/try_next//%d", mcnt);
+ break;
+
+ case finalize_push:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ printf("/finalize_push//%d", mcnt);
+ break;
+
+ case finalize_push_n:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ EXTRACT_NUMBER_AND_INCR (mcnt2, p);
+ printf("/finalize_push_n//%d//%d", mcnt, mcnt2);
+ break;
+
+ case wordbound:
+ printf("/wordbound");
+ break;
+
+ case notwordbound:
+ printf("/notwordbound");
+ break;
+
+ case wordbeg:
+ printf("/wordbeg");
+ break;
+
+ case wordend:
+ printf("/wordend");
+
+ case wordchar:
+ printf("/wordchar");
+ break;
- case notwordchar:
- printf ("/notwordchar");
- break;
+ case notwordchar:
+ printf("/notwordchar");
+ break;
- case begbuf:
- printf ("/begbuf");
- break;
+ case begbuf:
+ printf("/begbuf");
+ break;
- case endbuf:
- printf ("/endbuf");
- break;
+ case endbuf:
+ printf("/endbuf");
+ break;
- case endbuf2:
- printf ("/endbuf2");
- break;
+ case endbuf2:
+ printf("/endbuf2");
+ break;
- default:
- printf ("?%d", *(p-1));
- }
+ default:
+ printf("?%d", *(p-1));
}
- printf ("/\n");
+ }
+ printf("/\n");
}
static void
print_compiled_pattern(bufp)
- struct re_pattern_buffer *bufp;
+ struct re_pattern_buffer *bufp;
{
unsigned char *buffer = (unsigned char*)bufp->buffer;
@@ -896,8 +943,8 @@ print_compiled_pattern(bufp)
static char*
calculate_must_string(start, end)
- char *start;
- char *end;
+ char *start;
+ char *end;
{
int mcnt;
int max = 0;
@@ -906,103 +953,136 @@ calculate_must_string(start, end)
char *must = 0;
if (start == NULL) return 0;
-
+
/* Loop over pattern commands. */
- while (p < pend)
- {
- switch ((enum regexpcode)*p++)
- {
- case unused:
- break;
+ while (p < pend) {
+ switch ((enum regexpcode)*p++) {
+ case unused:
+ break;
- case exactn:
- mcnt = *p;
- if (mcnt > max) {
- must = p;
- max = mcnt;
- }
- p += mcnt+1;
- break;
+ case exactn:
+ mcnt = *p;
+ if (mcnt > max) {
+ must = p;
+ max = mcnt;
+ }
+ p += mcnt+1;
+ break;
- case start_memory:
- case stop_memory:
- p += 2;
- break;
+ case start_memory:
+ case stop_memory:
+ p += 2;
+ break;
- case duplicate:
- p++;
- break;
-
- case casefold_on:
- case casefold_off:
- return 0; /* should not check must_string */
-
- case pop_and_fail:
- case anychar:
- case begline:
- case endline:
- case wordbound:
- case notwordbound:
- case wordbeg:
- case wordend:
- case wordchar:
- case notwordchar:
- case begbuf:
- case endbuf:
- case endbuf2:
- case push_dummy_failure:
- case stop_paren:
- break;
+ case duplicate:
+ p++;
+ break;
- case charset:
- case charset_not:
- mcnt = *p++;
- p += mcnt;
- mcnt = EXTRACT_UNSIGNED_AND_INCR(p);
- while (mcnt--) {
- p += 4;
- }
- break;
+ case casefold_on:
+ case casefold_off:
+ return 0; /* should not check must_string */
- case on_failure_jump:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- if (mcnt > 0) p += mcnt;
- if ((enum regexpcode)p[-3] == jump) {
- p -= 3;
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- if (mcnt > 0) p += mcnt;
- }
- break;
+ case pop_and_fail:
+ case anychar:
+ case anychar_repeat:
+ case begline:
+ case endline:
+ case wordbound:
+ case notwordbound:
+ case wordbeg:
+ case wordend:
+ case wordchar:
+ case notwordchar:
+ case begbuf:
+ case endbuf:
+ case endbuf2:
+ case push_dummy_failure:
+ case start_paren:
+ case stop_paren:
+ case posix_on:
+ case posix_off:
+ break;
- case dummy_failure_jump:
- case succeed_n:
- case try_next:
- case jump:
- EXTRACT_NUMBER_AND_INCR (mcnt, p);
- if (mcnt > 0) p += mcnt;
- break;
-
- case start_nowidth:
- case stop_nowidth:
- case finalize_jump:
- case maybe_finalize_jump:
- case finalize_push:
- p += 2;
- break;
+ case charset:
+ case charset_not:
+ mcnt = *p++;
+ p += mcnt;
+ mcnt = EXTRACT_UNSIGNED_AND_INCR(p);
+ while (mcnt--) {
+ p += 4;
+ }
+ break;
- case jump_n:
- case set_number_at:
- case finalize_push_n:
- p += 4;
- break;
+ case on_failure_jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ if (mcnt > 0) p += mcnt;
+ if ((enum regexpcode)p[-3] == jump) {
+ p -= 3;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ if (mcnt > 0) p += mcnt;
+ }
+ break;
- default:
- break;
- }
+ case dummy_failure_jump:
+ case succeed_n:
+ case try_next:
+ case jump:
+ EXTRACT_NUMBER_AND_INCR (mcnt, p);
+ if (mcnt > 0) p += mcnt;
+ break;
+
+ case start_nowidth:
+ case stop_nowidth:
+ case finalize_jump:
+ case maybe_finalize_jump:
+ case finalize_push:
+ p += 2;
+ break;
+
+ case jump_n:
+ case set_number_at:
+ case finalize_push_n:
+ p += 4;
+ break;
+
+ default:
+ break;
}
+ }
return must;
}
+static int
+read_backslash(c)
+ int c;
+{
+ switch (c) {
+ case 'n':
+ return '\n';
+
+ case 't':
+ return '\t';
+
+ case 'r':
+ return '\r';
+
+ case 'f':
+ return '\f';
+
+ case 'v':
+ return '\v';
+
+ case 'a':
+ return '\007';
+
+ case 'b':
+ return '\010';
+
+ case 'e':
+ return '\033';
+ }
+ return c;
+}
/* re_compile_pattern takes a regular-expression string
and converts it into a buffer full of byte commands for matching.
@@ -1021,1034 +1101,1095 @@ calculate_must_string(start, end)
char *
re_compile_pattern(pattern, size, bufp)
- char *pattern;
- size_t size;
+ const char *pattern;
+ int size;
struct re_pattern_buffer *bufp;
{
- register char *b = bufp->buffer;
- register char *p = pattern;
- char *pend = pattern + size;
- register unsigned c, c1;
- char *p0;
- int numlen;
+ register char *b = bufp->buffer;
+ register const char *p = pattern;
+ const char *nextp;
+ const char *pend = pattern + size;
+ register unsigned c, c1;
+ const char *p0;
+ int numlen;
- /* Address of the count-byte of the most recently inserted `exactn'
- command. This makes it possible to tell whether a new exact-match
- character can be added to that command or requires a new `exactn'
- command. */
+ /* Address of the count-byte of the most recently inserted `exactn'
+ command. This makes it possible to tell whether a new exact-match
+ character can be added to that command or requires a new `exactn'
+ command. */
- char *pending_exact = 0;
+ char *pending_exact = 0;
- /* Address of the place where a forward-jump should go to the end of
- the containing expression. Each alternative of an `or', except the
- last, ends with a forward-jump of this sort. */
+ /* Address of the place where a forward-jump should go to the end of
+ the containing expression. Each alternative of an `or', except the
+ last, ends with a forward-jump of this sort. */
- char *fixup_alt_jump = 0;
+ char *fixup_alt_jump = 0;
- /* Address of start of the most recently finished expression.
- This tells postfix * where to find the start of its operand. */
+ /* Address of start of the most recently finished expression.
+ This tells postfix * where to find the start of its operand. */
- char *laststart = 0;
+ char *laststart = 0;
- /* In processing a repeat, 1 means zero matches is allowed. */
+ /* In processing a repeat, 1 means zero matches is allowed. */
- char zero_times_ok;
+ char zero_times_ok;
- /* In processing a repeat, 1 means many matches is allowed. */
+ /* In processing a repeat, 1 means many matches is allowed. */
- char many_times_ok;
+ char many_times_ok;
- /* In processing a repeat, 1 means non-greedy matches. */
+ /* In processing a repeat, 1 means non-greedy matches. */
- char greedy;
+ char greedy;
- /* Address of beginning of regexp, or inside of last (. */
+ /* Address of beginning of regexp, or inside of last (. */
- char *begalt = b;
+ char *begalt = b;
- /* Place in the uncompiled pattern (i.e., the {) to
- which to go back if the interval is invalid. */
- char *beg_interval;
+ /* Place in the uncompiled pattern (i.e., the {) to
+ which to go back if the interval is invalid. */
+ const char *beg_interval;
- /* In processing an interval, at least this many matches must be made. */
- int lower_bound;
+ /* In processing an interval, at least this many matches must be made. */
+ int lower_bound;
- /* In processing an interval, at most this many matches can be made. */
- int upper_bound;
+ /* In processing an interval, at most this many matches can be made. */
+ int upper_bound;
- /* Stack of information saved by ( and restored by ).
- Five stack elements are pushed by each (:
- First, the value of b.
- Second, the value of fixup_alt_jump.
- Third, the value of begalt.
- Fourth, the value of regnum.
- Fifth, the type of the paren. */
+ /* Stack of information saved by ( and restored by ).
+ Five stack elements are pushed by each (:
+ First, the value of b.
+ Second, the value of fixup_alt_jump.
+ Third, the value of begalt.
+ Fourth, the value of regnum.
+ Fifth, the type of the paren. */
- size_t *stackb = RE_TALLOC(40, size_t);
- size_t *stackp = stackb;
- size_t *stacke = stackb + 40;
- size_t *stackt;
+ int *stackb = RE_TALLOC(40, int);
+ int *stackp = stackb;
+ int *stacke = stackb + 40;
+ int *stackt;
- /* Counts ('s as they are encountered. Remembered for the matching ),
- where it becomes the register number to put in the stop_memory
- command. */
+ /* Counts ('s as they are encountered. Remembered for the matching ),
+ where it becomes the register number to put in the stop_memory
+ command. */
- int regnum = 1;
+ int regnum = 1;
- int range = 0;
- int had_mbchar = 0;
- int had_char_class = 0;
+ int range = 0;
+ int had_mbchar = 0;
+ int had_char_class = 0;
- int options = bufp->options;
+ int options = bufp->options;
- bufp->fastmap_accurate = 0;
- bufp->must = 0;
- bufp->must_skip = 0;
- bufp->stclass = 0;
+ bufp->fastmap_accurate = 0;
+ bufp->must = 0;
+ bufp->must_skip = 0;
+ bufp->stclass = 0;
- /* Initialize the syntax table. */
- init_syntax_once();
+ /* Initialize the syntax table. */
+ init_syntax_once();
- if (bufp->allocated == 0) {
- bufp->allocated = INIT_BUF_SIZE;
- if (bufp->buffer)
- /* EXTEND_BUFFER loses when bufp->allocated is 0. */
- bufp->buffer = (char*)xrealloc (bufp->buffer, INIT_BUF_SIZE);
- else
- /* Caller did not allocate a buffer. Do it for them. */
- bufp->buffer = (char*)xmalloc(INIT_BUF_SIZE);
- if (!bufp->buffer) goto memory_exhausted;
- begalt = b = bufp->buffer;
- }
+ if (bufp->allocated == 0) {
+ bufp->allocated = INIT_BUF_SIZE;
+ if (bufp->buffer)
+ /* EXTEND_BUFFER loses when bufp->allocated is 0. */
+ bufp->buffer = (char*)xrealloc (bufp->buffer, INIT_BUF_SIZE);
+ else
+ /* Caller did not allocate a buffer. Do it for them. */
+ bufp->buffer = (char*)xmalloc(INIT_BUF_SIZE);
+ if (!bufp->buffer) goto memory_exhausted;
+ begalt = b = bufp->buffer;
+ }
- while (p != pend) {
- PATFETCH(c);
+ while (p != pend) {
+ PATFETCH(c);
- switch (c)
- {
- case '$':
- {
- p0 = p;
- /* When testing what follows the $,
- look past the \-constructs that don't consume anything. */
-
- while (p0 != pend)
- {
- if (*p0 == '\\' && p0 + 1 != pend
- && (p0[1] == 'b' || p0[1] == 'B'))
- p0 += 2;
- else
- break;
- }
- /* $ means succeed if at end of line, but only in special contexts.
- If validly in the middle of a pattern, it is a normal character. */
-
- if (p0 == pend || *p0 == '\n'
- || *p0 == ')'
- || *p0 == '|')
- {
- BUFPUSH(endline);
- break;
- }
- goto normal_char;
- }
- case '^':
- /* ^ means succeed if at beg of line, but only if no preceding
- pattern. */
-
- if (laststart)
- goto invalid_pattern;
- if (laststart && p - 2 >= pattern && p[-2] != '\n')
- goto normal_char;
+ switch (c) {
+ case '$':
+ if (bufp->options & RE_OPTION_POSIXLINE) {
+ BUFPUSH(endbuf);
+ }
+ else {
+ p0 = p;
+ /* When testing what follows the $,
+ look past the \-constructs that don't consume anything. */
+
+ while (p0 != pend) {
+ if (*p0 == '\\' && p0 + 1 != pend
+ && (p0[1] == 'b' || p0[1] == 'B'))
+ p0 += 2;
+ else
+ break;
+ }
+ BUFPUSH(endline);
+ }
+ break;
+ case '^':
+ if (bufp->options & RE_OPTION_POSIXLINE)
+ BUFPUSH(begbuf);
+ else
BUFPUSH(begline);
- break;
+ break;
- case '+':
+ case '+':
+ case '?':
+ case '*':
+ /* If there is no previous pattern, char not special. */
+ if (!laststart) {
+ goto invalid_pattern;
+ }
+ /* If there is a sequence of repetition chars,
+ collapse it down to just one. */
+ zero_times_ok = c != '+';
+ many_times_ok = c != '?';
+ greedy = 1;
+ if (p != pend) {
+ PATFETCH(c);
+ switch (c) {
case '?':
+ greedy = 0;
+ break;
case '*':
- /* If there is no previous pattern, char not special. */
- if (!laststart) {
- goto invalid_pattern;
- }
- /* If there is a sequence of repetition chars,
- collapse it down to just one. */
- zero_times_ok = c != '+';
- many_times_ok = c != '?';
- greedy = 1;
- if (p != pend) {
- PATFETCH(c);
- switch (c) {
- case '?':
- greedy = 0;
- break;
- case '*':
- case '+':
- goto nested_meta;
- default:
- PATUNFETCH;
- break;
- }
- }
+ case '+':
+ goto nested_meta;
+ default:
+ PATUNFETCH;
+ break;
+ }
+ }
- repeat:
- /* Star, etc. applied to an empty pattern is equivalent
- to an empty pattern. */
- if (!laststart)
- break;
+ repeat:
+ /* Star, etc. applied to an empty pattern is equivalent
+ to an empty pattern. */
+ if (!laststart)
+ break;
- /* Now we know whether or not zero matches is allowed
- and also whether or not two or more matches is allowed. */
- if (many_times_ok) {
- /* If more than one repetition is allowed, put in at the
- end a backward relative jump from b to before the next
- jump we're going to put in below (which jumps from
- laststart to after this jump). */
- GET_BUFFER_SPACE(3);
- store_jump(b,greedy?maybe_finalize_jump:finalize_push,laststart-3);
- b += 3; /* Because store_jump put stuff here. */
- }
+ if (greedy && many_times_ok && *laststart == anychar && b - laststart <= 2) {
+ if (b[-1] == stop_paren)
+ b--;
+ if (zero_times_ok)
+ *laststart = anychar_repeat;
+ else {
+ BUFPUSH(anychar_repeat);
+ }
+ break;
+ }
+ /* Now we know whether or not zero matches is allowed
+ and also whether or not two or more matches is allowed. */
+ if (many_times_ok) {
+ /* If more than one repetition is allowed, put in at the
+ end a backward relative jump from b to before the next
+ jump we're going to put in below (which jumps from
+ laststart to after this jump). */
+ GET_BUFFER_SPACE(3);
+ store_jump(b,greedy?maybe_finalize_jump:finalize_push,laststart-3);
+ b += 3; /* Because store_jump put stuff here. */
+ }
- /* On failure, jump from laststart to next pattern, which will be the
- end of the buffer after this jump is inserted. */
+ /* On failure, jump from laststart to next pattern, which will be the
+ end of the buffer after this jump is inserted. */
+ GET_BUFFER_SPACE(3);
+ insert_jump(on_failure_jump, laststart, b + 3, b);
+ b += 3;
+
+ if (zero_times_ok) {
+ if (greedy == 0) {
GET_BUFFER_SPACE(3);
- insert_jump(on_failure_jump, laststart, b + 3, b);
+ insert_jump(try_next, laststart, b + 3, b);
b += 3;
+ }
+ }
+ else {
+ /* At least one repetition is required, so insert a
+ `dummy_failure_jump' before the initial
+ `on_failure_jump' instruction of the loop. This
+ effects a skip over that instruction the first time
+ we hit that loop. */
+ GET_BUFFER_SPACE(3);
+ insert_jump(dummy_failure_jump, laststart, laststart + 6, b);
+ b += 3;
+ }
+ break;
- if (zero_times_ok) {
- if (greedy == 0) {
- GET_BUFFER_SPACE(3);
- insert_jump(try_next, laststart, b + 3, b);
- b += 3;
- }
- }
- else {
- /* At least one repetition is required, so insert a
- `dummy_failure_jump' before the initial
- `on_failure_jump' instruction of the loop. This
- effects a skip over that instruction the first time
- we hit that loop. */
- GET_BUFFER_SPACE(3);
- insert_jump(dummy_failure_jump, laststart, laststart + 6, b);
- b += 3;
- }
- break;
-
- case '.':
- laststart = b;
- BUFPUSH(anychar);
- break;
+ case '.':
+ laststart = b;
+ BUFPUSH(anychar);
+ break;
- case '[':
- if (p == pend)
- goto invalid_pattern;
- while ((b - bufp->buffer + 9 + (1 << BYTEWIDTH) / BYTEWIDTH)
- > bufp->allocated)
- EXTEND_BUFFER;
+ case '[':
+ if (p == pend)
+ goto invalid_pattern;
+ while ((b - bufp->buffer + 9 + (1 << BYTEWIDTH) / BYTEWIDTH)
+ > bufp->allocated)
+ EXTEND_BUFFER;
+
+ laststart = b;
+ if (*p == '^') {
+ BUFPUSH(charset_not);
+ p++;
+ }
+ else
+ BUFPUSH(charset);
+ p0 = p;
- laststart = b;
- if (*p == '^')
- {
- BUFPUSH(charset_not);
- p++;
- }
- else
- BUFPUSH(charset);
- p0 = p;
+ BUFPUSH((1 << BYTEWIDTH) / BYTEWIDTH);
+ /* Clear the whole map */
+ memset(b, 0, (1 << BYTEWIDTH) / BYTEWIDTH + 2);
- BUFPUSH((1 << BYTEWIDTH) / BYTEWIDTH);
- /* Clear the whole map */
- memset(b, 0, (1 << BYTEWIDTH) / BYTEWIDTH + 2);
+ had_mbchar = 0;
+ had_char_class = 0;
- had_mbchar = 0;
- had_char_class = 0;
- /* Read in characters and ranges, setting map bits. */
- for (;;)
- {
- int size;
- unsigned last = (unsigned)-1;
-
- if ((size = EXTRACT_UNSIGNED(&b[(1 << BYTEWIDTH) / BYTEWIDTH]))) {
- /* Ensure the space is enough to hold another interval
- of multi-byte chars in charset(_not)?. */
- size = (1 << BYTEWIDTH) / BYTEWIDTH + 2 + size*8 + 8;
- while (b + size + 1 > bufp->buffer + bufp->allocated)
- EXTEND_BUFFER;
- }
- range_retry:
- PATFETCH(c);
+ /* charset_not matches newline according to a syntax bit. */
+ if ((enum regexpcode)b[-2] == charset_not) {
+ if (bufp->options & RE_OPTION_POSIXLINE)
+ SET_LIST_BIT ('\n');
+ }
- if (c == ']') {
- if (p == p0 + 1) {
- if (p == pend)
- goto invalid_pattern;
- }
- else
- /* Stop if this isn't merely a ] inside a bracket
- expression, but rather the end of a bracket
- expression. */
- break;
- }
- /* Look ahead to see if it's a range when the last thing
- was a character class. */
- if (had_char_class && c == '-' && *p != ']')
- goto invalid_pattern;
- if (ismbchar(c)) {
- PATFETCH_MBC(c);
- had_mbchar++;
- }
+ /* Read in characters and ranges, setting map bits. */
+ for (;;) {
+ int size;
+ unsigned last = (unsigned)-1;
+
+ if ((size = EXTRACT_UNSIGNED(&b[(1 << BYTEWIDTH) / BYTEWIDTH]))
+ || current_mbctype) {
+ /* Ensure the space is enough to hold another interval
+ of multi-byte chars in charset(_not)?. */
+ size = (1 << BYTEWIDTH) / BYTEWIDTH + 2 + size*8 + 8;
+ while (b + size + 1 > bufp->buffer + bufp->allocated)
+ EXTEND_BUFFER;
+ }
+ range_retry:
+ PATFETCH(c);
- /* \ escapes characters when inside [...]. */
- if (c == '\\') {
- PATFETCH(c);
- switch (c) {
- case 'w':
- for (c = 0; c < (1 << BYTEWIDTH); c++) {
- if (SYNTAX(c) == Sword ||
- (!current_mbctype && SYNTAX(c) == Sword2))
- SET_LIST_BIT(c);
- }
- last = -1;
- continue;
-
- case 'W':
- for (c = 0; c < (1 << BYTEWIDTH); c++) {
- if (SYNTAX(c) != Sword &&
- (current_mbctype || SYNTAX(c) != Sword2))
- SET_LIST_BIT(c);
- }
- if (current_mbctype) {
- set_list_bits(0x0, 0xffffffff, b);
- }
- last = -1;
- continue;
-
- case 's':
- for (c = 0; c < 256; c++)
- if (ISSPACE(c))
- SET_LIST_BIT(c);
- last = -1;
- continue;
-
- case 'S':
- for (c = 0; c < 256; c++)
- if (!ISSPACE(c))
- SET_LIST_BIT(c);
- if (current_mbctype) {
- set_list_bits(0, 0xffffffff, b);
- }
- last = -1;
- continue;
-
- case 'd':
- for (c = '0'; c <= '9'; c++)
- SET_LIST_BIT(c);
- last = -1;
- continue;
-
- case 'D':
- for (c = 0; c < 256; c++)
- if (!ISDIGIT(c))
- SET_LIST_BIT(c);
- if (current_mbctype) {
- set_list_bits(0, 0xffffffff, b);
- }
- last = -1;
- continue;
-
- case 'x':
- c = scan_hex(p, 2, &numlen);
- p += numlen;
- break;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- PATUNFETCH;
- c = scan_oct(p, 3, &numlen);
- p += numlen;
- break;
-
- default:
- if (ismbchar(c)) {
- PATFETCH_MBC(c);
- had_mbchar++;
- }
- break;
- }
- }
+ if (c == ']') {
+ if (p == p0 + 1) {
+ if (p == pend)
+ goto invalid_pattern;
+ }
+ else
+ /* Stop if this isn't merely a ] inside a bracket
+ expression, but rather the end of a bracket
+ expression. */
+ break;
+ }
+ /* Look ahead to see if it's a range when the last thing
+ was a character class. */
+ if (had_char_class && c == '-' && *p != ']')
+ goto invalid_pattern;
+ if (ismbchar(c)) {
+ PATFETCH_MBC(c);
+ had_mbchar++;
+ }
- /* Get a range. */
- if (range) {
- if (last > c)
- goto invalid_pattern;
+ /* \ escapes characters when inside [...]. */
+ if (c == '\\') {
+ PATFETCH_RAW(c);
+ switch (c) {
+ case 'w':
+ for (c = 0; c < (1 << BYTEWIDTH); c++) {
+ if (SYNTAX(c) == Sword ||
+ (!current_mbctype && SYNTAX(c) == Sword2))
+ SET_LIST_BIT(c);
+ }
+ if (current_mbctype) {
+ set_list_bits(0x80, 0xffffffff, b);
+ }
+ last = -1;
+ continue;
- range = 0;
- if (had_mbchar == 0) {
- for (;last<=c;last++)
- SET_LIST_BIT(last);
- }
- else if (had_mbchar == 2) {
- set_list_bits(last, c, b);
- }
- else {
- /* restriction: range between sbc and mbc */
- goto invalid_pattern;
- }
- }
- else if (p[0] == '-' && p[1] != ']') {
- last = c;
- PATFETCH(c1);
- range = 1;
- goto range_retry;
- }
- else if (c == '[' && *p == ':') {
- /* Leave room for the null. */
- char str[CHAR_CLASS_MAX_LENGTH + 1];
-
- PATFETCH_RAW (c);
- c1 = 0;
-
- /* If pattern is `[[:'. */
- if (p == pend)
- goto invalid_pattern;
-
- for (;;) {
- PATFETCH (c);
- if (c == ':' || c == ']' || p == pend
- || c1 == CHAR_CLASS_MAX_LENGTH)
- break;
- str[c1++] = c;
- }
- str[c1] = '\0';
-
- /* If isn't a word bracketed by `[:' and:`]':
- undo the ending character, the letters, and leave
- the leading `:' and `[' (but set bits for them). */
- if (c == ':' && *p == ']') {
- int ch;
- char is_alnum = STREQ(str, "alnum");
- char is_alpha = STREQ(str, "alpha");
- char is_blank = STREQ(str, "blank");
- char is_cntrl = STREQ(str, "cntrl");
- char is_digit = STREQ(str, "digit");
- char is_graph = STREQ(str, "graph");
- char is_lower = STREQ(str, "lower");
- char is_print = STREQ(str, "print");
- char is_punct = STREQ(str, "punct");
- char is_space = STREQ(str, "space");
- char is_upper = STREQ(str, "upper");
- char is_xdigit = STREQ(str, "xdigit");
-
- if (!IS_CHAR_CLASS (str))
- goto invalid_pattern;
-
- /* Throw away the ] at the end of the character class. */
- PATFETCH (c);
-
- if (p == pend)
- goto invalid_pattern;
-
- for (ch = 0; ch < 1 << BYTEWIDTH; ch++) {
- if ( (is_alnum && ISALNUM(ch))
- || (is_alpha && ISALPHA(ch))
- || (is_blank && ISBLANK(ch))
- || (is_cntrl && ISCNTRL(ch))
- || (is_digit && ISDIGIT(ch))
- || (is_graph && ISGRAPH(ch))
- || (is_lower && ISLOWER(ch))
- || (is_print && ISPRINT(ch))
- || (is_punct && ISPUNCT(ch))
- || (is_space && ISSPACE(ch))
- || (is_upper && ISUPPER(ch))
- || (is_xdigit && ISXDIGIT(ch)))
- SET_LIST_BIT (ch);
- }
- had_char_class = 1;
- }
- else {
- c1++;
- while (c1--)
- PATUNFETCH;
- SET_LIST_BIT(translate?translate['[']:'[');
- SET_LIST_BIT(translate?translate[':']:':');
- had_char_class = 0;
- last = ':';
- }
- }
- else if (had_mbchar == 0)
+ case 'W':
+ for (c = 0; c < (1 << BYTEWIDTH); c++) {
+ if (SYNTAX(c) != Sword &&
+ (current_mbctype || SYNTAX(c) != Sword2))
SET_LIST_BIT(c);
- else
- set_list_bits(c, c, b);
- had_mbchar = 0;
}
+ last = -1;
+ continue;
- /* Discard any character set/class bitmap bytes that are all
- 0 at the end of the map. Decrement the map-length byte too. */
- while ((int)b[-1] > 0 && b[b[-1] - 1] == 0)
- b[-1]--;
- if (b[-1] != (1 << BYTEWIDTH) / BYTEWIDTH)
- memmove(&b[b[-1]], &b[(1 << BYTEWIDTH) / BYTEWIDTH],
- 2 + EXTRACT_UNSIGNED (&b[(1 << BYTEWIDTH) / BYTEWIDTH])*8);
- b += b[-1] + 2 + EXTRACT_UNSIGNED (&b[b[-1]])*8;
- break;
-
- case '(':
- PATFETCH(c);
- if (c == '?') {
- int negative = 0;
- PATFETCH_RAW(c);
- switch (c) {
- case 'x': case 'i': case '-':
- for (;;) {
- switch (c) {
- case '-':
- negative = 1;
- break;
-
- case ':':
- case ')':
- break;
-
- case 'x':
- if (negative)
- options &= ~RE_OPTION_EXTENDED;
- else
- options |= RE_OPTION_EXTENDED;
- break;
- case 'i':
- if (negative) {
- if (options&RE_OPTION_IGNORECASE) {
- options &= ~RE_OPTION_IGNORECASE;
- BUFPUSH(casefold_off);
- }
- }
- else if (!(options&RE_OPTION_IGNORECASE)) {
- options |= RE_OPTION_IGNORECASE;
- BUFPUSH(casefold_on);
- }
- break;
-
- default:
- FREE_AND_RETURN(stackb, "undefined (?...) inline option");
- }
- if (c == ')') {
- c = '#'; /* read whole in-line options */
- break;
- }
- if (c == ':') break;
- PATFETCH_RAW(c);
- }
- break;
+ case 's':
+ for (c = 0; c < 256; c++)
+ if (ISSPACE(c))
+ SET_LIST_BIT(c);
+ last = -1;
+ continue;
- case '#':
- for (;;) {
- PATFETCH(c);
- if (c == ')') break;
- }
- c = '#';
- break;
+ case 'S':
+ for (c = 0; c < 256; c++)
+ if (!ISSPACE(c))
+ SET_LIST_BIT(c);
+ if (current_mbctype)
+ set_list_bits(0x80, 0xffffffff, b);
+ last = -1;
+ continue;
+
+ case 'd':
+ for (c = '0'; c <= '9'; c++)
+ SET_LIST_BIT(c);
+ last = -1;
+ continue;
+
+ case 'D':
+ for (c = 0; c < 256; c++)
+ if (!ISDIGIT(c))
+ SET_LIST_BIT(c);
+ if (current_mbctype)
+ set_list_bits(0x80, 0xffffffff, b);
+ last = -1;
+ continue;
+
+ case 'x':
+ c = scan_hex(p, 2, &numlen);
+ p += numlen;
+ break;
- case ':':
- case '=':
- case '!':
- break;
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ PATUNFETCH;
+ c = scan_oct(p, 3, &numlen);
+ p += numlen;
+ break;
- default:
- FREE_AND_RETURN(stackb, "undefined (?...) sequence");
+ default:
+ c = read_backslash(c);
+ if (ismbchar(c)) {
+ PATFETCH_MBC(c);
+ had_mbchar++;
}
+ break;
}
- else {
- PATUNFETCH;
- c = '(';
+ }
+
+ /* Get a range. */
+ if (range) {
+ if (last > c)
+ goto invalid_pattern;
+
+ range = 0;
+ if (had_mbchar == 0) {
+ for (;last<=c;last++)
+ SET_LIST_BIT(last);
}
- if (c == '#') break;
- if (stackp+8 >= stacke) {
- int *stackx;
- unsigned int len = stacke - stackb;
-
- stackx = DOUBLE_STACK(stackx,stackb,len,int);
- /* Rearrange the pointers. */
- stackp = stackx + (stackp - stackb);
- stackb = stackx;
- stacke = stackb + 2 * len;
+ else if (had_mbchar == 2) {
+ set_list_bits(last, c, b);
}
+ else {
+ /* restriction: range between sbc and mbc */
+ goto invalid_pattern;
+ }
+ }
+ else if (p[0] == '-' && p[1] != ']') {
+ last = c;
+ PATFETCH(c1);
+ range = 1;
+ goto range_retry;
+ }
+ else if (c == '[' && *p == ':') {
+ /* Leave room for the null. */
+ char str[CHAR_CLASS_MAX_LENGTH + 1];
- /* Laststart should point to the start_memory that we are about
- to push (unless the pattern has RE_NREGS or more ('s). */
- /* obsolete: now RE_NREGS is just a default register size. */
- *stackp++ = b - bufp->buffer;
- *stackp++ = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
- *stackp++ = begalt - bufp->buffer;
- switch (c) {
- case '(':
- BUFPUSH(start_memory);
- BUFPUSH(regnum);
- *stackp++ = regnum++;
- *stackp++ = b - bufp->buffer;
- BUFPUSH(0);
- /* too many ()'s to fit in a byte. (max 254) */
- if (regnum >= RE_REG_MAX) goto too_big;
- break;
+ PATFETCH_RAW (c);
+ c1 = 0;
- case '=':
- case '!':
- BUFPUSH(start_nowidth);
- *stackp++ = b - bufp->buffer;
- BUFPUSH(0); /* temporary value */
- BUFPUSH(0);
- if (c == '=') break;
-
- BUFPUSH(on_failure_jump);
- *stackp++ = b - bufp->buffer;
- BUFPUSH(0); /* temporary value */
- BUFPUSH(0);
- break;
+ /* If pattern is `[[:'. */
+ if (p == pend)
+ goto invalid_pattern;
- case ':':
- pending_exact = 0;
- default:
+ for (;;) {
+ PATFETCH (c);
+ if (c == ':' || c == ']' || p == pend
+ || c1 == CHAR_CLASS_MAX_LENGTH)
break;
+ str[c1++] = c;
}
- *stackp++ = c;
- *stackp++ = options;
- fixup_alt_jump = 0;
- laststart = 0;
- begalt = b;
- break;
-
- case ')':
- if (stackp == stackb)
- FREE_AND_RETURN(stackb, "unmatched )");
- if ((options ^ stackp[-1]) & RE_OPTION_IGNORECASE) {
- BUFPUSH((options&RE_OPTION_IGNORECASE)?casefold_off:casefold_on);
+ str[c1] = '\0';
+
+ /* If isn't a word bracketed by `[:' and:`]':
+ undo the ending character, the letters, and leave
+ the leading `:' and `[' (but set bits for them). */
+ if (c == ':' && *p == ']') {
+ int ch;
+ char is_alnum = STREQ(str, "alnum");
+ char is_alpha = STREQ(str, "alpha");
+ char is_blank = STREQ(str, "blank");
+ char is_cntrl = STREQ(str, "cntrl");
+ char is_digit = STREQ(str, "digit");
+ char is_graph = STREQ(str, "graph");
+ char is_lower = STREQ(str, "lower");
+ char is_print = STREQ(str, "print");
+ char is_punct = STREQ(str, "punct");
+ char is_space = STREQ(str, "space");
+ char is_upper = STREQ(str, "upper");
+ char is_xdigit = STREQ(str, "xdigit");
+
+ if (!IS_CHAR_CLASS (str))
+ goto invalid_pattern;
+
+ /* Throw away the ] at the end of the character class. */
+ PATFETCH (c);
+
+ if (p == pend)
+ goto invalid_pattern;
+
+ for (ch = 0; ch < 1 << BYTEWIDTH; ch++) {
+ if ( (is_alnum && ISALNUM(ch))
+ || (is_alpha && ISALPHA(ch))
+ || (is_blank && ISBLANK(ch))
+ || (is_cntrl && ISCNTRL(ch))
+ || (is_digit && ISDIGIT(ch))
+ || (is_graph && ISGRAPH(ch))
+ || (is_lower && ISLOWER(ch))
+ || (is_print && ISPRINT(ch))
+ || (is_punct && ISPUNCT(ch))
+ || (is_space && ISSPACE(ch))
+ || (is_upper && ISUPPER(ch))
+ || (is_xdigit && ISXDIGIT(ch)))
+ SET_LIST_BIT (ch);
+ }
+ had_char_class = 1;
}
- pending_exact = 0;
- if (fixup_alt_jump)
- { /* Push a dummy failure point at the end of the
- alternative for a possible future
- `finalize_jump' to pop. See comments at
- `push_dummy_failure' in `re_match'. */
- BUFPUSH(push_dummy_failure);
-
- /* We allocated space for this jump when we assigned
- to `fixup_alt_jump', in the `handle_alt' case below. */
- store_jump(fixup_alt_jump, jump, b);
+ else {
+ c1++;
+ while (c1--)
+ PATUNFETCH;
+ SET_LIST_BIT(TRANSLATE_P()?translate['[']:'[');
+ SET_LIST_BIT(TRANSLATE_P()?translate[':']:':');
+ had_char_class = 0;
+ last = ':';
}
- options = *--stackp;
- switch (c = *--stackp) {
- case '(':
- {
- char *loc = bufp->buffer + *--stackp;
- *loc = regnum - stackp[-1];
- BUFPUSH(stop_memory);
- BUFPUSH(stackp[-1]);
- BUFPUSH(regnum - stackp[-1]);
- stackp--;
- }
- break;
+ }
+ else if (had_mbchar == 0)
+ SET_LIST_BIT(c);
+ else
+ set_list_bits(c, c, b);
+ had_mbchar = 0;
+ }
- case '!':
- BUFPUSH(pop_and_fail);
- /* back patch */
- STORE_NUMBER(bufp->buffer+stackp[-1], b - bufp->buffer - stackp[-1] - 2);
- stackp--;
- /* fall through */
- case '=':
- BUFPUSH(stop_nowidth);
- /* tell stack-pos place to start_nowidth */
- STORE_NUMBER(bufp->buffer+stackp[-1], b - bufp->buffer - stackp[-1] - 2);
- BUFPUSH(0); /* space to hold stack pos */
- BUFPUSH(0);
- stackp--;
+ /* Discard any character set/class bitmap bytes that are all
+ 0 at the end of the map. Decrement the map-length byte too. */
+ while ((int)b[-1] > 0 && b[b[-1] - 1] == 0)
+ b[-1]--;
+ if (b[-1] != (1 << BYTEWIDTH) / BYTEWIDTH)
+ memmove(&b[b[-1]], &b[(1 << BYTEWIDTH) / BYTEWIDTH],
+ 2 + EXTRACT_UNSIGNED (&b[(1 << BYTEWIDTH) / BYTEWIDTH])*8);
+ b += b[-1] + 2 + EXTRACT_UNSIGNED (&b[b[-1]])*8;
+ break;
+
+ case '(':
+ PATFETCH(c);
+ if (c == '?') {
+ int negative = 0;
+ PATFETCH_RAW(c);
+ switch (c) {
+ case 'x': case 'p': case 'i': case '-':
+ for (;;) {
+ switch (c) {
+ case '-':
+ negative = 1;
break;
case ':':
- BUFPUSH(stop_paren);
+ case ')':
+ break;
+
+ case 'x':
+ if (negative)
+ options &= ~RE_OPTION_EXTENDED;
+ else
+ options |= RE_OPTION_EXTENDED;
+ break;
+ case 'p':
+ if (negative) {
+ if (options&RE_OPTION_POSIXLINE) {
+ options &= ~RE_OPTION_POSIXLINE;
+ BUFPUSH(posix_off);
+ }
+ }
+ else if (!(options&RE_OPTION_POSIXLINE)) {
+ options |= RE_OPTION_POSIXLINE;
+ BUFPUSH(posix_on);
+ }
+ break;
+ case 'i':
+ if (negative) {
+ if (options&RE_OPTION_IGNORECASE) {
+ options &= ~RE_OPTION_IGNORECASE;
+ BUFPUSH(casefold_off);
+ }
+ }
+ else if (!(options&RE_OPTION_IGNORECASE)) {
+ options |= RE_OPTION_IGNORECASE;
+ BUFPUSH(casefold_on);
+ }
break;
default:
+ FREE_AND_RETURN(stackb, "undefined (?...) inline option");
+ }
+ if (c == ')') {
+ c = '#'; /* read whole in-line options */
break;
+ }
+ if (c == ':') break;
+ PATFETCH_RAW(c);
}
- begalt = *--stackp + bufp->buffer;
- stackp--;
- fixup_alt_jump = *stackp ? *stackp + bufp->buffer - 1 : 0;
- laststart = *--stackp + bufp->buffer;
- if (c == '!' || c == '=') laststart = b;
break;
- case '|':
- /* Insert before the previous alternative a jump which
- jumps to this alternative if the former fails. */
- GET_BUFFER_SPACE(3);
- insert_jump(on_failure_jump, begalt, b + 6, b);
- pending_exact = 0;
- b += 3;
- /* The alternative before this one has a jump after it
- which gets executed if it gets matched. Adjust that
- jump so it will jump to this alternative's analogous
- jump (put in below, which in turn will jump to the next
- (if any) alternative's such jump, etc.). The last such
- jump jumps to the correct final destination. A picture:
- _____ _____
- | | | |
- | v | v
- a | b | c
-
- If we are at `b', then fixup_alt_jump right now points to a
- three-byte space after `a'. We'll put in the jump, set
- fixup_alt_jump to right after `b', and leave behind three
- bytes which we'll fill in when we get to after `c'. */
-
- if (fixup_alt_jump)
- store_jump(fixup_alt_jump, jump_past_alt, b);
-
- /* Mark and leave space for a jump after this alternative,
- to be filled in later either by next alternative or
- when know we're at the end of a series of alternatives. */
- fixup_alt_jump = b;
- GET_BUFFER_SPACE(3);
- b += 3;
+ case '#':
+ for (;;) {
+ PATFETCH(c);
+ if (c == ')') break;
+ }
+ c = '#';
+ break;
- laststart = 0;
- begalt = b;
+ case ':':
+ case '=':
+ case '!':
break;
- case '{':
- /* If there is no previous pattern, this isn't an interval. */
- if (!laststart || p == pend)
- {
- goto normal_char;
- }
+ default:
+ FREE_AND_RETURN(stackb, "undefined (?...) sequence");
+ }
+ }
+ else {
+ PATUNFETCH;
+ c = '(';
+ }
+ if (c == '#') break;
+ if (stackp+8 >= stacke) {
+ int *stackx;
+ unsigned int len = stacke - stackb;
+
+ stackx = DOUBLE_STACK(stackx,stackb,len,int);
+ /* Rearrange the pointers. */
+ stackp = stackx + (stackp - stackb);
+ stackb = stackx;
+ stacke = stackb + 2 * len;
+ }
- beg_interval = p - 1;
+ /* Laststart should point to the start_memory that we are about
+ to push (unless the pattern has RE_NREGS or more ('s). */
+ /* obsolete: now RE_NREGS is just a default register size. */
+ *stackp++ = b - bufp->buffer;
+ *stackp++ = fixup_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0;
+ *stackp++ = begalt - bufp->buffer;
+ switch (c) {
+ case '(':
+ BUFPUSH(start_memory);
+ BUFPUSH(regnum);
+ *stackp++ = regnum++;
+ *stackp++ = b - bufp->buffer;
+ BUFPUSH(0);
+ /* too many ()'s to fit in a byte. (max 254) */
+ if (regnum >= RE_REG_MAX) goto too_big;
+ break;
- lower_bound = -1; /* So can see if are set. */
- upper_bound = -1;
- GET_UNSIGNED_NUMBER(lower_bound);
- if (c == ',') {
- GET_UNSIGNED_NUMBER(upper_bound);
- }
- else
- /* Interval such as `{1}' => match exactly once. */
- upper_bound = lower_bound;
+ case '=':
+ case '!':
+ BUFPUSH(start_nowidth);
+ *stackp++ = b - bufp->buffer;
+ BUFPUSH(0); /* temporary value */
+ BUFPUSH(0);
+ if (c == '=') break;
+
+ BUFPUSH(on_failure_jump);
+ *stackp++ = b - bufp->buffer;
+ BUFPUSH(0); /* temporary value */
+ BUFPUSH(0);
+ break;
+
+ case ':':
+ BUFPUSH(start_paren);
+ pending_exact = 0;
+ default:
+ break;
+ }
+ *stackp++ = c;
+ *stackp++ = options;
+ fixup_alt_jump = 0;
+ laststart = 0;
+ begalt = b;
+ break;
+
+ case ')':
+ if (stackp == stackb)
+ FREE_AND_RETURN(stackb, "unmatched )");
+ if ((options ^ stackp[-1]) & RE_OPTION_IGNORECASE) {
+ BUFPUSH((options&RE_OPTION_IGNORECASE)?casefold_off:casefold_on);
+ }
+ if ((options ^ stackp[-1]) & RE_OPTION_POSIXLINE) {
+ BUFPUSH((options&RE_OPTION_POSIXLINE)?posix_off:posix_on);
+ }
+ pending_exact = 0;
+ if (fixup_alt_jump) {
+ /* Push a dummy failure point at the end of the
+ alternative for a possible future
+ `finalize_jump' to pop. See comments at
+ `push_dummy_failure' in `re_match'. */
+ BUFPUSH(push_dummy_failure);
+
+ /* We allocated space for this jump when we assigned
+ to `fixup_alt_jump', in the `handle_alt' case below. */
+ store_jump(fixup_alt_jump, jump, b);
+ }
+ p0 = b;
+ options = *--stackp;
+ switch (c = *--stackp) {
+ case '(':
+ {
+ char *loc = bufp->buffer + *--stackp;
+ *loc = regnum - stackp[-1];
+ BUFPUSH(stop_memory);
+ BUFPUSH(stackp[-1]);
+ BUFPUSH(regnum - stackp[-1]);
+ stackp--;
+ }
+ break;
- if (lower_bound < 0 || c != '}')
- goto unfetch_interval;
+ case '!':
+ BUFPUSH(pop_and_fail);
+ /* back patch */
+ STORE_NUMBER(bufp->buffer+stackp[-1], b - bufp->buffer - stackp[-1] - 2);
+ stackp--;
+ /* fall through */
+ case '=':
+ BUFPUSH(stop_nowidth);
+ /* tell stack-pos place to start_nowidth */
+ STORE_NUMBER(bufp->buffer+stackp[-1], b - bufp->buffer - stackp[-1] - 2);
+ BUFPUSH(0); /* space to hold stack pos */
+ BUFPUSH(0);
+ stackp--;
+ break;
- if (lower_bound >= RE_DUP_MAX || upper_bound >= RE_DUP_MAX)
- FREE_AND_RETURN(stackb, "too big quantifier in {,}");
- if (upper_bound < 0) upper_bound = RE_DUP_MAX;
- if (lower_bound > upper_bound)
- FREE_AND_RETURN(stackb, "can't do {n,m} with n > m");
+ case ':':
+ BUFPUSH(stop_paren);
+ break;
- beg_interval = 0;
- pending_exact = 0;
+ default:
+ break;
+ }
+ begalt = *--stackp + bufp->buffer;
+ stackp--;
+ fixup_alt_jump = *stackp ? *stackp + bufp->buffer - 1 : 0;
+ laststart = *--stackp + bufp->buffer;
+ if (c == '!' || c == '=') laststart = b;
+ break;
- greedy = 1;
- if (p != pend) {
- PATFETCH(c);
- if (c == '?') greedy = 0;
- else PATUNFETCH;
- }
+ case '|':
+ /* Insert before the previous alternative a jump which
+ jumps to this alternative if the former fails. */
+ GET_BUFFER_SPACE(3);
+ insert_jump(on_failure_jump, begalt, b + 6, b);
+ pending_exact = 0;
+ b += 3;
+ /* The alternative before this one has a jump after it
+ which gets executed if it gets matched. Adjust that
+ jump so it will jump to this alternative's analogous
+ jump (put in below, which in turn will jump to the next
+ (if any) alternative's such jump, etc.). The last such
+ jump jumps to the correct final destination. A picture:
+ _____ _____
+ | | | |
+ | v | v
+ a | b | c
+
+ If we are at `b', then fixup_alt_jump right now points to a
+ three-byte space after `a'. We'll put in the jump, set
+ fixup_alt_jump to right after `b', and leave behind three
+ bytes which we'll fill in when we get to after `c'. */
+
+ if (fixup_alt_jump)
+ store_jump(fixup_alt_jump, jump_past_alt, b);
+
+ /* Mark and leave space for a jump after this alternative,
+ to be filled in later either by next alternative or
+ when know we're at the end of a series of alternatives. */
+ fixup_alt_jump = b;
+ GET_BUFFER_SPACE(3);
+ b += 3;
+
+ laststart = 0;
+ begalt = b;
+ break;
- if (lower_bound == 0) {
- zero_times_ok = 1;
- if (upper_bound == RE_DUP_MAX) {
- many_times_ok = 1;
- goto repeat;
- }
- if (upper_bound == 1) {
- many_times_ok = 0;
- goto repeat;
- }
- }
- if (lower_bound == 1) {
- if (upper_bound == 1) {
- /* No need to repeat */
- break;
- }
- if (upper_bound == RE_DUP_MAX) {
- many_times_ok = 1;
- zero_times_ok = 0;
- goto repeat;
- }
- }
+ case '{':
+ /* If there is no previous pattern, this is an invalid pattern. */
+ if (!laststart || p == pend) {
+ goto invalid_pattern;
+ }
- /* If upper_bound is zero, don't want to succeed at all;
- jump from laststart to b + 3, which will be the end of
- the buffer after this jump is inserted. */
+ beg_interval = p - 1;
- if (upper_bound == 0) {
- GET_BUFFER_SPACE(3);
- insert_jump(jump, laststart, b + 3, b);
- b += 3;
- break;
- }
+ lower_bound = -1; /* So can see if are set. */
+ upper_bound = -1;
+ GET_UNSIGNED_NUMBER(lower_bound);
+ if (c == ',') {
+ GET_UNSIGNED_NUMBER(upper_bound);
+ }
+ else
+ /* Interval such as `{1}' => match exactly once. */
+ upper_bound = lower_bound;
+
+ if (lower_bound < 0 || c != '}')
+ goto unfetch_interval;
+
+ if (lower_bound >= RE_DUP_MAX || upper_bound >= RE_DUP_MAX)
+ FREE_AND_RETURN(stackb, "too big quantifier in {,}");
+ if (upper_bound < 0) upper_bound = RE_DUP_MAX;
+ if (lower_bound > upper_bound)
+ FREE_AND_RETURN(stackb, "can't do {n,m} with n > m");
+
+ beg_interval = 0;
+ pending_exact = 0;
+
+ greedy = 1;
+ if (p != pend) {
+ PATFETCH(c);
+ if (c == '?') greedy = 0;
+ else PATUNFETCH;
+ }
- /* Otherwise, we have a nontrivial interval. When
- we're all done, the pattern will look like:
- set_number_at <jump count> <upper bound>
- set_number_at <succeed_n count> <lower bound>
- succeed_n <after jump addr> <succed_n count>
- <body of loop>
- jump_n <succeed_n addr> <jump count>
- (The upper bound and `jump_n' are omitted if
- `upper_bound' is 1, though.) */
- { /* If the upper bound is > 1, we need to insert
- more at the end of the loop. */
- unsigned nbytes = upper_bound == 1 ? 10 : 20;
-
- GET_BUFFER_SPACE(nbytes);
- /* Initialize lower bound of the `succeed_n', even
- though it will be set during matching by its
- attendant `set_number_at' (inserted next),
- because `re_compile_fastmap' needs to know.
- Jump to the `jump_n' we might insert below. */
- insert_jump_n(succeed_n, laststart, b + (nbytes/2),
- b, lower_bound);
- b += 5; /* Just increment for the succeed_n here. */
-
- /* Code to initialize the lower bound. Insert
- before the `succeed_n'. The `5' is the last two
- bytes of this `set_number_at', plus 3 bytes of
- the following `succeed_n'. */
- insert_op_2(set_number_at, laststart, b, 5, lower_bound);
- b += 5;
-
- if (upper_bound > 1)
- { /* More than one repetition is allowed, so
- append a backward jump to the `succeed_n'
- that starts this interval.
-
- When we've reached this during matching,
- we'll have matched the interval once, so
- jump back only `upper_bound - 1' times. */
- GET_BUFFER_SPACE(5);
- store_jump_n(b, greedy?jump_n:finalize_push_n, laststart + 5,
- upper_bound - 1);
- b += 5;
-
- /* The location we want to set is the second
- parameter of the `jump_n'; that is `b-2' as
- an absolute address. `laststart' will be
- the `set_number_at' we're about to insert;
- `laststart+3' the number to set, the source
- for the relative address. But we are
- inserting into the middle of the pattern --
- so everything is getting moved up by 5.
- Conclusion: (b - 2) - (laststart + 3) + 5,
- i.e., b - laststart.
-
- We insert this at the beginning of the loop
- so that if we fail during matching, we'll
- reinitialize the bounds. */
- insert_op_2(set_number_at, laststart, b, b - laststart,
- upper_bound - 1);
- b += 5;
- }
- }
+ if (lower_bound == 0) {
+ zero_times_ok = 1;
+ if (upper_bound == RE_DUP_MAX) {
+ many_times_ok = 1;
+ goto repeat;
+ }
+ if (upper_bound == 1) {
+ many_times_ok = 0;
+ goto repeat;
+ }
+ }
+ if (lower_bound == 1) {
+ if (upper_bound == 1) {
+ /* No need to repeat */
break;
+ }
+ if (upper_bound == RE_DUP_MAX) {
+ many_times_ok = 1;
+ zero_times_ok = 0;
+ goto repeat;
+ }
+ }
- unfetch_interval:
- /* If an invalid interval, match the characters as literals. */
- p = beg_interval;
- beg_interval = 0;
+ /* If upper_bound is zero, don't want to succeed at all;
+ jump from laststart to b + 3, which will be the end of
+ the buffer after this jump is inserted. */
- /* normal_char and normal_backslash need `c'. */
- PATFETCH (c);
- goto normal_char;
+ if (upper_bound == 0) {
+ GET_BUFFER_SPACE(3);
+ insert_jump(jump, laststart, b + 3, b);
+ b += 3;
+ break;
+ }
- case '\\':
- if (p == pend) goto invalid_pattern;
- /* Do not translate the character after the \, so that we can
- distinguish, e.g., \B from \b, even if we normally would
- translate, e.g., B to b. */
- PATFETCH_RAW(c);
- switch (c)
- {
- case 's':
- case 'S':
- case 'd':
- case 'D':
- while (b - bufp->buffer + 9 + (1 << BYTEWIDTH) / BYTEWIDTH
- > bufp->allocated)
- EXTEND_BUFFER;
-
- laststart = b;
- if (c == 's' || c == 'd') {
- BUFPUSH(charset);
- }
- else {
- BUFPUSH(charset_not);
- }
+ /* If lower_bound == upper_bound, repeat cound can be removed */
+ if (lower_bound == upper_bound) {
+ int mcnt;
+ int skip_stop_paren = 0;
- BUFPUSH((1 << BYTEWIDTH) / BYTEWIDTH);
- memset(b, 0, (1 << BYTEWIDTH) / BYTEWIDTH + 2);
- if (c == 's' || c == 'S') {
- SET_LIST_BIT(' ');
- SET_LIST_BIT('\t');
- SET_LIST_BIT('\n');
- SET_LIST_BIT('\r');
- SET_LIST_BIT('\f');
- }
- else {
- char cc;
+ if (b[-1] == stop_paren) {
+ skip_stop_paren = 1;
+ b--;
+ }
- for (cc = '0'; cc <= '9'; cc++) {
- SET_LIST_BIT(cc);
- }
- }
+ if (*laststart == exactn && laststart[1]+2 == b - laststart
+ && laststart[1]*lower_bound < 256) {
+ mcnt = laststart[1];
+ GET_BUFFER_SPACE((lower_bound-1)*mcnt);
+ laststart[1] = lower_bound*mcnt;
+ while (--lower_bound) {
+ memcpy(b, laststart+2, mcnt);
+ b += mcnt;
+ }
+ if (skip_stop_paren) BUFPUSH(stop_paren);
+ break;
+ }
- while ((int)b[-1] > 0 && b[b[-1] - 1] == 0)
- b[-1]--;
- if (b[-1] != (1 << BYTEWIDTH) / BYTEWIDTH)
- memmove(&b[b[-1]], &b[(1 << BYTEWIDTH) / BYTEWIDTH],
- 2 + EXTRACT_UNSIGNED(&b[(1 << BYTEWIDTH) / BYTEWIDTH])*8);
- b += b[-1] + 2 + EXTRACT_UNSIGNED(&b[b[-1]])*8;
- break;
+ if (lower_bound < 5 && b - laststart < 10) {
+ /* 5 and 10 are the magic numbers */
- case 'w':
- laststart = b;
- BUFPUSH(wordchar);
- break;
+ mcnt = b - laststart;
+ GET_BUFFER_SPACE((lower_bound-1)*mcnt);
+ while (--lower_bound) {
+ memcpy(b, laststart, mcnt);
+ b += mcnt;
+ }
+ if (skip_stop_paren) BUFPUSH(stop_paren);
+ break;
+ }
+ if (skip_stop_paren) b++; /* push back stop_paren */
+ }
- case 'W':
- laststart = b;
- BUFPUSH(notwordchar);
- break;
+ /* Otherwise, we have a nontrivial interval. When
+ we're all done, the pattern will look like:
+ set_number_at <jump count> <upper bound>
+ set_number_at <succeed_n count> <lower bound>
+ succeed_n <after jump addr> <succed_n count>
+ <body of loop>
+ jump_n <succeed_n addr> <jump count>
+ (The upper bound and `jump_n' are omitted if
+ `upper_bound' is 1, though.) */
+ { /* If the upper bound is > 1, we need to insert
+ more at the end of the loop. */
+ unsigned nbytes = upper_bound == 1 ? 10 : 20;
+
+ GET_BUFFER_SPACE(nbytes);
+ /* Initialize lower bound of the `succeed_n', even
+ though it will be set during matching by its
+ attendant `set_number_at' (inserted next),
+ because `re_compile_fastmap' needs to know.
+ Jump to the `jump_n' we might insert below. */
+ insert_jump_n(succeed_n, laststart, b + (nbytes/2),
+ b, lower_bound);
+ b += 5; /* Just increment for the succeed_n here. */
+
+ /* Code to initialize the lower bound. Insert
+ before the `succeed_n'. The `5' is the last two
+ bytes of this `set_number_at', plus 3 bytes of
+ the following `succeed_n'. */
+ insert_op_2(set_number_at, laststart, b, 5, lower_bound);
+ b += 5;
+
+ if (upper_bound > 1) {
+ /* More than one repetition is allowed, so
+ append a backward jump to the `succeed_n'
+ that starts this interval.
+
+ When we've reached this during matching,
+ we'll have matched the interval once, so
+ jump back only `upper_bound - 1' times. */
+ GET_BUFFER_SPACE(5);
+ store_jump_n(b, greedy?jump_n:finalize_push_n, laststart + 5,
+ upper_bound - 1);
+ b += 5;
+
+ /* The location we want to set is the second
+ parameter of the `jump_n'; that is `b-2' as
+ an absolute address. `laststart' will be
+ the `set_number_at' we're about to insert;
+ `laststart+3' the number to set, the source
+ for the relative address. But we are
+ inserting into the middle of the pattern --
+ so everything is getting moved up by 5.
+ Conclusion: (b - 2) - (laststart + 3) + 5,
+ i.e., b - laststart.
+
+ We insert this at the beginning of the loop
+ so that if we fail during matching, we'll
+ reinitialize the bounds. */
+ insert_op_2(set_number_at, laststart, b, b - laststart,
+ upper_bound - 1);
+ b += 5;
+ }
+ }
+ break;
- case '<':
- BUFPUSH(wordbeg);
- break;
+ unfetch_interval:
+ /* If an invalid interval, match the characters as literals. */
+ p = beg_interval;
+ beg_interval = 0;
+
+ /* normal_char and normal_backslash need `c'. */
+ PATFETCH (c);
+ goto normal_char;
+
+ case '\\':
+ if (p == pend) goto invalid_pattern;
+ /* Do not translate the character after the \, so that we can
+ distinguish, e.g., \B from \b, even if we normally would
+ translate, e.g., B to b. */
+ PATFETCH_RAW(c);
+ switch (c) {
+ case 's':
+ case 'S':
+ case 'd':
+ case 'D':
+ while (b - bufp->buffer + 9 + (1 << BYTEWIDTH) / BYTEWIDTH
+ > bufp->allocated)
+ EXTEND_BUFFER;
+
+ laststart = b;
+ if (c == 's' || c == 'd') {
+ BUFPUSH(charset);
+ }
+ else {
+ BUFPUSH(charset_not);
+ }
- case '>':
- BUFPUSH(wordend);
- break;
+ BUFPUSH((1 << BYTEWIDTH) / BYTEWIDTH);
+ memset(b, 0, (1 << BYTEWIDTH) / BYTEWIDTH + 2);
+ if (c == 's' || c == 'S') {
+ SET_LIST_BIT(' ');
+ SET_LIST_BIT('\t');
+ SET_LIST_BIT('\n');
+ SET_LIST_BIT('\r');
+ SET_LIST_BIT('\f');
+ }
+ else {
+ char cc;
- case 'b':
- BUFPUSH(wordbound);
- break;
+ for (cc = '0'; cc <= '9'; cc++) {
+ SET_LIST_BIT(cc);
+ }
+ }
- case 'B':
- BUFPUSH(notwordbound);
- break;
+ while ((int)b[-1] > 0 && b[b[-1] - 1] == 0)
+ b[-1]--;
+ if (b[-1] != (1 << BYTEWIDTH) / BYTEWIDTH)
+ memmove(&b[b[-1]], &b[(1 << BYTEWIDTH) / BYTEWIDTH],
+ 2 + EXTRACT_UNSIGNED(&b[(1 << BYTEWIDTH) / BYTEWIDTH])*8);
+ b += b[-1] + 2 + EXTRACT_UNSIGNED(&b[b[-1]])*8;
+ break;
- case 'A':
- BUFPUSH(begbuf);
- break;
+ case 'w':
+ laststart = b;
+ BUFPUSH(wordchar);
+ break;
- case 'Z':
- BUFPUSH(endbuf2);
- break;
+ case 'W':
+ laststart = b;
+ BUFPUSH(notwordchar);
+ break;
- case 'z':
- BUFPUSH(endbuf);
- break;
+ case '<':
+ BUFPUSH(wordbeg);
+ break;
- /* hex */
- case 'x':
- had_mbchar = 0;
- c = scan_hex(p, 2, &numlen);
- p += numlen;
- goto numeric_char;
-
- /* octal */
- case '0':
- had_mbchar = 0;
- c = scan_oct(p, 3, &numlen);
- p += numlen;
- goto numeric_char;
-
- /* back-ref or octal */
- case '1': case '2': case '3':
- case '4': case '5': case '6':
- case '7': case '8': case '9':
- {
- char *p_save;
-
- PATUNFETCH;
- p_save = p;
-
- had_mbchar = 0;
- GET_UNSIGNED_NUMBER(c1);
- if (!ISDIGIT(c)) PATUNFETCH;
-
- if (c1 >= regnum) {
- /* need to get octal */
- p = p_save;
- c = scan_oct(p_save, 3, &numlen) & 0xff;
- p = p_save + numlen;
- c1 = 0;
- goto numeric_char;
- }
- }
+ case '>':
+ BUFPUSH(wordend);
+ break;
- /* Can't back reference to a subexpression if inside of it. */
- for (stackt = stackp - 2; stackt > stackb; stackt -= 5)
- if (*stackt == c1)
- goto normal_char;
- laststart = b;
- BUFPUSH(duplicate);
- BUFPUSH(c1);
- break;
+ case 'b':
+ BUFPUSH(wordbound);
+ break;
- default:
- goto normal_char;
- }
+ case 'B':
+ BUFPUSH(notwordbound);
+ break;
+
+ case 'A':
+ BUFPUSH(begbuf);
+ break;
+
+ case 'Z':
+ if ((bufp->options & RE_OPTION_POSIXLINE) == 0) {
+ BUFPUSH(endbuf2);
break;
+ }
+ /* fall through */
+ case 'z':
+ BUFPUSH(endbuf);
+ break;
- case '#':
- if (options & RE_OPTION_EXTENDED)
- {
- while (p != pend) {
- PATFETCH(c);
- if (c == '\n') break;
- }
- break;
- }
- goto normal_char;
-
- case ' ':
- case '\t':
- case '\f':
- case '\r':
- case '\n':
- if (options & RE_OPTION_EXTENDED)
- break;
+ /* hex */
+ case 'x':
+ had_mbchar = 0;
+ c = scan_hex(p, 2, &numlen);
+ p += numlen;
+ goto numeric_char;
+
+ /* octal */
+ case '0':
+ had_mbchar = 0;
+ c = scan_oct(p, 3, &numlen);
+ p += numlen;
+ goto numeric_char;
+
+ /* back-ref or octal */
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ {
+ const char *p_save;
+
+ PATUNFETCH;
+ p_save = p;
- default:
- normal_char: /* Expects the character in `c'. */
had_mbchar = 0;
- if (ismbchar(c)) {
- had_mbchar = 0;
- c1 = p - pattern;
- }
- numeric_char:
- if (!pending_exact || pending_exact + *pending_exact + 1 != b
- || *pending_exact >= (c1 ? 0176 : 0177)
- || *p == '+' || *p == '?'
- || *p == '*' || *p == '^'
- || *p == '{') {
- laststart = b;
- BUFPUSH(exactn);
- pending_exact = b;
- BUFPUSH(0);
- }
- if (!had_mbchar && c > 0x7f) {
- BUFPUSH(0xff);
- (*pending_exact)++;
+ c1 = 0;
+ GET_UNSIGNED_NUMBER(c1);
+ if (!ISDIGIT(c)) PATUNFETCH;
+
+ if (c1 >= regnum) {
+ /* need to get octal */
+ p = p_save;
+ c = scan_oct(p_save, 3, &numlen) & 0xff;
+ p = p_save + numlen;
+ c1 = 0;
+ goto numeric_char;
}
+ }
+
+ /* Can't back reference to a subexpression if inside of it. */
+ for (stackt = stackp - 2; stackt > stackb; stackt -= 5)
+ if (*stackt == c1)
+ goto normal_char;
+ laststart = b;
+ BUFPUSH(duplicate);
+ BUFPUSH(c1);
+ break;
+
+ default:
+ c = read_backslash(c);
+ goto normal_char;
+ }
+ break;
+
+ case '#':
+ if (options & RE_OPTION_EXTENDED) {
+ while (p != pend) {
+ PATFETCH(c);
+ if (c == '\n') break;
+ }
+ break;
+ }
+ goto normal_char;
+
+ case ' ':
+ case '\t':
+ case '\f':
+ case '\r':
+ case '\n':
+ if (options & RE_OPTION_EXTENDED)
+ break;
+
+ default:
+ normal_char: /* Expects the character in `c'. */
+ had_mbchar = 0;
+ if (ismbchar(c)) {
+ had_mbchar = 1;
+ c1 = p - pattern;
+ }
+ numeric_char:
+ nextp = p + mbclen(c) - 1;
+ if (!pending_exact || pending_exact + *pending_exact + 1 != b
+ || *pending_exact >= (c1 ? 0176 : 0177)
+ || *nextp == '+' || *nextp == '?'
+ || *nextp == '*' || *nextp == '^'
+ || *nextp == '{') {
+ laststart = b;
+ BUFPUSH(exactn);
+ pending_exact = b;
+ BUFPUSH(0);
+ }
+ if (!had_mbchar && c > 0x7f) {
+ BUFPUSH(0xff);
+ (*pending_exact)++;
+ }
+ BUFPUSH(c);
+ (*pending_exact)++;
+ if (had_mbchar) {
+ int len = mbclen(c) - 1;
+ while (len--) {
+ PATFETCH_RAW(c);
BUFPUSH(c);
(*pending_exact)++;
- if (had_mbchar) {
- int len = ismbchar(c);
- while (len--) {
- PATFETCH_RAW(c);
- BUFPUSH(c);
- (*pending_exact)++;
- }
- }
}
+ }
}
+ }
if (fixup_alt_jump)
store_jump(fixup_alt_jump, jump, b);
@@ -2062,17 +2203,29 @@ re_compile_pattern(pattern, size, bufp)
if (*laststart == start_memory) laststart += 3;
if (*laststart == dummy_failure_jump) laststart += 3;
else if (*laststart == try_next) laststart += 3;
- if (*laststart == on_failure_jump) {
+ if (*laststart == anychar_repeat) {
+ bufp->options |= RE_OPTIMIZE_ANCHOR;
+ }
+ else if (*laststart == on_failure_jump) {
int mcnt;
laststart++;
EXTRACT_NUMBER_AND_INCR(mcnt, laststart);
if (mcnt == 4 && *laststart == anychar) {
- bufp->options |= RE_OPTIMIZE_ANCHOR;
+ switch ((enum regexpcode)laststart[1]) {
+ case jump_n:
+ case finalize_jump:
+ case maybe_finalize_jump:
+ case jump:
+ case jump_past_alt:
+ case dummy_failure_jump:
+ bufp->options |= RE_OPTIMIZE_ANCHOR;
+ break;
+ }
}
else if (*laststart == charset || *laststart == charset_not) {
p0 = laststart;
- mcnt = *++p0 ;
+ mcnt = *++p0;
p0 += mcnt+1;
mcnt = EXTRACT_UNSIGNED_AND_INCR(p0);
p0 += 8*mcnt;
@@ -2116,6 +2269,13 @@ re_compile_pattern(pattern, size, bufp)
}
}
+ bufp->regstart = TMALLOC(regnum, unsigned char*);
+ bufp->regend = TMALLOC(regnum, unsigned char*);
+ bufp->old_regstart = TMALLOC(regnum, unsigned char*);
+ bufp->old_regend = TMALLOC(regnum, unsigned char*);
+ bufp->reg_info = TMALLOC(regnum, register_info_type);
+ bufp->best_regstart = TMALLOC(regnum, unsigned char*);
+ bufp->best_regend = TMALLOC(regnum, unsigned char*);
FREE_AND_RETURN(stackb, 0);
invalid_pattern:
@@ -2136,12 +2296,20 @@ re_compile_pattern(pattern, size, bufp)
void
re_free_pattern(bufp)
- struct re_pattern_buffer *bufp;
+ struct re_pattern_buffer *bufp;
{
- free(bufp->buffer);
- free(bufp->fastmap);
- if (bufp->must_skip) free(bufp->must_skip);
- free(bufp);
+ free(bufp->buffer);
+ free(bufp->fastmap);
+ if (bufp->must_skip) free(bufp->must_skip);
+
+ free(bufp->regstart);
+ free(bufp->regend);
+ free(bufp->old_regstart);
+ free(bufp->old_regend);
+ free(bufp->best_regstart);
+ free(bufp->best_regend);
+ free(bufp->reg_info);
+ free(bufp);
}
/* Store a jump of the form <OPCODE> <relative address>.
@@ -2317,7 +2485,7 @@ slow_search(little, llen, big, blen, translate)
}
else if (translate && !ismbchar(c)) {
while (big < bend) {
- if (ismbchar(*big)) big+=ismbchar(*big);
+ if (ismbchar(*big)) big+=mbclen(*big)-1;
else if (translate[*big] == c) break;
big++;
}
@@ -2325,7 +2493,7 @@ slow_search(little, llen, big, blen, translate)
else {
while (big < bend) {
if (*big == c) break;
- if (ismbchar(*big)) big+=ismbchar(*big);
+ if (ismbchar(*big)) big+=mbclen(*big)-1;
big++;
}
}
@@ -2333,34 +2501,33 @@ slow_search(little, llen, big, blen, translate)
if (slow_match(little, little+llen, big, bend, translate))
return big - bsave;
- if (ismbchar(*big)) big+=ismbchar(*big);
- big++;
+ big+=mbclen(*big);
}
return -1;
}
static void
bm_init_skip(skip, pat, m, translate)
- int *skip;
- unsigned char *pat;
- int m;
- char *translate;
+ int *skip;
+ unsigned char *pat;
+ int m;
+ const char *translate;
{
- int j, c;
+ int j, c;
- for (c=0; c<256; c++) {
- skip[c] = m;
- }
- if (translate) {
- for (j=0; j<m-1; j++) {
- skip[translate[pat[j]]] = m-1-j;
- }
+ for (c=0; c<256; c++) {
+ skip[c] = m;
+ }
+ if (translate) {
+ for (j=0; j<m-1; j++) {
+ skip[translate[pat[j]]] = m-1-j;
}
- else {
- for (j=0; j<m-1; j++) {
- skip[pat[j]] = m-1-j;
- }
+ }
+ else {
+ for (j=0; j<m-1; j++) {
+ skip[pat[j]] = m-1-j;
}
+ }
}
static int
@@ -2423,7 +2590,7 @@ re_compile_fastmap(bufp)
register int j, k;
unsigned is_a_succeed_n;
- unsigned char **stackb = RE_TALLOC(NFAILURES, unsigned char*);
+ unsigned char **stackb = TMALLOC(NFAILURES, unsigned char*);
unsigned char **stackp = stackb;
unsigned char **stacke = stackb + NFAILURES;
int options = bufp->options;
@@ -2432,309 +2599,305 @@ re_compile_fastmap(bufp)
bufp->fastmap_accurate = 1;
bufp->can_be_null = 0;
- while (p)
- {
- is_a_succeed_n = 0;
- if (p == pend)
- {
- bufp->can_be_null = 1;
- break;
- }
+ while (p) {
+ is_a_succeed_n = 0;
+ if (p == pend) {
+ bufp->can_be_null = 1;
+ break;
+ }
#ifdef SWITCH_ENUM_BUG
- switch ((int)((enum regexpcode)*p++))
+ switch ((int)((enum regexpcode)*p++))
#else
- switch ((enum regexpcode)*p++)
+ switch ((enum regexpcode)*p++)
#endif
- {
- case exactn:
- if (p[1] == 0xff) {
- if (TRANSLATE_P())
- fastmap[translate[p[2]]] = 2;
- else
- fastmap[p[2]] = 2;
- }
- else if (TRANSLATE_P())
- fastmap[translate[p[1]]] = 1;
- else
- fastmap[p[1]] = 1;
- break;
-
- case begline:
- case begbuf:
- case endbuf:
- case endbuf2:
- case wordbound:
- case notwordbound:
- case wordbeg:
- case wordend:
- case pop_and_fail:
- case push_dummy_failure:
- case stop_paren:
- continue;
-
- case casefold_on:
- bufp->options |= RE_MAY_IGNORECASE;
- case casefold_off:
- options ^= RE_OPTION_IGNORECASE;
- continue;
-
- case endline:
+ {
+ case exactn:
+ if (p[1] == 0xff) {
if (TRANSLATE_P())
- fastmap[translate['\n']] = 1;
+ fastmap[translate[p[2]]] = 2;
else
- fastmap['\n'] = 1;
+ fastmap[p[2]] = 2;
+ }
+ else if (TRANSLATE_P())
+ fastmap[translate[p[1]]] = 1;
+ else
+ fastmap[p[1]] = 1;
+ break;
- if (bufp->can_be_null == 0)
- bufp->can_be_null = 2;
- break;
+ case begline:
+ case begbuf:
+ case endbuf:
+ case endbuf2:
+ case wordbound:
+ case notwordbound:
+ case wordbeg:
+ case wordend:
+ case pop_and_fail:
+ case push_dummy_failure:
+ case start_paren:
+ case stop_paren:
+ continue;
+
+ case casefold_on:
+ bufp->options |= RE_MAY_IGNORECASE;
+ case casefold_off:
+ options ^= RE_OPTION_IGNORECASE;
+ continue;
+
+ case posix_on:
+ case posix_off:
+ options ^= RE_OPTION_POSIXLINE;
+ continue;
+
+ case endline:
+ if (TRANSLATE_P())
+ fastmap[translate['\n']] = 1;
+ else
+ fastmap['\n'] = 1;
+ if ((options & RE_OPTION_POSIXLINE) == 0 && bufp->can_be_null == 0)
+ bufp->can_be_null = 2;
+ break;
- case jump_n:
- case finalize_jump:
- case maybe_finalize_jump:
- case jump:
- case jump_past_alt:
- case dummy_failure_jump:
- EXTRACT_NUMBER_AND_INCR(j, p);
- p += j;
- if (j > 0)
- continue;
- /* Jump backward reached implies we just went through
- the body of a loop and matched nothing.
- Opcode jumped to should be an on_failure_jump.
- Just treat it like an ordinary jump.
- For a * loop, it has pushed its failure point already;
- If so, discard that as redundant. */
-
- if ((enum regexpcode)*p != on_failure_jump
- && (enum regexpcode)*p != try_next
- && (enum regexpcode)*p != succeed_n
- && (enum regexpcode)*p != finalize_push
- && (enum regexpcode)*p != finalize_push_n)
- continue;
- p++;
- EXTRACT_NUMBER_AND_INCR(j, p);
- p += j;
- if (stackp != stackb && *stackp == p)
- stackp--; /* pop */
- continue;
-
- case start_nowidth:
- case stop_nowidth:
- case finalize_push:
- p += 2;
+ case jump_n:
+ case finalize_jump:
+ case maybe_finalize_jump:
+ case jump:
+ case jump_past_alt:
+ case dummy_failure_jump:
+ case finalize_push:
+ case finalize_push_n:
+ EXTRACT_NUMBER_AND_INCR(j, p);
+ p += j;
+ if (j > 0)
continue;
-
- case finalize_push_n:
+ /* Jump backward reached implies we just went through
+ the body of a loop and matched nothing.
+ Opcode jumped to should be an on_failure_jump.
+ Just treat it like an ordinary jump.
+ For a * loop, it has pushed its failure point already;
+ If so, discard that as redundant. */
+
+ if ((enum regexpcode)*p != on_failure_jump
+ && (enum regexpcode)*p != try_next
+ && (enum regexpcode)*p != succeed_n)
+ continue;
+ p++;
+ EXTRACT_NUMBER_AND_INCR(j, p);
+ p += j;
+ if (stackp != stackb && *stackp == p)
+ stackp--; /* pop */
+ continue;
+
+ case try_next:
+ case start_nowidth:
+ case stop_nowidth:
+ p += 2;
+ continue;
+
+ case succeed_n:
+ is_a_succeed_n = 1;
+ /* Get to the number of times to succeed. */
+ EXTRACT_NUMBER(k, p + 2);
+ /* Increment p past the n for when k != 0. */
+ if (k != 0) {
p += 4;
continue;
+ }
+ /* fall through */
- case try_next:
- case on_failure_jump:
- handle_on_failure_jump:
- EXTRACT_NUMBER_AND_INCR(j, p);
- if (p + j < pend) {
- if (stackp == stacke) {
- unsigned char **stackx;
- unsigned int len = stacke - stackb;
+ case on_failure_jump:
+ EXTRACT_NUMBER_AND_INCR(j, p);
+ if (p + j < pend) {
+ if (stackp == stacke) {
+ unsigned char **stackx;
+ unsigned int len = stacke - stackb;
- EXPAND_FAIL_STACK(stackx, stackb, len);
- }
- *++stackp = p + j; /* push */
- }
- else {
- bufp->can_be_null = 1;
- }
- if (is_a_succeed_n)
- EXTRACT_NUMBER_AND_INCR(k, p); /* Skip the n. */
- continue;
+ EXPAND_FAIL_STACK(stackx, stackb, len);
+ }
+ *++stackp = p + j; /* push */
+ }
+ else {
+ bufp->can_be_null = 1;
+ }
+ if (is_a_succeed_n)
+ EXTRACT_NUMBER_AND_INCR(k, p); /* Skip the n. */
+ continue;
+
+ case set_number_at:
+ p += 4;
+ continue;
+
+ case start_memory:
+ case stop_memory:
+ p += 2;
+ continue;
+
+ case duplicate:
+ bufp->can_be_null = 1;
+ fastmap['\n'] = 1;
+ case anychar_repeat:
+ case anychar:
+ for (j = 0; j < (1 << BYTEWIDTH); j++) {
+ if (j != '\n' || (options & RE_OPTION_POSIXLINE))
+ fastmap[j] = 1;
+ }
+ if (bufp->can_be_null) {
+ FREE_AND_RETURN_VOID(stackb);
+ }
+ /* Don't return; check the alternative paths
+ so we can set can_be_null if appropriate. */
+ if ((enum regexpcode)p[-1] == anychar_repeat) {
+ continue;
+ }
+ break;
- case succeed_n:
- is_a_succeed_n = 1;
- /* Get to the number of times to succeed. */
- EXTRACT_NUMBER(k, p + 2);
- /* Increment p past the n for when k != 0. */
- if (k == 0) {
- p += 4;
- }
- else {
- goto handle_on_failure_jump;
+ case wordchar:
+ for (j = 0; j < 0x80; j++) {
+ if (SYNTAX(j) == Sword)
+ fastmap[j] = 1;
+ }
+ switch (current_mbctype) {
+ case MBCTYPE_ASCII:
+ for (j = 0x80; j < (1 << BYTEWIDTH); j++) {
+ if (SYNTAX(j) == Sword2)
+ fastmap[j] = 1;
}
- continue;
-
- case set_number_at:
- p += 4;
- continue;
-
- case start_memory:
- case stop_memory:
- p += 2;
- continue;
-
- case duplicate:
- bufp->can_be_null = 1;
- fastmap['\n'] = 1;
- case anychar:
- for (j = 0; j < (1 << BYTEWIDTH); j++)
- if (j != '\n')
+ break;
+ case MBCTYPE_EUC:
+ case MBCTYPE_SJIS:
+ case MBCTYPE_UTF8:
+ for (j = 0x80; j < (1 << BYTEWIDTH); j++) {
+ if (re_mbctab[j])
fastmap[j] = 1;
- if (bufp->can_be_null)
- {
- FREE_AND_RETURN_VOID(stackb);
- }
- /* Don't return; check the alternative paths
- so we can set can_be_null if appropriate. */
+ }
break;
+ }
+ break;
- case wordchar:
- for (j = 0; j < 0x80; j++) {
- if (SYNTAX(j) == Sword)
+ case notwordchar:
+ for (j = 0; j < 0x80; j++)
+ if (SYNTAX(j) != Sword)
+ fastmap[j] = 1;
+ switch (current_mbctype) {
+ case MBCTYPE_ASCII:
+ for (j = 0x80; j < (1 << BYTEWIDTH); j++) {
+ if (SYNTAX(j) != Sword2)
fastmap[j] = 1;
}
- switch (current_mbctype) {
- case MBCTYPE_ASCII:
- for (j = 0x80; j < (1 << BYTEWIDTH); j++) {
- if (SYNTAX(j) == Sword2)
- fastmap[j] = 1;
- }
- break;
- case MBCTYPE_EUC:
- case MBCTYPE_SJIS:
- case MBCTYPE_UTF8:
- for (j = 0x80; j < (1 << BYTEWIDTH); j++) {
- if (re_mbctab[j])
- fastmap[j] = 1;
- }
- break;
- }
break;
-
- case notwordchar:
- for (j = 0; j < 0x80; j++)
- if (SYNTAX(j) != Sword)
+ case MBCTYPE_EUC:
+ case MBCTYPE_SJIS:
+ case MBCTYPE_UTF8:
+ for (j = 0x80; j < (1 << BYTEWIDTH); j++) {
+ if (!re_mbctab[j])
fastmap[j] = 1;
- switch (current_mbctype) {
- case MBCTYPE_ASCII:
- for (j = 0x80; j < (1 << BYTEWIDTH); j++) {
- if (SYNTAX(j) != Sword2)
- fastmap[j] = 1;
- }
- break;
- case MBCTYPE_EUC:
- case MBCTYPE_SJIS:
- case MBCTYPE_UTF8:
- for (j = 0x80; j < (1 << BYTEWIDTH); j++) {
- if (!re_mbctab[j])
- fastmap[j] = 1;
- }
- break;
}
break;
+ }
+ break;
- case charset:
- /* NOTE: Charset for single-byte chars never contain
- multi-byte char. See set_list_bits(). */
- for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
- if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))
- {
- if (TRANSLATE_P())
- j = translate[j];
- fastmap[j] = (j>0x7f?2:1);
- }
- {
- unsigned short size;
- unsigned int c, beg, end;
-
- p += p[-1] + 2;
- size = EXTRACT_UNSIGNED(&p[-2]);
- for (j = 0; j < (int)size; j++) {
- c = EXTRACT_MBC(&p[j*8]);
- beg = WC2MBC1ST(c);
- c = EXTRACT_MBC(&p[j*8+4]);
- end = WC2MBC1ST(c);
- /* set bits for 1st bytes of multi-byte chars. */
- while (beg <= end) {
- /* NOTE: Charset for multi-byte chars might contain
- single-byte chars. We must reject them. */
- if (ismbchar(beg))
- fastmap[beg] = 1;
- beg++;
- }
+ case charset:
+ /* NOTE: Charset for single-byte chars never contain
+ multi-byte char. See set_list_bits(). */
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))) {
+ int tmp = TRANSLATE_P()?translate[j]:j;
+ fastmap[tmp] = (tmp>0x7f)?2:1;
+ }
+ {
+ unsigned short size;
+ unsigned long c, beg, end;
+
+ p += p[-1] + 2;
+ size = EXTRACT_UNSIGNED(&p[-2]);
+ for (j = 0; j < (int)size; j++) {
+ c = EXTRACT_MBC(&p[j*8]);
+ beg = WC2MBC1ST(c);
+ c = EXTRACT_MBC(&p[j*8+4]);
+ end = WC2MBC1ST(c);
+ /* set bits for 1st bytes of multi-byte chars. */
+ while (beg <= end) {
+ /* NOTE: Charset for multi-byte chars might contain
+ single-byte chars. We must reject them. */
+ if (ismbchar(beg))
+ fastmap[beg] = 1;
+ beg++;
}
}
- break;
+ }
+ break;
- case charset_not:
- /* S: set of all single-byte chars.
- M: set of all first bytes that can start multi-byte chars.
- s: any set of single-byte chars.
- m: any set of first bytes that can start multi-byte chars.
-
- We assume S+M = U.
- ___ _ _
- s+m = (S*s+M*m). */
- /* Chars beyond end of map must be allowed */
- /* NOTE: Charset_not for single-byte chars might contain
- multi-byte chars. See set_list_bits(). */
- for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
+ case charset_not:
+ /* S: set of all single-byte chars.
+ M: set of all first bytes that can start multi-byte chars.
+ s: any set of single-byte chars.
+ m: any set of first bytes that can start multi-byte chars.
+
+ We assume S+M = U.
+ ___ _ _
+ s+m = (S*s+M*m). */
+ /* Chars beyond end of map must be allowed */
+ /* NOTE: Charset_not for single-byte chars might contain
+ multi-byte chars. See set_list_bits(). */
+ for (j = *p * BYTEWIDTH; j < (1 << BYTEWIDTH); j++)
+ if (!ismbchar(j))
+ fastmap[j] = 1;
+
+ for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH)))) {
if (!ismbchar(j))
fastmap[j] = 1;
-
- for (j = *p++ * BYTEWIDTH - 1; j >= 0; j--)
+ }
+ if (current_mbctype) {
+ for (j = 0x80; j < (1 << BYTEWIDTH); j++)
if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
- {
- if (!ismbchar(j))
- fastmap[j] = 1;
- }
- if (current_mbctype) {
+ fastmap[j] = 2;
+ }
+ {
+ unsigned short size;
+ unsigned long c, beg;
+
+ p += p[-1] + 2;
+ size = EXTRACT_UNSIGNED(&p[-2]);
+ if (size == 0) {
for (j = 0x80; j < (1 << BYTEWIDTH); j++)
- if (!(p[j / BYTEWIDTH] & (1 << (j % BYTEWIDTH))))
- fastmap[j] = 2;
+ if (ismbchar(j))
+ fastmap[j] = 1;
+ break;
}
- {
- unsigned short size;
- unsigned int c, beg, end;
-
- p += p[-1] + 2;
- size = EXTRACT_UNSIGNED(&p[-2]);
- if (size == 0) {
- for (j = 0x80; j < (1 << BYTEWIDTH); j++)
- if (ismbchar(j))
- fastmap[j] = 1;
- break;
- }
- for (j = 0,c = 0x80;j < (int)size; j++) {
- int cc = EXTRACT_MBC(&p[j*8]);
- beg = WC2MBC1ST(cc);
- while (c < beg) {
- if (ismbchar(c))
- fastmap[c] = 1;
- c++;
- }
-
- cc = EXTRACT_MBC(&p[j*8+4]);
- c = WC2MBC1ST(cc) + 1;
+ for (j = 0,c = 0x80;j < (int)size; j++) {
+ int cc = EXTRACT_MBC(&p[j*8]);
+ beg = WC2MBC1ST(cc);
+ while (c < beg) {
+ if (ismbchar(c))
+ fastmap[c] = 1;
+ c++;
}
- for (j = c; j < (1 << BYTEWIDTH); j++)
- if (ismbchar(j))
- fastmap[j] = 1;
+ cc = EXTRACT_MBC(&p[j*8+4]);
+ c = WC2MBC1ST(cc) + 1;
}
- break;
- case unused: /* pacify gcc -Wall */
- break;
+ for (j = c; j < (1 << BYTEWIDTH); j++)
+ if (ismbchar(j))
+ fastmap[j] = 1;
}
+ break;
- /* Get here means we have successfully found the possible starting
- characters of one path of the pattern. We need not follow this
- path any farther. Instead, look at the next alternative
- remembered in the stack. */
- if (stackp != stackb)
- p = *stackp--; /* pop */
- else
+ case unused: /* pacify gcc -Wall */
break;
- }
- FREE_AND_RETURN_VOID(stackb);
+ }
+
+ /* Get here means we have successfully found the possible starting
+ characters of one path of the pattern. We need not follow this
+ path any farther. Instead, look at the next alternative
+ remembered in the stack. */
+ if (stackp != stackb)
+ p = *stackp--; /* pop */
+ else
+ break;
+ }
+ FREE_AND_RETURN_VOID(stackb);
}
@@ -2753,8 +2916,8 @@ re_compile_fastmap(bufp)
int
re_search(bufp, string, size, startpos, range, regs)
struct re_pattern_buffer *bufp;
- char *string;
- size_t size, startpos, range;
+ const char *string;
+ int size, startpos, range;
struct re_registers *regs;
{
register char *fastmap = bufp->fastmap;
@@ -2766,7 +2929,7 @@ re_search(bufp, string, size, startpos, range, regs)
/* Update the fastmap now if not correct already. */
if (fastmap && !bufp->fastmap_accurate) {
- re_compile_fastmap(bufp);
+ re_compile_fastmap(bufp);
}
/* If the search isn't to be a backwards one, don't waste time in a
@@ -2774,11 +2937,12 @@ re_search(bufp, string, size, startpos, range, regs)
if (bufp->used>0) {
switch ((enum regexpcode)bufp->buffer[0]) {
case begbuf:
+ begbuf_match:
if (range > 0) {
if (startpos > 0)
return -1;
else if (re_match(bufp, string, size, 0, regs) >= 0)
- return 0;
+ return 0;
return -1;
}
break;
@@ -2792,6 +2956,9 @@ re_search(bufp, string, size, startpos, range, regs)
}
}
if (bufp->options & RE_OPTIMIZE_ANCHOR) {
+ if (bufp->options&RE_OPTION_POSIXLINE) {
+ goto begbuf_match;
+ }
anchor = 1;
}
@@ -2804,7 +2971,7 @@ re_search(bufp, string, size, startpos, range, regs)
if (pbeg > pend) { /* swap pbeg,pend */
pos = pend; pend = pbeg; pbeg = pos;
}
- if (pend > size) pend = size;
+ pend = size;
if (bufp->options & RE_OPTIMIZE_NO_BM) {
pos = slow_search(bufp->must+1, len,
string+pbeg, pend-pbeg,
@@ -2823,136 +2990,135 @@ re_search(bufp, string, size, startpos, range, regs)
}
}
- for (;;)
- {
- /* If a fastmap is supplied, skip quickly over characters that
- cannot possibly be the start of a match. Note, however, that
- if the pattern can possibly match the null string, we must
- test it at each starting point so that we take the first null
- string we get. */
+ for (;;) {
+ /* If a fastmap is supplied, skip quickly over characters that
+ cannot possibly be the start of a match. Note, however, that
+ if the pattern can possibly match the null string, we must
+ test it at each starting point so that we take the first null
+ string we get. */
- if (fastmap && startpos < size
- && bufp->can_be_null != 1 && !(anchor && startpos == 0))
- {
- if (range > 0) /* Searching forwards. */
- {
- register unsigned char *p, c;
- int irange = range;
-
- p = (unsigned char*)string+startpos;
-
- while (range > 0) {
- c = *p++;
- if (ismbchar(c)) {
- if (fastmap[c])
- break;
- c = *p++;
- range--;
- if (fastmap[c] == 2)
- break;
- }
- else
- if (fastmap[MAY_TRANSLATE() ? translate[c] : c])
- break;
- range--;
- }
- startpos += irange - range;
- }
- else /* Searching backwards. */
- {
- register unsigned char c;
-
- c = string[startpos];
- c &= 0xff;
- if (MAY_TRANSLATE() ? !fastmap[translate[c]] : !fastmap[c])
- goto advance;
+ if (fastmap && startpos < size
+ && bufp->can_be_null != 1 && !(anchor && startpos == 0)) {
+ if (range > 0) { /* Searching forwards. */
+ register unsigned char *p, c;
+ int irange = range;
+
+ p = (unsigned char*)string+startpos;
+
+ while (range > 0) {
+ c = *p++;
+ if (ismbchar(c)) {
+ int len;
+
+ if (fastmap[c])
+ break;
+ len = mbclen(c) - 1;
+ while (len--) {
+ c = *p++;
+ range--;
+ if (fastmap[c] == 2)
+ goto startpos_adjust;
}
+ }
+ else {
+ if (fastmap[MAY_TRANSLATE() ? translate[c] : c])
+ break;
+ }
+ range--;
}
+ startpos_adjust:
+ startpos += irange - range;
+ }
+ else { /* Searching backwards. */
+ register unsigned char c;
- if (startpos > size) return -1;
- if (anchor && size > 0 && startpos == size) return -1;
- if (fastmap && startpos == size && range >= 0
- && (bufp->can_be_null == 0 ||
- (bufp->can_be_null && size > 0
- && string[startpos-1] == '\n')))
- return -1;
+ c = string[startpos];
+ c &= 0xff;
+ if (MAY_TRANSLATE() ? !fastmap[translate[c]] : !fastmap[c])
+ goto advance;
+ }
+ }
- val = re_match(bufp, string, size, startpos, regs);
- if (val >= 0)
- return startpos;
- if (val == -2)
- return -2;
+ if (startpos > size) return -1;
+ if (anchor && size > 0 && startpos == size) return -1;
+ val = re_match(bufp, string, size, startpos, regs);
+ if (val >= 0)
+ return startpos;
+ if (val == -2)
+ return -2;
#ifndef NO_ALLOCA
#ifdef C_ALLOCA
- alloca(0);
+ alloca(0);
#endif /* C_ALLOCA */
#endif /* NO_ALLOCA */
- if (range > 0) {
- if (anchor && startpos < size && startpos > 0 && string[startpos-1] != '\n') {
- while (range > 0 && string[startpos] != '\n') {
- range--;
- startpos++;
- }
+ if (range > 0) {
+ if (anchor && startpos < size &&
+ (startpos < 1 || string[startpos-1] != '\n')) {
+ while (range > 0 && string[startpos] != '\n') {
+ range--;
+ startpos++;
}
- else if (fastmap && (bufp->stclass)) {
- register unsigned char *p;
- unsigned int c;
- int irange = range;
-
- p = (unsigned char*)string+startpos;
- while (range > 0) {
- c = *p++;
- if (ismbchar(c) && fastmap[c] != 2) {
- MBC2WC(c, p);
- }
- else if (MAY_TRANSLATE())
- c = translate[c];
- if (*bufp->stclass == charset) {
- if (!is_in_list(c, bufp->stclass+1)) break;
- }
- else {
- if (is_in_list(c, bufp->stclass+1)) break;
- }
- range--;
- if (c > 256) range--;
+ }
+ else if (fastmap && (bufp->stclass)) {
+ register unsigned char *p;
+ unsigned long c;
+ int irange = range;
+
+ p = (unsigned char*)string+startpos;
+ while (range > 0) {
+ c = *p++;
+ if (ismbchar(c) && fastmap[c] != 2) {
+ MBC2WC(c, p);
}
- startpos += irange - range;
+ else if (MAY_TRANSLATE())
+ c = translate[c];
+ if (*bufp->stclass == charset) {
+ if (!is_in_list(c, bufp->stclass+1)) break;
+ }
+ else {
+ if (is_in_list(c, bufp->stclass+1)) break;
+ }
+ range--;
+ if (c > 256) range--;
}
+ startpos += irange - range;
}
+ }
- advance:
- if (!range)
- break;
- else if (range > 0) {
- const char *d = string + startpos;
+ advance:
+ if (!range)
+ break;
+ else if (range > 0) {
+ const char *d = string + startpos;
- if (ismbchar(*d)) {
- range-=ismbchar(*d), startpos+=ismbchar(*d);
+ if (ismbchar(*d)) {
+ int len = mbclen(*d) - 1;
+ range-=len, startpos+=len;
+ if (!range)
+ break;
+ }
+ range--, startpos++;
+ }
+ else {
+ range++, startpos--;
+ {
+ const char *s, *d, *p;
+
+ s = string; d = string + startpos;
+ for (p = d; p-- > s && ismbchar(*p); )
+ /* --p >= s would not work on 80[12]?86.
+ (when the offset of s equals 0 other than huge model.) */
+ ;
+ if (!((d - p) & 1)) {
if (!range)
break;
- }
- range--, startpos++;
- }
- else {
- range++, startpos--;
- {
- const char *s, *d, *p;
-
- s = string; d = string + startpos;
- for (p = d; p-- > s && ismbchar(*p); )
- /* --p >= s would not work on 80[12]?86.
- (when the offset of s equals 0 other than huge model.) */
- ;
- if (!((d - p) & 1)) {
- if (!range)
- break;
- range++, startpos--;
- }
+ range++, startpos--;
}
}
}
+ }
return -1;
}
@@ -2961,36 +3127,10 @@ re_search(bufp, string, size, startpos, range, regs)
/* The following are used for re_match, defined below: */
-/* Roughly the maximum number of failure points on the stack. Would be
- exactly that if always pushed MAX_NUM_FAILURE_ITEMS each time we failed. */
-
-int re_max_failures = 2000;
-
-/* Routine used by re_match. */
-/* static int memcmp_translate(); *//* already declared */
+/* Accessing macros used in re_match: */
-
-/* Structure and accessing macros used in re_match: */
-
-typedef union
-{
- unsigned char *word;
- struct
- {
- /* This field is one if this group can match the empty string,
- zero if not. If not yet determined, `MATCH_NULL_UNSET_VALUE'. */
-#define MATCH_NULL_UNSET_VALUE 3
- unsigned match_null_string_p : 2;
- unsigned is_active : 1;
- unsigned matched_something : 1;
- unsigned ever_matched_something : 1;
- } bits;
-} register_info_type;
-
-#define REG_MATCH_NULL_STRING_P(R) ((R).bits.match_null_string_p)
#define IS_ACTIVE(R) ((R).bits.is_active)
#define MATCHED_SOMETHING(R) ((R).bits.matched_something)
-#define EVER_MATCHED_SOMETHING(R) ((R).bits.ever_matched_something)
/* Macros used by re_match: */
@@ -3019,31 +3159,29 @@ typedef union
\
/* Find out how many registers are active or have been matched. \
(Aside from register zero, which is only set at the end.) */ \
- for (last_used_reg = num_regs - 1; last_used_reg > 0; last_used_reg--)\
+ for (last_used_reg = num_regs-1; last_used_reg > 0; last_used_reg--)\
if (!REG_UNSET(regstart[last_used_reg])) \
break; \
\
- if (stacke - stackp <= NUM_FAILURE_ITEMS) \
- { \
+ if (stacke - stackp <= NUM_FAILURE_ITEMS) { \
unsigned char **stackx; \
unsigned int len = stacke - stackb; \
/* if (len > re_max_failures * MAX_NUM_FAILURE_ITEMS) \
- { \
- FREE_VARIABLES(); \
- FREE_AND_RETURN(stackb,(-2)); \
- }*/ \
+ { \
+ FREE_VARIABLES(); \
+ FREE_AND_RETURN(stackb,(-2)); \
+ }*/ \
\
/* Roughly double the size of the stack. */ \
EXPAND_FAIL_STACK(stackx, stackb, len); \
} \
\
/* Now push the info for each of those registers. */ \
- for (this_reg = 1; this_reg <= last_used_reg; this_reg++) \
- { \
- *stackp++ = regstart[this_reg]; \
- *stackp++ = regend[this_reg]; \
- *stackp++ = reg_info[this_reg].word; \
- } \
+ for (this_reg = 1; this_reg <= last_used_reg; this_reg++) { \
+ *stackp++ = regstart[this_reg]; \
+ *stackp++ = regend[this_reg]; \
+ *stackp++ = reg_info[this_reg].word; \
+ } \
\
/* Push how many registers we saved. */ \
*stackp++ = (unsigned char*)last_used_reg; \
@@ -3053,77 +3191,75 @@ typedef union
*stackp++ = (unsigned char*)0; /* non-greedy flag */ \
} while(0)
+#define NON_GREEDY ((unsigned char*)1)
-/* This pops what PUSH_FAILURE_POINT pushes. */
+ /* This pops what PUSH_FAILURE_POINT pushes. */
#define POP_FAILURE_POINT() \
do { \
- int temp; \
+ long temp; \
stackp -= NUM_NONREG_ITEMS; /* Remove failure points (and flag). */ \
- temp = (int)*--stackp; /* How many regs pushed. */ \
+ temp = (long)*--stackp; /* How many regs pushed. */ \
temp *= NUM_REG_ITEMS; /* How much to take off the stack. */ \
stackp -= temp; /* Remove the register info. */ \
} while(0)
-/* Registers are set to a sentinel when they haven't yet matched. */
+ /* Registers are set to a sentinel when they haven't yet matched. */
#define REG_UNSET_VALUE ((unsigned char*)-1)
#define REG_UNSET(e) ((e) == REG_UNSET_VALUE)
#define PREFETCH if (d == dend) goto fail
-/* Call this when have matched something; it sets `matched' flags for the
+ /* Call this when have matched something; it sets `matched' flags for the
registers corresponding to the subexpressions of which we currently
are inside. */
#define SET_REGS_MATCHED \
do { unsigned this_reg; \
- for (this_reg = 0; this_reg < num_regs; this_reg++) \
- { \
+ for (this_reg = 0; this_reg < num_regs; this_reg++) { \
if (IS_ACTIVE(reg_info[this_reg])) \
MATCHED_SOMETHING(reg_info[this_reg]) \
- = EVER_MATCHED_SOMETHING (reg_info[this_reg]) \
= 1; \
else \
MATCHED_SOMETHING(reg_info[this_reg]) = 0; \
} \
} while(0)
-#define AT_STRINGS_BEG(d) (d == string)
-#define AT_STRINGS_END(d) (d == dend)
+#define AT_STRINGS_BEG(d) ((d) == string)
+#define AT_STRINGS_END(d) ((d) == dend)
-/* We have two special cases to check for:
- 1) if we're past the end of string1, we have to look at the first
- character in string2;
- 2) if we're before the beginning of string2, we have to look at the
- last character in string1; we assume there is a string1, so use
- this in conjunction with AT_STRINGS_BEG. */
#define IS_A_LETTER(d) (SYNTAX(*(d)) == Sword || \
(current_mbctype ? \
- re_mbctab[*(d)] == 1 : \
+ (re_mbctab[*(d)] && ((d)+mbclen(*(d)))<=dend): \
SYNTAX(*(d)) == Sword2))
+#define PREV_IS_A_LETTER(d) ((current_mbctype == MBCTYPE_SJIS)? \
+ IS_A_LETTER((d)-(!AT_STRINGS_BEG((d)-1)&& \
+ ismbchar((d)[-2])?2:1)): \
+ ((d)[-1] >= 0x80 || IS_A_LETTER((d)-1)))
+
static void
init_regs(regs, num_regs)
- struct re_registers *regs;
- unsigned int num_regs;
+ struct re_registers *regs;
+ unsigned int num_regs;
{
- int i;
+ int i;
- regs->num_regs = num_regs;
- if (num_regs < RE_NREGS)
- num_regs = RE_NREGS;
+ regs->num_regs = num_regs;
+ if (num_regs < RE_NREGS)
+ num_regs = RE_NREGS;
- if (regs->allocated == 0) {
- regs->beg = TMALLOC(num_regs, int);
- regs->end = TMALLOC(num_regs, int);
- regs->allocated = num_regs;
- }
- else if (regs->allocated < num_regs) {
- TREALLOC(regs->beg, num_regs, int);
- TREALLOC(regs->end, num_regs, int);
- }
- for (i=0; i<num_regs; i++) {
- regs->beg[i] = regs->end[i] = -1;
- }
+ if (regs->allocated == 0) {
+ regs->beg = TMALLOC(num_regs, int);
+ regs->end = TMALLOC(num_regs, int);
+ regs->allocated = num_regs;
+ }
+ else if (regs->allocated < num_regs) {
+ TREALLOC(regs->beg, num_regs, int);
+ TREALLOC(regs->end, num_regs, int);
+ }
+ for (i=0; i<num_regs; i++) {
+ regs->beg[i] = regs->end[i] = -1;
+ }
}
/* Match the pattern described by BUFP against STRING, which is of
@@ -3144,8 +3280,8 @@ init_regs(regs, num_regs)
int
re_match(bufp, string_arg, size, pos, regs)
struct re_pattern_buffer *bufp;
- char *string_arg;
- size_t size, pos;
+ const char *string_arg;
+ int size, pos;
struct re_registers *regs;
{
register unsigned char *p = (unsigned char*)bufp->buffer;
@@ -3162,15 +3298,15 @@ re_match(bufp, string_arg, size, pos, regs)
register int mcnt; /* Multipurpose. */
int options = bufp->options;
- /* Failure point stack. Each place that can handle a failure further
- down the line pushes a failure point on this stack. It consists of
- restart, regend, and reg_info for all registers corresponding to the
- subexpressions we're currently inside, plus the number of such
- registers, and, finally, two char *'s. The first char * is where to
- resume scanning the pattern; the second one is where to resume
- scanning the strings. If the latter is zero, the failure point is a
- ``dummy''; if a failure happens and the failure point is a dummy, it
- gets discarded and the next next one is tried. */
+ /* Failure point stack. Each place that can handle a failure further
+ down the line pushes a failure point on this stack. It consists of
+ restart, regend, and reg_info for all registers corresponding to the
+ subexpressions we're currently inside, plus the number of such
+ registers, and, finally, two char *'s. The first char * is where to
+ resume scanning the pattern; the second one is where to resume
+ scanning the strings. If the latter is zero, the failure point is a
+ ``dummy''; if a failure happens and the failure point is a dummy, it
+ gets discarded and the next next one is tried. */
unsigned char **stackb;
unsigned char **stackp;
@@ -3185,16 +3321,16 @@ re_match(bufp, string_arg, size, pos, regs)
stopped matching the regnum-th subexpression. (The zeroth register
keeps track of what the whole pattern matches.) */
- unsigned char **regstart = RE_TALLOC(num_regs, unsigned char*);
- unsigned char **regend = RE_TALLOC(num_regs, unsigned char*);
+ unsigned char **regstart = bufp->regstart;
+ unsigned char **regend = bufp->regend;
/* If a group that's operated upon by a repetition operator fails to
match anything, then the register for its start will need to be
restored because it will have been set to wherever in the string we
are when we last see its open-group operator. Similarly for a
register's end. */
- unsigned char **old_regstart = RE_TALLOC(num_regs, unsigned char*);
- unsigned char **old_regend = RE_TALLOC(num_regs, unsigned char*);
+ unsigned char **old_regstart = bufp->old_regstart;
+ unsigned char **old_regend = bufp->old_regend;
/* The is_active field of reg_info helps us keep track of which (possibly
nested) subexpressions we are currently in. The matched_something
@@ -3203,7 +3339,7 @@ re_match(bufp, string_arg, size, pos, regs)
subexpression. These two fields get reset each time through any
loop their register is in. */
- register_info_type *reg_info = RE_TALLOC(num_regs, register_info_type);
+ register_info_type *reg_info = bufp->reg_info;
/* The following record the register info as found in the above
variables when we find a match better than any we've seen before.
@@ -3211,8 +3347,8 @@ re_match(bufp, string_arg, size, pos, regs)
turn happens only if we have not yet matched the entire string. */
unsigned best_regs_set = 0;
- unsigned char **best_regstart = RE_TALLOC(num_regs, unsigned char*);
- unsigned char **best_regend = RE_TALLOC(num_regs, unsigned char*);
+ unsigned char **best_regstart = bufp->best_regstart;
+ unsigned char **best_regend = bufp->best_regend;
if (regs) {
init_regs(regs, num_regs);
@@ -3224,7 +3360,7 @@ re_match(bufp, string_arg, size, pos, regs)
stacke = &stackb[MAX_NUM_FAILURE_ITEMS * NFAILURES];
#ifdef DEBUG_REGEX
- fprintf (stderr, "Entering re_match(%s%s)\n", string1_arg, string2_arg);
+ fprintf(stderr, "Entering re_match(%s%s)\n", string1_arg, string2_arg);
#endif
/* Initialize subexpression text positions to -1 to mark ones that no
@@ -3238,10 +3374,8 @@ re_match(bufp, string_arg, size, pos, regs)
#ifdef __CHECKER__
reg_info[mcnt].word = 0;
#endif
- REG_MATCH_NULL_STRING_P (reg_info[mcnt]) = MATCH_NULL_UNSET_VALUE;
IS_ACTIVE (reg_info[mcnt]) = 0;
MATCHED_SOMETHING (reg_info[mcnt]) = 0;
- EVER_MATCHED_SOMETHING (reg_info[mcnt]) = 0;
}
/* Set up pointers to ends of strings.
@@ -3257,1022 +3391,743 @@ re_match(bufp, string_arg, size, pos, regs)
d = string + pos, dend = string + size;
-
/* This loops over pattern commands. It exits by returning from the
function if match is complete, or it drops through if match fails
at this starting point in the input data. */
- for (;;)
- {
+ for (;;) {
#ifdef DEBUG_REGEX
- fprintf(stderr,
- "regex loop(%d): matching 0x%02d\n",
- p - (unsigned char*)bufp->buffer,
- *p);
+ fprintf(stderr,
+ "regex loop(%d): matching 0x%02d\n",
+ p - (unsigned char*)bufp->buffer,
+ *p);
#endif
- /* End of pattern means we might have succeeded. */
- if (p == pend)
- {
- /* If not end of string, try backtracking. Otherwise done. */
- if (d != dend)
- {
- while (stackp != stackb && (int)stackp[-1] == 1)
- POP_FAILURE_POINT();
- if (stackp != stackb)
- {
- /* More failure points to try. */
-
- /* If exceeds best match so far, save it. */
- if (! best_regs_set || (d > best_regend[0]))
- {
- best_regs_set = 1;
- best_regend[0] = d; /* Never use regstart[0]. */
-
- for (mcnt = 1; mcnt < num_regs; mcnt++)
- {
- best_regstart[mcnt] = regstart[mcnt];
- best_regend[mcnt] = regend[mcnt];
- }
- }
- goto fail;
- }
- /* If no failure points, don't restore garbage. */
- else if (best_regs_set)
- {
- restore_best_regs:
- /* Restore best match. */
- d = best_regend[0];
-
- for (mcnt = 0; mcnt < num_regs; mcnt++)
- {
- regstart[mcnt] = best_regstart[mcnt];
- regend[mcnt] = best_regend[mcnt];
- }
- }
- }
-
- /* If caller wants register contents data back, convert it
- to indices. */
- if (regs)
- {
- regs->beg[0] = pos;
- regs->end[0] = d - string;
- for (mcnt = 1; mcnt < num_regs; mcnt++)
- {
- if (REG_UNSET(regend[mcnt]))
- {
- regs->beg[mcnt] = -1;
- regs->end[mcnt] = -1;
- continue;
- }
- regs->beg[mcnt] = regstart[mcnt] - string;
- regs->end[mcnt] = regend[mcnt] - string;
- }
+ /* End of pattern means we might have succeeded. */
+ if (p == pend) {
+ /* If not end of string, try backtracking. Otherwise done. */
+ if ((bufp->options & RE_OPTION_LONGEST) && d != dend) {
+ if (best_regs_set) /* non-greedy, no need to backtrack */
+ goto restore_best_regs;
+ while (stackp != stackb && stackp[-1] == NON_GREEDY) {
+ if (best_regs_set) /* non-greedy, no need to backtrack */
+ goto restore_best_regs;
+ POP_FAILURE_POINT();
+ }
+ if (stackp != stackb) {
+ /* More failure points to try. */
+
+ /* If exceeds best match so far, save it. */
+ if (! best_regs_set || (d > best_regend[0])) {
+ best_regs_set = 1;
+ best_regend[0] = d; /* Never use regstart[0]. */
+
+ for (mcnt = 1; mcnt < num_regs; mcnt++) {
+ best_regstart[mcnt] = regstart[mcnt];
+ best_regend[mcnt] = regend[mcnt];
}
- FREE_VARIABLES();
- FREE_AND_RETURN(stackb, (d - pos - string));
- }
+ }
+ goto fail;
+ }
+ /* If no failure points, don't restore garbage. */
+ else if (best_regs_set) {
+ restore_best_regs:
+ /* Restore best match. */
+ d = best_regend[0];
+
+ for (mcnt = 0; mcnt < num_regs; mcnt++) {
+ regstart[mcnt] = best_regstart[mcnt];
+ regend[mcnt] = best_regend[mcnt];
+ }
+ }
+ }
- /* Otherwise match next pattern command. */
+ /* If caller wants register contents data back, convert it
+ to indices. */
+ if (regs) {
+ regs->beg[0] = pos;
+ regs->end[0] = d - string;
+ for (mcnt = 1; mcnt < num_regs; mcnt++) {
+ if (REG_UNSET(regend[mcnt])) {
+ regs->beg[mcnt] = -1;
+ regs->end[mcnt] = -1;
+ continue;
+ }
+ regs->beg[mcnt] = regstart[mcnt] - string;
+ regs->end[mcnt] = regend[mcnt] - string;
+ }
+ }
+ FREE_VARIABLES();
+ FREE_AND_RETURN(stackb, (d - pos - string));
+ }
+
+ /* Otherwise match next pattern command. */
#ifdef SWITCH_ENUM_BUG
- switch ((int)((enum regexpcode)*p++))
+ switch ((int)((enum regexpcode)*p++))
#else
- switch ((enum regexpcode)*p++)
+ switch ((enum regexpcode)*p++)
#endif
+ {
+ /* ( [or `(', as appropriate] is represented by start_memory,
+ ) by stop_memory. Both of those commands are followed by
+ a register number in the next byte. The text matched
+ within the ( and ) is recorded under that number. */
+ case start_memory:
+ old_regstart[*p] = regstart[*p];
+ regstart[*p] = d;
+ IS_ACTIVE(reg_info[*p]) = 1;
+ MATCHED_SOMETHING(reg_info[*p]) = 0;
+ p += 2;
+ continue;
+
+ case stop_memory:
+ old_regend[*p] = regend[*p];
+ regend[*p] = d;
+ IS_ACTIVE(reg_info[*p]) = 0;
+ p += 2;
+ continue;
+
+ case start_paren:
+ case stop_paren:
+ break;
+
+ /* \<digit> has been turned into a `duplicate' command which is
+ followed by the numeric value of <digit> as the register number. */
+ case duplicate:
{
+ int regno = *p++; /* Get which register to match against */
+ register unsigned char *d2, *dend2;
- /* ( [or `(', as appropriate] is represented by start_memory,
- ) by stop_memory. Both of those commands are followed by
- a register number in the next byte. The text matched
- within the ( and ) is recorded under that number. */
- case start_memory:
- /* Find out if this group can match the empty string. */
- p1 = p; /* To send to group_match_null_string_p. */
- if (REG_MATCH_NULL_STRING_P (reg_info[*p]) == MATCH_NULL_UNSET_VALUE)
- REG_MATCH_NULL_STRING_P (reg_info[*p])
- = group_match_null_string_p (&p1, pend, reg_info);
-
- /* Save the position in the string where we were the last time
- we were at this open-group operator in case the group is
- operated upon by a repetition operator, e.g., with `(a*)*b'
- against `ab'; then we want to ignore where we are now in
- the string in case this attempt to match fails. */
- old_regstart[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
- ? REG_UNSET (regstart[*p]) ? d : regstart[*p]
- : regstart[*p];
- regstart[*p] = d;
- IS_ACTIVE(reg_info[*p]) = 1;
- MATCHED_SOMETHING(reg_info[*p]) = 0;
- p += 2;
- continue;
+ if (IS_ACTIVE(reg_info[regno])) break;
- case stop_memory:
- /* We need to save the string position the last time we were at
- this close-group operator in case the group is operated
- upon by a repetition operator, e.g., with `((a*)*(b*)*)*'
- against `aba'; then we want to ignore where we are now in
- the string in case this attempt to match fails. */
- old_regend[*p] = REG_MATCH_NULL_STRING_P (reg_info[*p])
- ? REG_UNSET (regend[*p]) ? d : regend[*p]
- : regend[*p];
-
- regend[*p] = d;
- IS_ACTIVE(reg_info[*p]) = 0;
-
- /* If just failed to match something this time around with a sub-
- expression that's in a loop, try to force exit from the loop. */
- if ((p + 1) != pend &&
- (! MATCHED_SOMETHING(reg_info[*p])
- || (enum regexpcode)p[-3] == start_memory))
- {
- p1 = p + 2;
- mcnt = 0;
- switch (*p1++)
- {
- case jump_n:
- case finalize_push_n:
- case finalize_jump:
- case maybe_finalize_jump:
- case jump:
- case dummy_failure_jump:
- EXTRACT_NUMBER_AND_INCR(mcnt, p1);
- break;
- }
- p1 += mcnt;
-
- /* If the next operation is a jump backwards in the pattern
- to an on_failure_jump, exit from the loop by forcing a
- failure after pushing on the stack the on_failure_jump's
- jump in the pattern, and d. */
- if (mcnt < 0 && (enum regexpcode)*p1 == on_failure_jump
- && (enum regexpcode)p1[3] == start_memory && p1[4] == *p)
- {
- /* If this group ever matched anything, then restore
- what its registers were before trying this last
- failed match, e.g., with `(a*)*b' against `ab' for
- regstart[1], and, e.g., with `((a*)*(b*)*)*'
- against `aba' for regend[3].
-
- Also restore the registers for inner groups for,
- e.g., `((a*)(b*))*' against `aba' (register 3 would
- otherwise get trashed). */
-
- if (EVER_MATCHED_SOMETHING (reg_info[*p]))
- {
- unsigned r;
-
- EVER_MATCHED_SOMETHING (reg_info[*p]) = 0;
-
- /* Restore this and inner groups' (if any) registers. */
- for (r = *p; r < *p + *(p + 1); r++)
- {
- regstart[r] = old_regstart[r];
-
- /* xx why this test? */
- if ((int)old_regend[r] >= (int)regstart[r])
- regend[r] = old_regend[r];
- }
- }
- p1++;
- EXTRACT_NUMBER_AND_INCR(mcnt, p1);
- PUSH_FAILURE_POINT(p1 + mcnt, d);
- goto fail;
- }
- }
- p += 2;
- continue;
+ /* Where in input to try to start matching. */
+ d2 = regstart[regno];
+ if (REG_UNSET(d2)) break;
- case stop_paren:
- break;
+ /* Where to stop matching; if both the place to start and
+ the place to stop matching are in the same string, then
+ set to the place to stop, otherwise, for now have to use
+ the end of the first string. */
- /* \<digit> has been turned into a `duplicate' command which is
- followed by the numeric value of <digit> as the register number. */
- case duplicate:
- {
- int regno = *p++; /* Get which register to match against */
- register unsigned char *d2, *dend2;
-
- if (IS_ACTIVE(reg_info[regno])) break;
-
- /* Where in input to try to start matching. */
- d2 = regstart[regno];
- if (REG_UNSET(d2)) break;
-
- /* Where to stop matching; if both the place to start and
- the place to stop matching are in the same string, then
- set to the place to stop, otherwise, for now have to use
- the end of the first string. */
-
- dend2 = regend[regno];
- if (REG_UNSET(dend2)) break;
- for (;;)
- {
- /* At end of register contents => success */
- if (d2 == dend2) break;
-
- /* If necessary, advance to next segment in data. */
- PREFETCH;
-
- /* How many characters left in this segment to match. */
- mcnt = dend - d;
-
- /* Want how many consecutive characters we can match in
- one shot, so, if necessary, adjust the count. */
- if (mcnt > dend2 - d2)
- mcnt = dend2 - d2;
-
- /* Compare that many; failure if mismatch, else move
- past them. */
- if ((options & RE_OPTION_IGNORECASE)
- ? memcmp_translate(d, d2, mcnt)
- : memcmp((char*)d, (char*)d2, mcnt))
- goto fail;
- d += mcnt, d2 += mcnt;
- }
+ dend2 = regend[regno];
+ if (REG_UNSET(dend2)) break;
+ for (;;) {
+ /* At end of register contents => success */
+ if (d2 == dend2) break;
+
+ /* If necessary, advance to next segment in data. */
+ PREFETCH;
+
+ /* How many characters left in this segment to match. */
+ mcnt = dend - d;
+
+ /* Want how many consecutive characters we can match in
+ one shot, so, if necessary, adjust the count. */
+ if (mcnt > dend2 - d2)
+ mcnt = dend2 - d2;
+
+ /* Compare that many; failure if mismatch, else move
+ past them. */
+ if ((options & RE_OPTION_IGNORECASE)
+ ? memcmp_translate(d, d2, mcnt)
+ : memcmp((char*)d, (char*)d2, mcnt))
+ goto fail;
+ d += mcnt, d2 += mcnt;
}
- break;
+ }
+ break;
- case start_nowidth:
- PUSH_FAILURE_POINT(0, d);
- EXTRACT_NUMBER_AND_INCR(mcnt, p);
- STORE_NUMBER(p+mcnt, stackp - stackb);
- continue;
+ case start_nowidth:
+ PUSH_FAILURE_POINT(0, d);
+ if (stackp - stackb > RE_DUP_MAX) {
+ FREE_VARIABLES();
+ FREE_AND_RETURN(stackb,(-2));
+ }
+ EXTRACT_NUMBER_AND_INCR(mcnt, p);
+ STORE_NUMBER(p+mcnt, stackp - stackb);
+ continue;
+
+ case stop_nowidth:
+ EXTRACT_NUMBER_AND_INCR(mcnt, p);
+ stackp = stackb + mcnt;
+ d = stackp[-2];
+ POP_FAILURE_POINT();
+ continue;
- case stop_nowidth:
- EXTRACT_NUMBER_AND_INCR(mcnt, p);
- stackp = stackb + mcnt;
- d = stackp[-2];
- POP_FAILURE_POINT();
- continue;
+ case pop_and_fail:
+ EXTRACT_NUMBER(mcnt, p+1);
+ stackp = stackb + mcnt;
+ POP_FAILURE_POINT();
+ goto fail;
- case pop_and_fail:
- EXTRACT_NUMBER(mcnt, p+1);
- stackp = stackb + mcnt;
- POP_FAILURE_POINT();
+ case anychar:
+ PREFETCH;
+ if (ismbchar(*d)) {
+ if (d + mbclen(*d) > dend)
+ goto fail;
+ SET_REGS_MATCHED;
+ d += mbclen(*d);
+ break;
+ }
+ if (!(options&RE_OPTION_POSIXLINE) &&
+ (TRANSLATE_P() ? translate[*d] : *d) == '\n')
goto fail;
+ SET_REGS_MATCHED;
+ d++;
+ break;
- case anychar:
+ case anychar_repeat:
+ for (;;) {
+ PUSH_FAILURE_POINT(p, d);
PREFETCH;
- /* Match anything but a newline, maybe even a null. */
if (ismbchar(*d)) {
- if (d + mbclen(*d) > dend || d[1] == '\n' || d[1] == '\0')
+ if (d + mbclen(*d) > dend)
goto fail;
SET_REGS_MATCHED;
d += mbclen(*d);
- break;
+ continue;
}
- if (((TRANSLATE_P()) ? translate[*d] : *d) == '\n')
+ if (!(options&RE_OPTION_POSIXLINE) &&
+ (TRANSLATE_P() ? translate[*d] : *d) == '\n')
goto fail;
SET_REGS_MATCHED;
- d++;
- break;
+ d++;
+ }
+ break;
- case charset:
- case charset_not:
- {
- int not; /* Nonzero for charset_not. */
- int part; /* 2 if matched part of mbc */
- unsigned char *dsave = d + 1;
- int cc, c;
+ case charset:
+ case charset_not:
+ {
+ int not; /* Nonzero for charset_not. */
+ int part = 0; /* true if matched part of mbc */
+ unsigned char *dsave = d + 1;
+ int cc, c;
- PREFETCH;
- cc = c = (unsigned char)*d++;
- if (ismbchar(c)) {
- if (d + ismbchar(c) < dend) {
- MBC2WC(c, d);
- }
+ PREFETCH;
+ cc = c = (unsigned char)*d++;
+ if (ismbchar(c)) {
+ if (d + mbclen(c) - 1 <= dend) {
+ MBC2WC(c, d);
}
- else if (TRANSLATE_P())
- cc = c = (unsigned char)translate[c];
+ }
+ else if (TRANSLATE_P())
+ cc = c = (unsigned char)translate[c];
- part = not = is_in_list(c, p);
- if (*(p - 1) == (unsigned char)charset_not) {
- not = !not;
- }
- if (!not) goto fail;
+ not = is_in_list(c, p);
+ if (!not && cc != c) {
+ part = not = is_in_list(cc, p);
+ }
+ if (*(p - 1) == (unsigned char)charset_not) {
+ not = !not;
+ }
+ if (!not) goto fail;
- p += 1 + *p + 2 + EXTRACT_UNSIGNED(&p[1 + *p])*8;
- SET_REGS_MATCHED;
+ p += 1 + *p + 2 + EXTRACT_UNSIGNED(&p[1 + *p])*8;
+ SET_REGS_MATCHED;
- if (part == 2) d = dsave;
- break;
- }
+ if (part) d = dsave;
+ break;
+ }
- case begline:
- if (size == 0
- || AT_STRINGS_BEG(d)
- || (d && d[-1] == '\n'))
- break;
- else
- goto fail;
+ case begline:
+ if (size == 0 || AT_STRINGS_BEG(d))
+ break;
+ if (d[-1] == '\n' && !AT_STRINGS_END(d))
+ break;
+ goto fail;
- case endline:
- if (AT_STRINGS_END(d) || *d == '\n')
+ case endline:
+ if (AT_STRINGS_END(d)) {
+ if (size == 0 || d[-1] != '\n')
break;
- goto fail;
+ }
+ else if (*d == '\n')
+ break;
+ goto fail;
/* Match at the very beginning of the string. */
- case begbuf:
- if (AT_STRINGS_BEG(d))
- break;
- goto fail;
+ case begbuf:
+ if (AT_STRINGS_BEG(d))
+ break;
+ goto fail;
/* Match at the very end of the data. */
- case endbuf:
- if (AT_STRINGS_END(d))
- break;
- goto fail;
+ case endbuf:
+ if (AT_STRINGS_END(d))
+ break;
+ goto fail;
/* Match at the very end of the data. */
- case endbuf2:
- if (AT_STRINGS_END(d))
- break;
- /* .. or newline just before the end of the data. */
- if (*d == '\n' && AT_STRINGS_END(d+1))
+ case endbuf2:
+ if (AT_STRINGS_END(d)) {
+ if (size == 0 || d[-1] != '\n')
break;
- goto fail;
+ }
+ /* .. or newline just before the end of the data. */
+ if (*d == '\n' && AT_STRINGS_END(d+1))
+ break;
+ goto fail;
/* `or' constructs are handled by starting each alternative with
- an on_failure_jump that points to the start of the next
- alternative. Each alternative except the last ends with a
- jump to the joining point. (Actually, each jump except for
- the last one really jumps to the following jump, because
- tensioning the jumps is a hassle.) */
+ an on_failure_jump that points to the start of the next
+ alternative. Each alternative except the last ends with a
+ jump to the joining point. (Actually, each jump except for
+ the last one really jumps to the following jump, because
+ tensioning the jumps is a hassle.) */
/* The start of a stupid repeat has an on_failure_jump that points
past the end of the repeat text. This makes a failure point so
- that on failure to match a repetition, matching restarts past
- as many repetitions have been found with no way to fail and
- look for another one. */
+ that on failure to match a repetition, matching restarts past
+ as many repetitions have been found with no way to fail and
+ look for another one. */
/* A smart repeat is similar but loops back to the on_failure_jump
so that each repetition makes another failure point. */
- case on_failure_jump:
- on_failure:
- EXTRACT_NUMBER_AND_INCR(mcnt, p);
- PUSH_FAILURE_POINT(p + mcnt, d);
- continue;
+ case on_failure_jump:
+ on_failure:
+ EXTRACT_NUMBER_AND_INCR(mcnt, p);
+ PUSH_FAILURE_POINT(p + mcnt, d);
+ continue;
+
+ /* The end of a smart repeat has a maybe_finalize_jump back.
+ Change it either to a finalize_jump or an ordinary jump. */
+ case maybe_finalize_jump:
+ EXTRACT_NUMBER_AND_INCR(mcnt, p);
+ p1 = p;
+
+ /* Compare the beginning of the repeat with what in the
+ pattern follows its end. If we can establish that there
+ is nothing that they would both match, i.e., that we
+ would have to backtrack because of (as in, e.g., `a*a')
+ then we can change to pop_failure_jump, because we'll
+ never have to backtrack.
+
+ This is not true in the case of alternatives: in
+ `(a|ab)*' we do need to backtrack to the `ab' alternative
+ (e.g., if the string was `ab'). But instead of trying to
+ detect that here, the alternative has put on a dummy
+ failure point which is what we will end up popping. */
+
+ /* Skip over open/close-group commands. */
+ while (p1 + 2 < pend) {
+ if ((enum regexpcode)*p1 == stop_memory ||
+ (enum regexpcode)*p1 == start_memory)
+ p1 += 3; /* Skip over args, too. */
+ else if (/*(enum regexpcode)*p1 == start_paren ||*/
+ (enum regexpcode)*p1 == stop_paren)
+ p1 += 1;
+ else
+ break;
+ }
- /* The end of a smart repeat has a maybe_finalize_jump back.
- Change it either to a finalize_jump or an ordinary jump. */
- case maybe_finalize_jump:
- EXTRACT_NUMBER_AND_INCR(mcnt, p);
- {
- register unsigned char *p2 = p;
-
- /* Compare the beginning of the repeat with what in the
- pattern follows its end. If we can establish that there
- is nothing that they would both match, i.e., that we
- would have to backtrack because of (as in, e.g., `a*a')
- then we can change to pop_failure_jump, because we'll
- never have to backtrack.
-
- This is not true in the case of alternatives: in
- `(a|ab)*' we do need to backtrack to the `ab' alternative
- (e.g., if the string was `ab'). But instead of trying to
- detect that here, the alternative has put on a dummy
- failure point which is what we will end up popping. */
-
- /* Skip over open/close-group commands. */
- while (p2 + 2 < pend) {
- if ((enum regexpcode)*p2 == stop_memory ||
- (enum regexpcode)*p2 == start_memory)
- p2 += 3; /* Skip over args, too. */
- else if ((enum regexpcode)*p2 == stop_paren)
- p2 += 1;
- else
- break;
+ if (p1 == pend)
+ p[-3] = (unsigned char)finalize_jump;
+ else if (*p1 == (unsigned char)exactn ||
+ *p1 == (unsigned char)endline) {
+ register int c = *p1 == (unsigned char)endline ? '\n' : p1[2];
+ register unsigned char *p2 = p + mcnt;
+ /* p2[0] ... p2[2] are an on_failure_jump.
+ Examine what follows that. */
+ if (p2[3] == (unsigned char)exactn && p2[5] != c)
+ p[-3] = (unsigned char)finalize_jump;
+ else if (p2[3] == (unsigned char)charset ||
+ p2[3] == (unsigned char)charset_not) {
+ int not;
+ if (ismbchar(c)) {
+ unsigned char *pp = p1+3;
+ MBC2WC(c, pp);
}
-
- if (p2 == pend)
+ /* `is_in_list()' is TRUE if c would match */
+ /* That means it is not safe to finalize. */
+ not = is_in_list(c, p2 + 4);
+ if (p2[3] == (unsigned char)charset_not)
+ not = !not;
+ if (!not)
p[-3] = (unsigned char)finalize_jump;
- else if (*p2 == (unsigned char)exactn
- || *p2 == (unsigned char)endline)
- {
- register int c = *p2 == (unsigned char)endline ? '\n' : p2[2];
- register unsigned char *p1 = p + mcnt;
- /* p1[0] ... p1[2] are an on_failure_jump.
- Examine what follows that. */
- if (p1[3] == (unsigned char)exactn && p1[5] != c)
- p[-3] = (unsigned char)finalize_jump;
- else if (p1[3] == (unsigned char)charset
- || p1[3] == (unsigned char)charset_not) {
- int not;
- if (ismbchar(c)) {
- unsigned char *pp = p2+3;
- MBC2WC(c, pp);
- }
- /* `is_in_list()' is TRUE if c would match */
- /* That means it is not safe to finalize. */
- not = is_in_list(c, p1 + 4);
- if (p1[3] == (unsigned char)charset_not)
- not = !not;
- if (!not)
- p[-3] = (unsigned char)finalize_jump;
- }
- }
}
- p -= 2; /* Point at relative address again. */
- if (p[-1] != (unsigned char)finalize_jump)
- {
- p[-1] = (unsigned char)jump;
- goto nofinalize;
- }
- /* Note fall through. */
+ }
+ p -= 2; /* Point at relative address again. */
+ if (p[-1] != (unsigned char)finalize_jump) {
+ p[-1] = (unsigned char)jump;
+ goto nofinalize;
+ }
+ /* Note fall through. */
/* The end of a stupid repeat has a finalize_jump back to the
- start, where another failure point will be made which will
- point to after all the repetitions found so far. */
-
- /* Take off failure points put on by matching on_failure_jump
- because didn't fail. Also remove the register information
- put on by the on_failure_jump. */
- case finalize_jump:
- POP_FAILURE_POINT();
- /* Note fall through. */
-
- /* Jump without taking off any failure points. */
- case jump:
- nofinalize:
- EXTRACT_NUMBER_AND_INCR(mcnt, p);
- p += mcnt;
+ start, where another failure point will be made which will
+ point to after all the repetitions found so far. */
+
+ /* Take off failure points put on by matching on_failure_jump
+ because didn't fail. Also remove the register information
+ put on by the on_failure_jump. */
+ case finalize_jump:
+ if (stackp[-2] == d) {
+ p = stackp[-3];
+ POP_FAILURE_POINT();
continue;
+ }
+ POP_FAILURE_POINT();
+ /* Note fall through. */
- /* We need this opcode so we can detect where alternatives end
- in `group_match_null_string_p' et al. */
- case jump_past_alt:
- goto nofinalize;
-
- case dummy_failure_jump:
- /* Normally, the on_failure_jump pushes a failure point, which
- then gets popped at finalize_jump. We will end up at
- finalize_jump, also, and with a pattern of, say, `a+', we
- are skipping over the on_failure_jump, so we have to push
- something meaningless for finalize_jump to pop. */
- PUSH_FAILURE_POINT(0, 0);
- goto nofinalize;
-
- /* At the end of an alternative, we need to push a dummy failure
- point in case we are followed by a `finalize_jump', because
- we don't want the failure point for the alternative to be
- popped. For example, matching `(a|ab)*' against `aab'
- requires that we match the `ab' alternative. */
- case push_dummy_failure:
- /* See comments just above at `dummy_failure_jump' about the
- two zeroes. */
- PUSH_FAILURE_POINT(0, 0);
- break;
-
- /* Have to succeed matching what follows at least n times. Then
- just handle like an on_failure_jump. */
- case succeed_n:
- EXTRACT_NUMBER(mcnt, p + 2);
- /* Originally, this is how many times we HAVE to succeed. */
- if (mcnt > 0)
- {
- mcnt--;
- p += 2;
- STORE_NUMBER_AND_INCR(p, mcnt);
- PUSH_FAILURE_POINT(0, 0);
- }
- else if (mcnt == 0)
- {
- p[2] = unused;
- p[3] = unused;
- goto on_failure;
- }
- continue;
+ /* We need this opcode so we can detect where alternatives end
+ in `group_match_null_string_p' et al. */
+ case jump_past_alt:
+ /* fall through */
- case jump_n:
- EXTRACT_NUMBER(mcnt, p + 2);
- /* Originally, this is how many times we CAN jump. */
- if (mcnt)
- {
- mcnt--;
- STORE_NUMBER(p + 2, mcnt);
- goto nofinalize; /* Do the jump without taking off
- any failure points. */
- }
- /* If don't have to jump any more, skip over the rest of command. */
- else
- p += 4;
- continue;
-
- case set_number_at:
- EXTRACT_NUMBER_AND_INCR(mcnt, p);
- p1 = p + mcnt;
- EXTRACT_NUMBER_AND_INCR(mcnt, p);
- STORE_NUMBER(p1, mcnt);
- continue;
+ /* Jump without taking off any failure points. */
+ case jump:
+ nofinalize:
+ EXTRACT_NUMBER_AND_INCR(mcnt, p);
+ if (mcnt < 0 && stackp > stackb && stackp[-2] == d) /* avoid infinit loop */
+ goto fail;
+ p += mcnt;
+ continue;
+
+ case dummy_failure_jump:
+ /* Normally, the on_failure_jump pushes a failure point, which
+ then gets popped at finalize_jump. We will end up at
+ finalize_jump, also, and with a pattern of, say, `a+', we
+ are skipping over the on_failure_jump, so we have to push
+ something meaningless for finalize_jump to pop. */
+ PUSH_FAILURE_POINT(0, 0);
+ goto nofinalize;
+
+ /* At the end of an alternative, we need to push a dummy failure
+ point in case we are followed by a `finalize_jump', because
+ we don't want the failure point for the alternative to be
+ popped. For example, matching `(a|ab)*' against `aab'
+ requires that we match the `ab' alternative. */
+ case push_dummy_failure:
+ /* See comments just above at `dummy_failure_jump' about the
+ two zeroes. */
+ p1 = p;
+ /* Skip over open/close-group commands. */
+ while (p1 + 2 < pend) {
+ if ((enum regexpcode)*p1 == stop_memory ||
+ (enum regexpcode)*p1 == start_memory)
+ p1 += 3; /* Skip over args, too. */
+ else if (/*(enum regexpcode)*p1 == start_paren ||*/
+ (enum regexpcode)*p1 == stop_paren)
+ p1 += 1;
+ else
+ break;
+ }
+ if ((enum regexpcode)*p1 == jump)
+ p[-1] = unused;
+ else
+ PUSH_FAILURE_POINT(0, 0);
+ break;
- case try_next:
- EXTRACT_NUMBER_AND_INCR(mcnt, p);
- if (p + mcnt < pend) {
- PUSH_FAILURE_POINT(p, d);
- stackp[-1] = (unsigned char*)1;
- }
- p += mcnt;
- continue;
+ /* Have to succeed matching what follows at least n times. Then
+ just handle like an on_failure_jump. */
+ case succeed_n:
+ EXTRACT_NUMBER(mcnt, p + 2);
+ /* Originally, this is how many times we HAVE to succeed. */
+ if (mcnt > 0) {
+ mcnt--;
+ p += 2;
+ STORE_NUMBER_AND_INCR(p, mcnt);
+ PUSH_FAILURE_POINT(0, 0);
+ }
+ else if (mcnt == 0) {
+ p[2] = unused;
+ p[3] = unused;
+ goto on_failure;
+ }
+ continue;
+
+ case jump_n:
+ EXTRACT_NUMBER(mcnt, p + 2);
+ /* Originally, this is how many times we CAN jump. */
+ if (mcnt) {
+ mcnt--;
+ STORE_NUMBER(p + 2, mcnt);
+ goto nofinalize; /* Do the jump without taking off
+ any failure points. */
+ }
+ /* If don't have to jump any more, skip over the rest of command. */
+ else
+ p += 4;
+ continue;
+
+ case set_number_at:
+ EXTRACT_NUMBER_AND_INCR(mcnt, p);
+ p1 = p + mcnt;
+ EXTRACT_NUMBER_AND_INCR(mcnt, p);
+ STORE_NUMBER(p1, mcnt);
+ continue;
+
+ case try_next:
+ EXTRACT_NUMBER_AND_INCR(mcnt, p);
+ if (p + mcnt < pend) {
+ PUSH_FAILURE_POINT(p, d);
+ stackp[-1] = NON_GREEDY;
+ }
+ p += mcnt;
+ continue;
- case finalize_push:
- POP_FAILURE_POINT();
+ case finalize_push:
+ POP_FAILURE_POINT();
+ EXTRACT_NUMBER_AND_INCR(mcnt, p);
+ if (mcnt < 0 && stackp[-2] == d) /* avoid infinit loop */
+ goto fail;
+ PUSH_FAILURE_POINT(p + mcnt, d);
+ stackp[-1] = NON_GREEDY;
+ continue;
+
+ case finalize_push_n:
+ EXTRACT_NUMBER(mcnt, p + 2);
+ /* Originally, this is how many times we CAN jump. */
+ if (mcnt) {
+ int pos, i;
+
+ mcnt--;
+ STORE_NUMBER(p + 2, mcnt);
+ EXTRACT_NUMBER(pos, p);
+ EXTRACT_NUMBER(i, p+pos+5);
+ if (i > 0) goto nofinalize;
+ POP_FAILURE_POINT();
EXTRACT_NUMBER_AND_INCR(mcnt, p);
- PUSH_FAILURE_POINT(p + mcnt, d);
- stackp[-1] = (unsigned char*)1;
- continue;
-
- case finalize_push_n:
- EXTRACT_NUMBER(mcnt, p + 2);
- /* Originally, this is how many times we CAN jump. */
- if (mcnt) {
- int pos, i;
-
- mcnt--;
- STORE_NUMBER(p + 2, mcnt);
- EXTRACT_NUMBER(pos, p);
- EXTRACT_NUMBER(i, p+pos+5);
- if (i > 0) goto nofinalize;
- POP_FAILURE_POINT();
- EXTRACT_NUMBER_AND_INCR(mcnt, p);
- PUSH_FAILURE_POINT(p + mcnt, d);
- stackp[-1] = (unsigned char*)1;
- p += 2; /* skip n */
- }
- /* If don't have to push any more, skip over the rest of command. */
- else
- p += 4;
- continue;
-
- /* Ignore these. Used to ignore the n of succeed_n's which
- currently have n == 0. */
- case unused:
- continue;
-
- case casefold_on:
- options |= RE_OPTION_IGNORECASE;
- continue;
-
- case casefold_off:
- options &= ~RE_OPTION_IGNORECASE;
- continue;
+ PUSH_FAILURE_POINT(p + mcnt, d);
+ stackp[-1] = NON_GREEDY;
+ p += 2; /* skip n */
+ }
+ /* If don't have to push any more, skip over the rest of command. */
+ else
+ p += 4;
+ continue;
+
+ /* Ignore these. Used to ignore the n of succeed_n's which
+ currently have n == 0. */
+ case unused:
+ continue;
+
+ case casefold_on:
+ options |= RE_OPTION_IGNORECASE;
+ continue;
+
+ case casefold_off:
+ options &= ~RE_OPTION_IGNORECASE;
+ continue;
+
+ case posix_on:
+ options |= RE_OPTION_POSIXLINE;
+ continue;
+
+ case posix_off:
+ options &= ~RE_OPTION_POSIXLINE;
+ continue;
+
+ case wordbound:
+ if (AT_STRINGS_BEG(d)) {
+ if (IS_A_LETTER(d)) break;
+ else goto fail;
+ }
+ if (AT_STRINGS_BEG(d)) {
+ if (PREV_IS_A_LETTER(d)) break;
+ else goto fail;
+ }
+ if (PREV_IS_A_LETTER(d) != IS_A_LETTER(d))
+ break;
+ goto fail;
- case wordbound:
- if (AT_STRINGS_BEG(d)) {
- if (IS_A_LETTER(d)) break;
- else goto fail;
- }
- if (AT_STRINGS_BEG(d)) {
- if (IS_A_LETTER(d-1)) break;
- else goto fail;
- }
- if (IS_A_LETTER(d - 1) != IS_A_LETTER(d))
- break;
+ case notwordbound:
+ if (AT_STRINGS_BEG(d)) {
+ if (IS_A_LETTER(d)) goto fail;
+ else break;
+ }
+ if (AT_STRINGS_END(d)) {
+ if (PREV_IS_A_LETTER(d)) goto fail;
+ else break;
+ }
+ if (PREV_IS_A_LETTER(d) != IS_A_LETTER(d))
goto fail;
+ break;
- case notwordbound:
- if (AT_STRINGS_BEG(d)) {
- if (IS_A_LETTER(d)) goto fail;
- else break;
- }
- if (AT_STRINGS_END(d)) {
- if (IS_A_LETTER(d-1)) goto fail;
- else break;
- }
- if (IS_A_LETTER(d - 1) != IS_A_LETTER(d))
- goto fail;
+ case wordbeg:
+ if (IS_A_LETTER(d) && (AT_STRINGS_BEG(d) || !PREV_IS_A_LETTER(d)))
break;
+ goto fail;
- case wordbeg:
- if (IS_A_LETTER(d) && (AT_STRINGS_BEG(d) || !IS_A_LETTER(d - 1)))
- break;
- goto fail;
+ case wordend:
+ if (!AT_STRINGS_BEG(d) && PREV_IS_A_LETTER(d)
+ && (!IS_A_LETTER(d) || AT_STRINGS_END(d)))
+ break;
+ goto fail;
- case wordend:
- if (!AT_STRINGS_BEG(d) && IS_A_LETTER(d - 1)
- && (!IS_A_LETTER(d) || AT_STRINGS_END(d)))
- break;
- goto fail;
+ case wordchar:
+ PREFETCH;
+ if (!IS_A_LETTER(d))
+ goto fail;
+ if (ismbchar(*d) && d + mbclen(*d) - 1 < dend)
+ d += mbclen(*d) - 1;
+ d++;
+ SET_REGS_MATCHED;
+ break;
- case wordchar:
- PREFETCH;
- if (!IS_A_LETTER(d))
- goto fail;
- d++;
- SET_REGS_MATCHED;
- break;
+ case notwordchar:
+ PREFETCH;
+ if (IS_A_LETTER(d))
+ goto fail;
+ if (ismbchar(*d) && d + mbclen(*d) - 1 < dend)
+ d += mbclen(*d) - 1;
+ d++;
+ SET_REGS_MATCHED;
+ break;
- case notwordchar:
- PREFETCH;
- if (IS_A_LETTER(d))
- goto fail;
- if (ismbchar(*d) && d + ismbchar(*d) < dend)
- d += ismbchar(*d);
- d++;
- SET_REGS_MATCHED;
- break;
+ case exactn:
+ /* Match the next few pattern characters exactly.
+ mcnt is how many characters to match. */
+ mcnt = *p++;
+ /* This is written out as an if-else so we don't waste time
+ testing `translate' inside the loop. */
+ if (TRANSLATE_P()) {
+ do {
+ unsigned char c;
- case exactn:
- /* Match the next few pattern characters exactly.
- mcnt is how many characters to match. */
- mcnt = *p++;
- /* This is written out as an if-else so we don't waste time
- testing `translate' inside the loop. */
- if (TRANSLATE_P())
- {
- do
- {
- unsigned char c;
-
- PREFETCH;
- c = *d++;
- if (*p == 0xff) {
- p++;
- if (!--mcnt
- || AT_STRINGS_END(d)
- || (unsigned char)*d++ != (unsigned char)*p++)
- goto fail;
- continue;
- }
- if (ismbchar(c)) {
- if (c != (unsigned char)*p++
- || !--mcnt /* redundant check if pattern was
- compiled properly. */
- || AT_STRINGS_END(d)
- || (unsigned char)*d++ != (unsigned char)*p++)
- goto fail;
- continue;
- }
- /* compiled code translation needed for ruby */
- if ((unsigned char)translate[c]
- != (unsigned char)translate[*p++])
- goto fail;
- }
- while (--mcnt);
+ PREFETCH;
+ c = *d++;
+ if (*p == 0xff) {
+ p++;
+ if (!--mcnt
+ || AT_STRINGS_END(d)
+ || (unsigned char)*d++ != (unsigned char)*p++)
+ goto fail;
+ continue;
}
- else
- {
- do
- {
- PREFETCH;
- if (*p == 0xff) {p++; mcnt--;}
- if (*d++ != *p++) goto fail;
- }
- while (--mcnt);
+ if (ismbchar(c)) {
+ int n;
+
+ if (c != (unsigned char)*p++)
+ goto fail;
+ for (n = mbclen(c) - 1; n > 0; n--)
+ if (!--mcnt /* redundant check if pattern was
+ compiled properly. */
+ || AT_STRINGS_END(d)
+ || (unsigned char)*d++ != (unsigned char)*p++)
+ goto fail;
+ continue;
}
- SET_REGS_MATCHED;
- break;
+ /* compiled code translation needed for ruby */
+ if ((unsigned char)translate[c] != (unsigned char)translate[*p++])
+ goto fail;
+ }
+ while (--mcnt);
}
- while (stackp != stackb && (int)stackp[-1] == 1)
- POP_FAILURE_POINT();
- continue; /* Successfully executed one pattern command; keep going. */
+ else {
+ do {
+ PREFETCH;
+ if (*p == 0xff) {p++; mcnt--;}
+ if (*d++ != *p++) goto fail;
+ }
+ while (--mcnt);
+ }
+ SET_REGS_MATCHED;
+ break;
+ }
+ continue; /* Successfully executed one pattern command; keep going. */
/* Jump here if any matching operation fails. */
- fail:
- if (stackp != stackb)
- /* A restart point is known. Restart there and pop it. */
- {
- short last_used_reg, this_reg;
+ fail:
+ if (stackp != stackb) {
+ /* A restart point is known. Restart there and pop it. */
+ short last_used_reg, this_reg;
+
+ /* If this failure point is from a dummy_failure_point, just
+ skip it. */
+ if (stackp[-3] == 0 || (best_regs_set && stackp[-1] == NON_GREEDY)) {
+ POP_FAILURE_POINT();
+ goto fail;
+ }
+ stackp--; /* discard flag */
+ d = *--stackp;
+ p = *--stackp;
+ /* Restore register info. */
+ last_used_reg = (long)*--stackp;
+
+ /* Make the ones that weren't saved -1 or 0 again. */
+ for (this_reg = num_regs - 1; this_reg > last_used_reg; this_reg--) {
+ regend[this_reg] = REG_UNSET_VALUE;
+ regstart[this_reg] = REG_UNSET_VALUE;
+ IS_ACTIVE(reg_info[this_reg]) = 0;
+ MATCHED_SOMETHING(reg_info[this_reg]) = 0;
+ }
- /* If this failure point is from a dummy_failure_point, just
- skip it. */
- if (stackp[-3] == 0) {
- POP_FAILURE_POINT();
+ /* And restore the rest from the stack. */
+ for ( ; this_reg > 0; this_reg--) {
+ reg_info[this_reg].word = *--stackp;
+ regend[this_reg] = *--stackp;
+ regstart[this_reg] = *--stackp;
+ }
+ if (p < pend) {
+ int is_a_jump_n = 0;
+ int failed_paren = 0;
+
+ p1 = p;
+ /* If failed to a backwards jump that's part of a repetition
+ loop, need to pop this failure point and use the next one. */
+ pop_loop:
+ switch ((enum regexpcode)*p1) {
+ case jump_n:
+ case finalize_push_n:
+ is_a_jump_n = 1;
+ case maybe_finalize_jump:
+ case finalize_jump:
+ case finalize_push:
+ case jump:
+ p1++;
+ EXTRACT_NUMBER_AND_INCR (mcnt, p1);
+ p1 += mcnt;
+
+ if (p1 >= pend) break;
+ if (( is_a_jump_n && (enum regexpcode)*p1 == succeed_n) ||
+ (!is_a_jump_n && (enum regexpcode)*p1 == on_failure_jump)) {
+ if (failed_paren) {
+ p1++;
+ EXTRACT_NUMBER_AND_INCR(mcnt, p1);
+ PUSH_FAILURE_POINT(p1 + mcnt, d);
+ }
goto fail;
}
- stackp--; /* discard flag */
- d = *--stackp;
- p = *--stackp;
- /* Restore register info. */
- last_used_reg = (long)*--stackp;
-
- /* Make the ones that weren't saved -1 or 0 again. */
- for (this_reg = num_regs - 1; this_reg > last_used_reg; this_reg--)
- {
- regend[this_reg] = REG_UNSET_VALUE;
- regstart[this_reg] = REG_UNSET_VALUE;
- IS_ACTIVE(reg_info[this_reg]) = 0;
- MATCHED_SOMETHING(reg_info[this_reg]) = 0;
- }
-
- /* And restore the rest from the stack. */
- for ( ; this_reg > 0; this_reg--)
- {
- reg_info[this_reg].word = *--stackp;
- regend[this_reg] = *--stackp;
- regstart[this_reg] = *--stackp;
- }
- if (p < pend)
- {
- int is_a_jump_n = 0;
- int failed_paren = 0;
-
- p1 = p;
- /* If failed to a backwards jump that's part of a repetition
- loop, need to pop this failure point and use the next one. */
- pop_loop:
- switch ((enum regexpcode)*p1) {
- case stop_paren:
- failed_paren = 1;
- p1++;
- goto pop_loop;
-
- case jump_n:
- case finalize_push_n:
- is_a_jump_n = 1;
- case maybe_finalize_jump:
- case finalize_jump:
- case finalize_push:
- case jump:
- p1++;
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- p1 += mcnt;
-
- if (p1 >= pend) break;
- if (( is_a_jump_n && (enum regexpcode)*p1 == succeed_n) ||
- (!is_a_jump_n && (enum regexpcode)*p1 == on_failure_jump)) {
- if (failed_paren) {
- p1++;
- EXTRACT_NUMBER_AND_INCR(mcnt, p1);
- PUSH_FAILURE_POINT(p1 + mcnt, d);
- }
- goto fail;
- }
- break;
- default:
- /* do nothing */ ;
- }
- }
- }
- else
- break; /* Matching at this starting point really fails. */
+ break;
+ default:
+ /* do nothing */;
+ }
+ }
}
+ else
+ break; /* Matching at this starting point really fails. */
+ }
if (best_regs_set)
goto restore_best_regs;
+ FREE_VARIABLES();
FREE_AND_RETURN(stackb,(-1)); /* Failure to match. */
}
-/* We are passed P pointing to a register number after a start_memory.
-
- Return true if the pattern up to the corresponding stop_memory can
- match the empty string, and false otherwise.
-
- If we find the matching stop_memory, sets P to point to one past its number.
- Otherwise, sets P to an undefined byte less than or equal to END.
-
- We don't handle duplicates properly (yet). */
-
-static int
-group_match_null_string_p (p, end, reg_info)
- unsigned char **p, *end;
- register_info_type *reg_info;
-{
- int mcnt;
- /* Point to after the args to the start_memory. */
- unsigned char *p1 = *p + 2;
-
- while (p1 < end)
- {
- /* Skip over opcodes that can match nothing, and return true or
- false, as appropriate, when we get to one that can't, or to the
- matching stop_memory. */
-
- switch ((enum regexpcode)*p1)
- {
- /* Could be either a loop or a series of alternatives. */
- case on_failure_jump:
- p1++;
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-
- /* If the next operation is not a jump backwards in the
- pattern. */
-
- if (mcnt >= 0)
- {
- /* Go through the on_failure_jumps of the alternatives,
- seeing if any of the alternatives cannot match nothing.
- The last alternative starts with only a jump,
- whereas the rest start with on_failure_jump and end
- with a jump, e.g., here is the pattern for `a|b|c':
-
- /on_failure_jump/0/6/exactn/1/a/jump_past_alt/0/6
- /on_failure_jump/0/6/exactn/1/b/jump_past_alt/0/3
- /exactn/1/c
-
- So, we have to first go through the first (n-1)
- alternatives and then deal with the last one separately. */
-
-
- /* Deal with the first (n-1) alternatives, which start
- with an on_failure_jump (see above) that jumps to right
- past a jump_past_alt. */
-
- while ((enum regexpcode)p1[mcnt-3] == jump_past_alt)
- {
- /* `mcnt' holds how many bytes long the alternative
- is, including the ending `jump_past_alt' and
- its number. */
-
- if (!alt_match_null_string_p (p1, p1 + mcnt - 3,
- reg_info))
- return 0;
-
- /* Move to right after this alternative, including the
- jump_past_alt. */
- p1 += mcnt;
-
- /* Break if it's the beginning of an n-th alternative
- that doesn't begin with an on_failure_jump. */
- if ((enum regexpcode)*p1 != on_failure_jump)
- break;
-
- /* Still have to check that it's not an n-th
- alternative that starts with an on_failure_jump. */
- p1++;
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- if ((enum regexpcode)p1[mcnt-3] != jump_past_alt)
- {
- /* Get to the beginning of the n-th alternative. */
- p1 -= 3;
- break;
- }
- }
-
- /* Deal with the last alternative: go back and get number
- of the `jump_past_alt' just before it. `mcnt' contains
- the length of the alternative. */
- EXTRACT_NUMBER (mcnt, p1 - 2);
-#if 0
- if (!alt_match_null_string_p (p1, p1 + mcnt, reg_info))
- return 0;
-#endif
- p1 += mcnt; /* Get past the n-th alternative. */
- } /* if mcnt > 0 */
- break;
-
-
- case stop_memory:
- *p = p1 + 2;
- return 1;
-
-
- default:
- if (!common_op_match_null_string_p (&p1, end, reg_info))
- return 0;
- }
- } /* while p1 < end */
-
- return 0;
-} /* group_match_null_string_p */
-
-
-/* Similar to group_match_null_string_p, but doesn't deal with alternatives:
- It expects P to be the first byte of a single alternative and END one
- byte past the last. The alternative can contain groups. */
-
-static int
-alt_match_null_string_p (p, end, reg_info)
- unsigned char *p, *end;
- register_info_type *reg_info;
-{
- int mcnt;
- unsigned char *p1 = p;
-
- while (p1 < end)
- {
- /* Skip over opcodes that can match nothing, and break when we get
- to one that can't. */
-
- switch ((enum regexpcode)*p1)
- {
- /* It's a loop. */
- case on_failure_jump:
- p1++;
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- p1 += mcnt;
- break;
-
- default:
- if (!common_op_match_null_string_p (&p1, end, reg_info))
- return 0;
- }
- } /* while p1 < end */
-
- return 1;
-} /* alt_match_null_string_p */
-
-
-/* Deals with the ops common to group_match_null_string_p and
- alt_match_null_string_p.
-
- Sets P to one after the op and its arguments, if any. */
-
-static int
-common_op_match_null_string_p (p, end, reg_info)
- unsigned char **p, *end;
- register_info_type *reg_info;
-{
- int mcnt;
- int ret;
- int reg_no;
- unsigned char *p1 = *p;
-
- switch ((enum regexpcode)*p1++)
- {
- case unused:
- case begline:
- case endline:
- case begbuf:
- case endbuf:
- case endbuf2:
- case wordbeg:
- case wordend:
- case wordbound:
- case notwordbound:
-#ifdef emacs
- case before_dot:
- case at_dot:
- case after_dot:
-#endif
- break;
-
- case start_memory:
- reg_no = *p1;
- ret = group_match_null_string_p (&p1, end, reg_info);
-
- /* Have to set this here in case we're checking a group which
- contains a group and a back reference to it. */
-
- if (REG_MATCH_NULL_STRING_P (reg_info[reg_no]) == MATCH_NULL_UNSET_VALUE)
- REG_MATCH_NULL_STRING_P (reg_info[reg_no]) = ret;
-
- if (!ret)
- return 0;
- break;
-
- /* If this is an optimized succeed_n for zero times, make the jump. */
- case jump:
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- if (mcnt >= 0)
- p1 += mcnt;
- else
- return 0;
- break;
-
- case succeed_n:
- /* Get to the number of times to succeed. */
- p1 += 2;
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
-
- if (mcnt == 0)
- {
- p1 -= 4;
- EXTRACT_NUMBER_AND_INCR (mcnt, p1);
- p1 += mcnt;
- }
- else
- return 0;
- break;
-
- case duplicate:
- if (!REG_MATCH_NULL_STRING_P (reg_info[*p1]))
- return 0;
- break;
-
- case set_number_at:
- p1 += 4;
-
- default:
- /* All other opcodes mean we cannot match the empty string. */
- return 0;
- }
-
- *p = p1;
- return 1;
-} /* common_op_match_null_string_p */
-
-
static int
memcmp_translate(s1, s2, len)
unsigned char *s1, *s2;
register int len;
{
register unsigned char *p1 = s1, *p2 = s2, c;
- while (len)
- {
- c = *p1++;
- if (ismbchar(c)) {
- if (c != *p2++) return 1;
- if (memcmp(p1, p2, ismbchar(c))) return 1;
- }
- else
- if (translate[c] != translate[*p2++])
+ while (len) {
+ c = *p1++;
+ if (ismbchar(c)) {
+ int n;
+
+ if (c != *p2++) return 1;
+ for (n = mbclen(c) - 1; n > 0; n--)
+ if (!--len || *p1++ != *p2++)
return 1;
- len--;
}
+ else
+ if (translate[c] != translate[*p2++])
+ return 1;
+ len--;
+ }
return 0;
}
@@ -4280,33 +4135,33 @@ void
re_copy_registers(regs1, regs2)
struct re_registers *regs1, *regs2;
{
- int i;
+ int i;
- if (regs1 == regs2) return;
- if (regs1->allocated == 0) {
- regs1->beg = TMALLOC(regs2->num_regs, int);
- regs1->end = TMALLOC(regs2->num_regs, int);
- regs1->allocated = regs2->num_regs;
- }
- else if (regs1->allocated < regs2->num_regs) {
- TREALLOC(regs1->beg, regs2->num_regs, int);
- TREALLOC(regs1->end, regs2->num_regs, int);
- regs1->allocated = regs2->num_regs;
- }
- for (i=0; i<regs2->num_regs; i++) {
- regs1->beg[i] = regs2->beg[i];
- regs1->end[i] = regs2->end[i];
- }
- regs1->num_regs = regs2->num_regs;
+ if (regs1 == regs2) return;
+ if (regs1->allocated == 0) {
+ regs1->beg = TMALLOC(regs2->num_regs, int);
+ regs1->end = TMALLOC(regs2->num_regs, int);
+ regs1->allocated = regs2->num_regs;
+ }
+ else if (regs1->allocated < regs2->num_regs) {
+ TREALLOC(regs1->beg, regs2->num_regs, int);
+ TREALLOC(regs1->end, regs2->num_regs, int);
+ regs1->allocated = regs2->num_regs;
+ }
+ for (i=0; i<regs2->num_regs; i++) {
+ regs1->beg[i] = regs2->beg[i];
+ regs1->end[i] = regs2->end[i];
+ }
+ regs1->num_regs = regs2->num_regs;
}
void
re_free_registers(regs)
struct re_registers *regs;
{
- if (regs->allocated == 0) return;
- if (regs->beg) free(regs->beg);
- if (regs->end) free(regs->end);
+ if (regs->allocated == 0) return;
+ if (regs->beg) free(regs->beg);
+ if (regs->end) free(regs->end);
}
/* Functions for multi-byte support.
diff --git a/regex.h b/regex.h
index f61b980648..b9619a7dbf 100644
--- a/regex.h
+++ b/regex.h
@@ -17,11 +17,25 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
/* Multi-byte extension added May, 1993 by t^2 (Takahiro Tanimoto)
Last change: May 21, 1993 by t^2 */
-/* modifis for Ruby by matz@caelum.co.jp */
+/* modified for Ruby by matz@netlab.co.jp */
#ifndef __REGEXP_LIBRARY
#define __REGEXP_LIBRARY
+/* symbol mangling for ruby */
+#ifdef RUBY
+# define re_compile_fastmap ruby_re_compile_fastmap
+# define re_compile_pattern ruby_re_compile_pattern
+# define re_copy_registers ruby_re_copy_registers
+# define re_free_pattern ruby_re_free_pattern
+# define re_free_registers ruby_re_free_registers
+# define re_match ruby_re_match
+# define re_mbcinit ruby_re_mbcinit
+# define re_search ruby_re_search
+# define re_set_casetable ruby_re_set_casetable
+# define register_info_type ruby_register_info_type
+#endif
+
#include <stddef.h>
/* Define number of parens for which we record the beginnings and ends.
@@ -46,12 +60,19 @@
If not set, then character classes are not supported. */
#define RE_CHAR_CLASSES (1L << 9)
-#define RE_OPTION_EXTENDED (1L<<0)
-#define RE_OPTION_IGNORECASE (1L<<1)
-#define RE_MAY_IGNORECASE (1L<<2)
-#define RE_OPTIMIZE_ANCHOR (1L<<4)
-#define RE_OPTIMIZE_EXACTN (1L<<5)
-#define RE_OPTIMIZE_NO_BM (1L<<6)
+/* match will be done case insensetively */
+#define RE_OPTION_IGNORECASE (1L)
+/* perl-style extended pattern available */
+#define RE_OPTION_EXTENDED (RE_OPTION_IGNORECASE<<1)
+/* newline will be included for . and invert charclass matches */
+#define RE_OPTION_POSIXLINE (RE_OPTION_EXTENDED<<1)
+/* search for longest match, in accord with POSIX regexp */
+#define RE_OPTION_LONGEST (RE_OPTION_POSIXLINE<<1)
+
+#define RE_MAY_IGNORECASE (RE_OPTION_LONGEST<<1)
+#define RE_OPTIMIZE_ANCHOR (RE_MAY_IGNORECASE<<1)
+#define RE_OPTIMIZE_EXACTN (RE_OPTIMIZE_ANCHOR<<1)
+#define RE_OPTIMIZE_NO_BM (RE_OPTIMIZE_EXACTN<<1)
/* For multi-byte char support */
#define MBCTYPE_ASCII 0
@@ -59,11 +80,10 @@
#define MBCTYPE_SJIS 2
#define MBCTYPE_UTF8 3
-#ifdef __STDC__
extern const unsigned char *re_mbctab;
+#if defined(__STDC__)
void re_mbcinit (int);
#else
-extern unsigned char *re_mbctab;
void re_mbcinit ();
#endif
@@ -71,13 +91,24 @@ void re_mbcinit ();
#define ismbchar(c) re_mbctab[(unsigned char)(c)]
#define mbclen(c) (re_mbctab[(unsigned char)(c)]+1)
+/* Structure used in re_match() */
+
+typedef union
+{
+ unsigned char *word;
+ struct {
+ unsigned is_active : 1;
+ unsigned matched_something : 1;
+ } bits;
+} register_info_type;
+
/* This data structure is used to represent a compiled pattern. */
struct re_pattern_buffer
{
char *buffer; /* Space holding the compiled pattern commands. */
- size_t allocated; /* Size of space that `buffer' points to. */
- size_t used; /* Length of portion of buffer actually occupied */
+ int allocated; /* Size of space that `buffer' points to. */
+ int used; /* Length of portion of buffer actually occupied */
char *fastmap; /* Pointer to fastmap, if any, or zero if none. */
/* re_search uses the fastmap, if there is one,
to skip over totally implausible characters. */
@@ -97,6 +128,15 @@ struct re_pattern_buffer
2 as value means can match null string
but at end of range or before a character
listed in the fastmap. */
+
+ /* stack & working area for re_match() */
+ unsigned char **regstart;
+ unsigned char **regend;
+ unsigned char **old_regstart;
+ unsigned char **old_regend;
+ register_info_type *reg_info;
+ unsigned char **best_regstart;
+ unsigned char **best_regend;
};
typedef struct re_pattern_buffer regex_t;
@@ -113,8 +153,8 @@ typedef struct re_pattern_buffer regex_t;
struct re_registers
{
- size_t allocated;
- size_t num_regs;
+ int allocated;
+ int num_regs;
int *beg;
int *end;
};
@@ -138,22 +178,22 @@ typedef struct
#ifdef __STDC__
-extern char *re_compile_pattern (char *, size_t, struct re_pattern_buffer *);
+extern char *re_compile_pattern (const char *, int, struct re_pattern_buffer *);
void re_free_pattern (struct re_pattern_buffer *);
/* Is this really advertised? */
extern void re_compile_fastmap (struct re_pattern_buffer *);
-extern int re_search (struct re_pattern_buffer *, char*, size_t, size_t, size_t,
+extern int re_search (struct re_pattern_buffer *, const char*, int, int, int,
struct re_registers *);
-extern int re_match (struct re_pattern_buffer *, char *, size_t, size_t,
+extern int re_match (struct re_pattern_buffer *, const char *, int, int,
struct re_registers *);
-extern void re_set_casetable (char *table);
+extern void re_set_casetable (const char *table);
extern void re_copy_registers (struct re_registers*, struct re_registers*);
extern void re_free_registers (struct re_registers*);
#ifndef RUBY
/* 4.2 bsd compatibility. */
-extern char *re_comp (char *);
-extern int re_exec (char *);
+extern char *re_comp (const char *);
+extern int re_exec (const char *);
#endif
#else /* !__STDC__ */
diff --git a/ruby.1 b/ruby.1
index 8665ca79bb..677d71741f 100644
--- a/ruby.1
+++ b/ruby.1
@@ -1,6 +1,6 @@
.\"Ruby is copyrighted by Yukihiro Matsumoto <matz@netlab.co.jp>.
.na
-.TH RUBY 1 "ruby 1.3" "18/Jan/99" "Ruby Programmers Reference Guide"
+.TH RUBY 1 "ruby 1.4" "13/Aug/99" "Ruby Programmers Reference Guide"
.SH NAME
ruby - Interpreted object-oriented scripting language
.SH SYNOPSIS
@@ -161,8 +161,7 @@ OK" to the standard output.
.B -Kc
specifies KANJI (Japanese) code-set.
.TP
-.B
--d --debug
+.B -d --debug
turns on debug mode. $DEBUG will set TRUE.
.TP
.B -e script
@@ -172,6 +171,9 @@ search argv for script filenames.
.B -F regexp
specifies input field separator ($;).
.TP
+.B -h --help
+prints a summary of the options.
+.TP
.B -i extension
specifies in-place-edit mode. The extension, if specified, is
added to old filename to make a backup copy.
diff --git a/ruby.c b/ruby.c
index 9bf28022e8..51a9d991af 100644
--- a/ruby.c
+++ b/ruby.c
@@ -6,7 +6,7 @@
$Date$
created at: Tue Aug 10 12:47:31 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -18,7 +18,6 @@
#include "node.h"
#include <stdio.h>
#include <sys/types.h>
-#include <fcntl.h>
#include <ctype.h>
#ifdef __hpux
@@ -34,9 +33,9 @@
#endif
#ifndef HAVE_STRING_H
-char *strchr _((char*,char));
-char *strrchr _((char*,char));
-char *strstr _((char*,char*));
+char *strchr _((const char*,const char));
+char *strrchr _((const char*,const char));
+char *strstr _((const char*,const char*));
#endif
#include "util.h"
@@ -47,20 +46,21 @@ char *getenv();
static int version, copyright;
-VALUE rb_debug = Qfalse;
-VALUE rb_verbose = Qfalse;
-int rb_tainting = Qfalse;
+VALUE ruby_debug = Qfalse;
+VALUE ruby_verbose = Qfalse;
static int sflag = Qfalse;
char *ruby_inplace_mode = Qfalse;
+# ifndef strdup
char *strdup();
+# endif
extern int yydebug;
static int xflag = Qfalse;
static void load_stdin _((void));
static void load_file _((char *, int));
-static void forbid_setid _((char *));
+static void forbid_setid _((const char *));
static VALUE do_loop = Qfalse, do_print = Qfalse;
static VALUE do_check = Qfalse, do_line = Qfalse;
@@ -71,6 +71,46 @@ static char *script;
static int origargc;
static char **origargv;
+static void
+usage(name)
+ const char *name;
+{
+ /* This message really ought to be max 23 lines.
+ * Removed -h because the user already knows that opton. Others? */
+
+ static char *usage_msg[] = {
+"-0[octal] specify record separator (\\0, if no argument)",
+"-a autosplit mode with -n or -p (splits $_ into $F)",
+"-c check syntax only",
+"-d set debugging flags (set $DEBUG to true)",
+"-e 'command' one line of script. Several -e's allowed. Omit [programfile]",
+"-Fpattern split() pattern for autosplit (-a)",
+"-i[extension] edit ARGV files in place (make backup if extension supplied)",
+"-Idirectory specify $LOAD_PATH directory (may be used more than once)",
+"-K[kcode] specifies KANJI (Japanese) code-set",
+"-l enable line ending processing",
+"-n assume 'while gets; ...; end' loop around your script",
+"-p assume loop like -n but print line also like sed",
+"-rlibrary require the library, before executing your script",
+"-s enable some switch parsing for switches after script name",
+"-S look for the script using PATH environment variable",
+"-T[level] turn on tainting checks",
+"-v enables verbose mode",
+"-w turn warnings on for compilation of your script",
+"-x[directory] strip off text before #!ruby line and perhaps cd to directory",
+"-X[directory] cd to directory, before executing your script",
+"--copyright print the copyright",
+"--version print the version",
+"\n",
+NULL
+};
+ char **p = usage_msg;
+
+ printf("\nUsage: %s [switches] [--] [programfile] [arguments]", name);
+ while (*p)
+ printf("\n %s", *p++);
+}
+
#ifndef RUBY_LIB
#define RUBY_LIB "/usr/local/lib/ruby"
#endif
@@ -83,52 +123,109 @@ extern VALUE rb_load_path;
static FILE *e_fp;
static char *e_tmpname;
+#define STATIC_FILE_LENGTH 255
+
+#if defined(_WIN32) || defined(DJGPP)
+static char *
+rubylib_mangle(s, l)
+ char *s;
+ unsigned int l;
+{
+ static char *newp, *oldp;
+ static int newl, oldl, notfound;
+ static char ret[STATIC_FILE_LENGTH+1];
+
+ if (!newp && !notfound) {
+ newp = getenv("RUBYLIB_PREFIX");
+ if (newp) {
+ char *s;
+
+ oldp = newp;
+ while (*newp && !ISSPACE(*newp) && *newp != ';') {
+ newp++; oldl++; /* Skip digits. */
+ }
+ while (*newp && (ISSPACE(*newp) || *newp == ';')) {
+ newp++; /* Skip whitespace. */
+ }
+ newl = strlen(newp);
+ if (newl == 0 || oldl == 0 || newl > STATIC_FILE_LENGTH) {
+ rb_fatal("malformed RUBYLIB_PREFIX");
+ }
+ strcpy(ret, newp);
+ s = ret;
+ while (*s) {
+ if (*s == '\\') *s = '/';
+ s++;
+ }
+ } else {
+ notfound = 1;
+ }
+ }
+ if (!newp) {
+ return s;
+ }
+ if (l == 0) {
+ l = strlen(s);
+ }
+ if (l < oldl || strncasecmp(oldp, s, oldl) != 0) {
+ return s;
+ }
+ if (l + newl - oldl > STATIC_FILE_LENGTH || newl > STATIC_FILE_LENGTH) {
+ rb_fatal("malformed RUBYLIB_PREFIX");
+ }
+ strcpy(ret + newl, s + oldl);
+ return ret;
+}
+#else
+#define rubylib_mangle(s, l) (s)
+#endif
+
static void
addpath(path)
- char *path;
+ const char *path;
{
- const char sep = RUBY_PATH_SEP[0];
+ const char sep = PATH_SEP_CHAR;
if (path == 0) return;
#if defined(__CYGWIN32__)
{
char rubylib[FILENAME_MAX];
- conv_to_posix_path(path, rubylib);
+ conv_to_posix_path(path, rubylib, FILENAME_MAX);
path = rubylib;
}
#endif
if (strchr(path, sep)) {
- char *p, *s;
+ const char *p, *s;
VALUE ary = rb_ary_new();
p = path;
while (*p) {
while (*p == sep) p++;
if (s = strchr(p, sep)) {
- rb_ary_push(ary, rb_str_new(p, (int)(s-p)));
+ rb_ary_push(ary, rb_str_new(rubylib_mangle(p, (int)(s-p)), (int)(s-p)));
p = s + 1;
}
else {
- rb_ary_push(ary, rb_str_new2(p));
+ rb_ary_push(ary, rb_str_new2(rubylib_mangle(p, 0)));
break;
}
}
rb_load_path = rb_ary_plus(ary, rb_load_path);
}
else {
- rb_ary_unshift(rb_load_path, rb_str_new2(path));
+ rb_ary_unshift(rb_load_path, rb_str_new2(rubylib_mangle(path, 0)));
}
}
struct req_list {
- char *name;
+ const char *name;
struct req_list *next;
} req_list_head;
struct req_list *req_list_last = &req_list_head;
static void
add_modules(mod)
- char *mod;
+ const char *mod;
{
struct req_list *list;
@@ -140,14 +237,14 @@ add_modules(mod)
}
void
-ruby_require_modules()
+ruby_require_libraries()
{
struct req_list *list = req_list_head.next;
struct req_list *tmp;
req_list_last = 0;
while (list) {
- rb_f_require(Qnil, rb_str_new2(list->name));
+ rb_require(list->name);
tmp = list->next;
free(list);
list = tmp;
@@ -193,8 +290,8 @@ proc_options(argcp, argvp)
goto reswitch;
case 'd':
- rb_debug = Qtrue;
- rb_verbose |= 1;
+ ruby_debug = Qtrue;
+ ruby_verbose |= 1;
s++;
goto reswitch;
@@ -205,9 +302,9 @@ proc_options(argcp, argvp)
case 'v':
ruby_show_version();
- rb_verbose = 2;
+ ruby_verbose = 2;
case 'w':
- rb_verbose |= 1;
+ ruby_verbose |= 1;
s++;
goto reswitch;
@@ -222,6 +319,10 @@ proc_options(argcp, argvp)
s++;
goto reswitch;
+ case 'h':
+ usage(origargv[0]);
+ exit(0);
+
case 'l':
do_line = Qtrue;
rb_output_rs = rb_rs;
@@ -236,6 +337,14 @@ proc_options(argcp, argvp)
case 'e':
forbid_setid("-e");
+ if (!*++s) {
+ s = argv[1];
+ argc--,argv++;
+ }
+ if (!s) {
+ fprintf(stderr, "%s: no code specified for -e\n", origargv[0]);
+ exit(2);
+ }
if (!e_fp) {
e_tmpname = ruby_mktemp();
if (!e_tmpname) rb_fatal("Can't mktemp");
@@ -245,10 +354,7 @@ proc_options(argcp, argvp)
}
if (script == 0) script = e_tmpname;
}
- if (argv[1]) {
- fputs(argv[1], e_fp);
- argc--, argv++;
- }
+ fputs(s, e_fp);
putc('\n', e_fp);
break;
@@ -308,7 +414,6 @@ proc_options(argcp, argvp)
if (numlen == 0) v = 1;
}
rb_set_safe_level(v);
- rb_tainting = Qtrue;
}
break;
@@ -350,15 +455,21 @@ proc_options(argcp, argvp)
if (strcmp("copyright", s) == 0)
copyright = 1;
else if (strcmp("debug", s) == 0)
- rb_debug = 1;
+ ruby_debug = 1;
else if (strcmp("version", s) == 0)
version = 1;
else if (strcmp("verbose", s) == 0)
- rb_verbose = 2;
+ ruby_verbose = 2;
else if (strcmp("yydebug", s) == 0)
yydebug = 1;
+ else if (strcmp("help", s) == 0) {
+ usage(origargv[0]);
+ exit(0);
+ }
else {
- rb_fatal("Unrecognized long option: --%s",s);
+ fprintf(stderr, "%s: invalid option --%s (-h will show valid options)\n",
+ origargv[0], s);
+ exit(2);
}
break;
@@ -368,7 +479,9 @@ proc_options(argcp, argvp)
break;
default:
- rb_fatal("Unrecognized switch: -%s",s);
+ fprintf(stderr, "%s: invalid option -%c (-h will show valid options)\n",
+ origargv[0], *s);
+ exit(2);
case 0:
break;
@@ -397,7 +510,7 @@ proc_options(argcp, argvp)
Init_ext(); /* should be called here for some reason :-( */
if (script_given == Qfalse) {
if (argc == 0) { /* no more args */
- if (rb_verbose == 3) exit(0);
+ if (ruby_verbose == 3) exit(0);
script = "-";
load_stdin();
}
@@ -425,8 +538,8 @@ proc_options(argcp, argvp)
argc--; argv++;
}
}
- if (rb_verbose) rb_verbose = Qtrue;
- if (rb_debug) rb_debug = Qtrue;
+ if (ruby_verbose) ruby_verbose = Qtrue;
+ if (ruby_debug) ruby_debug = Qtrue;
xflag = Qfalse;
*argvp = argv;
@@ -491,6 +604,12 @@ load_file(fname, script)
xflag = Qfalse;
while (!NIL_P(line = rb_io_gets(f))) {
line_start++;
+#if defined(__EMX__) || defined(OS2)
+/*
+ if (p = strstr(RSTRING(line)->ptr, "extproc"))
+ line = io_gets(f);
+*/
+#endif /* __EMX__ */
if (RSTRING(line)->len > 2
&& RSTRING(line)->ptr[0] == '#'
&& RSTRING(line)->ptr[1] == '!') {
@@ -514,7 +633,7 @@ load_file(fname, script)
char *path;
char *pend = RSTRING(line)->ptr + RSTRING(line)->len;
- p = RSTRING(line)->ptr + 2; /* skip `#!' */
+ p = RSTRING(line)->ptr + 1; /* skip `#!' */
if (pend[-1] == '\n') pend--; /* chomp line */
if (pend[-1] == '\r') pend--;
*pend = '\0';
@@ -547,10 +666,10 @@ load_file(fname, script)
if (RSTRING(line)->ptr[RSTRING(line)->len-2] == '\r')
RSTRING(line)->ptr[RSTRING(line)->len-2] = '\0';
if (p = strstr(p, " -")) {
- int argc; char *argv[2]; char **argvp = argv;
+ int argc; char *argv[3]; char **argvp = argv;
char *s = ++p;
- argc = 2; argv[0] = 0;
+ argc = 2; argv[0] = argv[2] = 0;
while (*p == '-') {
while (*s && !ISSPACE(*s))
s++;
@@ -678,7 +797,7 @@ init_ids()
static void
forbid_setid(s)
- char *s;
+ const char *s;
{
if (euid != uid)
rb_raise(rb_eSecurityError, "No %s allowed while running setuid", s);
@@ -701,10 +820,15 @@ ruby_libpath()
strcpy(libpath, __dos_argv0);
#endif
p = strrchr(libpath, '\\');
- if (p)
+ if (p) {
*p = 0;
- if (!strcasecmp(p-4, "\\bin"))
- p -= 4;
+ if (!strcasecmp(p-4, "\\bin"))
+ p -= 4;
+ } else {
+ strcpy(libpath, ".");
+ p = libpath + 1;
+ }
+
strcpy(p, "\\lib");
#if defined(__CYGWIN32__)
p = (char *)malloc(strlen(libpath)+10);
@@ -728,10 +852,10 @@ ruby_prog_init()
init_ids();
ruby_sourcefile = "ruby";
- rb_define_variable("$VERBOSE", &rb_verbose);
- rb_define_variable("$-v", &rb_verbose);
- rb_define_variable("$DEBUG", &rb_debug);
- rb_define_variable("$-d", &rb_debug);
+ rb_define_variable("$VERBOSE", &ruby_verbose);
+ rb_define_variable("$-v", &ruby_verbose);
+ rb_define_variable("$DEBUG", &ruby_debug);
+ rb_define_variable("$-d", &ruby_debug);
rb_define_readonly_variable("$-p", &do_print);
rb_define_readonly_variable("$-l", &do_line);
@@ -743,9 +867,6 @@ ruby_prog_init()
#if defined(_WIN32) || defined(DJGPP)
addpath(ruby_libpath());
#endif
-#ifdef __MACOS__
- setup_macruby_libpath();
-#endif
#ifdef RUBY_ARCHLIB
addpath(RUBY_ARCHLIB);
@@ -762,6 +883,10 @@ ruby_prog_init()
addpath(RUBY_SITE_THIN_ARCHLIB);
#endif
+#ifdef RUBY_SEARCH_PATH
+ addpath(RUBY_SEARCH_PATH);
+#endif
+
if (rb_safe_level() == 0) {
addpath(getenv("RUBYLIB"));
}
diff --git a/ruby.h b/ruby.h
index 44c1abd2c6..765fd75ee8 100644
--- a/ruby.h
+++ b/ruby.h
@@ -3,10 +3,9 @@
ruby.h -
$Author$
- $Date$
created at: Thu Jun 10 14:26:32 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
*************************************************/
@@ -20,12 +19,6 @@ extern "C" {
#include "config.h"
#include "defines.h"
-#if 0
-#ifndef RUBY_RENAME
-#include "rename2.h"
-#endif
-#endif
-
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif
@@ -40,10 +33,11 @@ extern "C" {
#include <stdio.h>
/* need to include <ctype.h> to use these macros */
+#undef ISPRINT
+#define ISPRINT(c) isprint((unsigned char)(c))
#define ISSPACE(c) isspace((unsigned char)(c))
#define ISUPPER(c) isupper((unsigned char)(c))
#define ISLOWER(c) islower((unsigned char)(c))
-#define ISPRINT(c) isprint((unsigned char)(c))
#define ISALNUM(c) isalnum((unsigned char)(c))
#define ISALPHA(c) isalpha((unsigned char)(c))
#define ISDIGIT(c) isdigit((unsigned char)(c))
@@ -51,19 +45,16 @@ extern "C" {
#ifndef __STDC__
# define volatile
-# ifdef __GNUC__
-# define const __const__
-# else
-# define const
-# endif
#endif
+#undef _
#ifdef HAVE_PROTOTYPES
# define _(args) args
#else
# define _(args) ()
#endif
+#undef __
#ifdef HAVE_STDARG_PROTOTYPES
# define __(args) args
#else
@@ -81,12 +72,14 @@ extern "C" {
#endif
#if defined(__CYGWIN32__)
-#if defined(DLLIMPORT)
+#if defined(USEIMPORTLIB)
#include "import.h"
#else
+#if !defined(__CYGWIN__)
#define environ (*__imp___cygwin_environ)
#endif
#endif
+#endif
#ifdef _AIX
#pragma alloca
@@ -94,7 +87,7 @@ extern "C" {
#if SIZEOF_LONG != SIZEOF_VOIDP
---->> ruby requires sizeof(void*) == sizeof(long) to be compiled. <<----
-# endif
+#endif
typedef unsigned long VALUE;
typedef unsigned int ID;
@@ -137,7 +130,7 @@ VALUE rb_int2inum _((long));
#define Qtrue 2
#define Qnil 4
-# define RTEST(v) rb_test_false_or_nil((VALUE)(v))
+#define RTEST(v) rb_test_false_or_nil((VALUE)(v))
#define NIL_P(v) ((VALUE)(v) == Qnil)
#define CLASS_OF(v) rb_class_of((VALUE)(v))
@@ -182,7 +175,7 @@ void rb_secure _((int));
long rb_num2long _((VALUE));
unsigned long rb_num2ulong _((VALUE));
-#define NUM2LONG(x) (FIXNUM_P(x)?FIX2INT(x):rb_num2long((VALUE)x))
+#define NUM2LONG(x) (FIXNUM_P(x)?FIX2LONG(x):rb_num2long((VALUE)x))
#define NUM2ULONG(x) rb_num2ulong((VALUE)x)
#if SIZEOF_INT < SIZEOF_LONG
int rb_num2int _((VALUE));
@@ -206,8 +199,8 @@ char *rb_str2cstr _((VALUE,int*));
#define STR2CSTR(x) rb_str2cstr((VALUE)(x),0)
#define NUM2CHR(x) (((TYPE(x) == T_STRING)&&(RSTRING(x)->len>=1))?\
- RSTRING(x)->ptr[0]:(char)NUM2INT(x))
-#define CHR2FIX(x) INT2FIX((int)x)
+ RSTRING(x)->ptr[0]:(char)(NUM2INT(x)&0xff))
+#define CHR2FIX(x) INT2FIX((long)((x)&0xff))
VALUE rb_newobj _((void));
#define NEWOBJ(obj,type) type *obj = (type*)rb_newobj()
@@ -216,10 +209,11 @@ VALUE rb_newobj _((void));
RBASIC(obj)->flags = (t);\
if (rb_safe_level() >= 3) FL_SET(obj, FL_TAINT);\
}
-#define CLONESETUP(clone,obj) {\
+#define CLONESETUP(clone,obj) do {\
OBJSETUP(clone,rb_singleton_class_clone(RBASIC(obj)->klass),RBASIC(obj)->flags);\
rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);\
-}
+ if (FL_TEST(obj, FL_EXIVAR)) rb_clone_generic_ivar((VALUE)clone,(VALUE)obj);\
+} while (0)
struct RBasic {
unsigned long flags;
@@ -245,21 +239,21 @@ struct RFloat {
struct RString {
struct RBasic basic;
- size_t len;
+ long len;
char *ptr;
VALUE orig;
};
struct RArray {
struct RBasic basic;
- size_t len, capa;
+ long len, capa;
VALUE *ptr;
};
struct RRegexp {
struct RBasic basic;
struct re_pattern_buffer *ptr;
- size_t len;
+ long len;
char *str;
};
@@ -272,7 +266,6 @@ struct RHash {
struct RFile {
struct RBasic basic;
- struct st_table *iv_tbl;
struct OpenFile *fptr;
};
@@ -283,7 +276,6 @@ struct RData {
void *data;
};
-extern VALUE rb_cData;
#define DATA_PTR(dta) (RDATA(dta)->data)
VALUE rb_data_object_alloc _((VALUE,void*,void (*)(),void (*)()));
@@ -304,14 +296,14 @@ VALUE rb_data_object_alloc _((VALUE,void*,void (*)(),void (*)()));
struct RStruct {
struct RBasic basic;
- size_t len;
+ long len;
VALUE *ptr;
};
struct RBignum {
struct RBasic basic;
char sign;
- size_t len;
+ long len;
unsigned short *digits;
};
@@ -371,30 +363,30 @@ void *xrealloc _((void*,size_t));
#define MEMCPY(p1,p2,type,n) memcpy((p1), (p2), sizeof(type)*(n))
#define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), sizeof(type)*(n))
-VALUE rb_define_class _((char*,VALUE));
-VALUE rb_define_module _((char*));
-VALUE rb_define_class_under _((VALUE, char *, VALUE));
-VALUE rb_define_module_under _((VALUE, char *));
+VALUE rb_define_class _((const char*,VALUE));
+VALUE rb_define_module _((const char*));
+VALUE rb_define_class_under _((VALUE, const char*, VALUE));
+VALUE rb_define_module_under _((VALUE, const char*));
void rb_include_module _((VALUE,VALUE));
void rb_extend_object _((VALUE,VALUE));
-void rb_define_variable _((char*,VALUE*));
-void rb_define_virtual_variable _((char*,VALUE(*)(),void(*)()));
-void rb_define_hooked_variable _((char*,VALUE*,VALUE(*)(),void(*)()));
-void rb_define_readonly_variable _((char*,VALUE*));
-void rb_define_const _((VALUE,char*,VALUE));
-void rb_define_global_const _((char*,VALUE));
+void rb_define_variable _((const char*,VALUE*));
+void rb_define_virtual_variable _((const char*,VALUE(*)(),void(*)()));
+void rb_define_hooked_variable _((const char*,VALUE*,VALUE(*)(),void(*)()));
+void rb_define_readonly_variable _((const char*,VALUE*));
+void rb_define_const _((VALUE,const char*,VALUE));
+void rb_define_global_const _((const char*,VALUE));
-void rb_define_method _((VALUE,char*,VALUE(*)(),int));
-void rb_define_module_function _((VALUE,char*,VALUE(*)(),int));
-void rb_define_global_function _((char*,VALUE(*)(),int));
+void rb_define_method _((VALUE,const char*,VALUE(*)(),int));
+void rb_define_module_function _((VALUE,const char*,VALUE(*)(),int));
+void rb_define_global_function _((const char*,VALUE(*)(),int));
-void rb_undef_method _((VALUE,char*));
-void rb_define_alias _((VALUE,char*,char*));
-void rb_define_attr _((VALUE,char*,int,int));
+void rb_undef_method _((VALUE,const char*));
+void rb_define_alias _((VALUE,const char*,const char*));
+void rb_define_attr _((VALUE,const char*,int,int));
-ID rb_intern _((char*));
+ID rb_intern _((const char*));
char *rb_id2name _((ID));
ID rb_to_id _((VALUE));
@@ -402,34 +394,37 @@ char *rb_class2name _((VALUE));
void rb_p _((VALUE));
-VALUE rb_eval_string _((char*));
-VALUE rb_eval_string_protect _((char*, int*));
+VALUE rb_eval_string _((const char*));
+VALUE rb_eval_string_protect _((const char*, int*));
+VALUE rb_eval_string_wrap _((const char*, int*));
VALUE rb_funcall __((VALUE, ID, int, ...));
-int rb_scan_args __((int, VALUE*, char*, ...));
+VALUE rb_funcall2 _((VALUE, ID, int, VALUE*));
+VALUE rb_funcall3 _((VALUE, ID, int, VALUE*));
+int rb_scan_args __((int, VALUE*, const char*, ...));
-VALUE rb_iv_get _((VALUE, char *));
-VALUE rb_iv_set _((VALUE, char *, VALUE));
+VALUE rb_iv_get _((VALUE, const char*));
+VALUE rb_iv_set _((VALUE, const char*, VALUE));
VALUE rb_const_get _((VALUE, ID));
VALUE rb_const_get_at _((VALUE, ID));
void rb_const_set _((VALUE, ID, VALUE));
VALUE rb_equal _((VALUE,VALUE));
-EXTERN VALUE rb_verbose, rb_debug;
+EXTERN VALUE ruby_verbose, ruby_debug;
int rb_safe_level _((void));
void rb_set_safe_level _((int));
-void rb_raise __((VALUE, char*, ...)) NORETURN;
-void rb_fatal __((char*, ...)) NORETURN;
-void rb_bug __((char*, ...)) NORETURN;
-void rb_sys_fail _((char*)) NORETURN;
+void rb_raise __((VALUE, const char*, ...)) NORETURN;
+void rb_fatal __((const char*, ...)) NORETURN;
+void rb_bug __((const char*, ...)) NORETURN;
+void rb_sys_fail _((const char*)) NORETURN;
void rb_iter_break _((void)) NORETURN;
void rb_exit _((int)) NORETURN;
void rb_notimplement _((void)) NORETURN;
-void rb_warn __((char*, ...));
-void rb_warning __((char*, ...)); /* reports if `-w' specified */
+void rb_warn __((const char*, ...));
+void rb_warning __((const char*, ...)); /* reports if `-w' specified */
VALUE rb_each _((VALUE));
VALUE rb_yield _((VALUE));
@@ -437,8 +432,10 @@ int rb_iterator_p _((void));
VALUE rb_iterate _((VALUE(*)(),VALUE,VALUE(*)(),VALUE));
VALUE rb_rescue _((VALUE(*)(),VALUE,VALUE(*)(),VALUE));
VALUE rb_ensure _((VALUE(*)(),VALUE,VALUE(*)(),VALUE));
-VALUE rb_catch _((char*,VALUE(*)(),VALUE));
-void rb_throw _((char*,VALUE)) NORETURN;
+VALUE rb_catch _((const char*,VALUE(*)(),VALUE));
+void rb_throw _((const char*,VALUE)) NORETURN;
+
+VALUE rb_require _((const char*));
void ruby_init _((void));
void ruby_options _((int, char**));
@@ -447,6 +444,7 @@ void ruby_run _((void));
EXTERN VALUE rb_mKernel;
EXTERN VALUE rb_mComparable;
EXTERN VALUE rb_mEnumerable;
+EXTERN VALUE rb_mPrecision;
EXTERN VALUE rb_mErrno;
EXTERN VALUE rb_mFileTest;
EXTERN VALUE rb_mGC;
@@ -480,7 +478,10 @@ EXTERN VALUE rb_cStruct;
EXTERN VALUE rb_eException;
EXTERN VALUE rb_eStandardError;
-EXTERN VALUE rb_eSystemExit, rb_eInterrupt, rb_eFatal;
+EXTERN VALUE rb_eSystemExit;
+EXTERN VALUE rb_eInterrupt;
+EXTERN VALUE rb_eSignal;
+EXTERN VALUE rb_eFatal;
EXTERN VALUE rb_eArgError;
EXTERN VALUE rb_eEOFError;
EXTERN VALUE rb_eIndexError;
@@ -492,8 +493,9 @@ EXTERN VALUE rb_eSecurityError;
EXTERN VALUE rb_eSyntaxError;
EXTERN VALUE rb_eSystemCallError;
EXTERN VALUE rb_eTypeError;
-EXTERN VALUE rb_eZeroDiv;
+EXTERN VALUE rb_eZeroDivError;
EXTERN VALUE rb_eNotImpError;
+EXTERN VALUE rb_eFloatDomainError;
#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(RUBY_NO_INLINE)
extern __inline__ VALUE rb_class_of _((VALUE));
@@ -525,7 +527,11 @@ rb_type(VALUE obj)
extern __inline__ int
rb_special_const_p(VALUE obj)
{
- return (FIXNUM_P(obj)||obj == Qnil||obj == Qfalse||obj == Qtrue)?Qtrue:Qfalse;
+ if (FIXNUM_P(obj)) return Qtrue;
+ if (obj == Qnil) return Qtrue;
+ if (obj == Qfalse) return Qtrue;
+ if (obj == Qtrue) return Qtrue;;
+ return Qfalse;
}
extern __inline__ int
diff --git a/rubyio.h b/rubyio.h
new file mode 100644
index 0000000000..81f162a012
--- /dev/null
+++ b/rubyio.h
@@ -0,0 +1,63 @@
+/************************************************
+
+ rubyio.h -
+
+ $Author$
+ $Date$
+ created at: Fri Nov 12 16:47:09 JST 1993
+
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
+
+************************************************/
+
+#ifndef IO_H
+#define IO_H
+
+#include <stdio.h>
+#include <errno.h>
+
+typedef struct OpenFile {
+ FILE *f; /* stdio ptr for read/write */
+ FILE *f2; /* additional ptr for rw pipes */
+ int mode; /* mode flags */
+ int pid; /* child's pid (for pipes) */
+ int lineno; /* number of lines read */
+ char *path; /* pathname for file */
+ void (*finalize)(); /* finalize proc */
+} OpenFile;
+
+#define FMODE_READABLE 1
+#define FMODE_WRITABLE 2
+#define FMODE_READWRITE 3
+#define FMODE_BINMODE 4
+#define FMODE_SYNC 8
+
+#define GetOpenFile(obj,fp) rb_io_check_closed((fp) = RFILE(obj)->fptr)
+
+#define MakeOpenFile(obj, fp) do {\
+ fp = RFILE(obj)->fptr = ALLOC(OpenFile);\
+ fp->f = fp->f2 = NULL;\
+ fp->mode = 0;\
+ fp->pid = 0;\
+ fp->lineno = 0;\
+ fp->path = NULL;\
+ fp->finalize = 0;\
+} while (0)
+
+#define GetReadFile(fptr) ((fptr)->f)
+#define GetWriteFile(fptr) (((fptr)->f2) ? (fptr)->f2 : (fptr)->f)
+
+FILE *rb_fopen _((const char*, const char*));
+FILE *rb_fdopen _((int, const char*));
+int rb_getc _((FILE*));
+int rb_io_mode_flags _((const char*));
+void rb_io_check_writable _((OpenFile*));
+void rb_io_check_readable _((OpenFile*));
+void rb_io_fptr_finalize _((OpenFile*));
+void rb_io_unbuffered _((OpenFile*));
+void rb_io_check_closed _((OpenFile*));
+void rb_eof_error _((void));
+
+void rb_read_check _((FILE*)); /* thread aware check */
+
+#endif
diff --git a/rubysig.h b/rubysig.h
new file mode 100644
index 0000000000..97de44216b
--- /dev/null
+++ b/rubysig.h
@@ -0,0 +1,50 @@
+/************************************************
+
+ rubysig.h -
+
+ $Author$
+ $Date$
+ created at: Wed Aug 16 01:15:38 JST 1995
+
+************************************************/
+#ifndef SIG_H
+#define SIG_H
+
+EXTERN int rb_trap_immediate;
+#define TRAP_BEG (rb_trap_immediate=1)
+#define TRAP_END (rb_trap_immediate=0)
+
+EXTERN int rb_prohibit_interrupt;
+#define DEFER_INTS {rb_prohibit_interrupt++;}
+#define ALLOW_INTS {rb_prohibit_interrupt--; CHECK_INTS;}
+#define ENABLE_INTS {rb_prohibit_interrupt--;}
+
+VALUE rb_with_disable_interrupt _((VALUE(*)(),VALUE));
+
+EXTERN int rb_trap_pending;
+void rb_trap_restore_mask _((void));
+
+EXTERN int rb_thread_critical;
+void rb_thread_schedule _((void));
+#if defined(HAVE_SETITIMER) && !defined(__BOW__)
+EXTERN int rb_thread_pending;
+# define CHECK_INTS if (!rb_prohibit_interrupt) {\
+ if (rb_trap_pending) rb_trap_exec();\
+ if (rb_thread_pending && !rb_thread_critical) rb_thread_schedule();\
+}
+#else
+/* pseudo preemptive thread switching */
+EXTERN int rb_thread_tick;
+#define THREAD_TICK 500
+#define CHECK_INTS if (!rb_prohibit_interrupt) {\
+ if (rb_trap_pending) rb_trap_exec();\
+ if (!rb_thread_critical) {\
+ if (rb_thread_tick-- <= 0) {\
+ rb_thread_tick = THREAD_TICK;\
+ rb_thread_schedule();\
+ }\
+ }\
+}
+#endif
+
+#endif
diff --git a/rubytest.rb b/rubytest.rb
index cf583c1dfb..61b31ceaf1 100644
--- a/rubytest.rb
+++ b/rubytest.rb
@@ -3,9 +3,27 @@
require 'rbconfig'
include Config
+if File.exist? CONFIG['LIBRUBY_SO']
+ case RUBY_PLATFORM
+ when /-hpux/
+ dldpath = "SHLIB_PATH"
+ when /-aix/
+ dldpath = "LIBPATH"
+ else
+ dldpath = "LD_LIBRARY_PATH"
+ end
+ x = ENV[dldpath]
+ x = x ? ".:"+x : "."
+ ENV[dldpath] = x
+end
+
+if /linux/ =~ RUBY_PLATFORM and File.exist? CONFIG['LIBRUBY_SO']
+ ENV["LD_PRELOAD"] = "./#{CONFIG['LIBRUBY_SO']}"
+end
+
$stderr.reopen($stdout)
error = ''
-`./ruby #{CONFIG["srcdir"]}/sample/test.rb`.each do |line|
+`./#{CONFIG["ruby_install_name"]} #{CONFIG["srcdir"]}/sample/test.rb`.each do |line|
if line =~ /^end of test/
print "test succeeded\n"
exit 0
diff --git a/sample/README b/sample/README
new file mode 100644
index 0000000000..1bdc85f32b
--- /dev/null
+++ b/sample/README
@@ -0,0 +1,56 @@
+README this file
+biorhythm.rb biorhythm calculator
+cal.rb cal(1) clone
+cbreak.rb no echo done by ioctl
+clnt.rb socket client
+dbmtest.rb test for dbm
+dir.rb directory access
+dualstack-fetch.rb IPv6 demo
+dualstack-httpd.rb IPv6 demo
+dstore.rb object database on dbm
+eval.rb simple evaluator
+export.rb method access example
+exyacc.rb extrace BNF from yacc file
+fact.rb factorial calculator
+fib.awk Fibonacci number (AWK)
+fib.pl Fibonacci number (Perl)
+fib.py Fibonacci number (Python)
+fib.rb Fibonacci number (Ruby)
+fib.scm Fibonacci number (Scheme)
+freq.rb count word occurrence
+from.rb scan mail spool
+fullpath.rb convert ls -lR to fullpath format
+getopts.test test fot getopt.rb
+goodfriday.rb print various christian calendar event.
+inf-ruby.el program to run ruby under emacs
+io.rb io test
+less.rb front end for less
+list.rb stupid object sample
+list2.rb stupid object sample
+list3.rb stupid object sample
+mine.rb simple mine sweeper
+mkproto.rb extract protptype from C
+mpart.rb split file int multi part
+mrshtest.rb test marshal
+observ.rb observer design pattern sample
+occur.pl count word occurrence (Perl)
+occur.rb count word occurrence (Ruby)
+occur2.rb count word occurrence - another style
+philos.rb famous dining philosophers
+pi.rb calculate PI
+rbc.rb interactive ruby, to be removed by irb
+rcs.awk random character stereogram (AWK)
+rcs.rb random character stereogram (Ruby)
+rcs.dat data for random character stereogram
+rd2html.rb rd (Ruby Document) to HTML translator
+regx.rb regular expression tester
+ruby-mode.el ruby mode for emacs
+rubydb2x.el ruby debugger support for emacs 19.2x or before
+rubydb3x.el ruby debugger support for emacs 19.3x or later
+sieve.rb sieve of Eratosthenes
+svr.rb socket server
+test.rb test suite used by `make test'
+time.rb /usr/bin/time clone
+trojan.rb simple tool to find file that may be trojan horse.
+tsvr.rb socket server using thread
+uumerge.rb merge files and uudecode them
diff --git a/sample/biorhythm.rb b/sample/biorhythm.rb
index 50ad1f2ef7..d2cbb113ec 100644
--- a/sample/biorhythm.rb
+++ b/sample/biorhythm.rb
@@ -19,11 +19,11 @@ def usage()
print "Usage:\n"
print "biorhythm.rb [options]\n"
print " options...\n"
- print " -D YYYYMMDD(birthday) : ¤¹¤Ù¤Æ default Ãͤò»È¤¦. \n"
- print " --sdate | --date YYYYMMDD : system date ¤â¤·¤¯¤Ï»ØÄꤷ¤¿ÆüÉÕ¤ò»È¤¦.\n"
- print " --birthday YYYYMMDD : ÃÂÀ¸Æü¤Î»ØÄê¤ò¤¹¤ë. \n"
- print " -v | -g : Values or Graph ¤Î»ØÄê. \n"
- print " --days DAYS : ´ü´Ö¤Î»ØÄê¤ò¤¹¤ë(Graph ¤Î»þ¤Î¤ßÍ­¸ú). \n"
+ print " -D YYYYMMDD(birthday) : use default values.\n"
+ print " --sdate | --date YYYYMMDD : use system date; use specified date.\n"
+ print " --birthday YYYYMMDD : specifies your birthday.\n"
+ print " -v | -g : show values or graph.\n"
+ print " --days DAYS : graph range (only in effect for graphs).\n"
print " --help : help\n"
end
$USAGE = 'usage'
diff --git a/sample/cal.rb b/sample/cal.rb
new file mode 100644
index 0000000000..cf82c6421c
--- /dev/null
+++ b/sample/cal.rb
@@ -0,0 +1,119 @@
+#! /usr/local/bin/ruby
+
+# cal.rb: Written by Tadayoshi Funaba 1998, 1999
+# $Id: cal.rb,v 1.5 1999/08/04 14:54:18 tadf Exp $
+
+require 'date2'
+
+$tab =
+{
+ 'cn' => true, # China
+ 'de' => 2342032, # Germany (protestant states)
+ 'dk' => 2342032, # Denmark
+ 'es' => 2299161, # Spain
+ 'fi' => 2361390, # Finland
+ 'fr' => 2299227, # France
+ 'gb' => 2361222, # United Kingdom
+ 'gr' => 2423868, # Greece
+ 'hu' => 2301004, # Hungary
+ 'it' => 2299161, # Italy
+ 'jp' => true, # Japan
+ 'no' => 2342032, # Norway
+ 'pl' => 2299161, # Poland
+ 'pt' => 2299161, # Portugal
+ 'ru' => 2421639, # Russia
+ 'se' => 2361390, # Sweden
+ 'us' => 2361222, # United States
+ 'os' => false, # (old style)
+ 'ns' => true # (new style)
+}
+
+$cc = 'gb'
+
+def usage
+ $stderr.puts 'usage: cal [-c iso3166] [-jy] [[month] year]'
+ exit 1
+end
+
+def cal(m, y, sg)
+ for d in 1..31
+ break if jd = Date.exist?(y, m, d, sg)
+ end
+ fst = cur = Date.new(jd, sg)
+ ti = Date::MONTHNAMES[m]
+ ti << ' ' << y.to_s unless $yr
+ mo = ti.center((($w + 1) * 7) - 1) << "\n"
+ mo << ['S', 'M', 'Tu', 'W', 'Th', 'F', 'S'].
+ collect{|x| x.rjust($w)}.join(' ') << "\n"
+ mo << ' ' * (($w + 1) * fst.wday)
+ while cur.mon == fst.mon
+ mo << (if $jd then cur.yday else cur.mday end).to_s.rjust($w)
+ mo << (if (cur += 1).wday != 0 then "\s" else "\n" end)
+ end
+ mo << "\n" * (6 - ((fst.wday + (cur - fst)) / 7))
+ mo
+end
+
+def zip(xs)
+ yr = ''
+ until xs.empty?
+ ln = (if $jd then l, r, *xs = xs; [l, r]
+ else l, c, r, *xs = xs; [l, c, r] end).
+ collect{|x| x.split(/\n/no, -1)}
+ 8.times do
+ yr << ln.collect{|x|
+ x.shift.ljust((($w + 1) * 7) - 1)}.join(' ') << "\n"
+ end
+ end
+ yr
+end
+
+while /^-([^-].*)$/no =~ $*[0]
+ a = $1
+ if /^c(.+)?$/no =~ a
+ if $1
+ $cc = $1.downcase
+ elsif $*.length >= 2
+ $cc = $*[1].downcase
+ $*.shift
+ else
+ usage
+ end
+ else
+ a.scan(/./no) do |c|
+ case c
+ when 'j'; $jd = true
+ when 'y'; $yr = true
+ else usage
+ end
+ end
+ end
+ $*.shift
+end
+$*.shift if /^--/no =~ $*[0]
+usage if (sg = $tab[$cc]).nil?
+case $*.length
+when 0
+ td = Date.today
+ m = td.mon
+ y = td.year
+when 1
+ y = $*[0].to_i
+ $yr = true
+when 2
+ m = $*[0].to_i
+ y = $*[1].to_i
+else
+ usage
+end
+usage unless m.nil? or (1..12) === m
+usage unless y >= -4712
+$w = if $jd then 3 else 2 end
+unless $yr
+ print cal(m, y, sg)
+else
+ print y.to_s.center(((($w + 1) * 7) - 1) *
+ (if $jd then 2 else 3 end) +
+ (if $jd then 2 else 4 end)), "\n\n",
+ zip((1..12).collect{|m| cal(m, y, sg)}), "\n"
+end
diff --git a/sample/fib.py b/sample/fib.py
new file mode 100644
index 0000000000..8318021d24
--- /dev/null
+++ b/sample/fib.py
@@ -0,0 +1,10 @@
+# calculate Fibonacci(20)
+# for benchmark
+def fib(n):
+ if n<2:
+ return n
+ else:
+ return fib(n-2)+fib(n-1)
+
+print fib(20)
+
diff --git a/sample/from.rb b/sample/from.rb
index 93b6c4bade..bed3433f1e 100644
--- a/sample/from.rb
+++ b/sample/from.rb
@@ -17,6 +17,7 @@ class String
len += 1
me = self[0, len].ljust(len)
if me =~ /.$/ and $&.size == 2
+ me[-2..-1] = ' '
me[-2, 2] = ' '
end
me.chop!
diff --git a/sample/goodfriday.rb b/sample/goodfriday.rb
new file mode 100644
index 0000000000..cc541af3f3
--- /dev/null
+++ b/sample/goodfriday.rb
@@ -0,0 +1,35 @@
+#! /usr/local/bin/ruby
+
+# goodfriday.rb: Written by Tadayoshi Funaba 1998
+# $Id: goodfriday.rb,v 1.3 1999/08/04 14:54:18 tadf Exp $
+
+require 'date2'
+require 'holiday'
+
+es = Date.easter(Date.today.year)
+[[-9*7, 'Septuagesima Sunday'],
+ [-8*7, 'Sexagesima Sunday'],
+ [-7*7, 'Quinquagesima Sunday (Shrove Sunday)'],
+ [-48, 'Shrove Monday'],
+ [-47, 'Shrove Tuesday'],
+ [-46, 'Ash Wednesday'],
+ [-6*7, 'Quadragesima Sunday'],
+ [-3*7, 'Mothering Sunday'],
+ [-2*7, 'Passion Sunday'],
+ [-7, 'Palm Sunday'],
+ [-3, 'Maunday Thursday'],
+ [-2, 'Good Friday'],
+ [-1, 'Easter Eve'],
+ [0, 'Easter Day'],
+ [1, 'Easter Monday'],
+ [7, 'Low Sunday'],
+ [5*7, 'Rogation Sunday'],
+ [39, 'Ascension Day (Holy Thursday)'],
+ [42, 'Sunday after Ascension Day'],
+ [7*7, 'Pentecost (Whitsunday)'],
+ [50, 'Whitmonday'],
+ [8*7, 'Trinity Sunday'],
+ [60, 'Corpus Christi (Thursday after Trinity)']].
+each do |xs|
+ puts ((es + xs.shift).to_s + ' ' + xs.shift)
+end
diff --git a/sample/list.rb b/sample/list.rb
index 76035e67d6..221f7edb16 100644
--- a/sample/list.rb
+++ b/sample/list.rb
@@ -1,8 +1,8 @@
# Linked list example
class MyElem
- # ¥ª¥Ö¥¸¥§¥¯¥ÈÀ¸À®»þ¤Ë¼«Æ°Åª¤Ë¸Æ¤Ð¤ì¤ë¥á¥½¥Ã¥É
+ # object initializer called from Class#new
def initialize(item)
- # @ÊÑ¿ô¤Ï¥¤¥ó¥¹¥¿¥ó¥¹ÊÑ¿ô(Àë¸À¤ÏÍפé¤Ê¤¤)
+ # @variables are instance variable, no declaration needed
@data = item
@succ = nil
end
@@ -15,7 +15,7 @@ class MyElem
@succ
end
- # ¡Öobj.data = val¡×¤È¤·¤¿¤È¤­¤Ë°ÅÌۤ˸ƤФì¤ë¥á¥½¥Ã¥É
+ # the method invoked by ``obj.data = val''
def succ=(new)
@succ = new
end
@@ -40,12 +40,12 @@ class MyList
end
end
- # ¥ª¥Ö¥¸¥§¥¯¥È¤òʸ»úÎó¤ËÊÑ´¹¤¹¤ë¥á¥½¥Ã¥É
- # ¤³¤ì¤òºÆÄêµÁ¤¹¤ë¤Èprint¤Ç¤Îɽ¸½¤¬ÊѤï¤ë
+ # the method to convert object into string.
+ # redefining this will affect print.
def to_s
str = "<MyList:\n";
for elt in self
- # ¡Östr = str + elt.data.to_s + "\n"¡×¤Î¾Êά·Á
+ # short form of ``str = str + elt.data.to_s + "\n"''
str += elt.data.to_s + "\n"
end
str += ">"
@@ -64,7 +64,7 @@ class Point
end
end
-# Âç°èÊÑ¿ô¤Ï`$'¤Ç»Ï¤Þ¤ë¡¥
+# global variable name starts with `$'.
$list1 = MyList.new
$list1.add_to_list(10)
$list1.add_to_list(20)
@@ -75,6 +75,6 @@ $list2.add_to_list(20)
$list2.add_to_list(Point.new(4, 5))
$list2.add_to_list($list1)
-# Û£Ëæ¤Ç¤Ê¤¤¸Â¤ê¥á¥½¥Ã¥É¸Æ¤Ó½Ð¤·¤Î³ç¸Ì¤Ï¾Êά¤Ç¤­¤ë
+# parenthesises around method arguments can be ommitted unless ambiguous.
print "list1:\n", $list1, "\n"
print "list2:\n", $list2, "\n"
diff --git a/sample/mine.rb b/sample/mine.rb
index b9557d54a2..fd326482a5 100644
--- a/sample/mine.rb
+++ b/sample/mine.rb
@@ -10,19 +10,19 @@ class Board
end
def put(x, y, col, str)
pos(x,y); colorstr(43,str)
- pos(0,@hi); print "$B;D$j(B:",@mc,"/",@total," "
+ pos(0,@hi); print "»Ä¤ê:",@mc,"/",@total," "
pos(x,y)
end
private :clr, :pos, :colorstr, :put
- CHR=["$B!&(B","$B#1(B","$B#2(B","$B#3(B","$B#4(B","$B#5(B","$B#6(B","$B#7(B","$B#8(B","$B!z(B","$B!|(B","@@"]
+ CHR=["¡¦","£±","£²","£³","£´","£µ","£¶","£·","£¸","¡ú","¡ü","@@"]
COL=[46,43,45] # default,opened,over
def initialize(h,w,m)
- # $B%2!<%`HW$N@8@.(B(h:$B=D!$(Bw:$B2#!$(Bm:$BGzCF$N?t(B)
+ # ¥²¡¼¥àÈפÎÀ¸À®(h:½Ä¡¤w:²£¡¤m:ÇúÃƤοô)
@hi=h; @wi=w; @m=m
reset
end
def reset
- # $B%2!<%`HW$r(B($B:F(B)$B=i4|2=$9$k(B
+ # ¥²¡¼¥àÈפò(ºÆ)½é´ü²½¤¹¤ë
srand()
@cx=0; @cy=0; @mc=@m
@over=false
@@ -44,7 +44,7 @@ class Board
pos(@cx,@cy)
end
def mark
- # $B8=:_$N%+!<%=%k0LCV$K%^!<%/$r$D$1$k(B
+ # ¸½ºß¤Î¥«¡¼¥½¥ë°ÌÃ֤˥ޡ¼¥¯¤ò¤Ä¤±¤ë
if @state[@wi*@cy+@cx] != nil then return end
@state[@wi*@cy+@cx] = "MARK"
@mc=@mc-1;
@@ -52,8 +52,8 @@ class Board
put(@cx, @cy, COL[1], CHR[9])
end
def open(x=@cx,y=@cy)
- # $B8=:_$N%+!<%=%k0LCV$r%*!<%W%s$K$9$k(B
- # $BGzCF$,$"$l$P%2!<%`%*!<%P!<(B
+ # ¸½ºß¤Î¥«¡¼¥½¥ë°ÌÃÖ¤ò¥ª¡¼¥×¥ó¤Ë¤¹¤ë
+ # ÇúÃƤ¬¤¢¤ì¤Ð¥²¡¼¥à¥ª¡¼¥Ð¡¼
if @state[@wi*y+x] =="OPEN" then return 0 end
if @state[@wi*y+x] == nil then @total=@total-1 end
if @state[@wi*y+x] =="MARK" then @mc=@mc+1 end
@@ -73,7 +73,7 @@ class Board
pos(@cx,@cy)
end
def fetch(x,y)
- # (x,y)$B$N0LCV$NGzCF$N?t(B(0 or 1)$B$rJV$9(B
+ # (x,y)¤Î°ÌÃÖ¤ÎÇúÃƤοô(0 or 1)¤òÊÖ¤¹
if x < 0 then 0
elsif x >= @wi then 0
elsif y < 0 then 0
@@ -83,13 +83,13 @@ class Board
end
end
def count(x,y)
- # (x,y)$B$KNY@\$9$kGzCF$N?t$rJV$9(B
+ # (x,y)¤ËÎÙÀܤ¹¤ëÇúÃƤοô¤òÊÖ¤¹
fetch(x-1,y-1)+fetch(x,y-1)+fetch(x+1,y-1)+
fetch(x-1,y) + fetch(x+1,y)+
fetch(x-1,y+1)+fetch(x,y+1)+fetch(x+1,y+1)
end
def over(win)
- # $B%2!<%`$N=*N;(B
+ # ¥²¡¼¥à¤Î½ªÎ»
quit
unless win
pos(@cx,@cy); print CHR[11]
@@ -100,8 +100,8 @@ class Board
end
end
def over?
- # $B%2!<%`$N=*N;%A%'%C%/(B
- # $B=*N;=hM}$b8F$S=P$9(B
+ # ¥²¡¼¥à¤Î½ªÎ»¥Á¥§¥Ã¥¯
+ # ½ªÎ»½èÍý¤â¸Æ¤Ó½Ð¤¹
remain = (@mc+@total == 0)
if @over || remain
over(remain)
@@ -111,8 +111,8 @@ class Board
end
end
def quit
- # $B%2!<%`$NCfCG(B($B$^$?$O=*N;(B)
- # $BHWLL$rA4$F8+$;$k(B
+ # ¥²¡¼¥à¤ÎÃæÃÇ(¤Þ¤¿¤Ï½ªÎ»)
+ # È×Ì̤òÁ´¤Æ¸«¤»¤ë
@hi.times do|y|
pos(0,y)
@wi.times do|x|
@@ -122,19 +122,19 @@ class Board
end
end
def down
- # $B%+!<%=%k$r2<$K(B
+ # ¥«¡¼¥½¥ë¤ò²¼¤Ë
if @cy < @hi-1 then @cy=@cy+1; pos(@cx, @cy) end
end
def up
- # $B%+!<%=%k$r>e$K(B
+ # ¥«¡¼¥½¥ë¤ò¾å¤Ë
if @cy > 0 then @cy=@cy-1; pos(@cx, @cy) end
end
def left
- # $B%+!<%=%k$r:8$K(B
+ # ¥«¡¼¥½¥ë¤òº¸¤Ë
if @cx > 0 then @cx=@cx-1; pos(@cx, @cy) end
end
def right
- # $B%+!<%=%k$r1&$K(B
+ # ¥«¡¼¥½¥ë¤ò±¦¤Ë
if @cx < @wi-1 then @cx=@cx+1; pos(@cx, @cy) end
end
end
@@ -143,7 +143,7 @@ bd=Board.new(10,10,10)
system("stty raw -echo")
begin
loop do
- case getc
+ case STDIN.getc
when ?n # new game
bd.reset
when ?m # mark
@@ -163,11 +163,11 @@ begin
break
end
if bd.over?
- if getc == ?q then break end
+ if STDIN.getc == ?q then break end
bd.reset
end
end
ensure
- system("stty -raw echo")
+ system("stty -raw echo")
end
print "\n"
diff --git a/sample/rbc.rb b/sample/rbc.rb
index 83796255cc..9f1ab9443d 100644
--- a/sample/rbc.rb
+++ b/sample/rbc.rb
@@ -273,7 +273,7 @@ module BC_APPLICATION__
rests.unshift op
identify_number(rests)
else
- # obj.if ¤Ê¤É¤ÎÂбþ
+ # handle ``obj.if'' and such
identify_identifier(rests, TRUE)
@lex_state = EXPR_ARG
end
@@ -344,7 +344,7 @@ module BC_APPLICATION__
@lex_state = EXPR_BEG
end
end
- @OP.def_rule('$') do
+ @OP.def_rule('$') do #'
|op, rests|
identify_gvar(rests)
end
@@ -466,7 +466,7 @@ module BC_APPLICATION__
print token, "\n" if CONFIG[:DEBUG]
if state = CLAUSE_STATE_TRANS[token]
if @lex_state != EXPR_BEG and token =~ /^(if|unless|while|until)/
- # ½¤¾þ»Ò
+ # modifiers
else
if ENINDENT_CLAUSE.include?(token)
@indent += 1
@@ -640,7 +640,7 @@ module BC_APPLICATION__
def_exception :ErrNodeAlreadyExists, "node already exists"
class Node
- # postproc¤¬¤Ê¤±¤ì¤ÐÃê¾Ý¥Î¡¼¥É, nil¤¸¤ã¤Ê¤±¤ì¤Ð¶ñ¾Ý¥Î¡¼¥É
+ # abstract node if postproc is nil.
def initialize(preproc = nil, postproc = nil)
@Tree = {}
@preproc = preproc
diff --git a/sample/rcs.rb b/sample/rcs.rb
index 3f74da9ef2..7c091936f3 100644
--- a/sample/rcs.rb
+++ b/sample/rcs.rb
@@ -1,12 +1,12 @@
# random dot steraogram
# usage: rcs.rb rcs.dat
-sw = 40.0 # Œ³‚̃pƒ^[ƒ“‚Ì•
-dw = 78.0 # ¶¬‚³‚ê‚é Random Character Streogram ‚Ì•
+sw = 40.0 # width of original pattern
+dw = 78.0 # width of generating Random Character Streogram
hdw = dw / 2.0
-w = 20.0 # —¼Šá‚Ì•
-h =1.0 # ‰æ–ʂƊʂ̋——£
-d = 0.2 # ’PˆÊ“–‚½‚è‚Ì•‚‚«ã‚ª‚è•û
+w = 20.0 # distance between eyes
+h =1.0 # distance from screen and base plane
+d = 0.2 # z value unit
ss="abcdefghijklmnopqrstuvwxyz0123456789#!$%^&*()-=\\[];'`,./"
rnd = srand()
diff --git a/sample/rename.rb b/sample/rename.rb
index 9abea7e327..cacb2b7508 100644
--- a/sample/rename.rb
+++ b/sample/rename.rb
@@ -140,8 +140,8 @@ gsub!(/\beof_error\b/,"rb_eof_error")
gsub!(/\bf_gets\b/,"rb_f_gets")
gsub!(/\bio_binmode\b/,"rb_io_binmode")
gsub!(/\bio_check_closed\b/,"rb_io_check_closed")
-gsub!(/\bio_check_readable\b/,"rb_io_check_readable")
-gsub!(/\bio_check_writable\b/,"rb_io_check_writable")
+gsub!(/\bio_readable\b/,"rb_io_check_readable")
+gsub!(/\bio_writable\b/,"rb_io_check_writable")
gsub!(/\bio_close\b/,"rb_io_close")
gsub!(/\bio_fptr_finalize\b/,"rb_io_fptr_finalize")
gsub!(/\bio_getc\b/,"rb_io_getc")
@@ -248,8 +248,8 @@ gsub!(/\bstr_plus\b/,"rb_str_plus")
gsub!(/\bstr_resize\b/,"rb_str_resize")
gsub!(/\bstr_split\b/,"rb_str_split")
gsub!(/\bstr_substr\b/,"rb_str_substr")
-gsub!(/\bstr_taint\b/,"rb_str_taint")
-gsub!(/\bstr_tainted\b/,"rb_str_tainted")
+gsub!(/\bstr_taint\b/,"rb_obj_taint")
+gsub!(/\bstr_tainted\b/,"rb_obj_tainted")
gsub!(/\bstr_times\b/,"rb_str_times")
gsub!(/\bstr_to_str\b/,"rb_str_to_str")
gsub!(/\bstr_upto\b/,"rb_str_upto")
@@ -283,8 +283,8 @@ gsub!(/\bobj_instance_variables\b/,"rb_obj_instance_variables")
gsub!(/\bobj_remove_instance_variable\b/,"rb_obj_remove_instance_variable")
gsub!(/\bshow_copyright\b/,"ruby_show_copyright")
gsub!(/\bshow_version\b/,"ruby_show_version")
-gsub!(/\bdebug\b/,"rb_debug")
-gsub!(/\bverbose\b/,"rb_verbose")
+gsub!(/\bdebug\b/,"ruby_debug")
+gsub!(/\bverbose\b/,"ruby_verbose")
gsub!(/\bFail\(/,"rb_raise(rb_eRuntimeError, ")
gsub!(/\bArgError\(/,"rb_raise(rb_eArgError, ")
gsub!(/\bTypeError\(/,"rb_raise(rb_eTypeError, ")
@@ -294,4 +294,4 @@ gsub!(/\bError\b/,"rb_compile_error")
gsub!(/\bErrorAppend\b/,"rb_compile_error_append")
gsub!(/\bTRUE\b/,"Qtrue")
gsub!(/\bFALSE\b/,"Qfalse")
-gsub!(/\berrinfo\b/,"rb_errinfo")
+gsub!(/\berrinfo\b/,"ruby_errinfo")
diff --git a/sample/sieve.rb b/sample/sieve.rb
index 5e9f792d81..359c185f20 100644
--- a/sample/sieve.rb
+++ b/sample/sieve.rb
@@ -1,17 +1,14 @@
# sieve of Eratosthenes
-sieve = []
max = Integer(ARGV.shift || 100)
+sieve = []
+for i in 2 .. max
+ sieve[i] = i
+end
-print "1"
-for i in 2 .. max
- begin
- for d in sieve
- fail if i % d == 0
- end
- print ", "
- print i
- sieve.push(i)
- rescue
+for i in 2 .. Math.sqrt(max)
+ next unless sieve[i]
+ (i*i).step(max, i) do |j|
+ sieve[j] = nil
end
end
-print "\n"
+puts sieve.compact.join ", "
diff --git a/sample/test.rb b/sample/test.rb
index f28327659e..a849a42fc2 100644
--- a/sample/test.rb
+++ b/sample/test.rb
@@ -183,7 +183,7 @@ ok(i>4)
check "exception";
begin
- fail "this must be handled"
+ raise "this must be handled"
ok(false)
rescue
ok(true)
@@ -191,7 +191,7 @@ end
$bad = true
begin
- fail "this must be handled no.2"
+ raise "this must be handled no.2"
rescue
if $bad
$bad = false
@@ -205,9 +205,9 @@ ok(true)
$string = "this must be handled no.3"
begin
begin
- fail "exception in rescue clause"
+ raise "exception in rescue clause"
rescue
- fail $string
+ raise $string
end
ok(false)
rescue
@@ -217,9 +217,9 @@ end
# exception in ensure clause
begin
begin
- fail "this must be handled no.4"
+ raise "this must be handled no.4"
ensure
- fail "exception in ensure clause"
+ raise "exception in ensure clause"
end
ok(false)
rescue
@@ -229,7 +229,7 @@ end
$bad = true
begin
begin
- fail "this must be handled no.5"
+ raise "this must be handled no.5"
ensure
$bad = false
end
@@ -240,7 +240,7 @@ ok(!$bad)
$bad = true
begin
begin
- fail "this must be handled no.6"
+ raise "this must be handled no.6"
ensure
$bad = false
end
@@ -355,7 +355,7 @@ ok($x[1] == 2)
ok(begin
for k,v in $y
- fail if k*2 != v
+ raise if k*2 != v
end
true
rescue
@@ -417,7 +417,7 @@ ok(i == 5)
done = true
loop{
break
- done = false
+ done = false # should not reach here
}
ok(done)
@@ -427,7 +427,7 @@ loop {
break if done
done = true
next
- $bad = true
+ $bad = true # should not reach here
}
ok(!$bad)
@@ -437,7 +437,7 @@ loop {
break if done
done = true
redo
- $bad = true
+ $bad = true # should not reach here
}
ok(!$bad)
@@ -599,14 +599,29 @@ ok(("abc" =~ /d*$/) == 3)
ok("" =~ /^$/)
ok("\n" =~ /^$/)
ok("a\n\n" =~ /^$/)
-"abcabc" =~ /.*a/
-ok($& == "abca")
-"abcabc" =~ /.*c/
-ok($& == "abcabc")
-"abcabc" =~ /.*?a/
-ok($& == "a")
-"abcabc" =~ /.*?c/
-ok($& == "abc")
+ok("abcabc" =~ /.*a/ && $& == "abca")
+ok("abcabc" =~ /.*c/ && $& == "abcabc")
+ok("abcabc" =~ /.*?a/ && $& == "a")
+ok("abcabc" =~ /.*?c/ && $& == "abc")
+ok(/(.|\n)*?\n(b|\n)/ =~ "a\nb\n\n" && $& == "a\nb")
+$x = <<END;
+ABCD
+ABCD
+END
+
+ok(/^(ab+)+b/ =~ "ababb" && $& == "ababb")
+ok(/^(?:ab+)+b/ =~ "ababb" && $& == "ababb")
+ok(/^(ab+)+/ =~ "ababb" && $& == "ababb")
+ok(/^(?:ab+)+/ =~ "ababb" && $& == "ababb")
+
+ok(/(\s+\d+){2}/ =~ " 1 2" && $& == " 1 2")
+ok(/(?:\s+\d+){2}/ =~ " 1 2" && $& == " 1 2")
+
+$x.gsub!(/((.|\n)*?)B((.|\n)*?)D/){$1+$3}
+ok($x == "AC\nAC\n")
+
+ok("foobar" =~ /foo(?=(bar)|(baz))/)
+ok("foobaz" =~ /foo(?=(bar)|(baz))/)
$foo = "abc"
ok("#$foo = abc" == "abc = abc")
@@ -746,7 +761,7 @@ if defined? Process.kill
sleep 0.1
ok($x == 2)
- trap "SIGINT", proc{fail "Interrupt"}
+ trap "SIGINT", proc{raise "Interrupt"}
x = false
begin
@@ -841,47 +856,55 @@ $x = []
x = proc{binding}.call
eval "(0..9).each{|i5| $x[i5] = proc{i5*2}}", x
ok($x[4].call == 8)
+x = proc{binding}.call
+eval "for i6 in 1..1; j6=i6; end", x
+ok(eval("defined? i6", x))
+ok(eval("defined? j6", x))
proc {
p = binding
eval "foo11 = 1", p
+ foo22 = 5
proc{foo11=22}.call
+ proc{foo22=55}.call
ok(eval("foo11", p) == eval("foo11"))
ok(eval("foo11") == 1)
+ ok(eval("foo22", p) == eval("foo22"))
+ ok(eval("foo22") == 55)
}.call
-p1 = proc{i6 = 0; proc{i6}}.call
+p1 = proc{i7 = 0; proc{i7}}.call
ok(p1.call == 0)
-eval "i6=5", p1
+eval "i7=5", p1
ok(p1.call == 5)
-ok(!defined?(i6))
+ok(!defined?(i7))
-p1 = proc{i6 = 0; proc{i6}}.call
-i6 = nil
+p1 = proc{i7 = 0; proc{i7}}.call
+i7 = nil
ok(p1.call == 0)
-eval "i6=1", p1
+eval "i7=1", p1
ok(p1.call == 1)
-eval "i6=5", p1
+eval "i7=5", p1
ok(p1.call == 5)
-ok(i6 == nil)
+ok(i7 == nil)
check "system"
ok(`echo foobar` == "foobar\n")
-ok(`./ruby -e 'print "foobar"'` == 'foobar')
+ok(`./miniruby -e 'print "foobar"'` == 'foobar')
tmp = open("script_tmp", "w")
tmp.print "print $zzz\n";
tmp.close
-ok(`./ruby -s script_tmp -zzz` == 'true')
-ok(`./ruby -s script_tmp -zzz=555` == '555')
+ok(`./miniruby -s script_tmp -zzz` == 'true')
+ok(`./miniruby -s script_tmp -zzz=555` == '555')
tmp = open("script_tmp", "w")
tmp.print "#! /usr/local/bin/ruby -s\n";
tmp.print "print $zzz\n";
tmp.close
-ok(`./ruby script_tmp -zzz=678` == '678')
+ok(`./miniruby script_tmp -zzz=678` == '678')
tmp = open("script_tmp", "w")
tmp.print "this is a leading junk\n";
@@ -891,8 +914,8 @@ tmp.print "__END__\n";
tmp.print "this is a trailing junk\n";
tmp.close
-ok(`./ruby -x script_tmp` == 'nil')
-ok(`./ruby -x script_tmp -zzz=555` == '555')
+ok(`./miniruby -x script_tmp` == 'nil')
+ok(`./miniruby -x script_tmp -zzz=555` == '555')
tmp = open("script_tmp", "w")
for i in 1..5
@@ -900,7 +923,7 @@ for i in 1..5
end
tmp.close
-`./ruby -i.bak -pe 'sub(/^[0-9]+$/){$&.to_i * 5}' script_tmp`
+`./miniruby -i.bak -pe 'sub(/^[0-9]+$/){$&.to_i * 5}' script_tmp`
done = true
tmp = open("script_tmp", "r")
while tmp.gets
@@ -917,7 +940,7 @@ File.unlink "script_tmp.bak" or `/bin/rm -f "script_tmp.bak"`
$bad = false
for script in Dir["{lib,sample}/*.rb"]
- unless `./ruby -c #{script}`.chomp == "Syntax OK"
+ unless `./miniruby -c #{script}`.chomp == "Syntax OK"
$bad = true
end
end
diff --git a/sample/trojan.rb b/sample/trojan.rb
index edf8ee63ce..6e9b18f502 100644
--- a/sample/trojan.rb
+++ b/sample/trojan.rb
@@ -1,5 +1,6 @@
#! /usr/local/bin/ruby
-path = ENV['PATH'].split(/:/)
+
+path = ENV['PATH'].split(File::PATH_SEPARATOR)
for dir in path
if File.directory?(dir)
diff --git a/sample/uumerge.rb b/sample/uumerge.rb
index 26f28923d5..418323c439 100644
--- a/sample/uumerge.rb
+++ b/sample/uumerge.rb
@@ -1,4 +1,4 @@
-#!/usr/local/bin/ruby
+#!/usr/bin/env ruby
if ARGV[0] == "-c"
out_stdout = 1
@@ -18,7 +18,7 @@ while gets()
out = open($file, "w") if $file != ""
end
out.binmode
- next
+ break
end
end
diff --git a/signal.c b/signal.c
index d7ce4921b2..857aa8a453 100644
--- a/signal.c
+++ b/signal.c
@@ -179,6 +179,18 @@ signm2signo(nm)
return 0;
}
+static char*
+signo2signm(no)
+ int no;
+{
+ struct signals *sigs;
+
+ for (sigs = siglist; sigs->signm; sigs++)
+ if (sigs->signo == no)
+ return sigs->signm;
+ return 0;
+}
+
VALUE
rb_f_kill(argc, argv)
int argc;
@@ -200,7 +212,7 @@ rb_f_kill(argc, argv)
sig = FIX2UINT(argv[0]);
if (sig >= NSIG) {
s = rb_id2name(sig);
- if (!s) rb_raise(rb_eArgError, "Bad signal");
+ if (!s) rb_raise(rb_eArgError, "bad signal");
goto str_signal;
}
break;
@@ -216,7 +228,7 @@ rb_f_kill(argc, argv)
if (strncmp("SIG", s, 3) == 0)
s += 3;
if((sig = signm2signo(s)) == 0)
- rb_raise(rb_eArgError, "Unrecognized signal name `%s'", s);
+ rb_raise(rb_eArgError, "unrecognized signal name `%s'", s);
if (negative)
sig = -sig;
@@ -284,30 +296,62 @@ posix_signal(signum, handler)
sigact.sa_flags = 0;
sigaction(signum, &sigact, 0);
}
+#define ruby_signal(sig,handle) posix_signal((sig),(handle))
+#else
+#define ruby_signal(sig,handle) signal((sig),(handle))
#endif
-#ifdef USE_THREAD
-# define rb_interrupt rb_thread_interrupt
-# define rb_trap_eval rb_thread_trap_eval
+static void
+signal_exec(sig)
+ int sig;
+{
+ if (trap_list[sig] == 0) {
+ switch (sig) {
+ case SIGINT:
+ rb_thread_interrupt();
+ break;
+#ifndef NT
+ case SIGHUP:
+#endif
+#ifdef SIGPIPE
+ case SIGPIPE:
#endif
+#ifdef SIGQUIT
+ case SIGQUIT:
+#endif
+#ifdef SIGALRM
+ case SIGALRM:
+#endif
+#ifdef SIGUSR1
+ case SIGUSR1:
+#endif
+#ifdef SIGUSR2
+ case SIGUSR2:
+#endif
+ rb_thread_signal_raise(signo2signm(sig));
+ break;
+ }
+ }
+ else {
+ rb_thread_trap_eval(trap_list[sig], sig);
+ }
+}
static RETSIGTYPE
sighandle(sig)
int sig;
{
- if (sig >= NSIG ||(sig != SIGINT && !trap_list[sig]))
+ if (sig >= NSIG) {
rb_bug("trap_handler: Bad signal %d", sig);
+ }
#if !defined(POSIX_SIGNAL) && !defined(BSD_SIGNAL)
- signal(sig, sighandle);
+ ruby_signal(sig, sighandle);
#endif
if (rb_trap_immediate) {
rb_trap_immediate = 0;
- if (sig == SIGINT && !trap_list[SIGINT]) {
- rb_interrupt();
- }
- rb_trap_eval(trap_list[sig], sig);
+ signal_exec(sig);
rb_trap_immediate = 1;
}
else {
@@ -353,11 +397,7 @@ rb_trap_exec()
for (i=0; i<NSIG; i++) {
if (trap_pending_list[i]) {
trap_pending_list[i] = 0;
- if (i == SIGINT && trap_list[SIGINT] == 0) {
- rb_interrupt();
- return;
- }
- rb_trap_eval(trap_list[i], i);
+ signal_exec(i);
}
}
#endif /* MACOS_UNUSE_SIGNAL */
@@ -438,15 +478,15 @@ trap(arg)
s += 3;
sig = signm2signo(s);
if (sig == 0 && strcmp(s, "EXIT") != 0)
- rb_raise(rb_eArgError, "Invalid signal SIG%s", s);
+ rb_raise(rb_eArgError, "invalid signal SIG%s", s);
}
else {
sig = NUM2INT(arg->sig);
}
if (sig < 0 || sig > NSIG) {
- rb_raise(rb_eArgError, "Invalid signal no %d", sig);
+ rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
}
-#if defined(USE_THREAD) && defined(HAVE_SETITIMER) && !defined(__BOW__)
+#if defined(HAVE_SETITIMER) && !defined(__BOW__)
if (sig == SIGVTALRM) {
rb_raise(rb_eArgError, "SIGVTALRM reserved for Thread; cannot set handler");
}
@@ -454,6 +494,24 @@ trap(arg)
if (func == SIG_DFL) {
switch (sig) {
case SIGINT:
+#ifndef NT
+ case SIGHUP:
+#endif
+#ifdef SIGQUIT
+ case SIGQUIT:
+#endif
+#ifdef SIGALRM
+ case SIGALRM:
+#endif
+#ifdef SIGUSR1
+ case SIGUSR1:
+#endif
+#ifdef SIGUSR2
+ case SIGUSR2:
+#endif
+#ifdef SIGPIPE
+ case SIGPIPE:
+#endif
func = sighandle;
break;
#ifdef SIGBUS
@@ -468,11 +526,7 @@ trap(arg)
#endif
}
}
-#ifdef POSIX_SIGNAL
- posix_signal(sig, func);
-#else
- signal(sig, func);
-#endif
+ ruby_signal(sig, func);
old = trap_list[sig];
if (!old) old = Qnil;
@@ -507,7 +561,7 @@ trap_ensure(arg)
void
rb_trap_restore_mask()
{
-#ifndef NT
+#if !defined(NT) && !defined(USE_CWGUSI)
# ifdef HAVE_SIGPROCMASK
sigprocmask(SIG_SETMASK, &trap_last_mask, NULL);
# else
@@ -556,16 +610,31 @@ Init_signal()
{
#ifndef MACOS_UNUSE_SIGNAL
rb_define_global_function("trap", rb_f_trap, -1);
-#ifdef POSIX_SIGNAL
- posix_signal(SIGINT, sighandle);
-#else
- signal(SIGINT, sighandle);
+ ruby_signal(SIGINT, sighandle);
+#ifndef NT
+ ruby_signal(SIGHUP, sighandle);
+#endif
+#ifdef SIGPIPE
+ ruby_signal(SIGPIPE, sighandle);
+#endif
+#ifdef SIGQUIT
+ ruby_signal(SIGQUIT, sighandle);
+#endif
+#ifdef SIGALRM
+ ruby_signal(SIGALRM, sighandle);
+#endif
+#ifdef SIGUSR1
+ ruby_signal(SIGUSR1, sighandle);
+#endif
+#ifdef SIGUSR2
+ ruby_signal(SIGUSR2, sighandle);
#endif
+
#ifdef SIGBUS
- signal(SIGBUS, sigbus);
+ ruby_signal(SIGBUS, sigbus);
#endif
#ifdef SIGSEGV
- signal(SIGSEGV, sigsegv);
+ ruby_signal(SIGSEGV, sigsegv);
#endif
#endif /* MACOS_UNUSE_SIGNAL */
}
diff --git a/sprintf.c b/sprintf.c
index 3c09a8ed2a..c3a2772e67 100644
--- a/sprintf.c
+++ b/sprintf.c
@@ -6,14 +6,25 @@
$Date$
created at: Fri Oct 15 10:39:26 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include <ctype.h>
+#include <math.h>
+#define BIT_DIGITS(N) (((N)*146)/485 + 1) /* log2(10) =~ 146/485 */
+
+#ifndef atof
+double strtod();
+#endif
+
+#ifdef USE_CWGUSI
+static void fmt_setup();
+#else
static void fmt_setup _((char*,char,int,int,int));
+#endif
static char*
remove_sign_bits(str, base)
@@ -548,11 +559,13 @@ rb_f_sprintf(argc, argv)
case 'f':
case 'g':
+ case 'G':
case 'e':
case 'E':
{
VALUE val = GETARG();
double fval;
+ int i, need = 6;
char fbuf[32];
switch (TYPE(val)) {
@@ -566,7 +579,7 @@ rb_f_sprintf(argc, argv)
fval = rb_big2dbl(val);
break;
case T_STRING:
- fval = atof(RSTRING(val)->ptr);
+ fval = strtod(RSTRING(val)->ptr, 0);
break;
default:
Check_Type(val, T_FLOAT);
@@ -574,8 +587,19 @@ rb_f_sprintf(argc, argv)
}
fmt_setup(fbuf, *p, flags, width, prec);
+ need = 0;
+ if (*p != 'e' && *p != 'E') {
+ i = INT_MIN;
+ frexp(fval, &i);
+ if (i > 0)
+ need = BIT_DIGITS(i);
+ }
+ need += (flags&FPREC) ? prec : 6;
+ if ((flags&FWIDTH) && need < width)
+ need = width;
+ need += 20;
- CHECK(22);
+ CHECK(need);
sprintf(&buf[blen], fbuf, fval);
blen += strlen(&buf[blen]);
}
@@ -585,7 +609,7 @@ rb_f_sprintf(argc, argv)
}
sprint_exit:
- if (RTEST(rb_verbose) && argc > 1) {
+ if (RTEST(ruby_verbose) && argc > 0) {
rb_raise(rb_eArgError, "too many argument for format string");
}
result = rb_str_new(buf, blen);
diff --git a/st.c b/st.c
index 8c0a3861f5..486b72a434 100644
--- a/st.c
+++ b/st.c
@@ -10,6 +10,10 @@ static char sccsid[] = "@(#) st.c 5.1 89/12/14 Crucible";
#include <stdlib.h>
#endif
+#ifdef NT
+#include <malloc.h>
+#endif
+
typedef struct st_table_entry st_table_entry;
struct st_table_entry {
@@ -45,9 +49,11 @@ static struct st_hash_type type_strhash = {
strhash,
};
+#ifndef xmalloc
void *xmalloc();
void *xcalloc();
void *xrealloc();
+#endif
static void rehash();
#define alloc(type) (type*)xmalloc((unsigned)sizeof(type))
@@ -173,7 +179,7 @@ st_free_table(table)
register st_table_entry *ptr, *next;
int i;
- for(i = 0; i < table->num_bins ; i++) {
+ for(i = 0; i < table->num_bins; i++) {
ptr = table->bins[i];
while (ptr != 0) {
next = ptr->next;
@@ -186,7 +192,7 @@ st_free_table(table)
}
#define PTR_NOT_EQUAL(table, ptr, hash_val, key) \
-((ptr) != 0 && ptr->hash != (hash_val) && !EQUAL((table), (key), (ptr)->key))
+((ptr) != 0 && (ptr->hash != (hash_val) || !EQUAL((table), (key), (ptr)->key)))
#define FIND_ENTRY(table, ptr, hash_val, bin_pos) \
bin_pos = hash_val%(table)->num_bins;\
@@ -220,19 +226,19 @@ st_lookup(table, key, value)
#define ADD_DIRECT(table, key, value, hash_val, bin_pos)\
{\
- st_table_entry *tbl;\
+ st_table_entry *entry;\
if (table->num_entries/table->num_bins > ST_DEFAULT_MAX_DENSITY) {\
rehash(table);\
bin_pos = hash_val % table->num_bins;\
}\
\
- tbl = alloc(st_table_entry);\
+ entry = alloc(st_table_entry);\
\
- tbl->hash = hash_val;\
- tbl->key = key;\
- tbl->record = value;\
- tbl->next = table->bins[bin_pos];\
- table->bins[bin_pos] = tbl;\
+ entry->hash = hash_val;\
+ entry->key = key;\
+ entry->record = value;\
+ entry->next = table->bins[bin_pos];\
+ table->bins[bin_pos] = entry;\
table->num_entries++;\
}
@@ -281,7 +287,7 @@ rehash(table)
new_num_bins = new_size(old_num_bins);
new_bins = (st_table_entry**)Calloc(new_num_bins, sizeof(st_table_entry*));
- for(i = 0; i < old_num_bins ; i++) {
+ for(i = 0; i < old_num_bins; i++) {
ptr = table->bins[i];
while (ptr != 0) {
next = ptr->next;
@@ -301,7 +307,7 @@ st_copy(old_table)
st_table *old_table;
{
st_table *new_table;
- st_table_entry *ptr, *tbl;
+ st_table_entry *ptr, *entry;
int i, num_bins = old_table->num_bins;
new_table = alloc(st_table);
@@ -318,19 +324,19 @@ st_copy(old_table)
return 0;
}
- for(i = 0; i < num_bins ; i++) {
+ for(i = 0; i < num_bins; i++) {
new_table->bins[i] = 0;
ptr = old_table->bins[i];
while (ptr != 0) {
- tbl = alloc(st_table_entry);
- if (tbl == 0) {
+ entry = alloc(st_table_entry);
+ if (entry == 0) {
free(new_table->bins);
free(new_table);
return 0;
}
- *tbl = *ptr;
- tbl->next = new_table->bins[i];
- new_table->bins[i] = tbl;
+ *entry = *ptr;
+ entry->next = new_table->bins[i];
+ new_table->bins[i] = entry;
ptr = ptr->next;
}
}
@@ -397,16 +403,8 @@ st_delete_safe(table, key, value, never)
return 0;
}
- if (EQUAL(table, *key, ptr->key)) {
- table->num_entries--;
- *key = ptr->key;
- if (value != 0) *value = ptr->record;
- ptr->key = ptr->record = never;
- return 1;
- }
-
- for(; ptr->next != 0; ptr = ptr->next) {
- if (EQUAL(table, ptr->next->key, *key)) {
+ for(; ptr != 0; ptr = ptr->next) {
+ if (EQUAL(table, ptr->key, *key)) {
table->num_entries--;
*key = ptr->key;
if (value != 0) *value = ptr->record;
@@ -418,6 +416,25 @@ st_delete_safe(table, key, value, never)
return 0;
}
+static int
+delete_never(key, value, never)
+ char *key, *value, *never;
+{
+ if (value == never) return ST_DELETE;
+ return ST_CONTINUE;
+}
+
+void
+st_cleanup_safe(table, never)
+ st_table *table;
+ char *never;
+{
+ int num_entries = table->num_entries;
+
+ st_foreach(table, delete_never, never);
+ table->num_entries = num_entries;
+}
+
void
st_foreach(table, func, arg)
st_table *table;
diff --git a/st.h b/st.h
index ce87df6011..b626969f83 100644
--- a/st.h
+++ b/st.h
@@ -32,7 +32,7 @@ st_table *st_init_strtable();
st_table *st_init_strtable_with_size();
int st_delete(), st_delete_safe();
int st_insert(), st_lookup();
-void st_foreach(), st_add_direct(), st_free_table();
+void st_foreach(), st_add_direct(), st_free_table(), st_cleanup_safe();
st_table *st_copy();
#define ST_NUMCMP ((int (*)()) 0)
diff --git a/string.c b/string.c
index e5f0dd2a63..94acc767fb 100644
--- a/string.c
+++ b/string.c
@@ -6,7 +6,7 @@
$Date$
created at: Mon Aug 9 17:12:58 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -22,6 +22,10 @@
#include <unistd.h>
#endif
+#ifndef atof
+double strtod();
+#endif
+
VALUE rb_cString;
#define STR_FREEZE FL_USER1
@@ -31,8 +35,8 @@ extern VALUE rb_rs;
VALUE
rb_str_new(ptr, len)
- char *ptr;
- size_t len;
+ const char *ptr;
+ long len;
{
NEWOBJ(str, struct RString);
OBJSETUP(str, rb_cString, T_STRING);
@@ -50,24 +54,30 @@ rb_str_new(ptr, len)
VALUE
rb_str_new2(ptr)
- char *ptr;
+ const char *ptr;
{
return rb_str_new(ptr, strlen(ptr));
}
VALUE
rb_tainted_str_new(ptr, len)
- char *ptr;
- size_t len;
+ const char *ptr;
+ long len;
{
- return rb_obj_taint(rb_str_new(ptr, len));
+ VALUE str = rb_str_new(ptr, len);
+
+ FL_SET(str, FL_TAINT);
+ return str;
}
VALUE
rb_tainted_str_new2(ptr)
- char *ptr;
+ const char *ptr;
{
- return rb_obj_taint(rb_str_new2(ptr));
+ VALUE str = rb_str_new2(ptr);
+
+ FL_SET(str, FL_TAINT);
+ return str;
}
VALUE
@@ -102,7 +112,7 @@ rb_str_new4(orig)
str->ptr = RSTRING(orig)->ptr;
RSTRING(orig)->orig = (VALUE)str;
str->orig = 0;
- if (rb_safe_level() >= 3) {
+ if (FL_TEST(str, FL_TAINT)) {
FL_SET(str, FL_TAINT);
}
return (VALUE)str;
@@ -204,7 +214,6 @@ rb_str_s_new(klass, orig)
if (rb_safe_level() >= 3) {
FL_SET(str, FL_TAINT);
}
- rb_obj_call_init((VALUE)str);
return (VALUE)str;
}
@@ -213,7 +222,7 @@ static VALUE
rb_str_length(str)
VALUE str;
{
- return INT2FIX(RSTRING(str)->len);
+ return INT2NUM(RSTRING(str)->len);
}
static VALUE
@@ -249,9 +258,9 @@ rb_str_times(str, times)
VALUE times;
{
VALUE str2;
- size_t i, len;
+ long i, len;
- len = NUM2INT(times);
+ len = NUM2LONG(times);
if (len < 0) {
rb_raise(rb_eArgError, "negative argument");
}
@@ -290,61 +299,30 @@ rb_str_format(str, arg)
}
VALUE
-rb_str_substr(str, start, len)
+rb_str_substr(str, beg, len)
VALUE str;
- size_t start, len;
+ long beg, len;
{
VALUE str2;
- if (start < 0) {
- start = RSTRING(str)->len + start;
- }
- if (RSTRING(str)->len <= start || len < 0) {
- return rb_str_new(0,0);
- }
- if (RSTRING(str)->len < start + len) {
- len = RSTRING(str)->len - start;
- }
-
- str2 = rb_str_new(RSTRING(str)->ptr+start, len);
- if (OBJ_TAINTED(str)) OBJ_TAINT(str2);
-
- return str2;
-}
-
-static VALUE
-rb_str_subseq(str, beg, end)
- VALUE str;
- size_t beg, end;
-{
- size_t len;
-
- if ((beg > 0 && end > 0 || beg < 0 && end < 0) && beg > end) {
- rb_raise(rb_eIndexError, "end smaller than beg [%d..%d]", beg, end);
- }
-
+ if (len < 0) return Qnil;
+ if (beg > RSTRING(str)->len) return Qnil;
if (beg < 0) {
- beg = RSTRING(str)->len + beg;
- if (beg < 0) beg = 0;
- }
- if (end < 0) {
- end = RSTRING(str)->len + end;
- if (end < 0) end = -1;
- else if (RSTRING(str)->len < end) {
- end = RSTRING(str)->len;
- }
+ beg += RSTRING(str)->len;
+ if (beg < 0) return Qnil;
}
-
- if (beg >= RSTRING(str)->len) {
- return rb_str_new(0, 0);
+ if (beg + len > RSTRING(str)->len) {
+ len = RSTRING(str)->len - beg;
}
-
- len = end - beg + 1;
if (len < 0) {
len = 0;
}
+ if (len == 0) return rb_str_new(0,0);
- return rb_str_substr(str, beg, len);
+ str2 = rb_str_new(RSTRING(str)->ptr+beg, len);
+ if (OBJ_TAINTED(str)) OBJ_TAINT(str2);
+
+ return str2;
}
void
@@ -355,7 +333,7 @@ rb_str_modify(str)
if (FL_TEST(str, STR_FREEZE))
rb_raise(rb_eTypeError, "can't modify frozen string");
- if (rb_safe_level() >= 4 && !FL_TEST(str, FL_TAINT))
+ if (!FL_TEST(str, FL_TAINT) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify string");
if (!RSTRING(str)->orig || FL_TEST(str, STR_NO_ORIG)) return;
ptr = RSTRING(str)->ptr;
@@ -399,7 +377,7 @@ rb_str_dup_frozen(str)
VALUE
rb_str_resize(str, len)
VALUE str;
- size_t len;
+ long len;
{
rb_str_modify(str);
@@ -416,8 +394,8 @@ rb_str_resize(str, len)
VALUE
rb_str_cat(str, ptr, len)
VALUE str;
- char *ptr;
- size_t len;
+ const char *ptr;
+ long len;
{
if (len > 0) {
rb_str_modify(str);
@@ -434,6 +412,7 @@ VALUE
rb_str_concat(str1, str2)
VALUE str1, str2;
{
+ rb_str_modify(str1);
if (FIXNUM_P(str2)) {
int i = FIX2INT(str2);
if (0 <= i && i <= 0xff) { /* byte */
@@ -449,7 +428,7 @@ int
rb_str_hash(str)
VALUE str;
{
- register size_t len = RSTRING(str)->len;
+ register long len = RSTRING(str)->len;
register char *p = RSTRING(str)->ptr;
register int key = 0;
@@ -482,7 +461,7 @@ int
rb_str_cmp(str1, str2)
VALUE str1, str2;
{
- size_t len;
+ long len;
int retval;
if (ruby_ignorecase) {
@@ -531,7 +510,7 @@ rb_str_match(x, y)
VALUE x, y;
{
VALUE reg;
- size_t start;
+ long start;
switch (TYPE(y)) {
case T_REGEXP:
@@ -543,7 +522,7 @@ rb_str_match(x, y)
if (start == -1) {
return Qfalse;
}
- return INT2FIX(start);
+ return INT2NUM(start);
default:
return rb_funcall(y, rb_intern("=~"), 1, x);
@@ -557,26 +536,31 @@ rb_str_match2(str)
return rb_reg_match2(rb_reg_regcomp(str));
}
-static size_t
+static long
rb_str_index(str, sub, offset)
VALUE str, sub;
- size_t offset;
+ long offset;
{
char *s, *e, *p;
- size_t len;
+ long len;
+ if (offset < 0) {
+ offset += RSTRING(str)->len;
+ if (offset < 0) return -1;
+ }
if (RSTRING(str)->len - offset < RSTRING(sub)->len) return -1;
s = RSTRING(str)->ptr+offset;
p = RSTRING(sub)->ptr;
len = RSTRING(sub)->len;
- e = s + RSTRING(str)->len - len + 1;
+ if (len == 0) return offset;
+ e = RSTRING(str)->ptr + RSTRING(str)->len - len + 1;
while (s < e) {
if (*s == *(RSTRING(sub)->ptr) && memcmp(s, p, len) == 0) {
return (s-(RSTRING(str)->ptr));
}
s++;
}
- return (size_t)-1;
+ return -1;
}
static VALUE
@@ -587,10 +571,10 @@ rb_str_index_method(argc, argv, str)
{
VALUE sub;
VALUE initpos;
- size_t pos;
+ long pos;
if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
- pos = NUM2UINT(initpos);
+ pos = NUM2LONG(initpos);
}
else {
pos = 0;
@@ -608,22 +592,22 @@ rb_str_index_method(argc, argv, str)
case T_FIXNUM:
{
int c = FIX2INT(sub);
- size_t len = RSTRING(str)->len;
+ long len = RSTRING(str)->len;
char *p = RSTRING(str)->ptr;
for (;pos<len;pos++) {
- if (p[pos] == c) return INT2FIX(pos);
+ if (p[pos] == c) return INT2NUM(pos);
}
return Qnil;
}
default:
- rb_raise(rb_eTypeError, "Type mismatch: %s given",
+ rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_class2name(CLASS_OF(sub)));
}
if (pos == -1) return Qnil;
- return INT2FIX(pos);
+ return INT2NUM(pos);
}
static VALUE
@@ -633,13 +617,13 @@ rb_str_rindex(argc, argv, str)
VALUE str;
{
VALUE sub;
- VALUE initpos;
- size_t pos, len;
+ VALUE position;
+ int pos, len;
char *s, *sbeg, *t;
- if (rb_scan_args(argc, argv, "11", &sub, &initpos) == 2) {
- pos = NUM2UINT(initpos);
- if (pos >= RSTRING(str)->len) pos = RSTRING(str)->len;
+ if (rb_scan_args(argc, argv, "11", &sub, &position) == 2) {
+ pos = NUM2INT(position);
+ if (pos > RSTRING(str)->len) pos = RSTRING(str)->len;
}
else {
pos = RSTRING(str)->len;
@@ -647,37 +631,50 @@ rb_str_rindex(argc, argv, str)
switch (TYPE(sub)) {
case T_REGEXP:
- pos = rb_reg_search(sub, str, pos, 1);
- if (pos >= 0) return INT2FIX(pos);
+ if (RREGEXP(sub)->len) {
+ pos = rb_reg_search(sub, str, pos, 1);
+ }
+ if (pos >= 0) return INT2NUM(pos);
break;
case T_STRING:
+ len = RSTRING(sub)->len;
/* substring longer than string */
- if (pos > RSTRING(str)->len) return Qnil;
- sbeg = RSTRING(str)->ptr; s = sbeg + pos - RSTRING(sub)->len;
+ if (RSTRING(str)->len < len) return Qnil;
+ if (RSTRING(str)->len - pos < len) {
+ pos = RSTRING(str)->len - len;
+ }
+ sbeg = RSTRING(str)->ptr;
+ s = RSTRING(str)->ptr + pos;
t = RSTRING(sub)->ptr;
- len = RSTRING(sub)->len;
- while (sbeg <= s) {
- if (*s == *t && memcmp(s, t, len) == 0) {
- return INT2FIX(s - sbeg);
+ if (len) {
+ while (sbeg <= s) {
+ if (*s == *t && memcmp(s, t, len) == 0) {
+ return INT2NUM(s - RSTRING(str)->ptr);
+ }
+ s--;
}
- s--;
+ }
+ else {
+ return INT2NUM(pos);
}
break;
case T_FIXNUM:
{
int c = FIX2INT(sub);
- char *p = RSTRING(str)->ptr;
+ char *p = RSTRING(str)->ptr + pos;
+ char *pbeg = RSTRING(str)->ptr;
- for (;pos>=0;pos--) {
- if (p[pos] == c) return INT2FIX(pos);
+ while (pbeg <= p) {
+ if (*p == c) return INT2NUM(p - RSTRING(str)->ptr);
+ p--;
}
return Qnil;
}
default:
- rb_raise(rb_eTypeError, "Type mismatch: %s given",
+ rb_raise(rb_eTypeError, "type mismatch: %s given",
rb_class2name(CLASS_OF(sub)));
}
return Qnil;
@@ -714,7 +711,7 @@ rb_str_succ(orig)
{
VALUE str, str2;
char *sbeg, *s;
- char c = -1;
+ int c = -1;
str = rb_str_new(RSTRING(orig)->ptr, RSTRING(orig)->len);
@@ -754,25 +751,32 @@ rb_str_succ_bang(str)
}
VALUE
-rb_str_upto(beg, end)
+rb_str_upto(beg, end, excl)
VALUE beg, end;
+ int excl;
{
VALUE current;
if (TYPE(end) != T_STRING) end = rb_str_to_str(end);
- if (RTEST(rb_funcall(beg, '>', 1, end)))
- return Qnil;
current = beg;
for (;;) {
rb_yield(current);
- if (rb_str_equal(current, end)) break;
+ if (!excl && rb_str_equal(current, end)) break;
current = rb_str_succ(current);
+ if (excl && rb_str_equal(current, end)) break;
if (RSTRING(current)->len > RSTRING(end)->len)
break;
}
- return Qnil;
+ return beg;
+}
+
+static VALUE
+rb_str_upto_method(beg, end)
+ VALUE beg, end;
+{
+ return rb_str_upto(beg, end, 0);
}
static VALUE
@@ -780,11 +784,11 @@ rb_str_aref(str, indx)
VALUE str;
VALUE indx;
{
- size_t idx;
+ long idx;
switch (TYPE(indx)) {
case T_FIXNUM:
- idx = FIX2INT(indx);
+ idx = FIX2LONG(indx);
if (idx < 0) {
idx = RSTRING(str)->len + idx;
@@ -800,18 +804,23 @@ rb_str_aref(str, indx)
return Qnil;
case T_STRING:
- if (rb_str_index(str, indx, 0) != (size_t)-1) return indx;
+ if (rb_str_index(str, indx, 0) != -1) return indx;
return Qnil;
default:
/* check if indx is Range */
{
- size_t beg, end;
- if (rb_range_beg_end(indx, &beg, &end)) {
- return rb_str_subseq(str, beg, end);
+ long beg, len;
+ switch (rb_range_beg_len(indx, &beg, &len, RSTRING(str)->len, 0)) {
+ case Qfalse:
+ break;
+ case Qnil:
+ return Qnil;
+ default:
+ return rb_str_substr(str, beg, len);
}
}
- rb_raise(rb_eIndexError, "Invalid index for string");
+ rb_raise(rb_eIndexError, "invalid index for string");
}
return Qnil; /* not reached */
}
@@ -833,7 +842,8 @@ rb_str_aref_method(argc, argv, str)
static void
rb_str_replace(str, beg, len, val)
VALUE str, val;
- size_t beg, len;
+ int beg;
+ int len;
{
if (len < RSTRING(val)->len) {
/* expand string */
@@ -853,44 +863,6 @@ rb_str_replace(str, beg, len, val)
RSTRING(str)->ptr[RSTRING(str)->len] = '\0';
}
-/* rb_str_replace2() understands negatice offset */
-static void
-rb_str_replace2(str, beg, end, val)
- VALUE str, val;
- size_t beg, end;
-{
- size_t len;
-
- if ((beg > 0 && end > 0 || beg < 0 && end < 0) && beg > end) {
- rb_raise(rb_eIndexError, "end smaller than beg [%d..%d]", beg, end);
- }
-
- if (beg < 0) {
- beg = RSTRING(str)->len + beg;
- if (beg < 0) {
- beg = 0;
- }
- }
- if (RSTRING(str)->len <= beg) {
- beg = RSTRING(str)->len;
- }
- if (end < 0) {
- end = RSTRING(str)->len + end;
- if (end < 0) {
- end = 0;
- }
- }
- if (RSTRING(str)->len <= end) {
- end = RSTRING(str)->len - 1;
- }
- len = end - beg + 1; /* length of substring */
- if (len < 0) {
- len = 0;
- }
-
- rb_str_replace(str, beg, len, val);
-}
-
static VALUE rb_str_sub_bang _((int, VALUE*, VALUE));
static VALUE
@@ -898,23 +870,28 @@ rb_str_aset(str, indx, val)
VALUE str;
VALUE indx, val;
{
- size_t idx, beg, end;
+ int idx;
+ int beg;
switch (TYPE(indx)) {
case T_FIXNUM:
- idx = NUM2UINT(indx);
+ beg = idx = NUM2INT(indx);
if (idx < 0) {
- idx = RSTRING(str)->len + idx;
+ idx += RSTRING(str)->len;
}
if (idx < 0 || RSTRING(str)->len <= idx) {
- rb_raise(rb_eIndexError, "index %d out of range [0..%d]", idx,
- RSTRING(str)->len - 1);
+ rb_raise(rb_eIndexError, "index %d out of string", idx);
}
- if (TYPE(val) == T_STRING) {
- rb_str_replace(str, idx, 1, val);
+ if (FIXNUM_P(val)) {
+ if (RSTRING(str)->len == idx) {
+ RSTRING(str)->len += 1;
+ REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len);
+ }
+ RSTRING(str)->ptr[idx] = NUM2INT(val) & 0xff;
}
else {
- RSTRING(str)->ptr[idx] = NUM2INT(val) & 0xff;
+ if (TYPE(val) != T_STRING) val = rb_str_to_str(val);
+ rb_str_replace(str, idx, 1, val);
}
return val;
@@ -929,23 +906,23 @@ rb_str_aset(str, indx, val)
case T_STRING:
beg = rb_str_index(str, indx, 0);
- if (beg != (size_t)-1) {
- end = beg + RSTRING(indx)->len - 1;
- rb_str_replace2(str, beg, end, val);
+ if (beg != -1) {
+ if (TYPE(val) != T_STRING) val = rb_str_to_str(val);
+ rb_str_replace(str, beg, RSTRING(indx)->len, val);
}
return val;
default:
/* check if indx is Range */
{
- size_t beg, end;
- if (rb_range_beg_end(indx, &beg, &end)) {
+ long beg, len;
+ if (rb_range_beg_len(indx, &beg, &len, RSTRING(str)->len, 2)) {
if (TYPE(val) != T_STRING) val = rb_str_to_str(val);
- rb_str_replace2(str, beg, end, val);
+ rb_str_replace(str, beg, len, val);
return val;
}
}
- rb_raise(rb_eIndexError, "Invalid index for string");
+ rb_raise(rb_eIndexError, "invalid index for string");
}
}
@@ -960,16 +937,21 @@ rb_str_aset_method(argc, argv, str)
rb_str_modify(str);
if (rb_scan_args(argc, argv, "21", &arg1, &arg2, &arg3) == 3) {
- size_t beg, len;
+ int beg, len;
if (TYPE(arg3) != T_STRING) arg3 = rb_str_to_str(arg3);
- beg = NUM2UINT(arg1);
+ beg = NUM2INT(arg1);
+ len = NUM2INT(arg2);
+ if (len < 0) rb_raise(rb_eIndexError, "negative length %d", len);
if (beg < 0) {
- beg = RSTRING(str)->len + beg;
- if (beg < 0) beg = 0;
+ beg += RSTRING(str)->len;
+ }
+ if (beg < 0 || RSTRING(str)->len < beg) {
+ if (beg < 0) {
+ beg -= RSTRING(str)->len;
+ }
+ rb_raise(rb_eIndexError, "index %d out of string", beg);
}
- len = NUM2UINT(arg2);
- if (len < 0) rb_raise(rb_eIndexError, "negative length %d", len);
if (beg + len > RSTRING(str)->len) {
len = RSTRING(str)->len - beg;
}
@@ -1007,7 +989,7 @@ rb_str_sub_bang(argc, argv, str)
VALUE pat, repl, match;
struct re_registers *regs;
int iter = 0;
- size_t plen;
+ int plen;
if (argc == 1 && rb_iterator_p()) {
iter = 1;
@@ -1016,7 +998,7 @@ rb_str_sub_bang(argc, argv, str)
repl = rb_obj_as_string(argv[1]);;
}
else {
- rb_raise(rb_eArgError, "Wrong # of arguments(%d for 2)", argc);
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)", argc);
}
pat = get_pat(argv[0]);
@@ -1026,7 +1008,10 @@ rb_str_sub_bang(argc, argv, str)
regs = RMATCH(match)->regs;
if (iter) {
+ rb_match_busy(match, Qtrue);
repl = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
+ rb_match_busy(match, Qfalse);
+ rb_backref_set(match);
}
else {
repl = rb_reg_regsub(repl, str, regs);
@@ -1070,10 +1055,10 @@ rb_str_gsub_bang(argc, argv, str)
{
VALUE pat, val, repl, match;
struct re_registers *regs;
- int beg, offset, n;
+ int beg, n;
int iter = 0;
char *buf, *bp, *cp;
- size_t blen, len;
+ int offset, blen, len;
if (argc == 1 && rb_iterator_p()) {
iter = 1;
@@ -1082,7 +1067,7 @@ rb_str_gsub_bang(argc, argv, str)
repl = rb_obj_as_string(argv[1]);;
}
else {
- rb_raise(rb_eArgError, "Wrong # of arguments(%d for 2)", argc);
+ rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)", argc);
}
pat = get_pat(argv[0]);
@@ -1100,7 +1085,10 @@ rb_str_gsub_bang(argc, argv, str)
match = rb_backref_get();
regs = RMATCH(match)->regs;
if (iter) {
+ rb_match_busy(match, Qtrue);
val = rb_obj_as_string(rb_yield(rb_reg_nth_match(0, match)));
+ rb_match_busy(match, Qfalse);
+ rb_backref_set(match);
}
else {
val = rb_reg_regsub(repl, str, regs);
@@ -1138,7 +1126,7 @@ rb_str_gsub_bang(argc, argv, str)
}
if (RSTRING(str)->len > offset) {
len = bp - buf;
- if (blen - len < RSTRING(str)->len - offset) {
+ if (blen - len < RSTRING(str)->len - offset + 1) {
REALLOC_N(buf, char, len + RSTRING(str)->len - offset + 1);
bp = buf + len;
}
@@ -1207,8 +1195,8 @@ rb_f_sub(argc, argv)
{
VALUE line, v;
- line = rb_str_dup(uscore_get());
- v = rb_str_sub_bang(argc, argv, line);
+ line = uscore_get();
+ v = rb_str_sub_bang(argc, argv, line = rb_str_dup(line));
if (NIL_P(v)) return line;
rb_lastline_set(v);
return v;
@@ -1229,8 +1217,8 @@ rb_f_gsub(argc, argv)
{
VALUE line, v;
- line = rb_str_dup(uscore_get());
- v = rb_str_gsub_bang(argc, argv, line);
+ line = uscore_get();
+ v = rb_str_gsub_bang(argc, argv, line = rb_str_dup(line));
if (NIL_P(v)) return line;
rb_lastline_set(v);
return v;
@@ -1261,7 +1249,7 @@ rb_str_reverse(str)
VALUE obj;
char *s, *e, *p;
- if (RSTRING(str)->len <= 1) return str;
+ if (RSTRING(str)->len <= 1) return rb_str_dup(str);
obj = rb_str_new(0, RSTRING(str)->len);
s = RSTRING(str)->ptr; e = s + RSTRING(str)->len - 1;
@@ -1278,16 +1266,16 @@ static VALUE
rb_str_include(str, arg)
VALUE str, arg;
{
- size_t i;
+ long i;
if (FIXNUM_P(arg)) {
int c = FIX2INT(arg);
- size_t len = RSTRING(str)->len;
+ long len = RSTRING(str)->len;
char *p = RSTRING(str)->ptr;
for (i=0; i<len; i++) {
if (p[i] == c) {
- return INT2FIX(i);
+ return INT2NUM(i);
}
}
return Qfalse;
@@ -1296,8 +1284,8 @@ rb_str_include(str, arg)
if (TYPE(arg) != T_STRING) arg = rb_str_to_str(arg);
i = rb_str_index(str, arg, 0);
- if (i == (size_t)-1) return Qfalse;
- return INT2FIX(i);
+ if (i == -1) return Qfalse;
+ return INT2NUM(i);
}
static VALUE
@@ -1311,7 +1299,7 @@ static VALUE
rb_str_to_f(str)
VALUE str;
{
- double f = atof(RSTRING(str)->ptr);
+ double f = strtod(RSTRING(str)->ptr, 0);
return rb_float_new(f);
}
@@ -1347,18 +1335,20 @@ rb_str_inspect(str)
while (p < pend) {
char c = *p++;
if (ismbchar(c) && p < pend) {
- int len = mbclen(c)-1;
+ int len = mbclen(c);
CHECK(len);
*b++ = c;
- while (len--) {
+ while (--len) {
*b++ = *p++;
}
}
+#if 0
else if ((c & 0x80) && rb_kcode() != MBCTYPE_EUC) {
CHECK(1);
*b++ = c;
}
+#endif
else if (c == '"'|| c == '\\') {
CHECK(2);
*b++ = '\\';
@@ -1418,7 +1408,7 @@ static VALUE
rb_str_dump(str)
VALUE str;
{
- size_t len;
+ int len;
char *p, *pend;
char *q, *qend;
VALUE result;
@@ -1430,7 +1420,7 @@ rb_str_dump(str)
switch (c) {
case '"': case '\\':
case '\n': case '\r':
- case '\t': case '\f':
+ case '\t': case '\f': case '#':
case '\013': case '\007': case '\033':
len += 2;
break;
@@ -1458,6 +1448,10 @@ rb_str_dump(str)
*q++ = '\\';
*q++ = c;
}
+ else if (c == '#') {
+ *q++ = '\\';
+ *q++ = '#';
+ }
else if (ISPRINT(c)) {
*q++ = c;
}
@@ -1511,7 +1505,7 @@ rb_str_upcase_bang(str)
s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
while (s < send) {
if (ismbchar(*s)) {
- s+=mbclen(*s);
+ s+=mbclen(*s) - 1;
}
else if (islower(*s)) {
*s = toupper(*s);
@@ -1545,7 +1539,7 @@ rb_str_downcase_bang(str)
s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
while (s < send) {
if (ismbchar(*s)) {
- s+=mbclen(*s);
+ s+=mbclen(*s) - 1;
}
else if (ISUPPER(*s)) {
*s = tolower(*s);
@@ -1583,7 +1577,7 @@ rb_str_capitalize_bang(str)
}
while (++s < send) {
if (ismbchar(*s)) {
- s+=mbclen(*s);
+ s+=mbclen(*s) - 1;
}
else if (ISUPPER(*s)) {
*s = tolower(*s);
@@ -1615,7 +1609,7 @@ rb_str_swapcase_bang(str)
s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
while (s < send) {
if (ismbchar(*s)) {
- s+=mbclen(*s);
+ s+=mbclen(*s) - 1;
}
else if (ISUPPER(*s)) {
*s = tolower(*s);
@@ -1680,7 +1674,7 @@ trnext(t)
}
}
-static VALUE rb_str_delete_bang _((VALUE,VALUE));
+static VALUE rb_str_delete_bang _((int,VALUE*,VALUE));
static VALUE
tr_trans(str, src, repl, sflag)
@@ -1689,19 +1683,21 @@ tr_trans(str, src, repl, sflag)
{
struct tr trsrc, trrepl;
int cflag = 0;
- char trans[256];
- int i, c, c0, modify = 0;
+ int trans[256];
+ int i, c, modify = 0;
char *s, *send;
rb_str_modify(str);
if (TYPE(src) != T_STRING) src = rb_str_to_str(src);
trsrc.p = RSTRING(src)->ptr; trsrc.pend = trsrc.p + RSTRING(src)->len;
- if (RSTRING(src)->len > 2 && RSTRING(src)->ptr[0] == '^') {
+ if (RSTRING(src)->len >= 2 && RSTRING(src)->ptr[0] == '^') {
cflag++;
trsrc.p++;
}
if (TYPE(repl) != T_STRING) repl = rb_str_to_str(repl);
- if (RSTRING(repl)->len == 0) return rb_str_delete_bang(str, src);
+ if (RSTRING(repl)->len == 0) {
+ return rb_str_delete_bang(1, &src, str);
+ }
trrepl.p = RSTRING(repl)->ptr;
trrepl.pend = trrepl.p + RSTRING(repl)->len;
trsrc.gen = trrepl.gen = 0;
@@ -1713,28 +1709,21 @@ tr_trans(str, src, repl, sflag)
trans[i] = 1;
}
while ((c = trnext(&trsrc)) >= 0) {
- trans[c & 0xff] = 0;
+ trans[c & 0xff] = -1;
}
+ while ((c = trnext(&trrepl)) >= 0)
+ /* retrieve last replacer */;
for (i=0; i<256; i++) {
- if (trans[i] == 0) {
- trans[i] = i;
- }
- else {
- c = trnext(&trrepl);
- if (c == -1) {
- trans[i] = trrepl.now;
- }
- else {
- trans[i] = c;
- }
+ if (trans[i] >= 0) {
+ trans[i] = trrepl.now;
}
}
}
else {
- char r;
+ int r;
for (i=0; i<256; i++) {
- trans[i] = i;
+ trans[i] = -1;
}
while ((c = trnext(&trsrc)) >= 0) {
r = trnext(&trrepl);
@@ -1744,19 +1733,21 @@ tr_trans(str, src, repl, sflag)
}
s = RSTRING(str)->ptr; send = s + RSTRING(str)->len;
- c0 = -1;
if (sflag) {
char *t = s;
+ int c0, last = -1;
while (s < send) {
- c = trans[*s++ & 0xff] & 0xff;
- if (s[-1] == c || c != c0) {
- c0 = (s[-1] == c)?-1:c;
- if (*t != c) {
- *t = c;
- modify = 1;
- }
- *t++ = c;
+ c0 = *s++;
+ if ((c = trans[c0 & 0xff]) >= 0) {
+ if (last == c) continue;
+ last = c;
+ *t++ = c & 0xff;
+ modify = 1;
+ }
+ else {
+ last = -1;
+ *t++ = c0;
}
}
if (RSTRING(str)->len > (t - RSTRING(str)->ptr)) {
@@ -1767,9 +1758,8 @@ tr_trans(str, src, repl, sflag)
}
else {
while (s < send) {
- c = trans[*s & 0xff] & 0xff;
- if (*s != c) {
- *s = c;
+ if ((c = trans[*s & 0xff]) >= 0) {
+ *s = c & 0xff;
modify = 1;
}
s++;
@@ -1798,44 +1788,63 @@ rb_str_tr(str, src, repl)
}
static void
-tr_setup_table(str, table)
+tr_setup_table(str, table, init)
VALUE str;
char table[256];
+ int init;
{
+ char buf[256];
struct tr tr;
- int i, cflag = 0;
- int c;
+ int i, c;
+ int cflag = 0;
tr.p = RSTRING(str)->ptr; tr.pend = tr.p + RSTRING(str)->len;
tr.gen = tr.now = tr.max = 0;
if (RSTRING(str)->len > 1 && RSTRING(str)->ptr[0] == '^') {
- cflag++;
+ cflag = 1;
tr.p++;
}
- for (i=0; i<256; i++) {
- table[i] = cflag ? 1 : 0;
+ if (init) {
+ for (i=0; i<256; i++) {
+ table[i] = 1;
+ }
+ }
+ for (i=0; i<256; i++) {
+ buf[i] = cflag;
}
while ((c = trnext(&tr)) >= 0) {
- table[c & 0xff] = cflag ? 0 : 1;
+ buf[c & 0xff] = !cflag;
+ }
+ for (i=0; i<256; i++) {
+ table[i] = table[i]&&buf[i];
}
}
static VALUE
-rb_str_delete_bang(str1, str2)
- VALUE str1, str2;
+rb_str_delete_bang(argc, argv, str)
+ int argc;
+ VALUE *argv;
+ VALUE str;
{
char *s, *send, *t;
char squeez[256];
int modify = 0;
+ int init = 1;
+ int i;
- if (TYPE(str2) != T_STRING) str2 = rb_str_to_str(str2);
- tr_setup_table(str2, squeez);
+ for (i=0; i<argc; i++) {
+ VALUE s = argv[i];
- rb_str_modify(str1);
+ if (TYPE(s) != T_STRING)
+ s = rb_str_to_str(s);
+ tr_setup_table(s, squeez, init);
+ init = 0;
+ }
- s = t = RSTRING(str1)->ptr;
- send = s + RSTRING(str1)->len;
+ rb_str_modify(str);
+ s = t = RSTRING(str)->ptr;
+ send = s + RSTRING(str)->len;
while (s < send) {
if (squeez[*s & 0xff])
modify = 1;
@@ -1844,75 +1853,74 @@ rb_str_delete_bang(str1, str2)
s++;
}
*t = '\0';
- RSTRING(str1)->len = t - RSTRING(str1)->ptr;
+ RSTRING(str)->len = t - RSTRING(str)->ptr;
- if (modify) return str1;
+ if (modify) return str;
return Qnil;
}
static VALUE
-rb_str_delete(str1, str2)
- VALUE str1, str2;
+rb_str_delete(argc, argv, str)
+ int argc;
+ VALUE *argv;
+ VALUE str;
{
- VALUE val = rb_str_delete_bang(str1 = rb_str_dup(str1), str2);
+ VALUE val = rb_str_delete_bang(argc, argv, str = rb_str_dup(str));
- if (NIL_P(val)) return str1;
+ if (NIL_P(val)) return str;
return val;
}
static VALUE
-tr_squeeze(str1, str2)
- VALUE str1, str2;
+rb_str_squeeze_bang(argc, argv, str)
+ int argc;
+ VALUE *argv;
+ VALUE str;
{
char squeez[256];
char *s, *send, *t;
- char c, save, modify = 0;
+ int c, save, modify = 0;
+ int init = 1;
+ int i;
- if (!NIL_P(str2)) {
- tr_setup_table(str2, squeez);
+ if (argc == 0) {
+ for (i=0; i<256; i++) {
+ squeez[i] = 1;
+ }
}
else {
- int i;
+ for (i=0; i<argc; i++) {
+ VALUE s = argv[i];
- for (i=0; i<256; i++) {
- squeez[i] = 1;
+ if (TYPE(s) != T_STRING)
+ s = rb_str_to_str(s);
+ tr_setup_table(s, squeez, init);
+ init = 0;
}
}
- rb_str_modify(str1);
+ rb_str_modify(str);
- s = t = RSTRING(str1)->ptr;
- send = s + RSTRING(str1)->len;
+ s = t = RSTRING(str)->ptr;
+ send = s + RSTRING(str)->len;
save = -1;
while (s < send) {
c = *s++ & 0xff;
- if (c != save || !squeez[c & 0xff]) {
+ if (c != save || !squeez[c]) {
*t++ = save = c;
- modify = 1;
}
}
*t = '\0';
- RSTRING(str1)->len = t - RSTRING(str1)->ptr;
+ if (t - RSTRING(str)->ptr != RSTRING(str)->len) {
+ RSTRING(str)->len = t - RSTRING(str)->ptr;
+ modify = 1;
+ }
- if (modify) return str1;
+ if (modify) return str;
return Qnil;
}
static VALUE
-rb_str_squeeze_bang(argc, argv, str1)
- int argc;
- VALUE *argv;
- VALUE str1;
-{
- VALUE str2;
-
- if (rb_scan_args(argc, argv, "01", &str2) == 1 && TYPE(str2) != T_STRING) {
- str2 = rb_str_to_str(str2);
- }
- return tr_squeeze(str1, str2);
-}
-
-static VALUE
rb_str_squeeze(argc, argv, str)
int argc;
VALUE *argv;
@@ -1942,6 +1950,40 @@ rb_str_tr_s(str, src, repl)
}
static VALUE
+rb_str_count(argc, argv, str)
+ int argc;
+ VALUE *argv;
+ VALUE str;
+{
+ char table[256];
+ char *s, *send;
+ int init = 1;
+ int i;
+
+ if (argc < 0) {
+ rb_raise(rb_eArgError, "wrong # of arguments");
+ }
+ for (i=0; i<argc; i++) {
+ VALUE s = argv[i];
+
+ if (TYPE(s) != T_STRING)
+ s = rb_str_to_str(s);
+ tr_setup_table(s, table, init);
+ init = 0;
+ }
+
+ s = RSTRING(str)->ptr;
+ send = s + RSTRING(str)->len;
+ i = 0;
+ while (s < send) {
+ if (table[*s++ & 0xff]) {
+ i++;
+ }
+ }
+ return INT2NUM(i);
+}
+
+static VALUE
rb_str_split_method(argc, argv, str)
int argc;
VALUE *argv;
@@ -1990,7 +2032,7 @@ rb_str_split_method(argc, argv, str)
beg = 0;
if (char_sep >= 0) {
char *ptr = RSTRING(str)->ptr;
- size_t len = RSTRING(str)->len;
+ int len = RSTRING(str)->len;
char *eptr = ptr + len;
if (char_sep == ' ') { /* AWK emulation */
@@ -2031,9 +2073,9 @@ rb_str_split_method(argc, argv, str)
}
}
else {
- size_t start = beg;
+ int start = beg;
int last_null = 0;
- size_t idx;
+ int idx;
struct re_registers *regs;
while ((end = rb_reg_search(spat, str, start, 0)) >= 0) {
@@ -2060,14 +2102,14 @@ rb_str_split_method(argc, argv, str)
if (BEG(idx) == END(idx))
tmp = rb_str_new(0, 0);
else
- tmp = rb_str_subseq(str, BEG(idx), END(idx)-1);
+ tmp = rb_str_substr(str, BEG(idx), END(idx)-BEG(idx));
rb_ary_push(result, tmp);
}
if (!NIL_P(limit) && lim <= ++i) break;
}
}
if (!NIL_P(limit) || RSTRING(str)->len > beg || lim < 0) {
- rb_ary_push(result, rb_str_subseq(str, beg, -1));
+ rb_ary_push(result, rb_str_substr(str, beg, RSTRING(str)->len-beg));
}
if (NIL_P(limit) && lim == 0) {
while (RARRAY(result)->len > 0 &&
@@ -2081,7 +2123,7 @@ rb_str_split_method(argc, argv, str)
VALUE
rb_str_split(str, sep0)
VALUE str;
- char *sep0;
+ const char *sep0;
{
VALUE sep;
@@ -2109,7 +2151,7 @@ rb_str_each_line(argc, argv, str)
int rslen;
char *p = RSTRING(str)->ptr, *pend = p + RSTRING(str)->len, *s;
char *ptr = p;
- size_t len = RSTRING(str)->len;
+ int len = RSTRING(str)->len;
VALUE line;
if (rb_scan_args(argc, argv, "01", &rs) == 0) {
@@ -2118,9 +2160,11 @@ rb_str_each_line(argc, argv, str)
if (NIL_P(rs)) {
rb_yield(str);
- return Qnil;
+ return str;
+ }
+ if (TYPE(rs) != T_STRING) {
+ rs = rb_str_to_str(rs);
}
- if (TYPE(rs) != T_STRING) rs = rb_str_to_str(rs);
rslen = RSTRING(rs)->len;
if (rslen == 0) {
@@ -2132,7 +2176,7 @@ rb_str_each_line(argc, argv, str)
for (s = p, p += rslen; p < pend; p++) {
if (rslen == 0 && *p == '\n') {
- if (p[1] != '\n') continue;
+ if (*++p != '\n') continue;
while (*p == '\n') p++;
}
if (p[-1] == newline &&
@@ -2147,23 +2191,24 @@ rb_str_each_line(argc, argv, str)
}
if (s != pend) {
+ if (p > pend) p = pend;
line = rb_str_new(s, p - s);
rb_yield(line);
}
- return Qnil;
+ return str;
}
static VALUE
rb_str_each_byte(str)
- struct RString* str;
+ VALUE str;
{
- size_t i;
+ int i;
for (i=0; i<RSTRING(str)->len; i++) {
rb_yield(INT2FIX(RSTRING(str)->ptr[i] & 0xff));
}
- return Qnil;
+ return str;
}
static VALUE
@@ -2205,10 +2250,10 @@ rb_f_chop_bang(str)
static VALUE
rb_f_chop()
{
- VALUE str = rb_str_dup(uscore_get());
- VALUE val = rb_str_chop_bang(str);
+ VALUE str = uscore_get();
+ VALUE val = rb_str_chop_bang(str = rb_str_dup(str));
- if (NIL_P(str)) return str;
+ if (NIL_P(val)) return str;
rb_lastline_set(val);
return val;
}
@@ -2223,7 +2268,7 @@ rb_str_chomp_bang(argc, argv, str)
int newline;
int rslen;
char *p = RSTRING(str)->ptr;
- size_t len = RSTRING(str)->len;
+ int len = RSTRING(str)->len;
if (rb_scan_args(argc, argv, "01", &rs) == 0) {
rs = rb_rs;
@@ -2281,8 +2326,11 @@ rb_f_chomp(argc, argv)
int argc;
VALUE *argv;
{
- VALUE str = rb_str_dup(uscore_get());
- VALUE val = rb_str_chomp_bang(argc, argv, str);
+ VALUE str = uscore_get();
+ VALUE val = rb_str_chomp_bang(argc, argv, str = rb_str_dup(str));
+
+ if (NIL_P(val)) return str;
+ rb_lastline_set(val);
return val;
}
@@ -2335,11 +2383,11 @@ rb_str_strip(str)
static VALUE
scan_once(str, pat, start)
VALUE str, pat;
- size_t *start;
+ long *start;
{
VALUE result, match;
struct re_registers *regs;
- size_t i;
+ long i;
if (rb_reg_search(pat, str, *start, 0) >= 0) {
match = rb_backref_get();
@@ -2371,7 +2419,7 @@ rb_str_scan(str, pat)
VALUE str, pat;
{
VALUE result;
- size_t start = 0;
+ long start = 0;
pat = get_pat(pat);
if (!rb_iterator_p()) {
@@ -2386,7 +2434,7 @@ rb_str_scan(str, pat)
while (!NIL_P(result = scan_once(str, pat, &start))) {
rb_yield(result);
}
- return Qnil;
+ return str;
}
static VALUE
@@ -2402,9 +2450,17 @@ rb_str_oct(str)
{
int base = 8;
- if (RSTRING(str)->len > 2 && RSTRING(str)->ptr[0] == '0' &&
- (RSTRING(str)->ptr[1] == 'x' || RSTRING(str)->ptr[1] == 'X')) {
- base = 16;
+ if (RSTRING(str)->len > 2 && RSTRING(str)->ptr[0] == '0') {
+ switch (RSTRING(str)->ptr[1]) {
+ case 'x':
+ case 'X':
+ base = 16;
+ break;
+ case 'b':
+ case 'B':
+ base = 2;
+ break;
+ }
}
return rb_str2inum(RSTRING(str)->ptr, base);
}
@@ -2417,7 +2473,7 @@ rb_str_crypt(str, salt)
if (TYPE(salt) != T_STRING) salt = rb_str_to_str(salt);
if (RSTRING(salt)->len < 2)
- rb_raise(rb_eArgError, "salt too short(need >2 bytes)");
+ rb_raise(rb_eArgError, "salt too short(need >=2 bytes)");
return rb_str_new2(crypt(RSTRING(str)->ptr, RSTRING(salt)->ptr));
}
@@ -2484,7 +2540,7 @@ rb_str_ljust(str, w)
VALUE str;
VALUE w;
{
- size_t width = NUM2UINT(w);
+ long width = NUM2LONG(w);
VALUE res;
char *p, *pend;
@@ -2503,7 +2559,7 @@ rb_str_rjust(str, w)
VALUE str;
VALUE w;
{
- size_t width = NUM2UINT(w);
+ long width = NUM2LONG(w);
VALUE res;
char *p, *pend;
@@ -2522,10 +2578,10 @@ rb_str_center(str, w)
VALUE str;
VALUE w;
{
- size_t width = NUM2UINT(w);
+ long width = NUM2LONG(w);
VALUE res;
char *p, *pend;
- size_t n;
+ long n;
if (width < 0 || RSTRING(str)->len >= width) return str;
res = rb_str_new(0, width);
@@ -2570,7 +2626,7 @@ Init_String()
rb_define_method(rb_cString, "succ!", rb_str_succ_bang, 0);
rb_define_method(rb_cString, "next", rb_str_succ, 0);
rb_define_method(rb_cString, "next!", rb_str_succ_bang, 0);
- rb_define_method(rb_cString, "upto", rb_str_upto, 1);
+ rb_define_method(rb_cString, "upto", rb_str_upto_method, 1);
rb_define_method(rb_cString, "index", rb_str_index_method, -1);
rb_define_method(rb_cString, "rindex", rb_str_rindex, -1);
rb_define_method(rb_cString, "replace", rb_str_replace_method, 1);
@@ -2627,12 +2683,13 @@ Init_String()
rb_define_method(rb_cString, "tr", rb_str_tr, 2);
rb_define_method(rb_cString, "tr_s", rb_str_tr_s, 2);
- rb_define_method(rb_cString, "delete", rb_str_delete, 1);
+ rb_define_method(rb_cString, "delete", rb_str_delete, -1);
rb_define_method(rb_cString, "squeeze", rb_str_squeeze, -1);
+ rb_define_method(rb_cString, "count", rb_str_count, -1);
rb_define_method(rb_cString, "tr!", rb_str_tr_bang, 2);
rb_define_method(rb_cString, "tr_s!", rb_str_tr_s_bang, 2);
- rb_define_method(rb_cString, "delete!", rb_str_delete_bang, 1);
+ rb_define_method(rb_cString, "delete!", rb_str_delete_bang, -1);
rb_define_method(rb_cString, "squeeze!", rb_str_squeeze_bang, -1);
rb_define_method(rb_cString, "each_line", rb_str_each_line, -1);
diff --git a/struct.c b/struct.c
index 7aaf4e8d25..e22c539fac 100644
--- a/struct.c
+++ b/struct.c
@@ -16,6 +16,8 @@
VALUE rb_cStruct;
+static VALUE struct_alloc _((int, VALUE*, VALUE));
+
static VALUE
class_of(obj)
VALUE obj;
@@ -27,13 +29,30 @@ class_of(obj)
}
static VALUE
+iv_get(obj, name)
+ VALUE obj;
+ char *name;
+{
+ ID id;
+
+ id = rb_intern(name);
+ for (;;) {
+ if (rb_ivar_defined(obj, id))
+ return rb_ivar_get(obj, id);
+ obj = RCLASS(obj)->super;
+ if (obj == 0 || obj == rb_cStruct)
+ return Qnil;
+ }
+}
+
+static VALUE
rb_struct_s_members(obj)
VALUE obj;
{
VALUE member, ary;
VALUE *p, *pend;
- member = rb_iv_get(obj, "__member__");
+ member = iv_get(obj, "__member__");
if (NIL_P(member)) {
rb_bug("non-initialized struct");
}
@@ -60,13 +79,13 @@ rb_struct_getmember(obj, id)
ID id;
{
VALUE member, slot;
- int i;
+ long i;
- member = rb_iv_get(class_of(obj), "__member__");
+ member = iv_get(class_of(obj), "__member__");
if (NIL_P(member)) {
rb_bug("non-initialized struct");
}
- slot = INT2FIX(id);
+ slot = INT2NUM(id);
for (i=0; i<RARRAY(member)->len; i++) {
if (RARRAY(member)->ptr[i] == slot) {
return RSTRUCT(obj)->ptr[i];
@@ -94,7 +113,7 @@ static VALUE rb_struct_ref7(obj) VALUE obj; {return RSTRUCT(obj)->ptr[7];}
static VALUE rb_struct_ref8(obj) VALUE obj; {return RSTRUCT(obj)->ptr[8];}
static VALUE rb_struct_ref9(obj) VALUE obj; {return RSTRUCT(obj)->ptr[9];}
-VALUE (*ref_func[10])() = {
+static VALUE (*ref_func[10])() = {
rb_struct_ref0,
rb_struct_ref1,
rb_struct_ref2,
@@ -112,9 +131,9 @@ rb_struct_set(obj, val)
VALUE obj, val;
{
VALUE member, slot;
- int i;
+ long i;
- member = rb_iv_get(class_of(obj), "__member__");
+ member = iv_get(class_of(obj), "__member__");
if (NIL_P(member)) {
rb_bug("non-initialized struct");
}
@@ -134,7 +153,7 @@ make_struct(name, member, klass)
{
VALUE nstr;
ID id;
- int i;
+ long i;
if (NIL_P(name)) {
nstr = rb_class_new(klass);
@@ -147,11 +166,11 @@ make_struct(name, member, klass)
}
nstr = rb_define_class_under(klass, cname, klass);
}
- rb_iv_set(nstr, "__size__", INT2FIX(RARRAY(member)->len));
+ rb_iv_set(nstr, "__size__", INT2NUM(RARRAY(member)->len));
rb_iv_set(nstr, "__member__", member);
- rb_define_singleton_method(nstr, "new", rb_struct_alloc, -2);
- rb_define_singleton_method(nstr, "[]", rb_struct_alloc, -2);
+ rb_define_singleton_method(nstr, "new", struct_alloc, -1);
+ rb_define_singleton_method(nstr, "[]", struct_alloc, -1);
rb_define_singleton_method(nstr, "members", rb_struct_s_members, 0);
for (i=0; i< RARRAY(member)->len; i++) {
ID id = FIX2INT(RARRAY(member)->ptr[i]);
@@ -177,10 +196,10 @@ make_struct(name, member, klass)
VALUE
#ifdef HAVE_STDARG_PROTOTYPES
-rb_struct_define(char *name, ...)
+rb_struct_define(const char *name, ...)
#else
rb_struct_define(name, va_alist)
- char *name;
+ const char *name;
va_dcl
#endif
{
@@ -207,7 +226,7 @@ rb_struct_s_def(argc, argv, klass)
VALUE *argv;
{
VALUE name, rest;
- int i;
+ long i;
VALUE st;
rb_scan_args(argc, argv, "1*", &name, &rest);
@@ -216,35 +235,60 @@ rb_struct_s_def(argc, argv, klass)
RARRAY(rest)->ptr[i] = INT2FIX(id);
}
st = make_struct(name, rest, klass);
- rb_obj_call_init(st);
return st;
}
-VALUE
-rb_struct_alloc(klass, values)
- VALUE klass, values;
+static VALUE
+rb_struct_initialize(self, values)
+ VALUE self, values;
{
+ VALUE klass = CLASS_OF(self);
VALUE size;
- int n;
+ long n;
- size = rb_iv_get(klass, "__size__");
+ size = iv_get(klass, "__size__");
n = FIX2INT(size);
- if (n != RARRAY(values)->len) {
+ if (n < RARRAY(values)->len) {
rb_raise(rb_eArgError, "struct size differs");
}
- else {
- NEWOBJ(st, struct RStruct);
- OBJSETUP(st, klass, T_STRUCT);
- st->len = 0; /* avoid GC crashing */
- st->ptr = ALLOC_N(VALUE, n);
- st->len = n;
- MEMCPY(st->ptr, RARRAY(values)->ptr, VALUE, RARRAY(values)->len);
- rb_obj_call_init((VALUE)st);
-
- return (VALUE)st;
+ MEMCPY(RSTRUCT(self)->ptr, RARRAY(values)->ptr, VALUE, RARRAY(values)->len);
+ if (n > RARRAY(values)->len) {
+ rb_mem_clear(RSTRUCT(self)->ptr+RARRAY(values)->len,
+ n-RARRAY(values)->len);
}
- return Qnil; /* not reached */
+ return Qnil;
+}
+
+static VALUE
+struct_alloc(argc, argv, klass)
+ int argc;
+ VALUE *argv;
+ VALUE klass;
+{
+ VALUE size;
+ long n;
+
+ NEWOBJ(st, struct RStruct);
+ OBJSETUP(st, klass, T_STRUCT);
+
+ size = iv_get(klass, "__size__");
+ n = FIX2LONG(size);
+
+ st->len = 0; /* avoid GC crashing */
+ st->ptr = ALLOC_N(VALUE, n);
+ rb_mem_clear(st->ptr, n);
+ st->len = n;
+ rb_obj_call_init((VALUE)st, argc, argv);
+
+ return (VALUE)st;
+}
+
+VALUE
+rb_struct_alloc(klass, values)
+ VALUE klass, values;
+{
+ return struct_alloc(RARRAY(values)->len, RARRAY(values)->ptr, klass);
}
VALUE
@@ -256,33 +300,32 @@ rb_struct_new(klass, va_alist)
va_dcl
#endif
{
- VALUE val, mem;
- int size, i;
+ VALUE sz, *mem;
+ long size, i;
va_list args;
- val = rb_iv_get(klass, "__size__");
- size = FIX2INT(val);
- mem = rb_ary_new2(size);
+ sz = iv_get(klass, "__size__");
+ size = FIX2LONG(sz);
+ mem = ALLOCA_N(VALUE, size);
va_init_list(args, klass);
for (i=0; i<size; i++) {
- val = va_arg(args, VALUE);
- rb_ary_store(mem, i, val);
+ mem[i] = va_arg(args, VALUE);
}
va_end(args);
- return rb_struct_alloc(klass, mem);
+ return struct_alloc(size, mem, klass);
}
static VALUE
rb_struct_each(s)
VALUE s;
{
- int i;
+ long i;
for (i=0; i<RSTRUCT(s)->len; i++) {
rb_yield(RSTRUCT(s)->ptr[i]);
}
- return Qnil;
+ return s;
}
static VALUE
@@ -302,9 +345,9 @@ inspect_struct(s)
{
char *cname = rb_class2name(CLASS_OF(s));
VALUE str, member;
- int i;
+ long i;
- member = rb_iv_get(CLASS_OF(s), "__member__");
+ member = iv_get(CLASS_OF(s), "__member__");
if (NIL_P(member)) {
rb_bug("non-initialized struct");
}
@@ -320,7 +363,7 @@ inspect_struct(s)
rb_str_cat(str, ", ", 2);
}
slot = RARRAY(member)->ptr[i];
- p = rb_id2name(FIX2INT(slot));
+ p = rb_id2name(FIX2LONG(slot));
rb_str_cat(str, p, strlen(p));
rb_str_cat(str, "=", 1);
str2 = rb_inspect(RSTRUCT(s)->ptr[i]);
@@ -372,9 +415,9 @@ rb_struct_aref_id(s, id)
ID id;
{
VALUE member;
- int i, len;
+ long i, len;
- member = rb_iv_get(CLASS_OF(s), "__member__");
+ member = iv_get(CLASS_OF(s), "__member__");
if (NIL_P(member)) {
rb_bug("non-initialized struct");
}
@@ -393,13 +436,13 @@ VALUE
rb_struct_aref(s, idx)
VALUE s, idx;
{
- int i;
+ long i;
if (TYPE(idx) == T_STRING) {
return rb_struct_aref_id(s, rb_to_id(idx));
}
- i = NUM2INT(idx);
+ i = NUM2LONG(idx);
if (i < 0) i = RSTRUCT(s)->len + i;
if (i < 0)
rb_raise(rb_eIndexError, "offset %d too small for struct(size:%d)",
@@ -416,9 +459,9 @@ rb_struct_aset_id(s, id, val)
ID id;
{
VALUE member;
- int i, len;
+ long i, len;
- member = rb_iv_get(CLASS_OF(s), "__member__");
+ member = iv_get(CLASS_OF(s), "__member__");
if (NIL_P(member)) {
rb_bug("non-initialized struct");
}
@@ -437,13 +480,13 @@ VALUE
rb_struct_aset(s, idx, val)
VALUE s, idx, val;
{
- int i;
+ long i;
if (TYPE(idx) == T_STRING) {
return rb_struct_aset_id(s, rb_to_id(idx), val);
}
- i = NUM2INT(idx);
+ i = NUM2LONG(idx);
if (i < 0) i = RSTRUCT(s)->len + i;
if (i < 0)
rb_raise(rb_eIndexError, "offset %d too small for struct(size:%d)",
@@ -458,7 +501,7 @@ static VALUE
rb_struct_equal(s, s2)
VALUE s, s2;
{
- int i;
+ long i;
if (TYPE(s2) != T_STRUCT) return Qfalse;
if (CLASS_OF(s) != CLASS_OF(s2)) return Qfalse;
@@ -476,7 +519,7 @@ static VALUE
rb_struct_eql(s, s2)
VALUE s, s2;
{
- int i;
+ long i;
if (TYPE(s2) != T_STRUCT) return Qfalse;
if (CLASS_OF(s) != CLASS_OF(s2)) return Qfalse;
@@ -494,7 +537,8 @@ static VALUE
rb_struct_hash(s)
VALUE s;
{
- int i, h;
+ long i;
+ int h;
h = CLASS_OF(s);
for (i=0; i<RSTRUCT(s)->len; i++) {
@@ -511,6 +555,7 @@ Init_Struct()
rb_define_singleton_method(rb_cStruct, "new", rb_struct_s_def, -1);
+ rb_define_method(rb_cStruct, "initialize", rb_struct_initialize, -2);
rb_define_method(rb_cStruct, "clone", rb_struct_clone, 0);
rb_define_method(rb_cStruct, "==", rb_struct_equal, 1);
diff --git a/time.c b/time.c
index fc14d8e5b6..f8296e6e20 100644
--- a/time.c
+++ b/time.c
@@ -6,26 +6,22 @@
$Date$
created at: Tue Dec 28 14:31:59 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
#include "ruby.h"
#include <sys/types.h>
-#ifdef USE_CWGUSI
-int gettimeofday(struct timeval*, struct timezone*);
-int strcasecmp(char*, char*);
-#endif
-
#include <time.h>
#ifndef NT
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#else
+#define time_t long
struct timeval {
- long tv_sec; /* seconds */
- long tv_usec; /* and microseconds */
+ time_t tv_sec; /* seconds */
+ time_t tv_usec; /* and microseconds */
};
#endif
#endif /* NT */
@@ -33,7 +29,16 @@ struct timeval {
#ifdef HAVE_SYS_TIMES_H
#include <sys/times.h>
#endif
-#include <math.h>
+
+#ifdef USE_CWGUSI
+#define time_t long
+int gettimeofday(struct timeval*, struct timezone*);
+int strcasecmp(char*, char*);
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
VALUE rb_cTime;
#if defined(HAVE_TIMES) || defined(NT)
@@ -43,9 +48,7 @@ static VALUE S_Tms;
struct time_object {
struct timeval tv;
struct tm tm;
-#ifndef HAVE_TM_ZONE
int gmt;
-#endif
int tm_got;
};
@@ -63,10 +66,9 @@ time_s_now(klass)
obj = Data_Make_Struct(klass, struct time_object, 0, free, tobj);
tobj->tm_got=0;
- if (gettimeofday(&(tobj->tv), 0) == -1) {
+ if (gettimeofday(&tobj->tv, 0) < 0) {
rb_sys_fail("gettimeofday");
}
- rb_obj_call_init(obj);
return obj;
}
@@ -74,13 +76,15 @@ time_s_now(klass)
static VALUE
time_new_internal(klass, sec, usec)
VALUE klass;
- int sec, usec;
+ time_t sec, usec;
{
VALUE obj;
struct time_object *tobj;
+#ifndef USE_CWGUSI
if (sec < 0 || (sec == 0 && usec < 0))
rb_raise(rb_eArgError, "time must be positive");
+#endif
obj = Data_Make_Struct(klass, struct time_object, 0, free, tobj);
tobj->tm_got = 0;
tobj->tv.tv_sec = sec;
@@ -91,21 +95,20 @@ time_new_internal(klass, sec, usec)
VALUE
rb_time_new(sec, usec)
- int sec, usec;
+ time_t sec, usec;
{
return time_new_internal(rb_cTime, sec, usec);
}
struct timeval
-rb_time_timeval(time)
+rb_time_interval(time)
VALUE time;
{
- struct time_object *tobj;
struct timeval t;
switch (TYPE(time)) {
case T_FIXNUM:
- t.tv_sec = FIX2INT(time);
+ t.tv_sec = FIX2LONG(time);
if (t.tv_sec < 0)
rb_raise(rb_eArgError, "time must be positive");
t.tv_usec = 0;
@@ -114,37 +117,57 @@ rb_time_timeval(time)
case T_FLOAT:
if (RFLOAT(time)->value < 0.0)
rb_raise(rb_eArgError, "time must be positive");
- t.tv_sec = (long)floor(RFLOAT(time)->value);
- t.tv_usec = (long)((RFLOAT(time)->value - t.tv_sec) * 1000000.0);
+ t.tv_sec = (time_t)RFLOAT(time)->value;
+ t.tv_usec = (time_t)((RFLOAT(time)->value - (double)t.tv_sec)*1e6);
break;
case T_BIGNUM:
- t.tv_sec = NUM2INT(time);
+ t.tv_sec = NUM2LONG(time);
if (t.tv_sec < 0)
rb_raise(rb_eArgError, "time must be positive");
t.tv_usec = 0;
break;
default:
- if (!rb_obj_is_kind_of(time, rb_cTime)) {
- rb_raise(rb_eTypeError, "Can't convert %s into Time",
- rb_class2name(CLASS_OF(time)));
- }
- GetTimeval(time, tobj);
- t = tobj->tv;
+ rb_raise(rb_eTypeError, "can't convert %s into Time interval",
+ rb_class2name(CLASS_OF(time)));
break;
}
return t;
}
+struct timeval
+rb_time_timeval(time)
+ VALUE time;
+{
+ struct time_object *tobj;
+ struct timeval t;
+
+ if (rb_obj_is_kind_of(time, rb_cTime)) {
+ GetTimeval(time, tobj);
+ t = tobj->tv;
+ return t;
+ }
+ return rb_time_interval(time);
+}
+
static VALUE
time_s_at(klass, time)
VALUE klass, time;
{
struct timeval tv;
+ VALUE t;
tv = rb_time_timeval(time);
- return time_new_internal(klass, tv.tv_sec, tv.tv_usec);
+ t = time_new_internal(klass, tv.tv_sec, tv.tv_usec);
+ if (TYPE(time) == T_DATA) {
+ struct time_object *tobj, *tobj2;
+
+ GetTimeval(time, tobj);
+ GetTimeval(t, tobj2);
+ tobj2->gmt = tobj->gmt;
+ }
+ return t;
}
static char *months [12] = {
@@ -152,22 +175,22 @@ static char *months [12] = {
"jul", "aug", "sep", "oct", "nov", "dec",
};
-static int
-obj2int(obj)
+static long
+obj2long(obj)
VALUE obj;
{
if (TYPE(obj) == T_STRING) {
obj = rb_str2inum(RSTRING(obj)->ptr, 10);
}
- return NUM2INT(obj);
+ return NUM2LONG(obj);
}
static void
-time_arg(argc, argv, args)
+time_arg(argc, argv, tm)
int argc;
VALUE *argv;
- int *args;
+ struct tm *tm;
{
VALUE v[6];
int i;
@@ -184,102 +207,98 @@ time_arg(argc, argv, args)
rb_scan_args(argc, argv, "15", &v[0],&v[1],&v[2],&v[3],&v[4],&v[5]);
}
- args[0] = obj2int(v[0]);
- if (args[0] < 70) args[0] += 100;
- if (args[0] > 1900) args[0] -= 1900;
+ tm->tm_year = obj2long(v[0]);
+ if (tm->tm_year < 69) tm->tm_year += 100;
+ if (tm->tm_year >= 1000) tm->tm_year -= 1900;
if (NIL_P(v[1])) {
- args[1] = 0;
+ tm->tm_mon = 0;
}
else if (TYPE(v[1]) == T_STRING) {
- args[1] = -1;
+ tm->tm_mon = -1;
for (i=0; i<12; i++) {
- if (strcasecmp(months[i], RSTRING(v[1])->ptr) == 0) {
- args[1] = i;
+ if (RSTRING(v[1])->len == 3 &&
+ strcasecmp(months[i], RSTRING(v[1])->ptr) == 0) {
+ tm->tm_mon = i;
break;
}
}
- if (args[1] == -1) {
+ if (tm->tm_mon == -1) {
char c = RSTRING(v[1])->ptr[0];
if ('0' <= c && c <= '9') {
- args[1] = obj2int(v[1])-1;
+ tm->tm_mon = obj2long(v[1])-1;
}
}
}
else {
- args[1] = obj2int(v[1]) - 1;
+ tm->tm_mon = obj2long(v[1]) - 1;
}
if (NIL_P(v[2])) {
- args[2] = 1;
+ tm->tm_mday = 1;
}
else {
- args[2] = obj2int(v[2]);
- }
- for (i=3;i<6;i++) {
- if (NIL_P(v[i])) {
- args[i] = 0;
- }
- else {
- args[i] = obj2int(v[i]);
- }
+ tm->tm_mday = obj2long(v[2]);
}
+ tm->tm_hour = NIL_P(v[3])?0:obj2long(v[3]);
+ tm->tm_min = NIL_P(v[4])?0:obj2long(v[4]);
+ tm->tm_sec = NIL_P(v[5])?0:obj2long(v[5]);
/* value validation */
- if ( args[0] < 70|| args[0] > 137
- || args[1] < 0 || args[1] > 11
- || args[2] < 1 || args[2] > 31
- || args[3] < 0 || args[3] > 23
- || args[4] < 0 || args[4] > 59
- || args[5] < 0 || args[5] > 60)
+ if ( tm->tm_year < 69
+ || tm->tm_mon < 0 || tm->tm_mon > 11
+ || tm->tm_mday < 1 || tm->tm_mday > 31
+ || tm->tm_hour < 0 || tm->tm_hour > 23
+ || tm->tm_min < 0 || tm->tm_min > 59
+ || tm->tm_sec < 0 || tm->tm_sec > 60)
rb_raise(rb_eArgError, "argument out of range");
}
static VALUE time_gmtime _((VALUE));
static VALUE time_localtime _((VALUE));
-static VALUE
-time_gm_or_local(argc, argv, gm_or_local, klass)
- int argc;
- VALUE *argv;
- int gm_or_local;
- VALUE klass;
+static VALUE time_get_tm _((VALUE, int));
+
+static time_t
+make_time_t(tptr, fn)
+ struct tm *tptr;
+ struct tm *(*fn)();
{
- int args[6];
struct timeval tv;
- struct tm *tm;
time_t guess, t;
- int diff;
- struct tm *(*fn)();
- VALUE time;
-
- fn = (gm_or_local) ? gmtime : localtime;
- time_arg(argc, argv, args);
+ struct tm *tm;
+ long diff;
- gettimeofday(&tv, 0);
+ if (gettimeofday(&tv, 0) < 0) {
+ rb_sys_fail("gettimeofday");
+ }
guess = tv.tv_sec;
tm = (*fn)(&guess);
if (!tm) goto error;
- t = args[0];
+ t = tptr->tm_year;
+ if (t < 69) goto out_of_range;
while (diff = t - (tm->tm_year)) {
guess += diff * 364 * 24 * 3600;
- if (guess < 0) rb_raise(rb_eArgError, "too far future");
+ if (diff > 0 && guess < 0) goto out_of_range;
tm = (*fn)(&guess);
if (!tm) goto error;
}
- t = args[1];
+ t = tptr->tm_mon;
while (diff = t - tm->tm_mon) {
guess += diff * 27 * 24 * 3600;
tm = (*fn)(&guess);
if (!tm) goto error;
+ if (tptr->tm_year != tm->tm_year) goto out_of_range;
}
- guess += (args[2] - tm->tm_mday) * 3600 * 24;
- guess += (args[3] - tm->tm_hour) * 3600;
- guess += (args[4] - tm->tm_min) * 60;
- guess += args[5] - tm->tm_sec;
+ guess += (tptr->tm_mday - tm->tm_mday) * 3600 * 24;
+ guess += (tptr->tm_hour - tm->tm_hour) * 3600;
+ guess += (tptr->tm_min - tm->tm_min) * 60;
+ guess += tptr->tm_sec - tm->tm_sec;
+ if (guess < 0) goto out_of_range;
- time = time_new_internal(klass, guess, 0);
- if (gm_or_local) return time_gmtime(time);
- return time_localtime(time);
+ return guess;
+
+ out_of_range:
+ rb_raise(rb_eArgError, "time out of range");
error:
rb_raise(rb_eArgError, "gmtime/localtime error");
@@ -287,6 +306,25 @@ time_gm_or_local(argc, argv, gm_or_local, klass)
}
static VALUE
+time_gm_or_local(argc, argv, gm_or_local, klass)
+ int argc;
+ VALUE *argv;
+ int gm_or_local;
+ VALUE klass;
+{
+ struct tm tm;
+ struct tm *(*fn)();
+ VALUE time;
+
+ fn = (gm_or_local) ? gmtime : localtime;
+ time_arg(argc, argv, &tm);
+
+ time = time_new_internal(klass, make_time_t(&tm, fn), 0);
+ if (gm_or_local) return time_gmtime(time);
+ return time_localtime(time);
+}
+
+static VALUE
time_s_timegm(argc, argv, klass)
int argc;
VALUE *argv;
@@ -311,7 +349,7 @@ time_to_i(time)
struct time_object *tobj;
GetTimeval(time, tobj);
- return rb_int2inum(tobj->tv.tv_sec);
+ return INT2NUM(tobj->tv.tv_sec);
}
static VALUE
@@ -331,7 +369,7 @@ time_usec(time)
struct time_object *tobj;
GetTimeval(time, tobj);
- return INT2FIX(tobj->tv.tv_usec);
+ return INT2NUM(tobj->tv.tv_usec);
}
static VALUE
@@ -339,12 +377,12 @@ time_cmp(time1, time2)
VALUE time1, time2;
{
struct time_object *tobj1, *tobj2;
- int i;
+ long i;
GetTimeval(time1, tobj1);
switch (TYPE(time2)) {
case T_FIXNUM:
- i = FIX2INT(time2);
+ i = FIX2LONG(time2);
if (tobj1->tv.tv_sec == i) return INT2FIX(0);
if (tobj1->tv.tv_sec > i) return INT2FIX(1);
return FIX2INT(-1);
@@ -353,10 +391,13 @@ time_cmp(time1, time2)
{
double t;
- if (tobj1->tv.tv_sec == (int)RFLOAT(time2)->value) return INT2FIX(0);
+ if (tobj1->tv.tv_sec == (time_t)RFLOAT(time2)->value)
+ return INT2FIX(0);
t = (double)tobj1->tv.tv_sec + (double)tobj1->tv.tv_usec*1e-6;
- if (tobj1->tv.tv_sec == RFLOAT(time2)->value) return INT2FIX(0);
- if (tobj1->tv.tv_sec > RFLOAT(time2)->value) return INT2FIX(1);
+ if (tobj1->tv.tv_sec == (time_t)RFLOAT(time2)->value)
+ return INT2FIX(0);
+ if (tobj1->tv.tv_sec > (time_t)RFLOAT(time2)->value)
+ return INT2FIX(1);
return FIX2INT(-1);
}
}
@@ -371,7 +412,7 @@ time_cmp(time1, time2)
if (tobj1->tv.tv_sec > tobj2->tv.tv_sec) return INT2FIX(1);
return FIX2INT(-1);
}
- i = NUM2INT(time2);
+ i = NUM2LONG(time2);
if (tobj1->tv.tv_sec == i) return INT2FIX(0);
if (tobj1->tv.tv_sec > i) return INT2FIX(1);
return FIX2INT(-1);
@@ -394,11 +435,22 @@ time_eql(time1, time2)
}
static VALUE
+time_gmt_p(time)
+ VALUE time;
+{
+ struct time_object *tobj;
+
+ GetTimeval(time, tobj);
+ if (tobj->gmt) return Qtrue;
+ return Qfalse;
+}
+
+static VALUE
time_hash(time)
VALUE time;
{
struct time_object *tobj;
- int hash;
+ long hash;
GetTimeval(time, tobj);
hash = tobj->tv.tv_sec ^ tobj->tv.tv_usec;
@@ -406,19 +458,34 @@ time_hash(time)
}
static VALUE
+time_clone(time)
+ VALUE time;
+{
+ VALUE obj;
+ struct time_object *tobj, *newtobj;
+
+ GetTimeval(time, tobj);
+ obj = Data_Make_Struct(0, struct time_object, 0, free, newtobj);
+ CLONESETUP(obj, time);
+ MEMCPY(newtobj, tobj, struct time_object, 1);
+
+ return obj;
+}
+
+static VALUE
time_localtime(time)
VALUE time;
{
struct time_object *tobj;
struct tm *tm_tmp;
+ time_t t;
GetTimeval(time, tobj);
- tm_tmp = localtime((const time_t*)&tobj->tv.tv_sec);
+ t = tobj->tv.tv_sec;
+ tm_tmp = localtime(&t);
tobj->tm = *tm_tmp;
tobj->tm_got = 1;
-#ifndef HAVE_TM_ZONE
tobj->gmt = 0;
-#endif
return time;
}
@@ -428,18 +495,27 @@ time_gmtime(time)
{
struct time_object *tobj;
struct tm *tm_tmp;
+ time_t t;
GetTimeval(time, tobj);
- tm_tmp = gmtime((const time_t*)&tobj->tv.tv_sec);
+ t = tobj->tv.tv_sec;
+ tm_tmp = gmtime(&t);
tobj->tm = *tm_tmp;
tobj->tm_got = 1;
-#ifndef HAVE_TM_ZONE
tobj->gmt = 1;
-#endif
return time;
}
static VALUE
+time_get_tm(time, gmt)
+ VALUE time;
+ int gmt;
+{
+ if (gmt) return time_gmtime(time);
+ return time_localtime(time);
+}
+
+static VALUE
time_asctime(time)
VALUE time;
{
@@ -448,9 +524,9 @@ time_asctime(time)
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- time_localtime(time);
+ time_get_tm(time, tobj->gmt);
}
- s = asctime(&(tobj->tm));
+ s = asctime(&tobj->tm);
if (s[24] == '\n') s[24] = '\0';
return rb_str_new2(s);
@@ -461,21 +537,21 @@ time_to_s(time)
VALUE time;
{
struct time_object *tobj;
- char buf[64];
+ char buf[128];
int len;
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- time_localtime(time);
+ time_get_tm(time, tobj->gmt);
}
#ifndef HAVE_TM_ZONE
if (tobj->gmt == 1) {
- len = strftime(buf, 64, "%a %b %d %H:%M:%S GMT %Y", &(tobj->tm));
+ len = strftime(buf, 128, "%a %b %d %H:%M:%S GMT %Y", &tobj->tm);
}
else
#endif
{
- len = strftime(buf, 64, "%a %b %d %H:%M:%S %Z %Y", &(tobj->tm));
+ len = strftime(buf, 128, "%a %b %d %H:%M:%S %Z %Y", &tobj->tm);
}
return rb_str_new(buf, len);
}
@@ -484,64 +560,67 @@ static VALUE
time_plus(time1, time2)
VALUE time1, time2;
{
- struct time_object *tobj1, *tobj2;
- long sec, usec;
+ struct time_object *tobj;
+ time_t sec, usec;
+ double f;
- GetTimeval(time1, tobj1);
- if (TYPE(time2) == T_FLOAT) {
- unsigned int nsec = (unsigned int)RFLOAT(time2)->value;
- sec = tobj1->tv.tv_sec + nsec;
- usec = tobj1->tv.tv_usec + (long)(RFLOAT(time2)->value-(double)nsec)*1e6;
- }
- else if (rb_obj_is_instance_of(time2, rb_cTime)) {
- GetTimeval(time2, tobj2);
- sec = tobj1->tv.tv_sec + tobj2->tv.tv_sec;
- usec = tobj1->tv.tv_usec + tobj2->tv.tv_usec;
- }
- else {
- sec = tobj1->tv.tv_sec + NUM2INT(time2);
- usec = tobj1->tv.tv_usec;
+ GetTimeval(time1, tobj);
+
+ if (rb_obj_is_kind_of(time2, rb_cTime)) {
+ rb_raise(rb_eTypeError, "time + time?");
}
+ f = NUM2DBL(time2);
+ sec = (time_t)f;
+ usec = tobj->tv.tv_usec + (time_t)((f - (double)sec)*1e6);
+ sec = tobj->tv.tv_sec + sec;
if (usec >= 1000000) { /* usec overflow */
sec++;
usec -= 1000000;
}
- return rb_time_new(sec, usec);
+ time2 = rb_time_new(sec, usec);
+ if (tobj->gmt) {
+ GetTimeval(time2, tobj);
+ tobj->gmt = 1;
+ }
+ return time2;
}
static VALUE
time_minus(time1, time2)
VALUE time1, time2;
{
- struct time_object *tobj1, *tobj2;
- int sec, usec;
+ struct time_object *tobj;
+ time_t sec, usec;
+ double f;
- GetTimeval(time1, tobj1);
+ GetTimeval(time1, tobj);
if (rb_obj_is_instance_of(time2, rb_cTime)) {
- double f;
+ struct time_object *tobj2;
GetTimeval(time2, tobj2);
- f = tobj1->tv.tv_sec - tobj2->tv.tv_sec;
-
- f += (tobj1->tv.tv_usec - tobj2->tv.tv_usec)*1e-6;
+ f = tobj->tv.tv_sec - tobj2->tv.tv_sec;
+ f += (tobj->tv.tv_usec - tobj2->tv.tv_usec)*1e-6;
return rb_float_new(f);
}
- else if (TYPE(time2) == T_FLOAT) {
- sec = tobj1->tv.tv_sec - (int)RFLOAT(time2)->value;
- usec = tobj1->tv.tv_usec - (RFLOAT(time2)->value - (double)sec)*1e6;
- }
else {
- sec = tobj1->tv.tv_sec - NUM2INT(time2);
- usec = tobj1->tv.tv_usec;
+ f = NUM2DBL(time2);
+ sec = (time_t)f;
+ usec = tobj->tv.tv_usec - (time_t)((f - (double)sec)*1e6);
+ sec = tobj->tv.tv_sec - sec;
}
if (usec < 0) { /* usec underflow */
sec--;
usec += 1000000;
}
- return rb_time_new(sec, usec);
+ time2 = rb_time_new(sec, usec);
+ if (tobj->gmt) {
+ GetTimeval(time2, tobj);
+ tobj->gmt = 1;
+ }
+ return time2;
}
static VALUE
@@ -552,7 +631,7 @@ time_sec(time)
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- time_localtime(time);
+ time_get_tm(time, tobj->gmt);
}
return INT2FIX(tobj->tm.tm_sec);
}
@@ -565,7 +644,7 @@ time_min(time)
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- time_localtime(time);
+ time_get_tm(time, tobj->gmt);
}
return INT2FIX(tobj->tm.tm_min);
}
@@ -578,7 +657,7 @@ time_hour(time)
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- time_localtime(time);
+ time_get_tm(time, tobj->gmt);
}
return INT2FIX(tobj->tm.tm_hour);
}
@@ -591,7 +670,7 @@ time_mday(time)
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- time_localtime(time);
+ time_get_tm(time, tobj->gmt);
}
return INT2FIX(tobj->tm.tm_mday);
}
@@ -604,7 +683,7 @@ time_mon(time)
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- time_localtime(time);
+ time_get_tm(time, tobj->gmt);
}
return INT2FIX(tobj->tm.tm_mon+1);
}
@@ -617,7 +696,7 @@ time_year(time)
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- time_localtime(time);
+ time_get_tm(time, tobj->gmt);
}
return INT2FIX(tobj->tm.tm_year+1900);
}
@@ -630,7 +709,7 @@ time_wday(time)
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- time_localtime(time);
+ time_get_tm(time, tobj->gmt);
}
return INT2FIX(tobj->tm.tm_wday);
}
@@ -643,9 +722,9 @@ time_yday(time)
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- time_localtime(time);
+ time_get_tm(time, tobj->gmt);
}
- return INT2FIX(tobj->tm.tm_yday);
+ return INT2FIX(tobj->tm.tm_yday+1);
}
static VALUE
@@ -656,7 +735,7 @@ time_isdst(time)
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- time_localtime(time);
+ time_get_tm(time, tobj->gmt);
}
return tobj->tm.tm_isdst?Qtrue:Qfalse;
}
@@ -666,15 +745,15 @@ time_zone(time)
VALUE time;
{
struct time_object *tobj;
- char buf[10];
+ char buf[64];
int len;
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- time_localtime(time);
+ time_get_tm(time, tobj->gmt);
}
- len = strftime(buf, 10, "%Z", &(tobj->tm));
+ len = strftime(buf, 64, "%Z", &tobj->tm);
return rb_str_new(buf, len);
}
@@ -686,7 +765,7 @@ time_to_a(time)
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- time_localtime(time);
+ time_get_tm(time, tobj->gmt);
}
return rb_ary_new3(10,
INT2FIX(tobj->tm.tm_sec),
@@ -696,7 +775,7 @@ time_to_a(time)
INT2FIX(tobj->tm.tm_mon+1),
INT2FIX(tobj->tm.tm_year+1900),
INT2FIX(tobj->tm.tm_wday),
- INT2FIX(tobj->tm.tm_yday),
+ INT2FIX(tobj->tm.tm_yday+1),
tobj->tm.tm_isdst?Qtrue:Qfalse,
time_zone(time));
}
@@ -708,23 +787,31 @@ rb_strftime(buf, format, time)
char * volatile format;
struct tm * volatile time;
{
- volatile int i;
- int len;
+ volatile int size;
+ int len, flen;
+ (*buf)[0] = '\0';
+ flen = strlen(format);
+ if (flen == 0) {
+ return 0;
+ }
len = strftime(*buf, SMALLBUF, format, time);
if (len != 0) return len;
- for (i=1024; i<8192; i+=1024) {
- *buf = xmalloc(i);
- len = strftime(*buf, i-1, format, time);
- if (len == 0) {
- free(*buf);
- continue;
- }
- return len;
+ for (size=1024; ; size*=2) {
+ *buf = xmalloc(size);
+ (*buf)[0] = '\0';
+ len = strftime(*buf, size, format, time);
+ /*
+ * buflen can be zero EITHER because there's not enough
+ * room in the string, or because the control command
+ * goes to the empty string. Make a reasonable guess that
+ * if the buffer is 1024 times bigger than the length of the
+ * format string, it's not failing for lack of room.
+ */
+ if (len > 0 || len >= 1024 * flen) return len;
+ free(*buf);
}
-
- rb_raise(rb_eArgError, "bad strftime format or result too long");
- return Qnil; /* not reached */
+ /* not reached */
}
static VALUE
@@ -740,23 +827,28 @@ time_strftime(time, format)
GetTimeval(time, tobj);
if (tobj->tm_got == 0) {
- time_localtime(time);
+ time_get_tm(time, tobj->gmt);
}
fmt = str2cstr(format, &len);
+ if (len == 0) {
+ rb_warning("strftime called with empty format string");
+ }
if (strlen(fmt) < len) {
/* Ruby string may contain \0's. */
char *p = fmt, *pe = fmt + len;
str = rb_str_new(0, 0);
while (p < pe) {
- len = rb_strftime(&buf, p, &(tobj->tm));
+ len = rb_strftime(&buf, p, &tobj->tm);
rb_str_cat(str, buf, len);
p += strlen(p) + 1;
+ if (p <= pe)
+ rb_str_cat(str, "\0", 1);
if (len > SMALLBUF) free(buf);
}
return str;
}
- len = rb_strftime(&buf, RSTRING(format)->ptr, &(tobj->tm));
+ len = rb_strftime(&buf, RSTRING(format)->ptr, &tobj->tm);
str = rb_str_new(buf, len);
if (buf != buffer) free(buf);
return str;
@@ -797,26 +889,43 @@ time_s_times(obj)
}
static VALUE
-time_dump(time, limit)
- VALUE time, limit;
+time_dump(argc, argv, time)
+ int argc;
+ VALUE *argv;
+ VALUE time;
{
+ VALUE dummy;
struct time_object *tobj;
- int sec, usec;
+ struct tm *tm;
+ unsigned long p, s;
unsigned char buf[8];
+ time_t t;
int i;
+ rb_scan_args(argc, argv, "01", &dummy);
GetTimeval(time, tobj);
- sec = tobj->tv.tv_sec;
- usec = tobj->tv.tv_usec;
+
+ t = tobj->tv.tv_sec;
+ tm = gmtime(&t);
+
+ p = 0x1 << 31 | /* 1 */
+ tm->tm_year << 14 | /* 17 */
+ tm->tm_mon << 10 | /* 4 */
+ tm->tm_mday << 5 | /* 5 */
+ tm->tm_hour; /* 5 */
+ s = tm->tm_min << 26 | /* 6 */
+ tm->tm_sec << 20 | /* 6 */
+ tobj->tv.tv_usec; /* 20 */
for (i=0; i<4; i++) {
- buf[i] = sec & 0xff;
- sec = RSHIFT(sec, 8);
+ buf[i] = p & 0xff;
+ p = RSHIFT(p, 8);
}
for (i=4; i<8; i++) {
- buf[i] = usec & 0xff;
- usec = RSHIFT(usec, 8);
+ buf[i] = s & 0xff;
+ s = RSHIFT(s, 8);
}
+
return rb_str_new(buf, 8);
}
@@ -824,8 +933,10 @@ static VALUE
time_load(klass, str)
VALUE klass, str;
{
- int sec, usec;
+ unsigned long p, s;
+ time_t sec, usec;
unsigned char *buf;
+ struct tm tm;
int i;
buf = str2cstr(str, &i);
@@ -833,14 +944,28 @@ time_load(klass, str)
rb_raise(rb_eTypeError, "marshaled time format differ");
}
- sec = usec = 0;
+ p = s = 0;
for (i=0; i<4; i++) {
- sec |= buf[i]<<(8*i);
+ p |= buf[i]<<(8*i);
}
for (i=4; i<8; i++) {
- usec |= buf[i]<<(8*(i-4));
+ s |= buf[i]<<(8*(i-4));
}
+ if ((p & (1<<31)) == 0) {
+ return time_new_internal(klass, p, s);
+ }
+ p &= ~(1<<31);
+ tm.tm_year = (p >> 14) & 0x1ffff;
+ tm.tm_mon = (p >> 10) & 0xf;
+ tm.tm_mday = (p >> 5) & 0x1f;
+ tm.tm_hour = p & 0x1f;
+ tm.tm_min = (s >> 26) & 0x3f;
+ tm.tm_sec = (s >> 20) & 0x3f;
+
+ sec = make_time_t(&tm, gmtime);
+ usec = (time_t) s & 0xfffff;
+
return time_new_internal(klass, sec, usec);
}
@@ -864,6 +989,7 @@ Init_Time()
rb_define_method(rb_cTime, "<=>", time_cmp, 1);
rb_define_method(rb_cTime, "eql?", time_eql, 1);
rb_define_method(rb_cTime, "hash", time_hash, 0);
+ rb_define_method(rb_cTime, "clone", time_clone, 0);
rb_define_method(rb_cTime, "localtime", time_localtime, 0);
rb_define_method(rb_cTime, "gmtime", time_gmtime, 0);
@@ -889,6 +1015,8 @@ Init_Time()
rb_define_method(rb_cTime, "isdst", time_isdst, 0);
rb_define_method(rb_cTime, "zone", time_zone, 0);
+ rb_define_method(rb_cTime, "gmt?", time_gmt_p, 0);
+
rb_define_method(rb_cTime, "tv_sec", time_to_i, 0);
rb_define_method(rb_cTime, "tv_usec", time_usec, 0);
rb_define_method(rb_cTime, "usec", time_usec, 0);
@@ -900,6 +1028,6 @@ Init_Time()
#endif
/* methods for marshaling */
+ rb_define_method(rb_cTime, "_dump", time_dump, -1);
rb_define_singleton_method(rb_cTime, "_load", time_load, 1);
- rb_define_method(rb_cTime, "_dump", time_dump, 1);
}
diff --git a/top.sed b/top.sed
index a9ec12f7b6..feef9006ba 100644
--- a/top.sed
+++ b/top.sed
@@ -1,7 +1,7 @@
/^SHELL/s,/bin/sh,$(COMPSEC),
s/@srcdir@/./g
s/@top_srcdir@/../
-s%@CFLAGS@%-g -O2%g
+s%@CFLAGS@%-O2%g
s%@CPPFLAGS@%%g
s%@LDFLAGS@%%g
s%@LIBS@%-lm %g
@@ -33,8 +33,12 @@ 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%@LIBOBJS@% crypt.o flock.o fnmatch.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
@@ -44,8 +48,11 @@ s%@STRIP@%strip%g
s%@EXTSTATIC@%%g
s%@binsuffix@%.exe%g
s%@setup@%Setup.dj%g
+s%@RUBY_INSTALL_NAME@%ruby%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-djgpp%g
s%/bin/rm%rm%
@@ -55,4 +62,7 @@ s%@archlib@%/usr/local/lib/ruby/i386-djgpp%
s,/dev/null 2>&1, nul,
s,2> /dev/null,,
}
+/^config.status/ {
+ N;N;N;N;N;d
+}
s%y\.tab\.c%y_tab.c%
diff --git a/util.c b/util.c
index ae0914d217..04b3dd6dbe 100644
--- a/util.c
+++ b/util.c
@@ -6,7 +6,7 @@
$Date$
created at: Fri Mar 10 17:22:34 JST 1995
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -19,6 +19,10 @@
#define RUBY_NO_INLINE
#include "ruby.h"
+#ifdef USE_CWGUSI
+extern char* mktemp(char*);
+#endif
+
VALUE
rb_class_of(obj)
VALUE obj;
@@ -69,11 +73,11 @@ char *strchr _((char*,char));
unsigned long
scan_oct(start, len, retlen)
-char *start;
+const char *start;
int len;
int *retlen;
{
- register char *s = start;
+ register const char *s = start;
register unsigned long retval = 0;
while (len-- && *s >= '0' && *s <= '7') {
@@ -86,12 +90,12 @@ int *retlen;
unsigned long
scan_hex(start, len, retlen)
-char *start;
+const char *start;
int len;
int *retlen;
{
static char hexdigit[] = "0123456789abcdef0123456789ABCDEFx";
- register char *s = start;
+ register const char *s = start;
register unsigned long retval = 0;
char *tmp;
@@ -109,7 +113,7 @@ int *retlen;
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
-#if defined(HAVE_FCNTL)
+#if defined(HAVE_FCNTL_H)
#include <fcntl.h>
#endif
@@ -262,7 +266,7 @@ ruby_add_suffix(str, suffix)
slen = extlen;
t = buf; baselen = 0; s = RSTRING(str)->ptr;
- while ( (*t = *s) && *s != '.') {
+ while ((*t = *s) && *s != '.') {
baselen++;
if (*s == '\\' || *s == '/') baselen = 0;
s++; t++;
@@ -325,7 +329,6 @@ valid_filename(char *s)
#endif
#ifdef DJGPP
-/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
#include <libc/stubs.h>
#include <stdio.h> /* For FILENAME_MAX */
@@ -569,14 +572,14 @@ static void mmprepare(base, size) void *base; int size;
if (size <= 0) die("mmsize <= 0");
#endif
- if ( ((int)base & (4-1)) == 0 && (size & (4-1)) == 0 )
- if (size >= 16) mmkind = 1;
- else mmkind = 0;
- else mmkind = -1;
+ if (((long)base & (4-1)) == 0 && ((long)base & (4-1)) == 0)
+ if (size >= 16) mmkind = 1;
+ else mmkind = 0;
+ else mmkind = -1;
mmsize = size;
high = (size & (-16));
- low = (size & 0x0C );
+ low = (size & 0x0c);
}
static void mmswap(a, b) register char *a, *b;
@@ -591,7 +594,7 @@ static void mmswap(a, b) register char *a, *b;
s = A[1]; A[1] = B[1]; B[1] = s;
s = A[2]; A[2] = B[2]; B[2] = s;
s = A[3]; A[3] = B[3]; B[3] = s; a += 16; b += 16;
- }while (a < t);
+ } while (a < t);
}
if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = s;
@@ -661,7 +664,7 @@ typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */
#define med3(a,b,c) ((*cmp)(a,b)<0 ? \
((*cmp)(b,c)<0 ? b : ((*cmp)(a,c)<0 ? c : a)) : \
- ((*cmp)(b,c)>0 ? b : ((*cmp)(a,c)<0 ? a : c)) )
+ ((*cmp)(b,c)>0 ? b : ((*cmp)(a,c)<0 ? a : c)))
void ruby_qsort (base, nel, size, cmp) void* base; int nel; int size; int (*cmp)();
{
@@ -673,7 +676,7 @@ void ruby_qsort (base, nel, size, cmp) void* base; int nel; int size; int (*cmp)
stack_node stack[32], *top = stack; /* 32 is enough for 32bit CPU */
if (nel <= 1) return; /* need not to sort */
- mmprepare( base, size );
+ mmprepare(base, size);
goto start;
nxt:
@@ -697,18 +700,18 @@ void ruby_qsort (base, nel, size, cmp) void* base; int nel; int size; int (*cmp)
register char *p1 = l + t;
register char *p2 = p1 + t;
register char *p3 = p2 + t;
- m1 = med3( p1, p2, p3 );
+ m1 = med3(p1, p2, p3);
p1 = m + t;
p2 = p1 + t;
p3 = p2 + t;
- m3 = med3( p1, p2, p3 );
+ m3 = med3(p1, p2, p3);
}
}else{
t = size*(t>>2); /* number of bytes in splitting 4 */
m1 = l + t;
m3 = m + t;
}
- m = med3( m1, m, m3 );
+ m = med3(m1, m, m3);
}
if ((t = (*cmp)(l,m)) < 0) { /*3-5-?*/
@@ -757,7 +760,7 @@ void ruby_qsort (base, nel, size, cmp) void* base; int nel; int size; int (*cmp)
if (t < 0) {mmswap(L,l); l = L; goto loopB;} /*535-5*/
}
- loopA: eq_l = 1; eq_r = 1; /* splitting type A */ /* left <= median < right±¦*/
+ loopA: eq_l = 1; eq_r = 1; /* splitting type A */ /* left <= median < right */
for (;;) {
for (;;) {
if ((l += size) == r)
@@ -805,3 +808,4 @@ void ruby_qsort (base, nel, size, cmp) void* base; int nel; int size; int (*cmp)
else goto nxt; /* need not to sort both sides */
}
}
+
diff --git a/util.h b/util.h
index 756daeeac6..41ce2a5a19 100644
--- a/util.h
+++ b/util.h
@@ -6,28 +6,33 @@
$Date$
created at: Thu Mar 9 11:55:53 JST 1995
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
#ifndef UTIL_H
#define UTIL_H
#ifndef _
-# ifdef __STDC__
-# define _(args) args
-# else
-# define _(args) ()
-# endif
+#ifdef HAVE_PROTOTYPES
+# define _(args) args
+#else
+# define _(args) ()
+#endif
+#ifdef HAVE_STDARG_PROTOTYPES
+# define __(args) args
+#else
+# define __(args) ()
+#endif
#endif
#define scan_oct ruby_scan_oct
-unsigned long scan_oct _((char*, int, int*));
+unsigned long scan_oct _((const char*, int, int*));
#define scan_hex ruby_scan_hex
-unsigned long scan_hex _((char*, int, int*));
+unsigned long scan_hex _((const char*, int, int*));
#if defined(MSDOS) || defined(__CYGWIN32__) || defined(NT)
+void ruby_add_suffix();
#define add_suffix ruby_add_suffix
-void add_suffix();
#endif
char *ruby_mktemp _((void));
@@ -35,4 +40,11 @@ char *ruby_mktemp _((void));
void ruby_qsort _((void*, int, int, int (*)()));
#define qsort(b,n,s,c) ruby_qsort(b,n,s,c)
+void ruby_setenv _((const char*, const char*));
+void ruby_unsetenv _((const char*));
+#undef setenv
+#undef unsetenv
+#define setenv(name,val) ruby_setenv((name),(val))
+#define unsetenv(name,val) ruby_unsetenv((name));
+
#endif /* UTIL_H */
diff --git a/variable.c b/variable.c
index 03262c5d83..23ae945870 100644
--- a/variable.c
+++ b/variable.c
@@ -13,8 +13,8 @@
#include "node.h"
#include "st.h"
-#ifdef USE_CWGUSI
-char* strdup(char*);
+#ifndef strdup
+char *strdup();
#endif
static st_table *rb_global_tbl;
@@ -106,7 +106,7 @@ find_class_path(klass)
st_foreach(rb_class_tbl, fc_i, &arg);
}
if (arg.name) {
- rb_iv_set(klass, "__classpath__", arg.path);
+ st_insert(ROBJECT(klass)->iv_tbl,rb_intern("__classpath__"),arg.path);
return arg.path;
}
return Qnil;
@@ -116,22 +116,20 @@ static VALUE
classname(klass)
VALUE klass;
{
- VALUE path;
+ VALUE path = Qnil;
ID classpath = rb_intern("__classpath__");
while (TYPE(klass) == T_ICLASS || FL_TEST(klass, FL_SINGLETON)) {
klass = (VALUE)RCLASS(klass)->super;
}
if (!klass) klass = rb_cObject;
- if (!ROBJECT(klass)->iv_tbl ||
- !st_lookup(ROBJECT(klass)->iv_tbl, classpath, &path)) {
+ if (!ROBJECT(klass)->iv_tbl)
+ ROBJECT(klass)->iv_tbl = st_init_numtable();
+ else if (!st_lookup(ROBJECT(klass)->iv_tbl, classpath, &path)) {
ID classid = rb_intern("__classid__");
- path = rb_ivar_get(klass, classid);
- if (!NIL_P(path)) {
+ if (st_lookup(ROBJECT(klass)->iv_tbl, classid, &path)) {
path = rb_str_new2(rb_id2name(FIX2INT(path)));
- if (!ROBJECT(klass)->iv_tbl)
- ROBJECT(klass)->iv_tbl = st_init_numtable();
st_insert(ROBJECT(klass)->iv_tbl, classpath, path);
st_delete(RCLASS(klass)->iv_tbl, &classid, 0);
}
@@ -170,7 +168,7 @@ rb_class_path(klass)
char *s = "Class";
if (TYPE(klass) == T_MODULE) s = "Module";
- sprintf(buf, "#<%s 0x%x>", s, klass);
+ sprintf(buf, "#<%s 0lx%lx>", s, klass);
return rb_str_new2(buf);
}
}
@@ -178,7 +176,7 @@ rb_class_path(klass)
void
rb_set_class_path(klass, under, name)
VALUE klass, under;
- char *name;
+ const char *name;
{
VALUE str;
@@ -195,7 +193,7 @@ rb_set_class_path(klass, under, name)
VALUE
rb_path2class(path)
- char *path;
+ const char *path;
{
if (path[0] == '#') {
rb_raise(rb_eArgError, "can't retrieve anonymous class %s", path);
@@ -216,7 +214,7 @@ static st_table *autoload_tbl = 0;
static void
rb_autoload_id(id, filename)
ID id;
- char *filename;
+ const char *filename;
{
if (!rb_is_const_id(id)) {
rb_raise(rb_eNameError, "autoload must be constant name",
@@ -231,7 +229,7 @@ rb_autoload_id(id, filename)
void
rb_autoload(klass, filename)
- char *klass, *filename;
+ const char *klass, *filename;
{
rb_autoload_id(rb_intern(klass), filename);
}
@@ -248,6 +246,9 @@ char *
rb_class2name(klass)
VALUE klass;
{
+ if (klass == rb_cNilClass) return "nil";
+ if (klass == rb_cTrueClass) return "true";
+ if (klass == rb_cFalseClass) return "false";
return RSTRING(rb_class_path(klass))->ptr;
}
@@ -305,7 +306,7 @@ static VALUE
undef_getter(id)
ID id;
{
- if (rb_verbose) {
+ if (ruby_verbose) {
rb_warning("global variable `%s' not initialized", rb_id2name(id));
}
return Qnil;
@@ -386,7 +387,7 @@ readonly_setter(val, id, var)
ID id;
void *var;
{
- rb_raise(rb_eNameError, "Can't set variable %s", rb_id2name(id));
+ rb_raise(rb_eNameError, "can't set variable %s", rb_id2name(id));
}
static int
@@ -413,7 +414,7 @@ rb_gc_mark_global_tbl()
static ID
global_id(name)
- char *name;
+ const char *name;
{
ID id;
@@ -429,7 +430,7 @@ global_id(name)
void
rb_define_hooked_variable(name, var, getter, setter)
- char *name;
+ const char *name;
VALUE *var;
VALUE (*getter)();
void (*setter)();
@@ -446,7 +447,7 @@ rb_define_hooked_variable(name, var, getter, setter)
void
rb_define_variable(name, var)
- char *name;
+ const char *name;
VALUE *var;
{
rb_define_hooked_variable(name, var, 0, 0);
@@ -454,7 +455,7 @@ rb_define_variable(name, var)
void
rb_define_readonly_variable(name, var)
- char *name;
+ const char *name;
VALUE *var;
{
rb_define_hooked_variable(name, var, 0, readonly_setter);
@@ -462,7 +463,7 @@ rb_define_readonly_variable(name, var)
void
rb_define_virtual_variable(name, getter, setter)
- char *name;
+ const char *name;
VALUE (*getter)();
void (*setter)();
{
@@ -630,7 +631,7 @@ rb_gvar_set(entry, val)
VALUE
rb_gvar_set2(name, val)
- char *name;
+ const char *name;
VALUE val;
{
struct global_entry *entry;
@@ -768,27 +769,28 @@ generic_ivar_remove(obj, id)
return val;
}
-static int
-givar_mark_i(key, value)
- ID key;
- VALUE value;
-{
- rb_gc_mark(value);
- return ST_CONTINUE;
-}
-
void
rb_mark_generic_ivar(obj)
VALUE obj;
{
st_table *tbl;
+ if (!generic_iv_tbl) return;
if (st_lookup(generic_iv_tbl, obj, &tbl)) {
rb_mark_tbl(tbl);
}
}
static int
+givar_mark_i(key, value)
+ ID key;
+ VALUE value;
+{
+ rb_gc_mark(value);
+ return ST_CONTINUE;
+}
+
+static int
givar_i(obj, tbl)
VALUE obj;
st_table *tbl;
@@ -802,8 +804,8 @@ givar_i(obj, tbl)
void
rb_mark_generic_ivar_tbl()
{
- if (special_generic_ivar == 0) return;
if (!generic_iv_tbl) return;
+ if (special_generic_ivar == 0) return;
st_foreach(generic_iv_tbl, givar_i, 0);
}
@@ -817,6 +819,18 @@ rb_free_generic_ivar(obj)
st_free_table(tbl);
}
+void
+rb_clone_generic_ivar(clone, obj)
+ VALUE clone, obj;
+{
+ st_table *tbl;
+
+ if (!generic_iv_tbl) return;
+ if (st_lookup(generic_iv_tbl, obj, &tbl)) {
+ st_add_direct(generic_iv_tbl, clone, st_copy(tbl));
+ }
+}
+
VALUE
rb_ivar_get(obj, id)
VALUE obj;
@@ -824,11 +838,12 @@ rb_ivar_get(obj, id)
{
VALUE val;
+ if (!FL_TEST(obj, FL_TAINT) && rb_safe_level() >= 4)
+ rb_raise(rb_eSecurityError, "Insecure: can't access instance variable");
switch (TYPE(obj)) {
case T_OBJECT:
case T_CLASS:
case T_MODULE:
- case T_FILE:
if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, &val))
return val;
break;
@@ -837,7 +852,7 @@ rb_ivar_get(obj, id)
return generic_ivar_get(obj, id);
break;
}
- if (rb_verbose) {
+ if (ruby_verbose) {
rb_warning("instance var %s not initialized", rb_id2name(id));
}
return Qnil;
@@ -849,13 +864,12 @@ rb_ivar_set(obj, id, val)
ID id;
VALUE val;
{
+ if (!FL_TEST(obj, FL_TAINT) && rb_safe_level() >= 4)
+ rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
switch (TYPE(obj)) {
case T_OBJECT:
case T_CLASS:
case T_MODULE:
- case T_FILE:
- if (rb_safe_level() >= 4 && !FL_TEST(obj, FL_TAINT))
- rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
if (!ROBJECT(obj)->iv_tbl) ROBJECT(obj)->iv_tbl = st_init_numtable();
st_insert(ROBJECT(obj)->iv_tbl, id, val);
break;
@@ -871,13 +885,10 @@ rb_ivar_defined(obj, id)
VALUE obj;
ID id;
{
- if (!rb_is_instance_id(id)) return Qfalse;
-
switch (TYPE(obj)) {
case T_OBJECT:
case T_CLASS:
case T_MODULE:
- case T_FILE:
if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, 0))
return Qtrue;
break;
@@ -907,17 +918,19 @@ rb_obj_instance_variables(obj)
{
VALUE ary;
+ if (!FL_TEST(obj, FL_TAINT) && rb_safe_level() >= 4)
+ rb_raise(rb_eSecurityError, "Insecure: can't get metainfo");
switch (TYPE(obj)) {
case T_OBJECT:
case T_CLASS:
case T_MODULE:
- case T_FILE:
ary = rb_ary_new();
if (ROBJECT(obj)->iv_tbl) {
st_foreach(ROBJECT(obj)->iv_tbl, ivar_i, ary);
}
return ary;
default:
+ if (!generic_iv_tbl) return Qnil;
if (FL_TEST(obj, FL_EXIVAR) || rb_special_const_p(obj)) {
st_table *tbl;
@@ -938,6 +951,8 @@ rb_obj_remove_instance_variable(obj, name)
VALUE val = Qnil;
ID id = rb_to_id(name);
+ if (!FL_TEST(obj, FL_TAINT) && rb_safe_level() >= 4)
+ rb_raise(rb_eSecurityError, "Insecure: can't modify instance variable");
if (!rb_is_instance_id(id)) {
rb_raise(rb_eNameError, "`%s' is not an instance variable",
rb_id2name(id));
@@ -947,7 +962,6 @@ rb_obj_remove_instance_variable(obj, name)
case T_OBJECT:
case T_CLASS:
case T_MODULE:
- case T_FILE:
if (ROBJECT(obj)->iv_tbl) {
st_delete(ROBJECT(obj)->iv_tbl, &id, &val);
}
@@ -973,7 +987,7 @@ rb_const_get_at(klass, id)
if (klass == rb_cObject) {
return rb_const_get(klass, id);
}
- rb_raise(rb_eNameError, "Uninitialized constant %s::%s",
+ rb_raise(rb_eNameError, "uninitialized constant %s::%s",
RSTRING(rb_class_path(klass))->ptr,
rb_id2name(id));
return Qnil; /* not reached */
@@ -1016,11 +1030,11 @@ rb_const_get(klass, id)
/* Uninitialized constant */
if (klass && klass != rb_cObject)
- rb_raise(rb_eNameError, "Uninitialized constant %s::%s",
+ rb_raise(rb_eNameError, "uninitialized constant %s::%s",
RSTRING(rb_class_path(klass))->ptr,
rb_id2name(id));
else {
- rb_raise(rb_eNameError, "Uninitialized constant %s",rb_id2name(id));
+ rb_raise(rb_eNameError, "uninitialized constant %s",rb_id2name(id));
}
return Qnil; /* not reached */
}
@@ -1066,7 +1080,7 @@ rb_mod_remove_const(mod, name)
static int
autoload_i(key, name, ary)
ID key;
- char *name;
+ const char *name;
VALUE ary;
{
VALUE kval = rb_str_new2(rb_id2name(key));
@@ -1080,6 +1094,8 @@ VALUE
rb_mod_const_at(mod, ary)
VALUE mod, ary;
{
+ if (!FL_TEST(mod, FL_TAINT) && rb_safe_level() >= 4)
+ rb_raise(rb_eSecurityError, "Insecure: can't get metainfo");
if (RCLASS(mod)->iv_tbl) {
st_foreach(RCLASS(mod)->iv_tbl, const_i, ary);
}
@@ -1163,23 +1179,22 @@ rb_const_set(klass, id, val)
ID id;
VALUE val;
{
- if (rb_safe_level() >= 4 && !FL_TEST(klass, FL_TAINT))
+ if (!FL_TEST(klass, FL_TAINT) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't set constant");
if (!RCLASS(klass)->iv_tbl) {
RCLASS(klass)->iv_tbl = st_init_numtable();
}
else if (st_lookup(RCLASS(klass)->iv_tbl, id, 0)) {
- rb_raise(rb_eNameError, "already initialized constant %s",
- rb_id2name(id));
+ rb_warn("already initialized constant %s", rb_id2name(id));
}
- st_add_direct(RCLASS(klass)->iv_tbl, id, val);
+ st_insert(RCLASS(klass)->iv_tbl, id, val);
}
void
rb_define_const(klass, name, val)
VALUE klass;
- char *name;
+ const char *name;
VALUE val;
{
ID id = rb_intern(name);
@@ -1195,7 +1210,7 @@ rb_define_const(klass, name, val)
void
rb_define_global_const(name, val)
- char *name;
+ const char *name;
VALUE val;
{
rb_define_const(rb_cObject, name, val);
@@ -1204,7 +1219,7 @@ rb_define_global_const(name, val)
VALUE
rb_iv_get(obj, name)
VALUE obj;
- char *name;
+ const char *name;
{
ID id = rb_intern(name);
@@ -1214,7 +1229,7 @@ rb_iv_get(obj, name)
VALUE
rb_iv_set(obj, name, val)
VALUE obj;
- char *name;
+ const char *name;
VALUE val;
{
ID id = rb_intern(name);
diff --git a/version.c b/version.c
index 22393f0f4a..6cd9943430 100644
--- a/version.c
+++ b/version.c
@@ -3,11 +3,10 @@
version.c -
$Author$
- $Revision$
$Date$
created at: Thu Sep 30 20:08:01 JST 1993
- Copyright (C) 1993-1998 Yukihiro Matsumoto
+ Copyright (C) 1993-1999 Yukihiro Matsumoto
************************************************/
@@ -18,19 +17,29 @@
void
Init_version()
{
- rb_define_global_const("VERSION", rb_str_new2(RUBY_VERSION));
- rb_define_global_const("PLATFORM", rb_str_new2(RUBY_PLATFORM));
+ VALUE v = rb_str_new2(RUBY_VERSION);
+ VALUE d = rb_str_new2(RUBY_RELEASE_DATE);
+ VALUE p = rb_str_new2(RUBY_PLATFORM);
+
+ rb_define_global_const("RUBY_VERSION", v);
+ rb_define_global_const("RUBY_RELEASE_DATE", d);
+ rb_define_global_const("RUBY_PLATFORM", p);
+
+ /* obsolete constants */
+ rb_define_global_const("VERSION", v);
+ rb_define_global_const("RELEASE_DATE", d);
+ rb_define_global_const("PLATFORM", p);
}
void
ruby_show_version()
{
- fprintf(stderr, "ruby %s(%s) [%s]\n", RUBY_VERSION, VERSION_DATE, RUBY_PLATFORM);
+ printf("ruby %s (%s) [%s]\n", RUBY_VERSION, RUBY_RELEASE_DATE, RUBY_PLATFORM);
}
void
ruby_show_copyright()
{
- fprintf(stderr, "ruby - Copyright (C) 1993-1998 Yukihiro Matsumoto\n");
+ printf("ruby - Copyright (C) 1993-1999 Yukihiro Matsumoto\n");
exit(0);
}
diff --git a/version.h b/version.h
index 3b291392b3..d2c5ba958d 100644
--- a/version.h
+++ b/version.h
@@ -1,2 +1,4 @@
-#define RUBY_VERSION "1.3.1"
-#define VERSION_DATE "99/01/20"
+#define RUBY_VERSION "1.4.0"
+#define RUBY_RELEASE_DATE "1999-08-13"
+#define RUBY_VERSION_CODE 140
+#define RUBY_RELEASE_CODE 19990813
diff --git a/win32/Makefile b/win32/Makefile
index 152bdc88ea..5275069bf8 100644
--- a/win32/Makefile
+++ b/win32/Makefile
@@ -7,34 +7,36 @@ VPATH = .:./missing
CC = cl
YACC = byacc
-RANLIB =
-AR =
-INSTALL = ginstall -c
-INSTALL_PROGRAM = $(INSTALL)
-INSTALL_DATA = $(INSTALL) -m 644
PURIFY =
+AUTOCONF = autoconf
-CFLAGS = -nologo -DNT=1 -Ox -I. -I./missing
-LDFLAGS = $(CFLAGS) -Fm
-#CFLAGS = -nologo -DNT=1 -Zi -MD
-#LDFLAGS = $(CFLAGS) -Fm -MD
-LIBS = $(EXTLIBS) advapi32.lib wsock32.lib
-MISSING = crypt.obj alloca.obj win32.obj
-
prefix =
-binprefix =
-exec_prefix =
-bindir =
-libdir =
+CFLAGS = -nologo -DNT=1 -Ox -I. -I./missing
+LDFLAGS = $(CFLAGS) -Fm
+#CFLAGS = -nologo -DNT=1 -Zi -I. -I./missing
+#LDFLAGS = $(CFLAGS) -Fm
+XLDFLAGS =
+#EXTLIBS =
+LIBS = advapi32.lib wsock32.lib $(EXTLIBS)
+MISSING = crypt.obj alloca.obj win32.obj fnmatch.obj isinf.obj isnan.obj
+LDSHARED =
+DLDFLAGS =
+SOLIBS =
+
+RUBY_INSTALL_NAME=ruby
+EXEEXT = .exe
+PROGRAM=$(RUBY_INSTALL_NAME)$(EXEEXT)
STACK = 0x200000
ORGLIBPATH = $(LIB)
#### End of system configuration section. ####
-
-LIBRUBY = libruby.lib
+LIBRUBY_A = libruby.lib
+LIBRUBY_SO = rubymw.dll
+LIBRUBY = $(LIBRUBY_SO)
+LIBRUBYARG = rubymw.lib
EXTOBJS = dmyext.obj
@@ -50,18 +52,17 @@ OBJS = array.obj \
error.obj \
eval.obj \
file.obj \
- fnmatch.obj \
gc.obj \
- glob.obj \
hash.obj \
inits.obj \
io.obj \
- math.obj \
marshal.obj \
+ math.obj \
numeric.obj \
object.obj \
pack.obj \
parse.obj \
+ prec.obj \
process.obj \
random.obj \
range.obj \
@@ -79,65 +80,71 @@ OBJS = array.obj \
version.obj \
$(MISSING)
-all: miniruby.exe ext/Setup $(MISCLIBS)
- cd ext
+all: miniruby$(EXEEXT) rbconfig.rb ext/extmk.rb ext/Setup.nt rubymw.lib $(MISCLIBS)
set LIB=..\..\win32;$(ORGLIBPATH)
- ..\miniruby .\extmk.rb static
-# ..\miniruby .\extmk.rb
- cd ..
+ @.\miniruby$(EXEEXT) -Xext extmk.rb
-miniruby.exe: $(OBJS) $(MAINOBJ) $(EXTOBJS)
+ext/extmk.rb: ext/extmk.rb.in rbconfig.rb
+ @echo Creating ext/extmk.rb
+ @.\miniruby$(EXEEXT) -Xext mswin32_extmk.rb
+
+miniruby$(EXEEXT): $(OBJS) $(MAINOBJ) $(EXTOBJS)
@echo $(EXTOBJS)
@echo $(LIBS)
- @rm -f miniruby.exe
- $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(LIBS) -o miniruby.exe
+ @rm -f $@
+ $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(EXTOBJS) $(OBJS) $(LIBS) -o $@
+
+$(PROGRAM): $(LIBRUBY) $(MAINOBJ) $(LIBRUBY_SO)
+ @rm -f $@
+ $(PURIFY) $(CC) $(LDFLAGS) $(XLDFLAGS) $(MAINOBJ) -o $@ $(LIBRUBYARG) -link /STACK:$(STACK)
+
+$(LIBRUBY_A): $(OBJS)
+ lib -nologo /OUT:$@ $(OBJS)
-ruby.exe: $(LIBRUBY) $(MAINOBJ) $(EXTOBJS) rubymw.dll
- @rm -f ruby.exe
-# $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBY) $(LIBS) -o ruby.exe
- $(CC) $(LDFLAGS) $(MAINOBJ) -o ruby.exe rubymw.lib -link /STACK:$(STACK)
+rubymw.lib: ruby.def
+ lib -nologo /OUT:$@ /DEF:ruby.def
-rubymw.dll: $(LIBRUBY) $(EXTOBJS)
+$(LIBRUBY_SO): $(LIBRUBY_A) $(EXTOBJS)
set LIB=.\win32;$(ORGLIBPATH)
- @rm -f rubymw.dll
- $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBY) $(LIBS) -o rubymw.dll -link /DLL /DEF:ruby.def
+ @rm -f $@
+ $(CC) $(LDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBY_A) $(LIBS) -o $@ -link /DLL /DEF:ruby.def
@mv rubymw.map rubydll.map
-$(LIBRUBY): $(OBJS)
- lib /OUT:$(LIBRUBY) $(OBJS)
-
-install:; $(INSTALL_PROGRAM) ruby.exe $(bindir)/ruby.exe
- @-strip $(bindir)/ruby
- @test -d $(libdir) || mkdir $(libdir)
- cd ext; ../miniruby ./extmk.rb install
- @for rb in `grep '^lib/' MANIFEST`; do \
- $(INSTALL_DATA) $$rb $(libdir); \
- done
-
-clean:; @rm -f $(OBJS) $(LIBRUBY) main.obj dmyext.obj *.pdb *.map *.exp
- @rm -f ext/extinit.c ext/extinit.obj
- cd ext
- ..\miniruby .\extmk.rb clean
- cd ..
-
-realclean: clean
- @rm -f Makefile ext/extmk.rb
- @rm -f config.cache config.h config.log config.status
- @rm -f core ruby miniruby *~
-
-test:; @-./ruby sample/test.rb > ./ruby_test 2>&1; \
- if grep '^end of test' ./ruby_test > /dev/null; then \
- echo "test succeeded"; \
- else \
- grep '^sample/test.rb' ./ruby_test; \
- grep '^not' ./ruby_test; \
- echo "test failed";\
- fi;\
- rm -f ./ruby_test
+install: rbconfig.rb
+ .\miniruby.exe $(srcdir)/instruby.rb $(DESTDIR)
+
+clean:; @rm -f $(OBJS) $(LIBRUBY_A) $(MAINOBJ) rbconfig.rb
+ @rm -f ext/extinit.c ext/extinit.obj ext/vc*.pdb *.obj
+ @-.\miniruby$(EXEEXT) -Xext extmk.rb clean
+
+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
+ @rm -f *.map *.pdb *.ilk rubymw.* ruby.def
+ @rm -f $(PROGRAM) miniruby$(EXEEXT)
+
+realclean: distclean
+ @rm -f parse.c
+ @rm -f lex.c
+
+test: miniruby$(EXEEXT)
+ @.\miniruby$(EXEEXT) $(srcdir)/rubytest.rb
+
+rbconfig.rb: miniruby$(EXEEXT)
+ @.\miniruby$(EXEEXT) $(srcdir)/mkconfig.rb rbconfig.rb
+
+config.status: $(srcdir)/configure
+# $(SHELL) ./config.status --recheck
.c.obj:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
+parse.c: parse.y
+ $(YACC) $(YFLAGS) parse.y
+ sed -e "s!^extern char \*getenv();!/* & */!" y.tab.c > parse.c
+ @rm y.tab.c
+
alloca.obj: missing/alloca.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/alloca.c
@@ -147,84 +154,120 @@ crypt.obj: missing/crypt.c
dup2.obj: missing/dup2.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/dup2.c
+finite.obj: missing/finite.c
+ $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/finite.c
+
flock.obj: missing/flock.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/flock.c
+isinf.obj: missing/isinf.c
+ $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/isinf.c
+
+isnan.obj: missing/isnan.c
+ $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/isnan.c
+
+fnmatch.obj: missing/fnmatch.c
+ $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/fnmatch.c
+
+memcmp.obj: missing/memcmp.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/memcmp.c
+
memmove.obj: missing/memmove.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c missing/memmove.c
mkdir.obj: missing/mkdir.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c missing/mkdir.c
-strerror.obj: missing/strerror.c
- $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/strerror.c
+vsnprintf.obj: missing/vsnprintf.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/vsnprintf.c
+
+strcasecmp.obj: missing/strcasecmp.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/strcasecmp.c
+
+strncasecmp.obj: missing/strncasecmp.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/strncasecmp.c
+
+strchr.obj: missing/strchr.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/strchr.c
strdup.obj: missing/strdup.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c missing/strdup.c
+strerror.obj: missing/strerror.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/strerror.c
+
strftime.obj: missing/strftime.c
$(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/strftime.c
strstr.obj: missing/strstr.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c missing/strstr.c
+strtod.obj: missing/strtod.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/strtod.c
+
strtol.obj: missing/strtol.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c missing/strtol.c
strtoul.obj: missing/strtoul.c
$(CC) $(CFLAGS) $(CPPFLAGS) -c missing/strtoul.c
+nt.obj: missing/nt.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/nt.c
+
+x68.obj: missing/x68.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/x68.c
+
+os2.obj: missing/os2.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/os2.c
+
+dl_os2.obj: missing/dl_os2.c
+ $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/dl_os2.c
+
# when I use -I., there is confliction at "OpenFile"
# so, set . into environment varible "include"
win32.obj: win32/win32.c
@set include=$(INCLUDE);.
$(CC) $(CFLAGS) $(CPPFLAGS) -c win32/win32.c
-parse.c: parse.y
- $(YACC) $(YFLAGS) parse.y
- sed -e "s!^extern char \*getenv();!/* & */!" y.tab.c > parse.c
- @rm y.tab.c
-
# Prevent GNU make v3 from overflowing arg limit on SysV.
.NOEXPORT:
###
-parse.obj : parse.y ruby.h defines.h config.h env.h node.h st.h regex.h
+parse.obj: parse.y ruby.h config.h defines.h intern.h env.h node.h st.h regex.h util.h lex.c
###
-array.obj: array.c ruby.h config.h defines.h
-bignum.obj: bignum.c ruby.h config.h defines.h
-class.obj: class.c ruby.h config.h defines.h node.h st.h
-compar.obj: compar.c ruby.h config.h defines.h
-dir.obj: dir.c ruby.h config.h defines.h
-dln.obj: dln.c config.h defines.h dln.h st.h
+array.obj: array.c ruby.h config.h defines.h intern.h
+bignum.obj: bignum.c ruby.h config.h defines.h intern.h
+class.obj: class.c ruby.h config.h defines.h intern.h node.h st.h
+compar.obj: compar.c ruby.h config.h defines.h intern.h
+dir.obj: dir.c ruby.h config.h defines.h intern.h
+dln.obj: dln.c config.h defines.h dln.h
dmyext.obj: dmyext.c
-enum.obj: enum.c ruby.h config.h defines.h
-error.obj: error.c ruby.h config.h defines.h env.h
-eval.obj: eval.c ruby.h config.h defines.h env.h node.h rubysig.h st.h dln.h
-file.obj: file.c ruby.h config.h defines.h rubyio.h rubysig.h
-fnmatch.obj: fnmatch.c config.h fnmatch.h
-gc.obj: gc.c ruby.h config.h defines.h env.h rubysig.h st.h node.h re.h regex.h
-glob.obj: glob.c config.h fnmatch.h
-hash.obj: hash.c ruby.h config.h defines.h st.h
-inits.obj: inits.c ruby.h config.h defines.h
-io.obj: io.c ruby.h config.h defines.h rubyio.h rubysig.h
-main.obj: main.c
-math.obj: math.c ruby.h config.h defines.h
-numeric.obj: numeric.c ruby.h config.h defines.h
-object.obj: object.c ruby.h config.h defines.h st.h
-pack.obj: pack.c ruby.h config.h defines.h
-process.obj: process.c ruby.h config.h defines.h rubysig.h st.h
-random.obj: random.c ruby.h config.h defines.h
-range.obj: range.c ruby.h config.h defines.h
-re.obj: re.c ruby.h config.h defines.h re.h regex.h
-regex.obj: regex.c config.h defines.h regex.h util.h
-ruby.obj: ruby.c ruby.h config.h defines.h re.h regex.h dln.h
-signal.obj: signal.c ruby.h config.h defines.h rubysig.h
-sprintf.obj: sprintf.c ruby.h config.h defines.h
+enum.obj: enum.c ruby.h config.h defines.h intern.h
+error.obj: error.c ruby.h config.h defines.h intern.h env.h
+eval.obj: eval.c ruby.h config.h defines.h intern.h node.h env.h rubysig.h st.h dln.h
+file.obj: file.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h
+gc.obj: gc.c ruby.h config.h defines.h intern.h rubysig.h st.h node.h env.h re.h regex.h
+hash.obj: hash.c ruby.h config.h defines.h intern.h st.h rubysig.h util.h
+inits.obj: inits.c ruby.h config.h defines.h intern.h
+io.obj: io.c ruby.h config.h defines.h intern.h rubyio.h rubysig.h
+main.obj: main.c ruby.h config.h defines.h intern.h
+marshal.obj: marshal.c ruby.h config.h defines.h intern.h rubyio.h st.h
+prec.obj: prec.c ruby.h config.h defines.h intern.h
+math.obj: math.c ruby.h config.h defines.h intern.h
+numeric.obj: numeric.c ruby.h config.h defines.h intern.h
+object.obj: object.c ruby.h config.h defines.h intern.h st.h
+pack.obj: pack.c ruby.h config.h defines.h intern.h
+process.obj: process.c ruby.h config.h defines.h intern.h rubysig.h st.h
+random.obj: random.c ruby.h config.h defines.h intern.h
+range.obj: range.c ruby.h config.h defines.h intern.h
+re.obj: re.c ruby.h config.h defines.h intern.h re.h regex.h
+regex.obj: regex.c config.h regex.h util.h
+ruby.obj: ruby.c ruby.h config.h defines.h intern.h dln.h util.h
+signal.obj: signal.c ruby.h config.h defines.h intern.h rubysig.h
+sprintf.obj: sprintf.c ruby.h config.h defines.h intern.h
st.obj: st.c config.h st.h
-string.obj: string.c ruby.h config.h defines.h re.h regex.h
-struct.obj: struct.c ruby.h config.h defines.h
-time.obj: time.c ruby.h config.h defines.h
-util.obj: util.c defines.h config.h util.h
-variable.obj: variable.c ruby.h config.h defines.h env.h st.h
-version.obj: version.c ruby.h config.h defines.h version.h
-director.obj : director.c dir.h
+string.obj: string.c ruby.h config.h defines.h intern.h re.h regex.h
+struct.obj: struct.c ruby.h config.h defines.h intern.h
+time.obj: time.c ruby.h config.h defines.h intern.h
+util.obj: util.c ruby.h config.h defines.h intern.h util.h
+variable.obj: variable.c ruby.h config.h defines.h intern.h env.h node.h st.h
+version.obj: version.c ruby.h config.h defines.h intern.h version.h
diff --git a/win32/config.h b/win32/config.h
index 8385154cd5..c871d7073d 100644
--- a/win32/config.h
+++ b/win32/config.h
@@ -1,7 +1,3 @@
-#define USE_THREAD 1
-#define SIZEOF_INT 4
-#define SIZEOF_LONG 4
-#define SIZEOF_VOIDP 4
#define HAVE_PROTOTYPES 1
#define HAVE_STDARG_PROTOTYPES 1
/* #define HAVE_ATTR_NORETURN 1 */
@@ -10,6 +6,7 @@
#define HAVE_STDLIB_H 1
#define HAVE_LIMITS_H 1
#define HAVE_SYS_FILE_H 1
+#define HAVE_FCNTL_H 1
/* #define HAVE_PWD_H 1 */
/* #define HAVE_SYS_TIME_H 1 */
/* #define HAVE_SYS_TIMES_H 1 */
@@ -27,7 +24,7 @@
#define vfork fork
#define HAVE_FMOD 1
/* #define HAVE_RANDOM 1 */
-/* #define HAVE_WAITPID 1 */
+#define HAVE_WAITPID 1
#define HAVE_GETCWD 1
/* #define HAVE_TRUNCATE 1 */
#define HAVE_CHSIZE 1
@@ -37,34 +34,18 @@
/* #define HAVE_SETITIMER 1 */
#define HAVE_GETGROUPS 1
/* #define HAVE_SIGPROCMASK 1 */
+#define HAVE_GETLOGIN 1
+
#define RSHIFT(x,y) ((x)>>y)
#define FILE_COUNT _cnt
#define DLEXT ".dll"
-#define RUBY_LIB ";/usr/local/lib/ruby;."
-#define RUBY_ARCHLIB "/usr/local/lib/ruby/i386-mswin32"
+#define RUBY_LIB "/usr/local/lib/ruby/1.4"
+#define RUBY_ARCHLIB "/usr/local/lib/ruby/1.4/i386-mswin32"
#define RUBY_PLATFORM "i386-mswin32"
-/* NNN */
-#define strcasecmp _strcmpi
-#define popen _popen
-#define pclose _pclose
-#define pipe _pipe
-#define bzero(x, y) memset(x, 0, y)
-#define snprintf _snprintf
-#define vsnprintf _vsnprintf
-
-
-#define S_IFMT _S_IFMT
-#define S_IFDIR _S_IFDIR
-#define S_IFCHR _S_IFCHR
-#define S_IFREG _S_IFREG
-#define S_IREAD _S_IREAD
-#define S_IWRITE _S_IWRITE
-#define S_IEXEC _S_IEXEC
-#define S_IFIFO _S_IFIFO
-
-#define UIDTYPE int
-#define GIDTYPE int
-#define pid_t int
-#define WNOHANG -1
-//#define NT
+#define SIZEOF_INT 4
+#define SIZEOF_SHORT 2
+#define SIZEOF_LONG 4
+#define SIZEOF_VOIDP 4
+#define SIZEOF_FLOAT 4
+#define SIZEOF_DOUBLE 8
diff --git a/win32/config.status b/win32/config.status
new file mode 100644
index 0000000000..09b2465390
--- /dev/null
+++ b/win32/config.status
@@ -0,0 +1,65 @@
+ac_given_srcdir=.
+s%@SHELL@%%g
+s%@CFLAGS@%-nologo -DNT=1 -Ox%g
+s%@CPPFLAGS@%%g
+s%@CXXFLAGS@%%g
+s%@FFLAGS@%%g
+s%@DEFS@%
+ -DUSE_THREAD -DSIZEOF_INT=4 -DSIZEOF_SHORT=2 -DSIZEOF_LONG=4 -DSIZEOF_VOIDP=4 -DSIZEOF_FLOAT=4 -DSIZEOF_DOUBLE=8 -DHAVE_PROTOTYPES=1 -DHAVE_STDARG_PROTOTYPES=1 -DHAVE_STDLIB_H=1 -DHAVE_LIMITS_H=1 -DHAVE_SYS_FILE_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_ST_RDEV=1 -DGETGROUPS_T=int -DRETSIGTYPE=void -DHAVE_ALLOCA=1 -DHAVE_FMOD=1 -DHAVE_WAITPID=1 -DHAVE_GETCWD=1 -DHAVE_CHSIZE=1 -DHAVE_GETGROUPS=1 -DHAVE_GETLOGIN=1 -DRSHIFT=\(x,y\)\ \(\(x\)\>\>y\) -DFILE_COUNT=_cnt -DDLEXT=\".dll\" -DRUBY_LIB=\"/usr/local/lib/ruby/1.4\" -DRUBY_ARCHLIB=\"/usr/local/lib/ruby/1.4/i386-mswin32\" -DRUBY_PLATFORM=\"i386-mswin32\" %g
+s%@LDFLAGS@%%g
+s%@LIBS@%advapi32.lib wsock32.lib%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-mswin32%g
+s%@host_alias@%i386-mswin32%g
+s%@host_cpu@%i386%g
+s%@host_vendor@%pc%g
+s%@host_os@%mswin32%g
+s%@CC@%cl%g
+s%@CPP@%cl -E%g
+s%@YACC@%byacc%g
+s%@RANLIB@%rem%g
+s%@AR@%lib -nologo%g
+s%@LN_S@%%g
+s%@SET_MAKE@%%g
+s%@LIBOBJS@% crypt.obj alloca.obj win32.obj fnmatch.obj isinf.obj isnan.obj%g
+s%@ALLOCA@%%g
+s%@DEFAULT_KCODE@%%g
+s%@EXEEXT@%.exe%g
+s%@OBJEXT@%obj%g
+s%@XLDFLAGS@%%g
+s%@DLDFLAGS@%%g
+s%@STATIC@%%g
+s%@CCDLFLAGS@%-DIMPORT%g
+s%@LDSHARED@%cl -LD%g
+s%@DLEXT@%dll%g
+s%@STRIP@%%g
+s%@EXTSTATIC@%%g
+s%@setup@%Setup.nt%g
+s%@LIBRUBY_LDSHARED@%%g
+s%@LIBRUBY_DLDFLAGS@%%g
+s%@RUBY_INSTALL_NAME@%ruby%g
+s%@LIBRUBY_A@%lib$(RUBY_INSTALL_NAME).lib%g
+s%@LIBRUBY_SO@%%g
+s%@LIBRUBY_ALIASES@%%g
+s%@LIBRUBY@%libruby.lib%g
+s%@LIBRUBYARG@%libruby.lib%g
+s%@SOLIBS@%%g
+s%@arch@%i386-mswin32%g
+s%@configure_args@%--with-make-prog=nmake%g
+s%@configure_input@%$configure_input%g
+s%@srcdir@%$srcdir%g
+s%@top_srcdir@%$top_srcdir%g
diff --git a/win32/ntsetup.bat b/win32/ntsetup.bat
index ee6294fada..dc67b70673 100755
--- a/win32/ntsetup.bat
+++ b/win32/ntsetup.bat
@@ -2,9 +2,7 @@
copy config.h ..
copy Makefile ..
copy ruby.def ..
-cd ..\ext
-copy Setup.nt Setup
-copy extmk.rb.nt extmk.rb
+copy config.status ..
cd ..
echo type `nmake' to make ruby for mswin32.
diff --git a/win32/ruby.def b/win32/ruby.def
index dfe63e5ba6..126b4f2697 100644
--- a/win32/ruby.def
+++ b/win32/ruby.def
@@ -2,65 +2,115 @@ LIBRARY rubymw.dll
DESCRIPTION 'win32 rubymw.dll'
EXPORTS
;;global objects
-;array.c:
+;array.c
rb_cArray
-;bignum.c:
+;bignum.c
rb_cBignum
+;compar.c
+ rb_mComparable
+;dir.c
+ rb_cDir
;enum.c
rb_mEnumerable
;error.c
- rb_eException;
+ rb_eException
rb_eSystemExit
rb_eInterrupt
- rb_eFatal;
- rb_eStandardError;
- rb_eRuntimeError;
- rb_eSyntaxError;
- rb_eTypeError;
- rb_eArgError;
- rb_eNameError;
- rb_eIndexError;
- rb_eLoadError;
- rb_eSecurityError;
- rb_eNotImpError;
- rb_eSystemCallError;
- rb_mErrno;
-;eval.c:
+ rb_eSignal
+ rb_eFatal
+ rb_eStandardError
+ rb_eRuntimeError
+ rb_eSyntaxError
+ rb_eTypeError
+ rb_eArgError
+ rb_eNameError
+ rb_eIndexError
+ rb_eLoadError
+ rb_eSecurityError
+ rb_eNotImpError
+ rb_eSystemCallError
+ rb_eZeroDivError
+ rb_mErrno
+;eval.c
rb_cProc
-;file.c:
+ rb_cThread
+ rb_thread_tick
+ rb_thread_critical
+;file.c
rb_cFile
-;hash.c:
+ rb_mFileTest
+;gc.c
+ rb_mGC
+;hash.c
rb_cHash
-;io.c:
+;io.c
rb_cIO
-;numeric.c:
+ rb_eEOFError
+ rb_eIOError
+;math.c
+ rb_mMath
+;numeric.c
rb_cNumeric
rb_cFloat
rb_cInteger
rb_cFixnum
+ rb_eFloatDomainError
;object.c
rb_mKernel
rb_cObject
rb_cModule
rb_cClass
rb_cData
-
rb_cNilClass
rb_cTrueClass
rb_cFalseClass
-;re.c:
+;prec.c
+ rb_mPrecision
+;process.c
+ rb_mProcess
+;range.c
+ rb_cRange
+;re.c
rb_cRegexp
-;string.c:
+;ruby.c
+ ruby_debug
+ ruby_verbose
+ rb_progname
+ rb_argv
+ rb_argv0
+;signal.c
+ rb_trap_pending
+ rb_trap_immediate
+ rb_prohibit_interrupt
+;string.c
rb_cString
rb_cStruct
+;time.c
+ rb_cTime
-; procedures/methods
-;missing/nt.c
+;;procedures/methods
+;missing/alloca.c
+ alloca
+;missing/crypt.c
+ definekey
+ encrypt
+ crypt
+;missing/fnmatch.c
+ fnmatch
+;missing/isinf.c
+ isinf
+;missing/isnan.c
+ isnan
+;win32/win32.c
NtInitialize
myfdopen
+ myfdclose
myaccept
mybind
myconnect
+ myfdset
+ myfdisset
+ myselect
mygetpeername
mygetsockname
mygetsockopt
@@ -80,10 +130,13 @@ EXPORTS
mygetprotobynumber
mygetservbyname
mygetservbyport
+ myget_osfhandle
+ win32_getenv
;array.c
+ rb_mem_clear
rb_ary_freeze
- rb_ary_new2
rb_ary_new
+ rb_ary_new2
rb_ary_new3
rb_ary_new4
rb_assoc_new
@@ -97,6 +150,8 @@ EXPORTS
rb_ary_each
rb_ary_join
rb_ary_to_s
+ rb_protect_inspect
+ rb_inspecting_p
rb_ary_reverse
rb_ary_sort_bang
rb_ary_sort
@@ -134,6 +189,7 @@ EXPORTS
rb_class_new
rb_singleton_class_new
rb_singleton_class_clone
+ rb_singleton_class_attached
rb_define_class_id
rb_define_class
rb_define_class_under
@@ -142,11 +198,17 @@ EXPORTS
rb_define_module
rb_define_module_under
rb_include_module
+ rb_mod_included_modules
+ rb_mod_ancestors
+ rb_class_instance_methods
+ rb_class_protected_instance_methods
+ rb_class_private_instance_methods
+ rb_obj_singleton_methods
rb_define_method_id
rb_define_method
- rb_undef_method
- rb_define_private_method
rb_define_protected_method
+ rb_define_private_method
+ rb_undef_method
rb_singleton_class
rb_define_singleton_method
rb_define_module_function
@@ -154,16 +216,14 @@ EXPORTS
rb_define_alias
rb_define_attr
rb_scan_args
-; dln.c
- dln_find_exe
- dln_find_file
+;dln.c
dln_load
dln_find_exe
dln_find_file
-; enum.c
+;enum.c
rb_each
rb_enum_length
-; error.c
+;error.c
rb_compile_error
rb_compile_error_append
rb_warn
@@ -180,12 +240,17 @@ EXPORTS
rb_sys_fail
;eval.c
rb_clear_cache
- rb_alias
rb_add_method
+ rb_alias
rb_remove_method
rb_disable_super
rb_enable_super
rb_method_boundp
+ rb_attr
+ rb_dvar_defined
+ rb_dvar_ref
+ rb_dvar_push
+ rb_dvar_asgn
rb_safe_level
rb_set_safe_level
rb_check_safe_str
@@ -194,55 +259,68 @@ EXPORTS
ruby_options
ruby_run
rb_eval_string
+ rb_eval_string_protect
+ rb_eval_string_wrap
rb_eval_cmd
- rb_trap_eval
- rb_test_false_or_nil
rb_respond_to
rb_exit
- rb_raise
- rb_fatal
+ rb_iter_break
+ rb_exc_raise
+ rb_exc_fatal
rb_interrupt
+ rb_jump_tag
rb_iterator_p
+ rb_yield
rb_iterate
rb_rescue
+ rb_protect
rb_ensure
+ rb_with_disable_interrupt
rb_apply
rb_funcall
rb_funcall2
rb_backtrace
rb_frame_last_func
+ rb_obj_instance_eval
rb_load
+ rb_load_protect
rb_provide
rb_f_require
- rb_obj_instance_eval
+ rb_require
rb_obj_call_init
rb_class_new_instance
rb_extend_object
- rb_f_global_variables
rb_set_end_proc
- rb_f_autoload
+ rb_exec_end_proc
rb_f_lambda
rb_gc_mark_threads
+ rb_thread_fd_close
rb_thread_schedule
rb_thread_wait_fd
rb_thread_fd_writable
rb_thread_wait_for
rb_thread_alone
rb_thread_select
+ rb_thread_current
+ rb_thread_main
+ rb_thread_wakeup
+ rb_thread_run
+ rb_thread_stop
rb_thread_sleep
rb_thread_sleep_forever
rb_thread_create
rb_thread_scope_shared_p
rb_thread_interrupt
+ rb_thread_signal_raise
rb_thread_trap_eval
+ rb_thread_local_aref
+ rb_thread_local_aset
rb_catch
rb_throw
- rb_yield
-; file.c
- rb_file_open
+;file.c
eaccess
rb_file_s_expand_path
-; gc.c
+;gc.c
xmalloc
xcalloc
xrealloc
@@ -250,61 +328,91 @@ EXPORTS
rb_newobj
rb_data_object_alloc
rb_gc_mark_locations
+ rb_mark_tbl
+ rb_mark_hash
rb_gc_mark_maybe
rb_gc_mark
rb_gc_force_recycle
rb_gc_mark_frame
rb_gc
-; hash.c
+ rb_gc_call_finalizer_at_exit
+;hash.c
rb_hash_freeze
rb_hash
rb_hash_new
rb_hash_aref
rb_hash_aset
-; inits.c
+ rb_path_check
+ rb_env_path_tainted
+ ruby_setenv
+ ruby_unsetenv
+;inits.c
rb_call_inits
-; io.c
+;io.c
rb_eof_error
+ rb_io_check_closed
+ rb_io_check_readable
+ rb_io_check_writable
+ rb_read_check
rb_io_write
+ rb_io_eof
rb_io_gets
rb_io_getc
+ rb_getc
rb_io_ungetc
rb_io_fptr_finalize
rb_io_close
+ rb_io_close_read
rb_io_binmode
rb_io_mode_flags
rb_fopen
rb_fdopen
+ rb_file_open
+ rb_file_sysopen
rb_io_unbuffered
- rb_io_reopen
+ rb_p
+ rb_gets
rb_str_setter
-; numeric.c
+;numeric.c
rb_num_zerodiv
rb_num_coerce_bin
rb_float_new
rb_num2long
rb_num2ulong
+ rb_num2int
+ rb_fix2int
rb_num2fix
rb_fix2str
-; object.c
+ rb_fix_upto
+;object.c
rb_equal
rb_eql
+ rb_obj_id
+ rb_obj_clone
rb_any_to_s
rb_inspect
rb_obj_is_instance_of
rb_obj_is_kind_of
+ rb_obj_tainted
+ rb_obj_taint
+ rb_obj_untaint
rb_obj_alloc
rb_to_id
- rb_class_of
- rb_type
- rb_special_const_p
+ rb_convert_type
rb_Integer
rb_Float
+ rb_num2dbl
+ rb_str2cstr
rb_String
rb_Array
-; parse.c
+;parse.c
+ rb_compile_string
+ rb_compile_cstr
+ rb_compile_file
rb_node_newnode
rb_id_attrset
+ rb_parser_append_print
+ rb_parser_while_loop
rb_intern
rb_id2name
rb_is_const_id
@@ -313,14 +421,15 @@ EXPORTS
rb_backref_set
rb_lastline_get
rb_lastline_set
-; process.c
+;process.c
rb_proc_exec
rb_syswait
-; range.c
+;range.c
rb_range_new
- rb_range_beg_end
-; re.c
+ rb_range_beg_len
+;re.c
rb_str_cicmp
+ rb_match_busy
rb_reg_search
rb_reg_nth_defined
rb_reg_nth_match
@@ -332,27 +441,33 @@ EXPORTS
rb_reg_regcomp
rb_reg_match
rb_reg_match2
+ rb_kcode
+ rb_reg_options
rb_reg_regsub
rb_get_kcode
rb_set_kcode
-; ruby.c
- ruby_require_modules
+;ruby.c
+ ruby_require_libraries
rb_load_file
ruby_script
ruby_prog_init
ruby_set_argv
ruby_process_options
-; signal.c
+;signal.c
+ rb_f_kill
rb_gc_mark_trap_list
rb_trap_exit
rb_trap_exec
-; sprintf.c
+ rb_trap_restore_mask
+;sprintf.c
rb_f_sprintf
-; st.c
+;st.c
st_init_table_with_size
st_init_table
st_init_numtable
+ st_init_numtable_with_size
st_init_strtable
+ st_init_strtable_with_size
st_free_table
st_lookup
st_insert
@@ -360,8 +475,9 @@ EXPORTS
st_copy
st_delete
st_delete_safe
+ st_cleanup_safe
st_foreach
-; string.c
+;string.c
rb_str_new
rb_str_new2
rb_tainted_str_new
@@ -379,30 +495,34 @@ EXPORTS
rb_str_dup_frozen
rb_str_resize
rb_str_cat
+ rb_str_concat
rb_str_hash
rb_str_cmp
rb_str_upto
rb_str_inspect
rb_str_split
-; struct.c
+;struct.c
rb_struct_getmember
rb_struct_define
rb_struct_alloc
rb_struct_new
rb_struct_aref
rb_struct_aset
-; time.c
+;time.c
rb_time_new
+ rb_time_interval
rb_time_timeval
-; util.c
+;util.c
rb_class_of
rb_type
rb_special_const_p
rb_test_false_or_nil
ruby_scan_oct
ruby_scan_hex
- rb_add_suffix
+ ruby_mktemp
+ ruby_qsort
;variable.c
+ rb_mod_name
rb_class_path
rb_set_class_path
rb_path2class
@@ -416,16 +536,26 @@ EXPORTS
rb_define_variable
rb_define_readonly_variable
rb_define_virtual_variable
+ rb_f_trace_var
+ rb_f_untrace_var
rb_gvar_get
rb_gvar_set
rb_gvar_set2
rb_gvar_defined
+ rb_f_global_variables
rb_alias_variable
+ rb_mark_generic_ivar
+ rb_mark_generic_ivar_tbl
+ rb_free_generic_ivar
+ rb_clone_generic_ivar
rb_ivar_get
rb_ivar_set
rb_ivar_defined
+ rb_obj_instance_variables
+ rb_obj_remove_instance_variable
rb_const_get_at
rb_const_get
+ rb_mod_remove_const
rb_mod_const_at
rb_mod_constants
rb_mod_const_of
@@ -437,7 +567,6 @@ EXPORTS
rb_define_global_const
rb_iv_get
rb_iv_set
-; version.c
+;version.c
ruby_show_version
ruby_show_copyright
-
diff --git a/win32/sdbm.c b/win32/sdbm.c
deleted file mode 100644
index d2d2171875..0000000000
--- a/win32/sdbm.c
+++ /dev/null
@@ -1,981 +0,0 @@
-/*
- * sdbm - ndbm work-alike hashed database library
- * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
- * author: oz@nexus.yorku.ca
- * status: public domain.
- *
- * core routines
- */
-
-#ifndef lint
-/*char sdbm_rcsid[] = "$Id: sdbm.c,v 1.16 90/12/13 13:01:31 oz Exp $";*/
-#endif
-
-#include "sdbm.h"
-
-/*#include "tune.h"*/
-/*
- * sdbm - ndbm work-alike hashed database library
- * tuning and portability constructs [not nearly enough]
- * author: oz@nexus.yorku.ca
- */
-
-#define BYTESIZ 8
-
-#ifdef SVID
-#include <unistd.h>
-#endif
-
-#ifdef __GO32__
-#include <unistd.h>
-#endif
-
-#ifdef BSD42
-#define SEEK_SET L_SET
-#define memset(s,c,n) bzero(s, n) /* only when c is zero */
-#define memcpy(s1,s2,n) bcopy(s2, s1, n)
-#define memcmp(s1,s2,n) bcmp(s1,s2,n)
-#endif
-
-/*
- * important tuning parms (hah)
- */
-
-#define SEEDUPS /* always detect duplicates */
-#define BADMESS /* generate a message for worst case:
- cannot make room after SPLTMAX splits */
-/*
- * misc
- */
-#ifdef DEBUG
-#define debug(x) printf x
-#else
-#define debug(x)
-#endif
-
-#ifdef BIG_E
-#define GET_SHORT(p, i) (((unsigned)((unsigned char *)(p))[(i)*2] << 8) + (((unsigned char *)(p))[(i)*2 + 1]))
-#define PUT_SHORT(p, i, s) (((unsigned char *)(p))[(i)*2] = (unsigned char)((s) >> 8), ((unsigned char *)(p))[(i)*2 + 1] = (unsigned char)(s))
-#else
-#define GET_SHORT(p, i) ((p)[i])
-#define PUT_SHORT(p, i, s) ((p)[i] = (s))
-#endif
-
-/*#include "pair.h"*/
-static int fitpair proto((char *, int));
-static void putpair proto((char *, datum, datum));
-static datum getpair proto((char *, datum));
-static int delpair proto((char *, datum));
-static int chkpage proto((char *));
-static datum getnkey proto((char *, int));
-static void splpage proto((char *, char *, long));
-#ifdef SEEDUPS
-static int duppair proto((char *, datum));
-#endif
-
-#ifdef MSDOS
-#include <stdio.h>
-#include <stdlib.h>
-#include <io.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef BSD42
-#include <sys/file.h>
-#else
-#include <fcntl.h>
-/*#include <memory.h>*/
-#endif
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-#include <errno.h>
-#ifndef EPERM
-#define EPERM EACCES
-#endif
-#include <string.h>
-
-#ifdef __STDC__
-#include <stddef.h>
-#endif
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-/*
- * externals
- */
-#ifndef sun
-#ifndef MSDOS
-extern int errno;
-#endif
-#endif
-
-/*
- * forward
- */
-static int getdbit proto((DBM *, long));
-static int setdbit proto((DBM *, long));
-static int getpage proto((DBM *, long));
-static datum getnext proto((DBM *));
-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 ioerr(db) ((db)->flags |= DBM_IOERR)
-
-#define OFF_PAG(off) (long) (off) * PBLKSIZ
-#define OFF_DIR(off) (long) (off) * DBLKSIZ
-
-static long masks[] = {
- 000000000000L, 000000000001L, 000000000003L,
- 000000000007L, 000000000017L, 000000000037L,
- 000000000077L, 000000000177L, 000000000377L,
- 000000000777L, 000000001777L, 000000003777L,
- 000000007777L, 000000017777L, 000000037777L,
- 000000077777L, 000000177777L, 000000377777L,
- 000000777777L, 000001777777L, 000003777777L,
- 000007777777L, 000017777777L, 000037777777L,
- 000077777777L, 000177777777L, 000377777777L,
- 000777777777L, 001777777777L, 003777777777L,
- 007777777777L, 017777777777L
-};
-
-datum nullitem = {NULL, 0};
-
-DBM *
-dbm_open(file, flags, mode)
-register char *file;
-register int flags;
-register int mode;
-{
- register DBM *db;
- register char *dirname;
- register char *pagname;
- register int n;
-
- if (file == NULL || !*file)
- return errno = EINVAL, (DBM *) NULL;
-/*
- * need space for two seperate filenames
- */
- n = strlen(file) * 2 + strlen(DIRFEXT) + strlen(PAGFEXT) + 2;
-
- if ((dirname = malloc((unsigned) n)) == NULL)
- return errno = ENOMEM, (DBM *) NULL;
-/*
- * build the file names
- */
- dirname = strcat(strcpy(dirname, file), DIRFEXT);
- pagname = strcpy(dirname + strlen(dirname) + 1, file);
- pagname = strcat(pagname, PAGFEXT);
-
- db = dbm_prep(dirname, pagname, flags, mode);
- free((char *) dirname);
- return db;
-}
-
-DBM *
-dbm_prep(dirname, pagname, flags, mode)
-char *dirname;
-char *pagname;
-int flags;
-int mode;
-{
- register DBM *db;
- struct stat dstat;
-
- if ((db = (DBM *) malloc(sizeof(DBM))) == NULL)
- return errno = ENOMEM, (DBM *) NULL;
-
- db->flags = 0;
- db->hmask = 0;
- db->blkptr = 0;
- db->keyptr = 0;
-/*
- * adjust user flags so that WRONLY becomes RDWR,
- * as required by this package. Also set our internal
- * flag for RDONLY.
- */
- if (flags & O_WRONLY)
- flags = (flags & ~O_WRONLY) | O_RDWR;
- if (flags & O_RDONLY)
- db->flags = DBM_RDONLY;
-/*
- * 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) {
-/*
- * need the dirfile size to establish max bit number.
- */
- if (fstat(db->dirf, &dstat) == 0) {
-/*
- * zero size: either a fresh database, or one with a single,
- * unsplit data page: dirpage is all zeros.
- */
- db->dirbno = (!dstat.st_size) ? 0 : -1;
- db->pagbno = -1;
- db->maxbno = dstat.st_size * (long) BYTESIZ;
-
- (void) memset(db->pagbuf, 0, PBLKSIZ);
- (void) memset(db->dirbuf, 0, DBLKSIZ);
- /*
- * success
- */
- return db;
- }
- (void) close(db->dirf);
- }
- (void) close(db->pagf);
- }
- free((char *) db);
- return (DBM *) NULL;
-}
-
-void
-dbm_close(db)
-register DBM *db;
-{
- if (db == NULL)
- errno = EINVAL;
- else {
- (void) close(db->dirf);
- (void) close(db->pagf);
- free((char *) db);
- }
-}
-
-datum
-dbm_fetch(db, key)
-register DBM *db;
-datum key;
-{
- if (db == NULL || bad(key))
- return errno = EINVAL, nullitem;
-
- if (getpage(db, exhash(key)))
- return getpair(db->pagbuf, key);
-
- return ioerr(db), nullitem;
-}
-
-int
-dbm_delete(db, key)
-register DBM *db;
-datum key;
-{
- if (db == NULL || bad(key))
- return errno = EINVAL, -1;
- if (dbm_rdonly(db))
- return errno = EPERM, -1;
-
- if (getpage(db, exhash(key))) {
- if (!delpair(db->pagbuf, key))
- return -1;
-/*
- * update the page file
- */
- if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
- || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return ioerr(db), -1;
-
- return 0;
- }
-
- return ioerr(db), -1;
-}
-
-int
-dbm_store(db, key, val, flags)
-register DBM *db;
-datum key;
-datum val;
-int flags;
-{
- int need;
- register long hash;
-
- if (db == NULL || bad(key))
- return errno = EINVAL, -1;
- if (dbm_rdonly(db))
- return errno = EPERM, -1;
-
- need = key.dsize + val.dsize;
-/*
- * is the pair too big (or too small) for this database ??
- */
- if (need < 0 || need > PAIRMAX)
- return errno = EINVAL, -1;
-
- if (getpage(db, (hash = exhash(key)))) {
-/*
- * if we need to replace, delete the key/data pair
- * first. If it is not there, ignore.
- */
- if (flags == DBM_REPLACE)
- (void) delpair(db->pagbuf, key);
-#ifdef SEEDUPS
- else if (duppair(db->pagbuf, key))
- return 1;
-#endif
-/*
- * if we do not have enough room, we have to split.
- */
- if (!fitpair(db->pagbuf, need))
- if (!makroom(db, hash, need))
- return ioerr(db), -1;
-/*
- * we have enough room or split is successful. insert the key,
- * and update the page file.
- */
- (void) putpair(db->pagbuf, key, val);
-
- if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
- || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return ioerr(db), -1;
- /*
- * success
- */
- return 0;
- }
-
- return ioerr(db), -1;
-}
-
-/*
- * makroom - make room by splitting the overfull page
- * this routine will attempt to make room for SPLTMAX times before
- * giving up.
- */
-static int
-makroom(db, hash, need)
-register DBM *db;
-long hash;
-int need;
-{
- long newp;
- char twin[PBLKSIZ];
-#ifdef MSDOS
- char zer[PBLKSIZ];
-#endif
- char *pag = db->pagbuf;
- char *new = twin;
- register int smax = SPLTMAX;
- long oldtail;
-
- do {
-/*
- * split the current page
- */
- (void) splpage(pag, new, db->hmask + 1);
-/*
- * address of the new page
- */
- newp = (hash & db->hmask) | (db->hmask + 1);
- debug(("newp: %ld\n", newp));
-/*
- * write delay, read avoidence/cache shuffle:
- * select the page for incoming pair: if key is to go to the new page,
- * 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.
- */
-
-#ifdef MSDOS
- /*
- * Fill hole with 0 if made it.
- * (hole is NOT read as 0)
- */
- oldtail = lseek(db->pagf, 0L, SEEK_END);
- memset(zer, 0, PBLKSIZ);
- while (OFF_PAG(newp) > oldtail) {
- if (lseek(db->pagf, 0L, SEEK_END) < 0 ||
- write(db->pagf, zer, PBLKSIZ) < 0) {
-
- return 0;
- }
- oldtail += PBLKSIZ;
- }
-#endif
-
- if (hash & (db->hmask + 1)) {
- if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
- || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return 0;
- db->pagbno = newp;
- (void) memcpy(pag, new, PBLKSIZ);
- }
- else if (lseek(db->pagf, OFF_PAG(newp), SEEK_SET) < 0
- || write(db->pagf, new, PBLKSIZ) < 0)
- return 0;
-
- if (!setdbit(db, db->curbit))
- return 0;
-/*
- * see if we have enough room now
- */
- if (fitpair(pag, need))
- return 1;
-/*
- * try again... update curbit and hmask as getpage would have
- * done. because of our update of the current page, we do not
- * need to read in anything. BUT we have to write the current
- * [deferred] page out, as the window of failure is too great.
- */
- db->curbit = 2 * db->curbit +
- ((hash & (db->hmask + 1)) ? 2 : 1);
- db->hmask |= (db->hmask + 1);
-
- if (lseek(db->pagf, OFF_PAG(db->pagbno), SEEK_SET) < 0
- || write(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return 0;
-
- } while (--smax);
-/*
- * if we are here, this is real bad news. After SPLTMAX splits,
- * we still cannot fit the key. say goodnight.
- */
-#ifdef BADMESS
- (void) write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);
-#endif
- return 0;
-
-}
-
-/*
- * the following two routines will break if
- * deletions aren't taken into account. (ndbm bug)
- */
-datum
-dbm_firstkey(db)
-register DBM *db;
-{
- if (db == NULL)
- return errno = EINVAL, nullitem;
-/*
- * start at page 0
- */
- (void) memset(db->pagbuf, 0, PBLKSIZ);
- if (lseek(db->pagf, OFF_PAG(0), SEEK_SET) < 0
- || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return ioerr(db), nullitem;
- db->pagbno = 0;
- db->blkptr = 0;
- db->keyptr = 0;
-
- return getnext(db);
-}
-
-datum
-dbm_nextkey(db)
-register DBM *db;
-{
- if (db == NULL)
- return errno = EINVAL, nullitem;
- return getnext(db);
-}
-
-/*
- * all important binary trie traversal
- */
-static int
-getpage(db, hash)
-register DBM *db;
-register long hash;
-{
- register int hbit;
- register long dbit;
- register long pagb;
-
- dbit = 0;
- hbit = 0;
- while (dbit < db->maxbno && getdbit(db, dbit))
- dbit = 2 * dbit + ((hash & ((long) 1 << hbit++)) ? 2 : 1);
-
- debug(("dbit: %d...", dbit));
-
- db->curbit = dbit;
- db->hmask = masks[hbit];
-
- pagb = hash & db->hmask;
-/*
- * see if the block we need is already in memory.
- * note: this lookaside cache has about 10% hit rate.
- */
- if (pagb != db->pagbno) {
-/*
- * note: here, we assume a "hole" is read as 0s.
- * if not, must zero pagbuf first.
- */
- (void) memset(db->pagbuf, 0, PBLKSIZ);
-
- if (lseek(db->pagf, OFF_PAG(pagb), SEEK_SET) < 0
- || read(db->pagf, db->pagbuf, PBLKSIZ) < 0)
- return 0;
- if (!chkpage(db->pagbuf)) {
- return 0;
- }
- db->pagbno = pagb;
-
- debug(("pag read: %d\n", pagb));
- }
- return 1;
-}
-
-static int
-getdbit(db, dbit)
-register DBM *db;
-register long dbit;
-{
- register long c;
- register long dirb;
-
- c = dbit / BYTESIZ;
- dirb = c / DBLKSIZ;
-
- if (dirb != db->dirbno) {
- if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
- || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
- return 0;
- db->dirbno = dirb;
-
- debug(("dir read: %d\n", dirb));
- }
-
- return db->dirbuf[c % DBLKSIZ] & (1 << (dbit % BYTESIZ));
-}
-
-static int
-setdbit(db, dbit)
-register DBM *db;
-register long dbit;
-{
- register long c;
- register long dirb;
-
- c = dbit / BYTESIZ;
- dirb = c / DBLKSIZ;
-
- if (dirb != db->dirbno) {
- if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
- || read(db->dirf, db->dirbuf, DBLKSIZ) < 0)
- return 0;
- db->dirbno = dirb;
-
- debug(("dir read: %d\n", dirb));
- }
-
- db->dirbuf[c % DBLKSIZ] |= (1 << (dbit % BYTESIZ));
-
- if (dbit >= db->maxbno)
- db->maxbno += (long) DBLKSIZ * BYTESIZ;
-
- if (lseek(db->dirf, OFF_DIR(dirb), SEEK_SET) < 0
- || write(db->dirf, db->dirbuf, DBLKSIZ) < 0)
- return 0;
-
- return 1;
-}
-
-/*
- * getnext - get the next key in the page, and if done with
- * the page, try the next page in sequence
- */
-static datum
-getnext(db)
-register DBM *db;
-{
- datum key;
-
- for (;;) {
- db->keyptr++;
- key = getnkey(db->pagbuf, db->keyptr);
- if (key.dptr != NULL)
- return key;
-/*
- * we either run out, or there is nothing on this page..
- * try the next one... If we lost our position on the
- * file, we will have to seek.
- */
- db->keyptr = 0;
- if (db->pagbno != db->blkptr++)
- if (lseek(db->pagf, OFF_PAG(db->blkptr), SEEK_SET) < 0)
- break;
- db->pagbno = db->blkptr;
- if (read(db->pagf, db->pagbuf, PBLKSIZ) <= 0)
- break;
- if (!chkpage(db->pagbuf)) {
- break;
- }
- }
-
- return ioerr(db), nullitem;
-}
-
-/* pair.c */
-/*
- * sdbm - ndbm work-alike hashed database library
- * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
- * author: oz@nexus.yorku.ca
- * status: public domain.
- *
- * page-level routines
- */
-
-#ifndef lint
-/*char pair_rcsid[] = "$Id: sdbm.c,v 1.1.1.1.2.1 1998/01/16 12:36:12 matz Exp $";*/
-#endif
-
-#ifndef BSD42
-/*#include <memory.h>*/
-#endif
-
-#define exhash(item) dbm_hash((item).dptr, (item).dsize)
-
-/*
- * forward
- */
-static int seepair proto((char *, int, char *, int));
-
-/*
- * page format:
- * +------------------------------+
- * ino | n | keyoff | datoff | keyoff |
- * +------------+--------+--------+
- * | datoff | - - - ----> |
- * +--------+---------------------+
- * | F R E E A R E A |
- * +--------------+---------------+
- * | <---- - - - | data |
- * +--------+-----+----+----------+
- * | key | data | key |
- * +--------+----------+----------+
- *
- * calculating the offsets for free area: if the number
- * of entries (ino[0]) is zero, the offset to the END of
- * the free area is the block size. Otherwise, it is the
- * nth (ino[ino[0]]) entry's offset.
- */
-
-static int
-fitpair(pag, need)
-char *pag;
-int need;
-{
- register int n;
- register int off;
- register int free;
- register short *ino = (short *) pag;
-
- off = ((n = GET_SHORT(ino,0)) > 0) ? GET_SHORT(ino,n) : PBLKSIZ;
- free = off - (n + 1) * sizeof(short);
- need += 2 * sizeof(short);
-
- debug(("free %d need %d\n", free, need));
-
- return need <= free;
-}
-
-static void
-putpair(pag, key, val)
-char *pag;
-datum key;
-datum val;
-{
- register int n;
- register int off;
- register short *ino = (short *) pag;
-
- off = ((n = GET_SHORT(ino,0)) > 0) ? GET_SHORT(ino,n) : PBLKSIZ;
-/*
- * enter the key first
- */
- off -= key.dsize;
- if (key.dsize)
- (void) memcpy(pag + off, key.dptr, key.dsize);
- PUT_SHORT(ino,n + 1,off);
-/*
- * now the data
- */
- off -= val.dsize;
- if (val.dsize)
- (void) memcpy(pag + off, val.dptr, val.dsize);
- PUT_SHORT(ino,n + 2,off);
-/*
- * adjust item count
- */
- PUT_SHORT(ino,0,GET_SHORT(ino,0) + 2);
-}
-
-static datum
-getpair(pag, key)
-char *pag;
-datum key;
-{
- register int i;
- register int n;
- datum val;
- register short *ino = (short *) pag;
-
- if ((n = GET_SHORT(ino,0)) == 0)
- return nullitem;
-
- if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
- return nullitem;
-
- val.dptr = pag + GET_SHORT(ino,i + 1);
- val.dsize = GET_SHORT(ino,i) - GET_SHORT(ino,i + 1);
- return val;
-}
-
-#ifdef SEEDUPS
-static int
-duppair(pag, key)
-char *pag;
-datum key;
-{
- register short *ino = (short *) pag;
- return GET_SHORT(ino,0) > 0 &&
- seepair(pag, GET_SHORT(ino,0), key.dptr, key.dsize) > 0;
-}
-#endif
-
-static datum
-getnkey(pag, num)
-char *pag;
-int num;
-{
- datum key;
- register int off;
- register short *ino = (short *) pag;
-
- num = num * 2 - 1;
- if (GET_SHORT(ino,0) == 0 || num > GET_SHORT(ino,0))
- return nullitem;
-
- off = (num > 1) ? GET_SHORT(ino,num - 1) : PBLKSIZ;
-
- key.dptr = pag + GET_SHORT(ino,num);
- key.dsize = off - GET_SHORT(ino,num);
-
- return key;
-}
-
-static int
-delpair(pag, key)
-char *pag;
-datum key;
-{
- register int n;
- register int i;
- register short *ino = (short *) pag;
-
- if ((n = GET_SHORT(ino,0)) == 0)
- return 0;
-
- if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
- return 0;
-/*
- * found the key. if it is the last entry
- * [i.e. i == n - 1] we just adjust the entry count.
- * hard case: move all data down onto the deleted pair,
- * shift offsets onto deleted offsets, and adjust them.
- * [note: 0 < i < n]
- */
- if (i < n - 1) {
- register int m;
- register char *dst = pag + (i == 1 ? PBLKSIZ : GET_SHORT(ino,i - 1));
- register char *src = pag + GET_SHORT(ino,i + 1);
- register int zoo = dst - src;
-
- debug(("free-up %d ", zoo));
-/*
- * shift data/keys down
- */
- m = GET_SHORT(ino,i + 1) - GET_SHORT(ino,n);
-#ifdef DUFF
-#define MOVB *--dst = *--src
-
- if (m > 0) {
- register int loop = (m + 8 - 1) >> 3;
-
- switch (m & (8 - 1)) {
- case 0: do {
- MOVB; case 7: MOVB;
- case 6: MOVB; case 5: MOVB;
- case 4: MOVB; case 3: MOVB;
- case 2: MOVB; case 1: MOVB;
- } while (--loop);
- }
- }
-#else
-#ifdef MEMMOVE
- memmove(dst, src, m);
-#else
- while (m--)
- *--dst = *--src;
-#endif
-#endif
-/*
- * adjust offset index up
- */
- while (i < n - 1) {
- PUT_SHORT(ino,i, GET_SHORT(ino,i + 2) + zoo);
- i++;
- }
- }
- PUT_SHORT(ino, 0, GET_SHORT(ino, 0) - 2);
- return 1;
-}
-
-/*
- * search for the key in the page.
- * return offset index in the range 0 < i < n.
- * return 0 if not found.
- */
-static int
-seepair(pag, n, key, siz)
-char *pag;
-register int n;
-register char *key;
-register int siz;
-{
- register int i;
- register int off = PBLKSIZ;
- register short *ino = (short *) pag;
-
- for (i = 1; i < n; i += 2) {
- if (siz == off - GET_SHORT(ino,i) &&
- memcmp(key, pag + GET_SHORT(ino,i), siz) == 0)
- return i;
- off = GET_SHORT(ino,i + 1);
- }
- return 0;
-}
-
-static void
-splpage(pag, new, sbit)
-char *pag;
-char *new;
-long sbit;
-{
- datum key;
- datum val;
-
- register int n;
- register int off = PBLKSIZ;
- char cur[PBLKSIZ];
- register short *ino = (short *) cur;
-
- (void) memcpy(cur, pag, PBLKSIZ);
- (void) memset(pag, 0, PBLKSIZ);
- (void) memset(new, 0, PBLKSIZ);
-
- n = GET_SHORT(ino,0);
- for (ino++; n > 0; ino += 2) {
- key.dptr = cur + GET_SHORT(ino,0);
- key.dsize = off - GET_SHORT(ino,0);
- val.dptr = cur + GET_SHORT(ino,1);
- val.dsize = GET_SHORT(ino,0) - GET_SHORT(ino,1);
-/*
- * select the page pointer (by looking at sbit) and insert
- */
- (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
-
- off = GET_SHORT(ino,1);
- n -= 2;
- }
-
- debug(("%d split %d/%d\n", ((short *) cur)[0] / 2,
- ((short *) new)[0] / 2,
- ((short *) pag)[0] / 2));
-}
-
-/*
- * check page sanity:
- * number of entries should be something
- * reasonable, and all offsets in the index should be in order.
- * this could be made more rigorous.
- */
-static int
-chkpage(pag)
-char *pag;
-{
- register int n;
- register int off;
- register short *ino = (short *) pag;
-
- if ((n = GET_SHORT(ino,0)) < 0 || n > PBLKSIZ / sizeof(short))
- return 0;
-
- if (n > 0) {
- off = PBLKSIZ;
- for (ino++; n > 0; ino += 2) {
- if (GET_SHORT(ino,0) > off || GET_SHORT(ino,1) > off ||
- GET_SHORT(ino,1) > GET_SHORT(ino,0))
- return 0;
- off = GET_SHORT(ino,1);
- n -= 2;
- }
- }
- return 1;
-}
-
-/* hash.c */
-/*
- * sdbm - ndbm work-alike hashed database library
- * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
- * author: oz@nexus.yorku.ca
- * status: public domain. keep it that way.
- *
- * hashing routine
- */
-
-/*
- * polynomial conversion ignoring overflows
- * [this seems to work remarkably well, in fact better
- * then the ndbm hash function. Replace at your own risk]
- * use: 65599 nice.
- * 65587 even better.
- */
-long
-dbm_hash(str, len)
-register char *str;
-register int len;
-{
- register unsigned long n = 0;
-
-#ifdef DUFF
-
-#define HASHC n = *str++ + 65599 * n
-
- if (len > 0) {
- register int loop = (len + 8 - 1) >> 3;
-
- switch(len & (8 - 1)) {
- case 0: do {
- HASHC; case 7: HASHC;
- case 6: HASHC; case 5: HASHC;
- case 4: HASHC; case 3: HASHC;
- case 2: HASHC; case 1: HASHC;
- } while (--loop);
- }
-
- }
-#else
- while (len--)
- n = ((*str++) & 255) + 65587L * n;
-#endif
- return n;
-}
diff --git a/win32/sdbm.h b/win32/sdbm.h
deleted file mode 100644
index 4b731c6574..0000000000
--- a/win32/sdbm.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * sdbm - ndbm work-alike hashed database library
- * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
- * author: oz@nexus.yorku.ca
- * status: public domain.
- */
-#ifndef _NDBM_H_
-#define _NDBM_H_
-
-#define DBLKSIZ 4096
-#define PBLKSIZ 1024
-#define PAIRMAX 1008 /* arbitrary on PBLKSIZ-N */
-#define SPLTMAX 10 /* maximum allowed splits */
- /* for a single insertion */
-#define DIRFEXT ".dir"
-#define PAGFEXT ".pag"
-
-typedef struct {
- int dirf; /* directory file descriptor */
- int pagf; /* page file descriptor */
- int flags; /* status/error flags, see below */
- long maxbno; /* size of dirfile in bits */
- long curbit; /* current bit number */
- long hmask; /* current hash mask */
- long blkptr; /* current block for nextkey */
- int keyptr; /* current key for nextkey */
- long blkno; /* current page to read/write */
- long pagbno; /* current page in pagbuf */
- char pagbuf[PBLKSIZ]; /* page file block buffer */
- long dirbno; /* current block in dirbuf */
- char dirbuf[DBLKSIZ]; /* directory file block buffer */
-} DBM;
-
-#define DBM_RDONLY 0x1 /* data base open read-only */
-#define DBM_IOERR 0x2 /* data base I/O error */
-
-/*
- * utility macros
- */
-#define dbm_rdonly(db) ((db)->flags & DBM_RDONLY)
-#define dbm_error(db) ((db)->flags & DBM_IOERR)
-
-#define dbm_clearerr(db) ((db)->flags &= ~DBM_IOERR) /* ouch */
-
-#define dbm_dirfno(db) ((db)->dirf)
-#define dbm_pagfno(db) ((db)->pagf)
-
-typedef struct {
- char *dptr;
- int dsize;
-} datum;
-
-extern datum nullitem;
-
-#if defined(__STDC__) || defined(MSDOS)
-#define proto(p) p
-#else
-#define proto(p) ()
-#endif
-
-/*
- * flags to dbm_store
- */
-#define DBM_INSERT 0
-#define DBM_REPLACE 1
-
-/*
- * 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 *));
-
-/*
- * other
- */
-extern DBM *dbm_prep proto((char *, char *, int, int));
-extern long dbm_hash proto((char *, int));
-
-#endif /* _NDBM_H_ */
diff --git a/win32/win32.c b/win32/win32.c
index 46489c4e08..fd70242e9e 100644
--- a/win32/win32.c
+++ b/win32/win32.c
@@ -23,7 +23,7 @@
#include <windows.h>
#include <winbase.h>
#include <wincon.h>
-#include "nt.h"
+#include "win32.h"
#include "dir.h"
#ifndef index
#define index(x, y) strchr((x), (y))
@@ -33,6 +33,8 @@
#define bool int
#endif
+#define TO_SOCKET(x) _get_osfhandle(x)
+
bool NtSyncProcess = TRUE;
#if 0 // declared in header file
extern char **environ;
@@ -302,6 +304,14 @@ isInternalCmd(char *cmd)
}
+SOCKET
+myget_osfhandle(int fh)
+{
+ return _get_osfhandle(fh);
+
+}
+
+
FILE *
mypopen (char *cmd, char *mode)
{
@@ -1582,40 +1592,101 @@ valid_filename(char *s)
// if we can prevent perl from trying to do stdio on sockets.
//
+EXTERN_C int __cdecl _alloc_osfhnd(void);
+EXTERN_C int __cdecl _set_osfhnd(int fh, long value);
+EXTERN_C void __cdecl _lock_fhandle(int);
+EXTERN_C void __cdecl _unlock_fhandle(int);
+EXTERN_C void __cdecl _unlock(int);
+
+typedef struct {
+ long osfhnd; /* underlying OS file HANDLE */
+ char osfile; /* attributes of file (e.g., open in text mode?) */
+ char pipech; /* one char buffer for handles opened on pipes */
+#if defined (_MT) && !defined (DLL_FOR_WIN32S)
+ int lockinitflag;
+ CRITICAL_SECTION lock;
+#endif /* defined (_MT) && !defined (DLL_FOR_WIN32S) */
+} ioinfo;
+
+EXTERN_C ioinfo * __pioinfo[];
+
+#define IOINFO_L2E 5
+#define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E)
+#define _pioinfo(i) (__pioinfo[i >> IOINFO_L2E] + (i & (IOINFO_ARRAY_ELTS - 1)))
+#define _osfile(i) (_pioinfo(i)->osfile)
+
+#define FOPEN 0x01 /* file handle open */
+#define FAPPEND 0x20 /* file handle opened O_APPEND */
+#define FDEV 0x40 /* file handle refers to device */
+#define FTEXT 0x80 /* file handle is in text mode */
+
+static int
+my_open_osfhandle(long osfhandle, int flags)
+{
+ int fh;
+ char fileflags; /* _osfile flags */
+
+ /* copy relevant flags from second parameter */
+ fileflags = FDEV;
+
+ if (flags & O_APPEND)
+ fileflags |= FAPPEND;
+
+ if (flags & O_TEXT)
+ fileflags |= FTEXT;
+
+ /* attempt to allocate a C Runtime file handle */
+ if ((fh = _alloc_osfhnd()) == -1) {
+ errno = EMFILE; /* too many open files */
+ _doserrno = 0L; /* not an OS error */
+ return -1; /* return error to caller */
+ }
+
+ /* the file is open. now, set the info in _osfhnd array */
+ _set_osfhnd(fh, osfhandle);
+
+ fileflags |= FOPEN; /* mark as open */
+
+ _osfile(fh) = fileflags; /* set osfile entry */
+// _unlock_fhandle(fh);
+
+ return fh; /* return handle */
+}
+
FILE *
myfdopen (int fd, const char *mode)
{
- FILE *fp;
char sockbuf[80];
int optlen;
int retval;
+ int fh;
extern int errno;
//fprintf(stderr, "myfdopen()\n");
+ optlen = sizeof(sockbuf);
retval = getsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen);
if (retval == SOCKET_ERROR) {
int iRet;
iRet = WSAGetLastError();
if (iRet == WSAENOTSOCK || iRet == WSANOTINITIALISED)
- return (_fdopen(fd, mode));
+ return (_fdopen(fd, mode));
}
//
// If we get here, then fd is actually a socket.
//
- fp = xcalloc(sizeof(FILE), 1);
-#if _MSC_VER < 800
- fileno(fp) = fd;
-#else
- fp->_file = fd;
-#endif
- if (*mode == 'r')
- fp->_flag = _IOREAD;
- else
- fp->_flag = _IOWRT;
- return fp;
+
+ fh = my_open_osfhandle((SOCKET)fd, O_RDWR|O_BINARY);
+ return _fdopen(fh, mode); // return file pointer
+}
+
+
+void
+myfdclose(FILE *fp)
+{
+ fclose(fp);
}
@@ -1709,6 +1780,36 @@ ioctl(int i, unsigned int u, long data)
}
+#undef FD_SET
+
+void
+myfdset(int fd, fd_set *set)
+{
+ unsigned int i;
+ SOCKET s = TO_SOCKET(fd);
+
+ for (i = 0; i < set->fd_count; i++) {
+ if (set->fd_array[i] == s) {
+ return;
+ }
+ }
+ if (i == set->fd_count) {
+ if (set->fd_count < FD_SETSIZE) {
+ set->fd_array[i] = s;
+ set->fd_count++;
+ }
+ }
+}
+
+
+#undef FD_ISSET
+
+int
+myfdisset(int fd, fd_set *set)
+{
+ return __WSAFDIsSet(TO_SOCKET(fd), set);
+}
+
//
// Networking trampolines
// These are used to avoid socket startup/shutdown overhead in case
@@ -1737,6 +1838,7 @@ StartSockets () {
WORD version;
WSADATA retdata;
int ret;
+ int iSockOpt;
//
// initalize the winsock interface and insure that it\'s
@@ -1752,6 +1854,13 @@ StartSockets () {
rb_fatal("could not find version 1 of winsock dll\n");
atexit((void (*)(void)) WSACleanup);
+
+ iSockOpt = SO_SYNCHRONOUS_NONALERT;
+ /*
+ * Enable the use of sockets as filehandles
+ */
+ setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
+ (char *)&iSockOpt, sizeof(iSockOpt));
}
#undef accept
@@ -1764,7 +1873,7 @@ myaccept (SOCKET s, struct sockaddr *addr, int *addrlen)
if (!NtSocketsInitialized++) {
StartSockets();
}
- if ((r = accept (s, addr, addrlen)) == INVALID_SOCKET)
+ if ((r = accept (TO_SOCKET(s), addr, addrlen)) == INVALID_SOCKET)
errno = WSAGetLastError();
return r;
}
@@ -1808,7 +1917,7 @@ mygetpeername (SOCKET s, struct sockaddr *addr, int *addrlen)
if (!NtSocketsInitialized++) {
StartSockets();
}
- if ((r = getpeername (s, addr, addrlen)) == SOCKET_ERROR)
+ if ((r = getpeername (TO_SOCKET(s), addr, addrlen)) == SOCKET_ERROR)
errno = WSAGetLastError();
return r;
}
@@ -1822,7 +1931,7 @@ mygetsockname (SOCKET s, struct sockaddr *addr, int *addrlen)
if (!NtSocketsInitialized++) {
StartSockets();
}
- if ((r = getsockname (s, addr, addrlen)) == SOCKET_ERROR)
+ if ((r = getsockname (TO_SOCKET(s), addr, addrlen)) == SOCKET_ERROR)
errno = WSAGetLastError();
return r;
}
@@ -1850,7 +1959,7 @@ myioctlsocket (SOCKET s, long cmd, u_long *argp)
if (!NtSocketsInitialized++) {
StartSockets();
}
- if ((r = ioctlsocket (s, cmd, argp)) == SOCKET_ERROR)
+ if ((r = ioctlsocket (TO_SOCKET(s), cmd, argp)) == SOCKET_ERROR)
errno = WSAGetLastError();
return r;
}
@@ -1878,7 +1987,7 @@ myrecv (SOCKET s, char *buf, int len, int flags)
if (!NtSocketsInitialized++) {
StartSockets();
}
- if ((r = recv (s, buf, len, flags)) == SOCKET_ERROR)
+ if ((r = recv (TO_SOCKET(s), buf, len, flags)) == SOCKET_ERROR)
errno = WSAGetLastError();
return r;
}
@@ -1893,7 +2002,7 @@ myrecvfrom (SOCKET s, char *buf, int len, int flags,
if (!NtSocketsInitialized++) {
StartSockets();
}
- if ((r = recvfrom (s, buf, len, flags, from, fromlen)) == SOCKET_ERROR)
+ if ((r = recvfrom (TO_SOCKET(s), buf, len, flags, from, fromlen)) == SOCKET_ERROR)
errno = WSAGetLastError();
return r;
}
@@ -1907,7 +2016,7 @@ mysend (SOCKET s, char *buf, int len, int flags)
if (!NtSocketsInitialized++) {
StartSockets();
}
- if ((r = send (s, buf, len, flags)) == SOCKET_ERROR)
+ if ((r = send (TO_SOCKET(s), buf, len, flags)) == SOCKET_ERROR)
errno = WSAGetLastError();
return r;
}
@@ -1922,7 +2031,7 @@ mysendto (SOCKET s, char *buf, int len, int flags,
if (!NtSocketsInitialized++) {
StartSockets();
}
- if ((r = sendto (s, buf, len, flags, to, tolen)) == SOCKET_ERROR)
+ if ((r = sendto (TO_SOCKET(s), buf, len, flags, to, tolen)) == SOCKET_ERROR)
errno = WSAGetLastError();
return r;
}
@@ -1936,7 +2045,8 @@ mysetsockopt (SOCKET s, int level, int optname, char *optval, int optlen)
if (!NtSocketsInitialized++) {
StartSockets();
}
- if ((r = setsockopt (s, level, optname, optval, optlen)) == SOCKET_ERROR)
+ if ((r = setsockopt (s, level, optname, optval, optlen))
+ == SOCKET_ERROR)
errno = WSAGetLastError();
return r;
}
@@ -1950,7 +2060,7 @@ myshutdown (SOCKET s, int how)
if (!NtSocketsInitialized++) {
StartSockets();
}
- if ((r = shutdown (s, how)) == SOCKET_ERROR)
+ if ((r = shutdown (TO_SOCKET(s), how)) == SOCKET_ERROR)
errno = WSAGetLastError();
return r;
}
@@ -2120,7 +2230,7 @@ waitpid (pid_t pid, int *stat_loc, int options)
#include <sys/timeb.h>
-void _cdecl
+int _cdecl
gettimeofday(struct timeval *tv, struct timezone *tz)
{
struct timeb tb;
@@ -2128,6 +2238,8 @@ gettimeofday(struct timeval *tv, struct timezone *tz)
ftime(&tb);
tv->tv_sec = tb.time;
tv->tv_usec = tb.millitm * 1000;
+
+ return 0;
}
char *
@@ -2170,16 +2282,17 @@ str_grow(struct RString *str, size_t new_size)
}
int
-chown(char *path, int owner, int group)
+chown(const char *path, int owner, int group)
{
return 0;
}
+#include <signal.h>
int
kill(int pid, int sig)
{
#if 1
- if (pid == GetCurrentProcessId())
+ if ((unsigned int)pid == GetCurrentProcessId())
return raise(sig);
if (sig == 2 && pid > 0)
@@ -2204,3 +2317,28 @@ wait()
return 0;
}
+char *
+win32_getenv(const char *name)
+{
+ static char *curitem = NULL; /* XXX threadead */
+ static DWORD curlen = 0; /* XXX threadead */
+ DWORD needlen;
+ if (!curitem) {
+ curlen = 512;
+ curitem = ALLOC_N(char, curlen);
+ }
+
+ needlen = GetEnvironmentVariable(name,curitem,curlen);
+ if (needlen != 0) {
+ while (needlen > curlen) {
+ REALLOC_N(curitem, char, needlen);
+ curlen = needlen;
+ needlen = GetEnvironmentVariable(name, curitem, curlen);
+ }
+ }
+ else {
+ return NULL;
+ }
+
+ return curitem;
+}
diff --git a/win32/win32.h b/win32/win32.h
index a3d1f21aa5..04cb192c43 100644
--- a/win32/win32.h
+++ b/win32/win32.h
@@ -85,6 +85,11 @@
#undef except
#undef finally
#undef leave
+
+#if defined(__cplusplus)
+}
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -94,10 +99,17 @@
#include <math.h>
#include <sys/types.h>
#include <sys/utime.h>
+#include <io.h>
+#include <malloc.h>
-//
-// Grrr...
-//
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define UIDTYPE int
+#define GIDTYPE int
+#define pid_t int
+#define WNOHANG -1
#define access _access
#define chmod _chmod
@@ -113,6 +125,7 @@
#define lseek _lseek
#define mktemp _mktemp
#define open _open
+#define perror _perror
#define read _read
#define setmode _setmode
#define sopen _sopen
@@ -129,6 +142,7 @@
#define execvp _execvp
#define execvpe _execvpe
#define getpid _getpid
+#define sleep(x) Sleep((x)*1000)
#define spawnl _spawnl
#define spawnle _spawnle
#define spawnlp _spawnlp
@@ -141,22 +155,29 @@
#define fileno _fileno
#endif
#define utime _utime
-//#define pipe _pipe
-#define perror _perror
-
-
+#define vsnprintf _vsnprintf
+#define snprintf _snprintf
+#define popen _popen
+#define pclose _pclose
+#define strcasecmp _stricmp
+#define strncasecmp _strnicmp
/* these are defined in nt.c */
extern int NtMakeCmdVector(char *, char ***, int);
-/* extern void NtInitialize(int *, char ***); */
+extern void NtInitialize(int *, char ***);
extern char *NtGetLib(void);
extern char *NtGetBin(void);
extern FILE *mypopen(char *, char *);
+extern int mypclose(FILE *);
extern int flock(int fd, int oper);
-extern FILE * myfdopen(int, char*);
+extern FILE * myfdopen(int, const char *);
+extern void myfdclose(FILE *);
extern SOCKET myaccept(SOCKET, struct sockaddr *, int *);
extern int mybind(SOCKET, struct sockaddr *, int);
extern int myconnect(SOCKET, struct sockaddr *, int);
+extern void myfdset(int, fd_set*);
+extern int myfdisset(int, fd_set*);
+extern long myselect(int, fd_set *, fd_set *, fd_set *, struct timeval *);
extern int mygetpeername(SOCKET, struct sockaddr *, int *);
extern int mygetsockname(SOCKET, struct sockaddr *, int *);
extern int mygetsockopt(SOCKET, int, int, char *, int *);
@@ -169,6 +190,7 @@ extern int mysendto(SOCKET, char *, int, int, struct sockaddr *, int);
extern int mysetsockopt(SOCKET, int, int, char *, int);
extern int myshutdown(SOCKET, int);
extern SOCKET mysocket(int, int, int);
+extern SOCKET myget_osfhandle(int);
extern struct hostent * mygethostbyaddr(char *, int, int);
extern struct hostent * mygethostbyname(char *);
extern int mygethostname(char *, int);
@@ -176,6 +198,17 @@ extern struct protoent * mygetprotobyname(char *);
extern struct protoent * mygetprotobynumber(int);
extern struct servent * mygetservbyname(char *, char *);
extern struct servent * mygetservbyport(int, char *);
+extern char *win32_getenv(const char *);
+
+extern int chown(const char *, int, int);
+extern int link(char *, char *);
+extern int gettimeofday(struct timeval *, struct timezone *);
+extern pid_t waitpid (pid_t, int *, int);
+extern int do_spawn(char *);
+extern int kill(int, int);
+extern int isinf(double);
+extern int isnan(double);
+
//
// define this so we can do inplace editing
@@ -186,14 +219,7 @@ extern struct servent * mygetservbyport(int, char *);
//
// stubs
//
-// extern int ioctl (int, unsigned int, char *);
extern int ioctl (int, unsigned int, long);
-#if 0
-extern void sleep (unsigned int);
-#else
-#define sleep(x) Sleep(x*1000)
-#endif
-
extern UIDTYPE getuid (void);
extern UIDTYPE geteuid (void);
extern GIDTYPE getgid (void);
@@ -202,8 +228,6 @@ extern int setuid (int);
extern int setgid (int);
-#undef IN /* confict in parse.c */
-
#if 0
extern int sys_nerr;
extern char *sys_errlist[];
@@ -214,11 +238,6 @@ extern char *mystrerror(int);
#define PIPE_BUF 1024
-#define HAVE_STDLIB_H 1
-#define HAVE_GETLOGIN 1
-#define HAVE_WAITPID 1
-#define HAVE_GETCWD 1
-
#define LOCK_SH 1
#define LOCK_EX 2
#define LOCK_NB 4
@@ -227,8 +246,6 @@ extern char *mystrerror(int);
#define EWOULDBLOCK 10035 /* EBASEERR + 35 (winsock.h) */
#endif
-#define O_BINARY 0x8000
-
#ifdef popen
#undef popen
#define popen mypopen
@@ -261,6 +278,15 @@ extern char *mystrerror(int);
#endif
#define connect myconnect
+#undef FD_SET
+#define FD_SET myfdset
+
+#undef FD_ISSET
+#define FD_ISSET myfdisset
+
+#undef select
+#define select myselect
+
#ifdef getpeername
#undef getpeername
#endif
@@ -355,4 +381,15 @@ extern char *mystrerror(int);
#undef getservbyport
#endif
#define getservbyport mygetservbyport
+
+#ifdef get_osfhandle
+#undef get_osfhandle
+#endif
+#define get_osfhandle myget_osfhandle
+
+#ifdef getenv
+#undef getenv
+#endif
+#define getenv win32_getenv
+
#endif