From 65a5162550f58047974793cdc8067a970b2435c0 Mon Sep 17 00:00:00 2001 From: matz Date: Fri, 13 Aug 1999 05:45:20 +0000 Subject: 1.4.0 git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@520 b2dd03c8-39d4-4d8f-98ff-823fe69b080e diff --git a/ChangeLog b/ChangeLog index 6a317e2..868572c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,1838 @@ +Fri Aug 13 03:16:07 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * eval.c (rb_eval): no automatic aggregate initialization. + + * eval.c (module_setup): ditto. + +Wed Aug 11 18:18:41 1999 WATANABE Tetsuya + + * eval.c (yield_under_i): automatic aggregate initialization is an + ANSI feature. + +Wed Aug 11 10:10:02 1999 Yukihiro Matsumoto + + * 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 + + * regex.c (re_match): bug on backward jump adjustment concerning + stop_paren. + +Tue Aug 10 14:54:25 1999 Yukihiro Matsumoto + + * ext/nkf/nkf.c (rb_nkf_guess): binary detection was wrong. + +Tue Aug 10 00:07:36 1999 Yukihiro Matsumoto + + * io.c (rb_io_clone): should use CLONESETUP(). + +Mon Aug 9 23:57:07 1999 Yukihiro Matsumoto + + * ruby.h (CLONESETUP): should have copied generic instance + variables too. + +Mon Aug 9 10:46:54 1999 Katsuyuki Komatsu + + * ext/socket/extconf.rb: add check for and + . + +Sat Aug 7 13:19:06 1999 EGUCHI Osamu + + * numeric.c (flo_cmp): comparing NaN should not return value. + raises FloatDomainError. + +Sat Aug 7 03:09:08 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * 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 + + * object.c (rb_mod_clone): should check if iv_tbl, m_tbl are + initialized. + +Tue Aug 3 19:03:02 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * object.c (rb_mod_ge): wrong comparison. + +Fri Jul 30 12:15:44 1999 Katsuyuki Komatsu + + * 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 + + * 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 . + +Wed Jul 28 01:18:28 1999 WATANABE Hirofumi + + * 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 + + * version 1.3.6 - version 1.4 alpha + +Tue Jul 27 09:38:08 1999 EGUCHI Osamu + + * eval.c (rb_eval): reduce recursive rb_eval() calls by + NODE_BLOCKs. + +Tue Jul 27 01:20:40 1999 WATANABE Hirofumi + + * file.c (rb_file_s_expand_path): drive letter patch. + +Mon Jul 26 02:36:31 1999 Shugo Maeda + + * 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 + + * dir.c (push_braces): should treat nested braces. + +Fri Jul 23 02:49:49 1999 Yukihiro Matsumoto + + * hash.c (rb_hash_clear): dummy argument added; suggested by + . thanks. + +Thu Jul 22 19:37:22 1999 Yukihiro Matsumoto + + * eval.c (rb_thread_join): get_backtrace() may retrun Qnil. + typecheck added. + +Tue Jul 20 14:36:43 1999 WATANABE Hirofumi + + * range.c (range_each): do not treat String specially (for future + override). + +Tue Jul 20 02:28:34 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * lib/jcode.rb: replaced by faster code. + +Mon Jul 19 01:57:28 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * 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 + + * lib/telnet.rb: version 0.231. + +Fri Jul 16 10:58:22 1999 WATANABE Tetsuya + + * regex.c (re_match): debug print removed. + +Fri Jul 16 09:58:15 1999 Katsuyuki Komatsu + + * 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 + + * 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 + + * lib/debug.rb: better display & frame treatment. + +Thu Jul 15 21:16:41 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * ext/tcltklib/tcltklib.c: move `#include "ruby.h"' forward. + +Thu Jul 15 16:54:16 1999 Yukihiro Matsumoto + + * version 1.3.5 - version 1.4 alpha + +Wed Jul 14 23:45:33 1999 Katsuyuki Komatsu + + * eval.c (ruby_init): initialize for the first time only. + +Tue Jul 13 00:15:19 1999 Yukihiro Matsumoto + + * 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 + + * io.c (rb_file_sysopen): wrong number of argument. + +Mon Jul 12 11:52:35 1999 Yukihiro Matsumoto + + * 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 + + * lib/debug.rb: patch to show proper position. + +Fri Jul 9 23:56:14 1999 WATANABE Hirofumi + + * 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 + + * random.c (RANDOM_NUMBER): should place parentheses. + +Fri Jul 8 11:00:51 1999 Shugo Maeda + + * 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 + + * st.c (st_delete_safe): was modifying wrong slot. + +Mon Jul 5 13:17:46 1999 Yukihiro Matsumoto + + * gc.c (rb_gc_call_finalizer_at_exit): close all files at exit. + +Fri Jul 2 18:00:21 1999 Minero Aoki + + * lib/Mail/README: Mail-0.3.0 added to the distribution. + +Fri Jul 2 01:45:32 1999 Yukihiro Matsumoto + + * regex.c (re_compile_fastmap): avoid allocation of register + variables for each invocation of re_match(). Suggested by + Zasukhin Ruslan . Thanks. + +Tue Jun 29 20:39:24 1999 Koji Arai + + * 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 + + * lib/CGI.rb: 0.30 - cleanup release, incompatible. + + * lib/telnet.rb: 0.22 - timeout added. + +Tue Jun 29 10:49:25 1999 SHIROYAMA Takayuki + + * configure.in: better Rhapsody support. + + * lib/mkmf.rb: Rhapsody/NEXTSTEP support. + +Tue Jun 29 01:42:13 1999 Yukihiro Matsumoto + + * ext/pty/pty.c (chld_changed): should use POSIX.1 style wait. + +Mon Jun 28 21:07:36 1999 KIMURA Koichi + + * ext/extmk.rb.nt: wrong result for have_library(). + +Mon Jun 28 15:24:05 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * 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 + + * 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 + + * string.c (rb_str_rindex): wrong position to search. + +Sat Jun 26 04:05:30 1999 Takaaki Tateishi + + * 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 + + * 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 + + * missing/isinf.c: include "config.h" added. + +Fri Jun 25 07:25:05 1999 Katsuyuki Komatsu + + * 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 + + * 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 + + * 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 + + * 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 + + * pack.c (uv_to_utf8): mask needed. + +Wed Jun 23 21:03:56 1999 Tadayoshi Funaba + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * pack.c (pack_pack): should initialize local variable `j'. + +Wed Jun 22 15:24:59 1999 Koji Arai + + * parse.y (here_document): a bug for multiline heredoc. + +Tue Jun 22 15:06:36 1999 WATANABE Hirofumi + + * ext/socket/socket.c (ruby_socket): forgot to return fd + explicitly. + +Tue Jun 22 13:34:12 1999 Yukihiro Matsumoto + + * rubyio.h (MakeOpenFile): should initialize member `iv_tbl'. + +Wed Jun 22 10:35:51 1999 Katsuyuki Komatsu + + * io.c (rb_io_gets_internal): getc(3) may not set errno on + interrupt. + +Mon Jun 21 22:39:28 1999 Yukihiro Matsumoto + + * 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 + + * ext/dbm/dbm.c: include for solaris 2.6. + +Mon Jun 21 15:59:47 1999 Nobuyoshi Nakada + + * ext/socket/socket.c (ip_addrsetup): forgot to put `else'. + +Mon Jun 21 15:38:37 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * string.c (rb_str_each_line): should have checked string + boundary. + +Sat Jun 19 22:24:12 1999 Kenji Nagasawa + + * OS/2 patch improved. + +Fri Jun 18 08:30:17 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * 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 + + * pack.c (pack_pack): template `Z' should be allowed. + +Wed Jun 9 13:26:38 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * 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 + + * 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 + + * regex.c (read_backslash): should decode \b within class. + +Thu Jun 3 01:06:18 1999 Katsuyuki Komatsu + + * dln.c (dln_load): AIX improvement (aix_findmain removed). + +Wed Jun 2 00:41:31 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * 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 + + * version 1.3.4 - preliminary release for 1.4 + +Mon May 31 15:57:41 1999 Yukihiro Matsumoto + + * 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 + + * regex.c (re_match): stack boundary check needed. + +Sat May 29 12:27:00 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * 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 + . + +Thu May 27 12:27:42 1999 Yukihiro Matsumoto + + * string.c (tr_trans): should handle NUL (\0) within strings. + +Tue May 25 16:45:11 1999 Yukihiro Matsumoto + + * 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 + + * regex.c (read_backslash): read backslash by regex. + +Sun May 23 19:44:58 1999 WATANABE Hirofumi + + * ext/pty/pty.c (getDevice): portability patch. + +Fri May 21 23:01:26 1999 Katsuyuki Komatsu + + * ext/socket/getaddrinfo.c (GET_AI): should set error code. + +Thu May 20 03:43:44 1999 Jun-ichiro itojun Hagino + + * 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 + + * 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 + + * regex.c (re_search): a bug in range adjustment. + +Tue May 18 11:35:59 1999 WATANABE Hirofumi + + * dln.c (conv_to_posix_path): path_len argument added. + +Mon May 17 12:26:31 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * regex.c (re_compile_fastmap): it should be k != 0 to skip. + +Fri May 14 12:46:56 1999 Yukihiro Matsumoto + + * 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 + + * regex.c (re_match): a bug in inline `.*' etc. + +Fri May 14 09:58:46 1999 Minero Aoki + + * ruby.c (addpath): should have specified string length. + +Thu May 13 10:40:44 1999 Yukihiro Matsumoto + + * 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 + + * struct.c (iv_get): in case of inheritance of generated struct + class, __member__ and __size__ should also be inherited. + Thanks for Pros Yeboah . + + * io.c (rb_f_gets_internal): should check number of arguments + before checking rb_rs == rb_default_rs. Thanks for Koji Arai + . + +Tue May 11 08:29:28 1999 Yukihiro Matsumoto + + * regex.c (re_compile_pattern): .?, .+ did not work. + +Mon May 10 00:59:33 1999 Yukihiro Matsumoto + + * 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 + + * ext/socket/socket.c (sock_s_getaddrinfo): conversion from + Fixnums to C integers needed. + +Sun May 9 11:51:43 1999 Koji Arai + + * 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 + + * 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 + + * 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 + + * dir.c (glob): removed GPL'ed glob.c completely. + +Fri May 7 08:17:19 1999 Yukihiro Matsumoto + + * ext/sdbm/extconf.rb: sdbm extension added to the distribution. + +Fri May 7 01:42:20 1999 Yukihiro Matsumoto + + * ext/socket/socket.c (tcp_s_gethostbyname): aboid using struct + sockaddr_storage. + +Thu May 6 13:21:41 1999 Yukihiro Matsumoto + + * array.c (rb_ary_indexes): should not use rb_ary_concat(). + +Thu May 4 12:34:18 1999 Koji Arai + + * 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 + + * 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 + + * ext/socket/socket.c (open_inet): typo (res and res0). + +Tue May 4 02:07:49 1999 Yukihiro Matsumoto + + * mkconfig.rb: leave undefined $(VARIABLE) unexpanded in the + Config::CONFIG hash table. + +Mon May 3 09:37:22 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * 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 + + * string.c (rb_str_aset): last index should not append. + +Thu Apr 29 18:55:31 1999 WATANABE Hirofumi + + * 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 + + * 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 + . + +Mon Apr 26 16:46:59 1999 Yukihiro Matsumoto + + * 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 + + * parse.y (operation): syntax like `a.[]=(1,2)' is allowed. + +Fri Apr 23 23:54:09 1999 Yukihiro Matsumoto + + * io.c (argf_binmode): binmode method added to ARGF. + +Fri Apr 23 13:55:22 1999 Yukihiro Matsumoto + + * 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 + + * eval.c (rb_callcc): call scope_dup() for all scopes in + the interpreter stack. + +Tue Apr 20 11:24:18 1999 Yukihiro Matsumoto + + * string.c (rb_str_dump): `#' should be escaped. + +Tue Apr 20 02:32:42 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * eval.c (eval): should restore ruby_dyna_vars. + +Fri Apr 16 21:40:43 1999 Nobuyoshi Nakada + + * 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 + + * 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 + + * ruby.c (rubylib_mangle): mangle path by RUBYLIB_PREFIX. + +Wed Apr 14 23:52:51 1999 SHIROYAMA Takayuki + + * node.h (NODE_LMASK): should be long to avoid overflow. + +Wed Apr 14 13:14:35 1999 Katsuyuki Komatsu + + * dln.c: AIX dynamic link. + + * ext/aix_ld.rb: ditto. + +Wed Apr 14 12:19:09 1999 Yukihiro Matsumoto + + * lib/thread.rb: Queue#{enq,deq} added. + +Tue Apr 13 17:43:56 1999 Yukihiro Matsumoto + + * hash.c (rb_hash_s_create): Hash::[] acts more like casting. + +Tue Apr 13 00:33:52 1999 Yukihiro Matsumoto + + * 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 + + * io.c (rb_io_reopen): check for reopening same IO. + +Fri Apr 9 17:45:11 1999 Yukihiro Matsumoto + + * 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 + + * pack.c (PACK_LENGTH_ADJUST): need to adjust for `*' length. + +Tue Apr 6 23:28:44 1999 Yukihiro Matsumoto + + * parse.y (void_check): add void context checks. + +Mon Apr 5 12:23:42 1999 Yukihiro Matsumoto + + * 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 + + * lib/debug.rb: wrong command interpreting. + +Fri Apr 2 11:46:22 1999 Yukihiro Matsumoto + + * version 1.3.2 + +Fri Apr 2 10:40:04 1999 Yukihiro Matsumoto + + * io.c (rb_io_s_pipe): forgot to define IO::pipe. + +Thu Apr 1 14:40:46 1999 Yukihiro Matsumoto + + * 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 + + * ext/nkf/nkf.c (rb_nkf_kconv): check size output_ctr before + decrement. + +Thu Mar 25 09:11:03 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * configure.in: AC_C_CONST check added. + +Tue Mar 23 02:07:35 1999 Yukihiro Matsumoto + + * time.c (time_plus): preserve gmt-mode for result. + +Mon Mar 22 01:32:37 1999 Yukihiro Matsumoto + + * 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 + + * lib/weakref.rb: avoid leak for two weakrefs for one object. + +Fri Mar 19 11:26:45 1999 WATANABE Hirofumi + + * eval.c (ruby_run): needed to eval END{} on exit. + + * eval.c (rb_exit): ditto. + +Fri Mar 19 02:17:27 1999 Yukihiro Matsumoto + + * signal.c (Init_signal): handles terminating signals HUP, TERM, + QUIT, PIPE, etc. + +Thu Mar 18 15:47:18 1999 Yukihiro Matsumoto + + * 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 + + * ext/extmk.rb.in: static linking cause infinite make loop. + +Tue Mar 16 18:50:04 1999 Yoshida Masato + + * 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 + + * file.c (utime_internal): suppress warning by const. + + * time.c (time_gmtime): ditto. + +Tue Mar 16 10:23:05 1999 Yukihiro Matsumoto + + * time.c (time_clone): Time object can be cloned. + +Tue Mar 16 03:13:10 1999 Koji Arai + + * ruby.c (load_file): argv[argc] should be NULL. + +Mon Mar 15 22:12:08 1999 Tadayoshi Funaba + + * sprintf.c (rb_f_sprintf): typo in arg_num check at exit. + +Mon Mar 15 16:42:22 1999 Yukihiro Matsumoto + + * array.c (rb_ary_dup): dup2 should copy class too. + +Mon Mar 15 15:12:53 1999 Yasuhiro Fukuma + + * lib/mkmf.rb: install program relative path check. + +Mon Mar 15 14:05:25 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * ext/readline/readline.c (readline_s_vi_editing_mode): wrong + number of arguments. + +Fri Mar 12 02:12:50 1999 Yukihiro Matsumoto + + * pack.c (PACK_ITEM_ADJUST): "a".unpack("C3") => [97, nil, nil] + +Thu Mar 11 18:23:50 1999 WATANABE Tetsuya + + * ext/socket/socket.c (Init_socket): UDPsocket was ommited. + +Thu Mar 11 16:43:30 1999 Yukihiro Matsumoto + + * 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 + + * hash.c (ruby_unsetenv): use ruby_setenv(name, 0). + + * hash.c (env_delete): ditto. + + * string.c (rb_str_upto): do not check `beg + + * string.c (rb_str_index): wrong end point calculation. + +Sat Mar 6 02:19:12 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * 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 + + * configure.in: remove --disable-thread, thread feature is no + longer optional. + +Thu Mar 4 00:32:17 1999 Yasuhiro Fukuma + + * parse.y (read_escape): wrong arguments for scan_oct,scan_hex. + +Wed Mar 3 11:51:53 1999 Yukihiro Matsumoto + + * ext/socket/socket.c (Init_socket): rename class names as + TCPsocket -> TCPSocket etc. + +Tue Mar 2 19:46:42 1999 WATANABE Hirofumi + + * configure.in (LDSHARED): use gcc -Wl,-G for solaris with gcc. + +Tue Mar 2 17:04:19 1999 Yukihiro Matsumoto + + * parse.y (yylex): backslashes do not concatenate comment lines + anymore. + +Mon Mar 1 14:05:12 1999 Yukihiro Matsumoto + + * 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 + + * parse.y (nextc): backslash at the eof cause infinite loop + +Sun Feb 28 11:01:26 1999 Tadayoshi Funaba + + * time.c (make_time_t): month range check added. + +Sat Feb 27 02:36:05 1999 Yukihiro Matsumoto + + * 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 + + * eval.c (error_print): bug for error message with newlines. + +Fri Feb 26 12:00:04 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * time.c (time_load): tm_year should be packed in 17 bits, not 18. + +Thu Feb 25 12:50:25 1999 Yukihiro Matsumoto + + * 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 + + * eval.c (rb_call): should handle T_ICLASS properly. + +Thu Feb 25 00:04:00 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * parse.y (yylex): warn if identifier! immediately followed by `='. + +Tue Feb 23 12:32:41 1999 WATANABE Hirofumi + + * 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 + + * 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 + + * 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 + + * numeric.c (rb_num2long): no implicit conversion from boolean. + +Sat Feb 20 09:58:42 1999 EGUCHI Osamu + + * numeric.c (flo_to_s): portable Infinity and NaN support. + +Sat Feb 20 07:13:31 1999 WATANABE Tetsuya + + * io.c (rb_file_sysopen): forgot to initialize a local variable. + +Fri Feb 19 23:05:07 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * 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 + + * missing/fnmatch.c: moved to missing directory. + +Wed Feb 17 16:22:26 1999 Yukihiro Matsumoto + + * struct.c (rb_struct_alloc): actual initialization now be done in + `initialize'. + +Wed Feb 17 09:47:15 1999 okabe katsuyuki + + * 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 + + * 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 + + * configure.in: BeOS patch. + +Tue Feb 16 14:25:00 1999 Yukihiro Matsumoto + + * 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 + + * configure.in: specify `-Wl,-E' only for GNU ld. + +Mon Feb 15 11:43:22 1999 GOTO Kentaro + + * array.c (rb_inspecting_p): should return Qfalse. + +Sun Feb 14 22:36:40 1999 EGUCHI Osamu + + * sprintf.c (rb_f_sprintf): `%G' was ommited. + +Sun Feb 14 12:47:48 1999 EGUCHI Osamu + + * 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 + + * eval.c (rb_thread_create_0): should protect th->thread. + +Fri Feb 12 16:16:47 1999 Yasuhiro Fukuma + + * string.c (rb_str_inspect): wrong mbc position. + +Fri Feb 12 16:21:17 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * 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 + + * numeric.c (fix_pow): `(5**1).type' should be Integer. + +Tue Feb 9 01:22:49 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * re.c (match_getter): accessng $~ without matching caused SEGV. + +Fri Feb 5 22:11:08 1999 EGUCHI Osamu + + * 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 + + * ruby.c (proc_options): -e without program prints error. + +Fri Feb 5 00:01:50 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * 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 + + * parse.y (yylex): too big float raise warning, not error. + +Tue Feb 2 23:41:42 1999 Yoshida Masato + + * 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 + + * 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 + + * string.c (rb_str_gsub_bang): too small realoc condition. + +Mon Feb 1 10:01:17 1999 EGUCHI Osamu + + * parse.y (yylex): range check for the float literal. + +Sat Jan 30 18:34:16 1999 Yukihiro Matsumoto + + * ruby.c (usage): -h option to show brief command description. + +Sat Jan 30 08:45:16 1999 IKARASHI Akira + + * lib/cgi-lib.rb: cookie support added. + +Sat Jan 30 13:38:24 1999 Yukihiro Matsumoto + + * 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 + + * 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 + + * 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 + + * hash.c (rb_f_setenv): SEGV caused by small typo. + +Fri Jan 29 00:15:58 1999 Yukihiro Matsumoto + + * 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 + + * numeric.c (flo_to_s): float format changed to "%16.10g". + +Thu Jan 28 02:13:11 1999 Yoshinori Toki + + * array.c (rb_ary_store): expand allocated buffer by 3/2. + +Wed Jan 27 17:50:02 1999 Kazuhiro HIWADA + + * 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 + + * 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 + + * prec.c: Precision support for numbers. + +Thu Jan 21 19:08:14 1999 Yukihiro Matsumoto + + * 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 * parse.y (yycompile): rb_in_compile renamed to ruby_in_compile. @@ -14,7 +1849,7 @@ Tue Jan 19 05:01:16 1999 Koji Arai * array.c (beg_len): round range value too much. -Mon Jan 18 13:02:27 1999 Kuroda Jun +Mon Jan 18 13:02:27 1999 Kuroda Jun * hash.c (env_keys): strchr() may return NULL. @@ -435,7 +2270,7 @@ Sat Oct 31 23:18:34 1998 Yukihiro Matsumoto * string.c (rb_str_split_method): if LIMIT is unspecified, trailing null fields are stripped. -Sat Oct 31 04:16:14 1998 Inaba Hiroto +Sat Oct 31 04:16:14 1998 Inaba Hiroto * string.c (str_aref): regexp index SEGVed. @@ -662,7 +2497,6 @@ Fri Sep 4 11:27:40 1998 Yukihiro Matsumoto * regex.c (re_search): wrong return value for \A. ->>>>>>> 1.1.1.2.2.154 Thu Sep 3 14:08:14 1998 Yukihiro Matsumoto * version 1.1c4 released. @@ -697,7 +2531,7 @@ Sat Aug 29 16:31:40 1998 Yukihiro Matsumoto * regex.c (re_compile_pattern): mask \nnn over 256. -Sat Aug 29 02:09:46 1998 1998 Koji Arai +Sat Aug 29 02:09:46 1998 Koji Arai * sprintf.c (f_sprintf): wrong buffer size check. @@ -1285,7 +3119,7 @@ Thu May 14 14:03:16 1998 Yukihiro Matsumoto * random.c (f_rand): use drand48 if possible. -Wed May 13 19:05:20 1998 1998 MAEDA shugo +Wed May 13 19:05:20 1998 MAEDA shugo * BeOS patches for io.c, error.c and config.guess. diff --git a/MANIFEST b/MANIFEST index 5c697d6..1b9e448 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 628b0e0..865318b 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 dd93c59..2a99cae 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 . + * 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 f169e54..241d6fa 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 . -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 } -- -¤Á¤ç¤Ã¤ÈÊ£»¨¤Ê¥Þ¥¯¥í¤Ç¤¹¤¬¡¤Íפ¹¤ë¤Ë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 0000000..da3902b --- /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-¤Ç»ØÄꤵ¤ì¤¿¥ª¥×¥·¥ç¥óÃͤòÆÀ¤ë¡¥ + +dir_config(target) + + --with--dir, --with--include, --with--lib + ¤Î¤¤¤º¤ì¤«¤Ç»ØÄꤵ¤ì¤ë¥Ç¥£¥ì¥¯¥È¥ê¤ò $CFLAGS ¤ä $LDFLAGS + ¤ËÄɲ乤롥 + +/* + * Local variables: + * fill-column: 60 + * end: + */ diff --git a/README.jp b/README.jp index d137a43..8115dc4 100644 --- a/README.jp +++ b/README.jp @@ -32,24 +32,45 @@ Ruby 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) (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 3bc7887..1ecd529 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 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 8f6c0c2..9cc0ac1 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; ilen; 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; ilen; + } + 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; ilen; 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; ilen; 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; ilen; 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 770e86a..36a46af 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; isign; } - z = bignew(l2, RBIGNUM(x)->sign || RBIGNUM(y)->sign); + z = bignew(l2, RBIGNUM(x)->sign && RBIGNUM(y)->sign); zds = BDIGITS(z); for (i=0; ilen; - 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 86ac8c5..32dc0e1 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 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 a6212a8..50e4fa3 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 042d209..7e23afe 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 #include @@ -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 <>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 0000000..7ba18e4 --- /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 31a40f0..700b05c 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 < 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 < 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 < 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 < Autoconf TIOCGETP @@ -1017,7 +1003,7 @@ rm -f conftest* if test $ac_cv_prog_gcc_traditional = no; then cat > conftest.$ac_ext < 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 <&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 <&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 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 < 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 <&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 < +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 <&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 < 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 < 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 <&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 < +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 <&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 < +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 <&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 <&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 <&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 < @@ -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 <&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 <&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 <&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 <&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 <&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 < #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 <&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 <&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 < #include @@ -1845,7 +2065,7 @@ else #include 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 @@ -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 @@ -1901,7 +2121,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #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 < +#include +#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 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 @@ -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 < #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 < #include @@ -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 < #include @@ -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 < #include @@ -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 <&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 @@ -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 < #include @@ -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 < 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 <&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 <&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 <&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 <&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 < #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 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 <&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 < @@ -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 <&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 <&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 <&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 < #include @@ -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 < #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 < #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 <&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 < @@ -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 < +#include + +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 < -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 < -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 < #include @@ -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 < #include @@ -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 <&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 <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 <&2; exit 1; } else cat > conftest.$ac_ext <&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 <&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 < 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 < 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 < 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 < 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 < +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 <&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 <&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 <&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 <&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 <&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 < @@ -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 < @@ -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 <> confdefs.h <> confdefs.h <> confdefs.h <> confdefs.h <> confdefs.h <> confdefs.h <> confdefs.h <> confdefs.h <> confdefs.h <> confdefs.h <> confdefs.h <> $CONFIG_STATUS <> $CONFIG_STATUS <> $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 093d435..ce0aa8b 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 0477ade..8e86e42 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 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 #include @@ -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 ], [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 ], [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 ], [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 ], [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 ], + [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 @@ -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 0000000..970e90e --- /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 fb10d62..8e6eb83 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 51d7f9e..31116a9 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 +#else +#include "missing/fnmatch.h" +#endif + #include +#ifdef USE_CWGUSI +# include +#endif -#ifndef NT +#ifndef HAVE_STDLIB_H char *getenv(); #endif -#ifdef USE_CWGUSI -# include +#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 858291d..e6c7add 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 #endif +#ifndef xmalloc void *xmalloc(); void *xcalloc(); void *xrealloc(); +#endif #include #ifndef NT @@ -56,7 +58,6 @@ void *xrealloc(); #endif #ifndef NT -char *strdup(); char *getenv(); #endif @@ -64,6 +65,7 @@ char *getenv(); # include # include # include +# 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 #include "dl.h" #endif @@ -1094,12 +1097,16 @@ dln_sym(name) #include #endif #endif +#ifdef __APPLE__ +#include +#endif + #ifdef _WIN32 #include #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 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 7af1f63..6e4f606 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 2b4b904..dc7e211 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 79fdfc2..6c38d4c 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 44ca067..300c09f 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 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 #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 && ind_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 && ind_args, rb_ary_new4(len-i, RARRAY(val)->ptr+i)); + if (node->nd_args == (NODE*)-1) { + /* ignore rest args */ + } + else if (!list && ind_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 && ind_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 = █ + + 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;ilen;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 11a8ded..9ac2db6 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 #ifdef HAVE_SYS_TIME_H # include #else @@ -39,6 +40,8 @@ struct timeval { #endif /* NT */ #endif +VALUE rb_time_new _((time_t, time_t)); + #ifdef HAVE_UTIME_H #include #endif @@ -48,7 +51,7 @@ struct timeval { #endif #ifndef HAVE_STRING_H -char *strrchr _((char*,char)); +char *strrchr _((const char*,const char)); #endif #include @@ -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 -#include "fnmatch.h" - -#ifdef USE_CWGUSI -#include -#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 62c8c8f..0000000 --- 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 31ed111..7e2a4f7 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; ilen; 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 09a47e0..0000000 --- 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 -#endif - -#if defined (HAVE_UNISTD_H) -# include -#endif - -#if defined (HAVE_STDLIB_H) -# include -#else -# if defined (SHELL) -# include "ansi_stdlib.h" -# endif /* SHELL */ -#endif - -#include - -#if defined (HAVE_DIRENT_H) -# include -# define D_NAMLEN(d) strlen ((d)->d_name) -#elif HAVE_DIRECT_H -# include -# 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 -# endif -# if defined (HAVE_SYS_DIR_H) -# include -# endif /* HAVE_SYS_DIR_H */ -# if defined (HAVE_NDIR_H) -# include -# 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 -#else /* !HAVE_STRING_H */ -# include -#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 -# 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 9141406..608f85d 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 @@ -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; itbl, 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 3708edc..fdc49f0 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 89fc9b0..e69de29 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 d489e0f..52c7c23 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 8b88751..4bfefa2 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 5573e76..fb1e0d8 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 #include @@ -20,8 +21,10 @@ #if !defined(DJGPP) && !defined(NT) && !defined(__human68k__) #include #endif -#if defined(HAVE_FCNTL) +#if defined(HAVE_FCNTL_H) || defined(NT) #include +#elif defined(HAVE_SYS_FCNTL_H) +#include #endif #ifdef HAVE_SYS_TIME_H @@ -40,7 +43,8 @@ struct timeval { #include -#ifdef HAVE_SYS_PARAM_H +/* EMX has sys/parm.h, but.. */ +#if defined(HAVE_SYS_PARAM_H) && !defined(__EMX__) # include #else # define NOFILE 64 @@ -55,9 +59,17 @@ struct timeval { #include #include #endif + +#ifndef strdup +char *strdup(); +#endif + extern void Init_File _((void)); #ifdef __BEOS__ +# ifdef _X86_ +# define NOFILE (OPEN_MAX) +# endif #include #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 #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; ilen; 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; ilen; 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; ilen; 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(¤t_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 1abc048..62e1ef6 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 0000000..b3ee3ba --- /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 < + + 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(/&/, "&").gsub(/\"/, """).gsub(/>/, ">").gsub(/" - print title - print "\n" - print msg - print "\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 + "" : "") + 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!(/&/, '&') - m.gsub!(//, '>') - msgs = ["
ERROR: #{m}"]
-    msgs << $@
-    msgs << "
" - 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 59caad6..0af8c20 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 0000000..58bfbe5 --- /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('#', @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 90270a3..d2f1da8 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 0771f2f..29f2a5d 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 bf860dc..e04ed4a 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 < 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 617d858..9336e0a 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 0000000..a37714c --- /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 9e1e8a2..5b9562d 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 50b7bee..92b9284 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 5e46606..2edcca0 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 265ef13..8d92272 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 64b0738..f5c8491 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 7e131fe..50920a0 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 +#include 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 +#include +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 +#include +int main() { return 0; } +int t() { #{func}(); return 0; } +SRC + unless r + r = try_link(<<"SRC", libs) +#include +#include +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 < +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 4b8d644..e0fcf0f 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 5928367..0c74b49 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 0000000..9e34acf --- /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 68550c6..6afec0f 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 0000000..e4b1b4b --- /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 1282f56..f976cf0 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 0000000..d6a3b10 --- /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 + + +=== 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 + 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 +- 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 0000000..11a8fba --- /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 ec75144..22610f2 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= 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 0000000..d4ea758 --- /dev/null +++ b/lib/timeout.rb @@ -0,0 +1,42 @@ +# +# timeout.rb -- execution timeout +# +#= SYNOPSIS +# +# require 'timeout' +# status = timeout(5) { +# # something may take time +# } +# +#= DESCRIPTION +# +# timeout executes the block. If the block execution terminates successfully +# before timeout, it returns true. If not, it terminates the execution and +# raise TimeoutError exception. +# +#== Parameters +# +# : timout +# +# The time in seconds to wait for block teminatation. +# +#=end + +class TimeoutError Raises WeakRef::RefError (because original GC'ed) +# p foo.to_s # should raise exception (recycled) require "delegate" @@ -15,27 +16,31 @@ class WeakRef [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 +#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 6a68b04..9d4808b 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 3ea30bd..978a23c 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 0000000..adc119d --- /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 0000000..eaa9049 --- /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 0000000..61c6d93 --- /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 0000000..a74265f --- /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 0000000..14e3dac --- /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 c541149..e7cc46f 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 #endif +#if !defined(HAVE_FCNTL) || !defined(F_DUPFD) +# include +#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 0000000..07fe326 --- /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 0000000..4cf7461 --- /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 + +#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 0000000..7738516 --- /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 0000000..e0cd6ac --- /dev/null +++ b/missing/isinf.c @@ -0,0 +1,44 @@ +#ifdef __osf__ + +#define _IEEE 1 +#include + +int +isinf(n) + double n; +{ + if (IsNANorINF(n) && IsINF(n)) { + return 1; + } else { + return 0; + } +} + +#else + +#include "config.h" +#ifdef HAVE_STRING_H +# include +#else +# include +#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 0000000..96bb93b --- /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 0000000..762eaf5 --- /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 0000000..aeb181f --- /dev/null +++ b/missing/os2.c @@ -0,0 +1,111 @@ +#include "ruby.h" +#include +#include +#include +#include +#include +#include + +#define INCL_DOS +#include + +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 83aa50d..ba7bf78 100644 --- a/missing/strcasecmp.c +++ b/missing/strcasecmp.c @@ -1,6 +1,5 @@ #include -#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 0000000..50714c9 --- /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 + +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 478471c..cc3f1a8 100644 --- a/missing/strftime.c +++ b/missing/strftime.c @@ -45,6 +45,8 @@ * January 1996 */ +#include "config.h" + #ifndef GAWK #include #include @@ -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 +#include +#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 0000000..c136703 --- /dev/null +++ b/missing/strncasecmp.c @@ -0,0 +1,18 @@ +#include + +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 0000000..e052cbc --- /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 +#endif +#include +#include +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 0000000..5865be7 --- /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 +#define u_long unsigned long +#define u_short unsigned short +#define u_int unsigned int + +#undef __P +#if defined(__STDC__) +# include +# if !defined(__P) +# define __P(x) x +# endif +#else +# define __P(x) () +# if !defined(const) +# define const +# endif +# include +#endif +#ifndef _BSD_VA_LIST_ +#define _BSD_VA_LIST_ va_list +#endif + +#ifdef __STDC__ +# include +#else +# ifndef LONG_MAX +# ifdef HAVE_LIMITS_H +# include +# 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 +#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 +#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 +/* #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 + +#if defined(__STDC__) +# include +#else +# include +#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 903cdda..093d023 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 <flags=((RNODE(n)->flags&~FL_UMASK)|(((t)<flags>>NODE_LSHIFT)&NODE_LMASK) #define nd_set_line(n,l) \ RNODE(n)->flags=((RNODE(n)->flags&~(-1< #include +#ifdef __FreeBSD__ +#include +#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 15e757d..9c5163a 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 dc393b8..38e970c 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 #include +#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>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 8c3bcc5..0000000 --- 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 - -/* 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 - -#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 -#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 -#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 */ - #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 -#include -#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); -