From ed131ebad88c2948d7b40f93ff6ce39f1eb8a2f7 Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> Date: Fri, 14 Apr 2000 14:35:50 +0000 Subject: This commit was manufactured by cvs2svn to create tag 'v1_4_4'. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/tags/v1_4_4@668 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 434 ++++++++++ MANIFEST | 10 +- Makefile.in | 2 + README | 2 +- README.jp | 4 +- array.c | 27 +- bignum.c | 27 +- class.c | 2 +- compar.c | 2 +- config.guess | 304 +++++-- config.sub | 316 +++++++- config_s.dj | 2 +- configure | 544 +++++++------ configure.in | 109 ++- cygwin/GNUmakefile.in | 2 +- dir.c | 176 +++- dln.c | 4 +- enum.c | 31 +- error.c | 26 +- eval.c | 345 +++++--- ext/Setup.nt | 19 - ext/Win32API/Win32API.c | 42 +- ext/Win32API/depend | 1 - ext/curses/MANIFEST | 1 + ext/curses/curses.c | 40 +- ext/curses/depend | 1 + ext/dbm/extconf.rb | 7 +- ext/extmk.rb.in | 2 +- ext/kconv/kconv.c | 2017 ++++++++++++++++++++++++++++++++++++++++++++++ ext/nkf/depend | 2 +- ext/nkf/nkf.c | 26 +- ext/pty/MANIFEST | 1 + ext/pty/depend | 1 + ext/pty/pty.c | 2 + ext/readline/MANIFEST | 1 + ext/readline/depend | 1 + ext/sdbm/MANIFEST | 1 + ext/sdbm/depend | 2 + ext/socket/extconf.rb | 31 +- ext/socket/getaddrinfo.c | 17 +- ext/socket/getnameinfo.c | 11 +- ext/socket/socket.c | 52 +- ext/tcltklib/extconf.rb | 2 + ext/tk/lib/tk.rb | 340 +++++--- ext/tk/lib/tkcanvas.rb | 31 +- ext/tk/lib/tkentry.rb | 10 +- ext/tk/lib/tkfont.rb | 15 +- ext/tk/lib/tktext.rb | 65 +- file.c | 32 +- gc.c | 35 +- hash.c | 21 +- inits.c | 2 +- instruby.rb | 39 +- intern.h | 12 +- io.c | 62 +- lib/complex.rb | 32 +- lib/debug.rb | 14 +- lib/find.rb | 6 +- lib/ftplib.rb | 647 +-------------- lib/getoptlong.rb | 87 +- lib/mkmf.rb | 4 +- lib/net/ftp.rb | 642 +++++++++++++++ lib/net/http.rb | 312 +++++++ lib/net/pop.rb | 315 ++++++-- lib/net/protocol.rb | 724 +++++++++++++++++ lib/net/session.rb | 565 +++++++++---- lib/net/smtp.rb | 178 ++-- lib/net/telnet.rb | 749 +++++++++++++++++ lib/observer.rb | 2 +- lib/parsedate.rb | 2 +- lib/pstore.rb | 38 +- lib/singleton.rb | 8 +- lib/telnet.rb | 235 +++--- lib/timeout.rb | 2 - lib/weakref.rb | 2 +- main.c | 2 +- marshal.c | 159 +++- math.c | 2 +- misc/inf-ruby.el | 7 +- misc/ruby-mode.el | 11 +- missing/file.h | 33 +- missing/flock.c | 48 ++ missing/fnmatch.c | 199 ----- missing/fnmatch.h | 57 -- missing/isnan.c | 13 + missing/strtod.c | 9 +- missing/x68.c | 2 + node.h | 13 +- numeric.c | 19 +- object.c | 3 +- pack.c | 2 +- parse.y | 77 +- prec.c | 2 +- process.c | 29 +- random.c | 71 +- range.c | 2 +- re.c | 29 +- re.h | 5 +- regex.c | 82 +- ruby.c | 24 +- ruby.h | 6 +- rubyio.h | 2 +- rubytest.rb | 2 + sample/io.rb | 44 - sample/mine.rb | 2 +- sample/mpart.rb | 2 +- sample/rbc.rb | 1015 ----------------------- signal.c | 6 +- sprintf.c | 8 +- st.c | 4 +- string.c | 161 ++-- struct.c | 1 + time.c | 12 +- top.sed | 2 +- util.c | 2 +- util.h | 2 +- variable.c | 24 +- version.c | 4 +- version.h | 8 +- win32/Makefile | 7 +- win32/config.status | 4 +- win32/ruby.def | 8 +- win32/win32.c | 152 ++-- win32/win32.h | 9 +- 124 files changed, 8491 insertions(+), 3773 deletions(-) delete mode 100644 ext/Setup.nt delete mode 100644 ext/Win32API/depend create mode 100644 ext/curses/depend create mode 100644 ext/kconv/kconv.c create mode 100644 ext/pty/depend create mode 100644 ext/readline/depend create mode 100644 ext/sdbm/depend create mode 100644 lib/net/ftp.rb create mode 100644 lib/net/http.rb create mode 100644 lib/net/protocol.rb create mode 100644 lib/net/telnet.rb delete mode 100644 missing/fnmatch.c delete mode 100644 missing/fnmatch.h delete mode 100644 sample/io.rb delete mode 100644 sample/rbc.rb diff --git a/ChangeLog b/ChangeLog index 900a94ea97..ddeda47f31 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,433 @@ +Mon Mar 13 18:14:52 2000 Yukihiro Matsumoto + + * stable version 1.4.4 released. + +Mon Mar 13 16:12:13 2000 Yukihiro Matsumoto + + * eval.c (block_pass): distinguish real orphan block and still + on-stack block passed by block argument. + +Mon Mar 13 00:20:25 2000 Yukihiro Matsumoto + + * parse.y (f_norm_arg): proper error message when constant comes + in formal argument list. this message is suggested by Muvaw + Pnazte . + + * eval.c (rb_f_raise): proper error message when the first + argument is not an exception class/object. + +Sat Mar 11 22:03:03 2000 Yukihiro Matsumoto + + * eval.c (rb_f_missing): check if argv[0] is ID. + +Sat Mar 11 05:07:11 2000 Yukihiro Matsumoto + + * process.c (proc_setpriority): should return 0, not nil. + + * process.c (proc_setpgid): ditto. + +Thu Mar 9 11:13:32 2000 Yukihiro Matsumoto + + * regex.c (re_compile_fastmap): fixed embarrassing brace bug. + +Thu Mar 9 01:36:32 2000 WATANABE Hirofumi + + * missing/flock.c: emulate missing flock() with fcntl(). + +Wed Mar 8 02:08:43 2000 Yukihiro Matsumoto + + * parse.y: escape expansion too early. + + * regex.c (re_compile_pattern): support \cX et al. + +Mon Mar 6 12:28:37 2000 Yukihiro Matsumoto + + * ext/socket/socket.c (ip_addrsetup): should check length of hostname. + + * ext/socket/socket.c (ip_addrsetup): check newline at the end of + hostname. These fixes suggested by Muvaw Pnazte . + +Sun Mar 5 20:35:45 2000 WATANABE Hirofumi + + * ext/Win32API/Win32API.c (Win32API_initialize): should call + LoadLibrary() everytime and should assign the hdll to Win32API + object(protect the hdll from GC). + +Sat Feb 26 22:39:31 2000 EGUCHI Osamu + + * Fix String#* with huge string. + +Fri Feb 25 06:42:26 2000 GOTOU YUUZOU + + * ext/socket/socket.c (ip_addrsetup): hostp should remain NULL if + host is nil. + +Thu Feb 24 16:53:47 2000 Yukihiro Matsumoto + + * eval.c (rb_thread_schedule): priority was too high for sleep + expired threads. + +Sat Feb 19 23:58:51 2000 Yukihiro Matsumoto + + * regex.c (re_match): pop_loop should not pop at forward jump. + +Thu Feb 17 19:09:05 2000 Katsuyuki Komatsu + + * win32/win32.c (mypopen): don't close handle if it is not assigned. + * win32/win32.c (my_open_osfhandle): support O_NOINHERIT flag. + * win32/win32.c (win32_getcwd): rename getcwd to win32_getcwd + in order to avoid using the C/C++ runtime DLL's getcwd. + Use CharNext() to process directory name. + * win32/win32.h: map getcwd to win32_getcwd. + +Wed Feb 16 00:32:49 2000 Yukihiro Matsumoto + + * eval.c (method_arity): nd_rest is -1 for no rest argument. + + * process.c (rb_f_waitpid): returns nil when waitpid(2) returns 0. + +Tue Feb 15 01:47:00 2000 Yukihiro Matsumoto + + * process.c (rb_f_waitpid): pid_t should be signed. + +Mon Feb 14 13:59:01 2000 Yukihiro Matsumoto + + * ruby.c (load_file): exit if reading file is empty. + +Mon Feb 14 03:34:52 2000 Yukihiro Matsumoto + + * parse.y (yylex): `foo.bar=' should be <.><=>. + + * eval.c (rb_thread_restore_context): process according to + RESTORE_* is moved after longjmp(). + + * eval.c (thread_switch): new function to process RESTORE_*. + +Thu Feb 10 02:12:04 2000 Yukihiro Matsumoto + + * string.c (rb_str_index_m): did not support negative offset. + +Wed Feb 9 21:54:26 2000 Katsuyuki Komatsu + + * ext/socket/getaddrinfo.c: gcc --traditional support. + Rearrange headers to work AC_C_CONST. + * ext/socket/getnameinfo.c: ditto. + * ext/socket/socket.c: mswin32: use double instead of long long. + +Wed Feb 9 16:30:41 2000 Yukihiro Matsumoto + + * numeric.c (num_coerce): should return [y, x]. + +Fri Feb 4 10:20:25 2000 Yukihiro Matsumoto + + * io.c (rb_io_close): should not check closed IO. + +Fri Feb 4 05:44:01 2000 Kentaro Inagaki + + * ext/socket/socket.c (s_recv): TRAP_BEG after retry entry. + +Thu Jan 27 01:27:10 2000 GOTO Kentaro + + * dir.c (glob): glob pattern "/*" did not match. + +Wed Jan 26 22:30:47 2000 Shigeo Kobayashi + + * numeric.c (flo_modulo): wrong result for negative modulo. + +Wed Jan 26 11:43:41 2000 Yukihiro Matsumoto + + * file.c (test_c): should use S_ISCHR. + +Sun Jan 16 20:12:13 2000 Koji Arai + + * eval.c (dvar_asgn): may need to push dvar. + +Sat Jan 15 22:21:08 2000 Nobuyoshi Nakada + + * eval.c (search_method): argument klass may be 0. + +Fri Jan 14 12:22:04 2000 Yukihiro Matsumoto + + * string.c (rb_str_replace): use memmove instead of memcpy for + overwrapping strings (e.g. a[1] = a). + +Fri Jan 7 00:59:29 2000 Masahiro Tomita + + * io.c (io_fread): TRAP_BEG/TRAP_END added around getc(). + +Wed Jan 5 02:14:46 2000 EGUCHI Osamu + + * parse.y: Fix SEGV on empty parens with UMINUS or UPLUS. + +Tue Jan 4 22:25:54 2000 Yukihiro Matsumoto + + * parse.y (stmt): `() while cond' dumped core. + +Mon Dec 27 12:35:47 1999 Katsuyuki Komatsu + + * ext/socket/socket.c (sock_finalize): mswin32: fix socket handle leak. + + * win32/win32.c (myfdclose): ditto. + +Sun Dec 26 23:15:13 1999 Katsuyuki Komatsu + + * win32/win32.c (mypopen): raise catchable error instead of rb_fatal. + * win32/win32.c (mypclose): fix process handle laek. + +Sun Dec 26 16:17:11 1999 Katsuyuki Komatsu + + * ext/Win32API/Win32API.c (Win32API_initialize): use UINT2NUM + instead of INT2NUM to set __dll__ and __proc__. + +Sat Dec 25 00:08:59 1999 KANEKO Naoshi + + * ext/Win32API/Win32API.c (Win32API_Call): remove 'dword ptr' + from _asm. + +Fri Dec 24 10:26:47 1999 Koji Oda + + * win32/win32.h: use "C++" linkage. + +Fri Dec 24 02:00:57 1999 Yukihiro Matsumoto + + * eval.c (THREAD_ALLOC): should initialize th->trace. + +Fri Dec 24 00:43:39 1999 KANEKO Naoshi + + * io.c (pipe_open): check for `fptr->f == NULL'. + * win32/win32.c (mypopen): STDERR does not work during ` function. + +Tue Dec 21 17:21:28 1999 Koji Oda + + * ext/socket/socket.c (sock_finalize): mswin32: fix FILE* leak. + +Mon Dec 20 19:08:12 1999 Nobuyoshi Nakada + + * file.c (rb_file_s_expand_path): handle dir separetor correctly. + +Sun Dec 19 22:56:31 1999 KANEKO Naoshi + + * lib/find.rb: support dosish root directory. + * win32/Makefile: ditto. + * win32/config.status: ditto. + * win32/win32.c (opendir): ditto. + * win32/win32.c (opendir): use CharPrev() to get last character + of the directory name. + +Fri Dec 17 19:27:43 1999 IWAMURO Motonori + + * eval.c (rb_load): should initialize ruby_frame->last_class. + +Wed Dec 15 01:35:29 1999 Yukihiro Matsumoto + + * ruby.c (proc_options): argv boundary check for `-X'. + +Sat Dec 11 03:34:38 1999 Yukihiro Matsumoto + + * gc.c (mark_hashentry): key should be VALUE, not ID. + + * io.c (argf_eof): should check next_p too. + +Thu Dec 9 18:09:13 1999 EGUCHI Osamu + + * error.c (exc_set_backtrace): forgot to declare a VALUE argument. + +Tue Dec 7 18:25:26 1999 Yukihiro Matsumoto + + * stable version 1.4.3 released. + +Mon Dec 6 15:55:30 1999 EGUCHI Osamu + + * numeric.c (fix_rshift): Fix -1 >> 32 returned 0 (should be -1). + + * numeric.c (fix_rshift): Fix 1 >> -1 returned 0 (should be 2). + +Mon Dec 6 11:47:23 1999 Yukihiro Matsumoto + + * sprintf.c (rb_f_sprintf): formatted string must be tainted if + any of parameters is tainted. + + * file.c (rb_file_s_expand_path): expanded file path need not to + be tainted always. + +Sat Dec 4 01:40:22 1999 Yukihiro Matsumoto + + * bignum.c (rb_big_rand): should not use rand/random where drand48 + may be available. RANDOM_NUMBER should be provided from outside. + +Fri Dec 3 09:54:59 1999 Yukihiro Matsumoto + + * eval.c (rb_f_require): should check require 'feature.o' too. + +Thu Dec 2 11:58:15 1999 Koji Arai + + * eval.c (rb_thread_loading): should maintain loading_tbl. + +Thu Dec 2 10:21:43 1999 Yukihiro Matsumoto + + * eval.c (rb_thread_loading_done): wrong parameter to st_delete(). + +Wed Dec 1 09:47:33 1999 Kazunori NISHI + + * string.c (rb_str_split_method): should increment end too. + +Tue Nov 30 01:46:18 1999 Yukihiro Matsumoto + + * re.c (rb_reg_source): generated source string must be tainted if + regex is tainted. + + * file.c (rb_file_s_basename): basename should not be tainted + unless the original path is tainted. + + * file.c (rb_file_s_dirname): ditto. + +Mon Nov 29 15:28:52 1999 Yukihiro Matsumoto + + * variable.c (rb_path2class): evaluated value from path should be + module or class. + +Fri Nov 26 18:12:49 1999 Yukihiro Matsumoto + + * eval.c (rb_exec_end_proc): should remove only end_procs defined + within load wrapper. + + * eval.c (rb_load): save and restore ruby_wrapper around loading. + + * eval.c (rb_mark_end_proc): mark end procs registered by END{} or + at_exit{}. + + * eval.c (rb_set_end_proc): should not call rb_global_variable() + on heap address; it crashed mod_ruby. + +Fri Nov 26 18:12:49 1999 Yukihiro Matsumoto + + * enum.c (enum_grep): does not return nil. + + * eval.c (rb_mark_end_proc): mark end procs registered by END{} or + at_exit{}. + + * eval.c (rb_set_end_proc): should not call rb_global_variable() + on heap address; it crashed mod_ruby. + +Thu Nov 18 16:18:27 1999 Yukihiro Matsumoto + + * lib/pstore.rb: mutual lock by flock(2). + +Thu Nov 18 11:44:13 1999 Masahiro Tomita + + * io.c (read_all): should check bytes too. + +Mon Nov 15 16:50:34 1999 Yukihiro Matsumoto + + * enum.c (enum_grep): grep with block returns collection of + evaluated values of block over matched elements. + +Mon Nov 15 04:50:33 1999 Koji Arai + + * re.c (rb_reg_source): should not call rb_reg_expr_str() + everytime. + +Fri Nov 12 23:52:19 1999 Katsuyuki Komatsu + + * process.c (rb_f_system): argument check for NT, __EMX__, DJGPP. + +Wed Nov 10 21:54:11 1999 EGUCHI Osamu + + * hash.c (rb_any_cmp): Fixed return without value. + +Tue Nov 9 13:21:04 1999 EGUCHI Osamu + + * configure.in: AC_MINIX move to before AC_EXEEXT and AC_OBJEXT. + +Mon Nov 8 19:52:29 1999 EGUCHI Osamu + + * configure.in: Renamed AC_CHAR_UNSIGNED to AC_C_CHAR_UNSIGNED. + + * configure.in: Added default to AC_CHECK_SIZEOF(). + +Mon Nov 8 14:28:18 1999 Yukihiro Matsumoto + + * eval.c (rb_f_eval): fake outer scope when eval() called without + bindings. + + * eval.c (rb_f_binding): should copy last_class in the outer frame too. + +Sun Nov 7 18:31:04 1999 Yasuhiro Fukuma + + * eval.c (is_defined): last_class may be 0. + +Sat Nov 6 19:26:55 1999 EGUCHI Osamu + + * Makefile.in: Added depend entry make parse.@OBJEXT@ from parse.c + for UCB make + +Wed Nov 3 08:52:57 1999 Masaki Fukushima + + * io.c (Init_IO): forgot to use INT2FIX() around SEEK_SET, etc. + +Wed Nov 3 00:25:20 1999 Yukihiro Matsumoto + + * string.c (rb_str_split_method): use mbclen2() to handle kcode + option of regexp objects. + +Sun Oct 31 13:12:42 1999 WATANABE Hirofumi + + * regex.c (re_compile_pattern): wrong [\W] match. + +Thu Oct 28 13:35:40 1999 Yukihiro Matsumoto + + * string.c (rb_str_split_method): should be mbchar aware with + single char separators. + +Wed Oct 27 12:57:21 1999 Yukihiro Matsumoto + + * random.c (rb_f_srand): random seed should be unsigned. + +Tue Oct 26 19:20:54 1999 Koji Arai + + * marshal.c (r_object): should register class/module objects. + +Sat Oct 23 15:59:39 1999 Takaaki Tateishi + + * process.c (rb_f_system): should require at least one argument. + +Thu Oct 21 16:14:19 1999 Yukihiro Matsumoto + + * dir.c (fnmatch): use eban's fnmatch; do not depend on systems's + fnmatch (which may have portability problem) anymore. + +Wed Oct 20 15:14:24 1999 Yukihiro Matsumoto + + * marshal.c (marshal_load): should protect the generated object + table (arg->data) from GC. + +Mon Oct 18 16:15:52 1999 Yukihiro Matsumoto + + * ext/nkf/nkf.c (rb_nkf_kconv): output should be NUL terminated. + +Fri Oct 15 22:50:41 1999 WATANABE Hirofumi + + * error.c (sys_nerr): on CYGWIN, it is _sys_nerr. + +Fri Oct 15 01:32:31 1999 WATANABE Hirofumi + + * ext/Win32API/Win32API.c (Win32API_Call): need to use NUM2ULONG, + not NUM2INT. + +Tue Oct 12 22:29:04 1999 Yukihiro Matsumoto + + * eval.c (block_pass): should copy block to prevent modifications. + tag in the structure should be updated from latest prot_tag. + + * eval.c (proc_s_new): tag in struct BLOCK should not point into + unused stack. + + * io.c (io_read): length may be 0 or negative. + +Tue Oct 12 13:26:27 1999 Jun-ichiro itojun Hagino + + * signal.c (posix_signal): RETSIGTYPE may be void. + Mon Oct 11 17:42:25 1999 Nobuyoshi Nakada * parse.y (rb_intern): should generate distinct ID_ATTRSET symbols @@ -16,6 +446,10 @@ Mon Oct 4 12:42:32 1999 Kazuhiko Izawa * pack.c (pack_unpack): % in printf format should be %%. +Wed Oct 6 17:13:19 1999 Nobuyoshi Nakada + + * ruby.c (addpath): rubylib_mangled_path() modified. + Mon Oct 4 10:01:40 1999 Yukihiro Matsumoto * variable.c (rb_obj_instance_variables): should always return diff --git a/MANIFEST b/MANIFEST index 335b570bed..e6fae1531f 100644 --- a/MANIFEST +++ b/MANIFEST @@ -75,7 +75,7 @@ util.c variable.c version.c version.h -beos/ruby.def.in +beos/GNUmakefile.in cygwin/GNUmakefile.in ext/Setup ext/Setup.dj @@ -89,6 +89,7 @@ lib/Env.rb lib/README lib/base64.rb lib/cgi.rb +lib/cgi/session.rb lib/cgi-lib.rb lib/complex.rb lib/date.rb @@ -125,6 +126,8 @@ lib/matrix.rb lib/mkmf.rb lib/monitor.rb lib/mutex_m.rb +lib/net/ftp.rb +lib/net/http.rb lib/net/pop.rb lib/net/session.rb lib/net/smtp.rb @@ -160,8 +163,6 @@ 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 @@ -222,7 +223,6 @@ sample/rename.rb sample/rcs.awk sample/rcs.dat sample/rcs.rb -sample/rd2html.rb sample/regx.rb sample/sieve.rb sample/svr.rb @@ -236,8 +236,6 @@ win32/config.h win32/config.status win32/ntsetup.bat win32/ruby.def -win32/sdbm.c -win32/sdbm.h win32/win32.c win32/win32.h x68/fconvert.c diff --git a/Makefile.in b/Makefile.in index e846d8d72f..5b66caa96b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -141,6 +141,8 @@ parse.c: parse.y $(YACC) $< mv -f y.tab.c parse.c +parse.@OBJEXT@: parse.c + alloca.@OBJEXT@: @srcdir@/missing/alloca.c $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c @srcdir@/missing/alloca.c diff --git a/README b/README index 2953cc98da..5ed6015be0 100644 --- a/README +++ b/README @@ -135,7 +135,7 @@ You can redistribute it and/or modify it under either the terms of the GPL The URL of the Ruby home-page is: - http://www.netlab.co.jp/ruby/ + http://www.ruby-lang.org/ * The Author diff --git a/README.jp b/README.jp index 19e5e0c896..515f658609 100644 --- a/README.jp +++ b/README.jp @@ -10,7 +10,7 @@ Ruby によって,より分かりやすいプログラミングが出来ます. -* Rubyの特長. +* Rubyの特長 + シンプルな文法 + 普通のオブジェクト指向機能(クラス,メソッドコールなど) @@ -44,7 +44,7 @@ Ruby RubyのホームページのURLは - http://www.netlab.co.jp/ruby/jp/ + http://www.ruby-lang.org/ です. diff --git a/array.c b/array.c index 9cc0ac1815..633e261dcc 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-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -280,6 +280,7 @@ VALUE rb_ary_pop(ary) VALUE ary; { + rb_ary_modify(ary); if (RARRAY(ary)->len == 0) return Qnil; if (RARRAY(ary)->len * 10 < RARRAY(ary)->capa && RARRAY(ary)->capa > ARY_DEFAULT_SIZE) { RARRAY(ary)->capa = RARRAY(ary)->len * 2; @@ -294,6 +295,7 @@ rb_ary_shift(ary) { VALUE top; + rb_ary_modify(ary); if (RARRAY(ary)->len == 0) return Qnil; top = RARRAY(ary)->ptr[0]; @@ -821,6 +823,7 @@ rb_ary_reverse(ary) VALUE *p1, *p2; VALUE tmp; + rb_ary_modify(ary); if (RARRAY(ary)->len == 0) return ary; p1 = RARRAY(ary)->ptr; @@ -940,22 +943,19 @@ rb_ary_delete_at(ary, at) VALUE ary; VALUE at; { - long i1, i2, pos; + long i, pos = NUM2LONG(at), len = RARRAY(ary)->len; VALUE del = Qnil; rb_ary_modify(ary); - pos = NUM2LONG(at); - for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) { - if (i1 == pos) { - del = RARRAY(ary)->ptr[i1]; - continue; - } - if (i1 != i2) { - RARRAY(ary)->ptr[i2] = RARRAY(ary)->ptr[i1]; - } - i2++; + if (pos >= len) return Qnil; + if (pos < 0) pos += len; + if (pos < 0) return Qnil; + + del = RARRAY(ary)->ptr[pos]; + for (i = pos + 1; i < len; i++, pos++) { + RARRAY(ary)->ptr[pos] = RARRAY(ary)->ptr[i]; } - RARRAY(ary)->len = i2; + RARRAY(ary)->len = pos; return del; } @@ -1005,6 +1005,7 @@ static VALUE rb_ary_clear(ary) VALUE ary; { + rb_ary_modify(ary); RARRAY(ary)->len = 0; if (ARY_DEFAULT_SIZE*3 < RARRAY(ary)->capa) { RARRAY(ary)->capa = ARY_DEFAULT_SIZE * 2; diff --git a/bignum.c b/bignum.c index 36a46af3fd..e411e93f1b 100644 --- a/bignum.c +++ b/bignum.c @@ -16,11 +16,11 @@ VALUE rb_cBignum; typedef unsigned short USHORT; #define BDIGITS(x) RBIGNUM(x)->digits -#define BITSPERDIG (sizeof(short)*CHAR_BIT) +#define BITSPERDIG (sizeof(USHORT)*CHAR_BIT) #define BIGRAD (1L << BITSPERDIG) -#define DIGSPERINT ((unsigned int)(sizeof(long)/sizeof(short))) +#define DIGSPERLONG ((unsigned int)(sizeof(long)/sizeof(USHORT))) #define BIGUP(x) ((unsigned long)(x) << BITSPERDIG) -#define BIGDN(x) (((x)<0) ? ~((~(x))>>BITSPERDIG) : (x)>>BITSPERDIG) +#define BIGDN(x) RSHIFT(x,BITSPERDIG) #define BIGLO(x) ((USHORT)((x) & (BIGRAD-1))) static VALUE @@ -33,7 +33,7 @@ bignew_1(klass, len, sign) OBJSETUP(big, klass, T_BIGNUM); big->sign = sign; big->len = len; - BDIGITS(big) = ALLOC_N(USHORT, len); + big->digits = ALLOC_N(USHORT, len); return (VALUE)big; } @@ -116,14 +116,14 @@ rb_uint2big(n) VALUE big; i = 0; - big = bignew(DIGSPERINT, 1); + big = bignew(DIGSPERLONG, 1); digits = BDIGITS(big); - while (i < DIGSPERINT) { + while (i < DIGSPERLONG) { digits[i++] = BIGLO(n); n = BIGDN(n); } - i = DIGSPERINT; + i = DIGSPERLONG; while (i-- && !digits[i]) ; RBIGNUM(big)->len = i+1; return big; @@ -1255,20 +1255,17 @@ rb_big_abs(x) */ VALUE -rb_big_rand(max) +rb_big_rand(max, rand) VALUE max; + double rand; { - struct RBignum *v; + VALUE v; long len; len = RBIGNUM(max)->len; - v = RBIGNUM(bignew(len,1)); + v = bignew(len,1); while (len--) { -#ifdef HAVE_RANDOM - BDIGITS(v)[len] = random(); -#else - BDIGITS(v)[len] = rand(); -#endif + BDIGITS(v)[len] = ((USHORT)~0) * rand; } return rb_big_mod((VALUE)v, max); diff --git a/class.c b/class.c index 32dc0e1372..a8a20b14fa 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-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ diff --git a/compar.c b/compar.c index 677b6a3cbd..6046a70ce3 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-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ diff --git a/config.guess b/config.guess index 7e23afe37b..53ebbce1a9 100644 --- a/config.guess +++ b/config.guess @@ -1,6 +1,7 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999 +# Free Software Foundation, Inc. # # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -23,6 +24,7 @@ # Written by Per Bothner . # The master version of this file is at the FSF in /home/gd/gnu/lib. +# Please send patches to the Autoconf mailing list . # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and @@ -35,6 +37,19 @@ # (but try to keep the structure clean). # +# Use $HOST_CC if defined. $CC may point to a cross-compiler +if test x"$CC_FOR_BUILD" = x; then + if test x"$HOST_CC" != x; then + CC_FOR_BUILD="$HOST_CC" + else + if test x"$CC" != x; then + CC_FOR_BUILD="$CC" + else + CC_FOR_BUILD=cc + fi + fi +fi + # Modified for Human68k by K.Okabe 1997.07.09 # Last change: 1997.07.09 @@ -57,7 +72,8 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown -trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15 +dummy=dummy-$$ +trap 'rm -f $dummy.c $dummy.o $dummy; exit 1' 1 2 15 # Note: order is significant - the case branches are not exclusive. @@ -73,7 +89,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - cat <dummy.s + cat <$dummy.s .globl main .ent main main: @@ -90,9 +106,9 @@ main: ret \$31,(\$26),1 .end main EOF - ${CC-cc} dummy.s -o dummy 2>/dev/null + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null if test "$?" = 0 ; then - ./dummy + ./$dummy case "$?" in 7) UNAME_MACHINE="alpha" @@ -111,8 +127,14 @@ EOF ;; esac fi - rm -f dummy.s dummy - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]` + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix exit 0 ;; 21064:Windows_NT:50:3) echo alpha-dec-winnt3.5 @@ -156,7 +178,7 @@ EOF SR2?01:HI-UX/MPP:*:*) echo hppa1.1-hitachi-hiuxmpp exit 0;; - Pyramid*:OSx*:*:*|MIS*:OSx*:*:*|MIS*:SMP_DC-OSx*:*:*) + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. if test "`(/bin/universe) 2>/dev/null`" = att ; then echo pyramid-pyramid-sysv3 @@ -164,7 +186,7 @@ EOF echo pyramid-pyramid-bsd fi exit 0 ;; - NILE:*:*:dcosx) + NILE*:*:*:dcosx) echo pyramid-pyramid-svr4 exit 0 ;; sun4H:SunOS:5.*:*) @@ -215,6 +237,32 @@ EOF atari*:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; sun3*:NetBSD:*:*) echo m68k-sun-netbsd${UNAME_RELEASE} exit 0 ;; @@ -248,12 +296,16 @@ EOF VAX*:ULTRIX*:*:*) echo vax-dec-ultrix${UNAME_RELEASE} exit 0 ;; - 2020:CLIX:*:*) + 2020:CLIX:*:* | 2430:CLIX:*:*) echo clipper-intergraph-clix${UNAME_RELEASE} exit 0 ;; mips:*:*:UMIPS | mips:*:*:RISCos) - sed 's/^ //' << EOF >dummy.c - int main (argc, argv) int argc; char **argv; { + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); @@ -268,10 +320,10 @@ EOF exit (-1); } EOF - ${CC-cc} dummy.c -o dummy \ - && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ - && rm dummy.c dummy && exit 0 - rm -f dummy.c dummy + $CC_FOR_BUILD $dummy.c -o $dummy \ + && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy echo mips-mips-riscos${UNAME_RELEASE} exit 0 ;; Night_Hawk:Power_UNIX:*:*) @@ -323,7 +375,7 @@ EOF exit 0 ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - sed 's/^ //' << EOF >dummy.c + sed 's/^ //' << EOF >$dummy.c #include main() @@ -334,8 +386,8 @@ EOF exit(0); } EOF - ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 - rm -f dummy.c dummy + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy echo rs6000-ibm-aix3.2.5 elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then echo rs6000-ibm-aix3.2.4 @@ -382,25 +434,25 @@ EOF case "${UNAME_MACHINE}" in 9000/31? ) HP_ARCH=m68000 ;; 9000/[34]?? ) HP_ARCH=m68k ;; - 9000/[678]?? ) - sed 's/^ //' << EOF >dummy.c + 9000/[678][0-9][0-9]) + sed 's/^ //' << EOF >$dummy.c #include #include - + int main () { #if defined(_SC_KERNEL_BITS) long bits = sysconf(_SC_KERNEL_BITS); - #endif + #endif long cpu = sysconf (_SC_CPU_VERSION); - - switch (cpu) + + switch (cpu) { case CPU_PA_RISC1_0: puts ("hppa1.0"); break; case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: + case CPU_PA_RISC2_0: #if defined(_SC_KERNEL_BITS) - switch (bits) + switch (bits) { case 64: puts ("hppa2.0w"); break; case 32: puts ("hppa2.0n"); break; @@ -408,20 +460,20 @@ EOF } break; #else /* !defined(_SC_KERNEL_BITS) */ puts ("hppa2.0"); break; - #endif + #endif default: puts ("hppa1.0"); break; } exit (0); } EOF - (${CC-cc} dummy.c -o dummy 2>/dev/null ) && HP_ARCH=`./dummy` - rm -f dummy.c dummy + ($CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null ) && HP_ARCH=`./$dummy` + rm -f $dummy.c $dummy esac HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` echo ${HP_ARCH}-hp-hpux${HPUX_REV} exit 0 ;; 3050*:HI-UX:*:*) - sed 's/^ //' << EOF >dummy.c + sed 's/^ //' << EOF >$dummy.c #include int main () @@ -446,8 +498,8 @@ EOF exit (0); } EOF - ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 - rm -f dummy.c dummy + $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy echo unknown-hitachi-hiuxwe2 exit 0 ;; 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) @@ -456,6 +508,9 @@ EOF 9000/8??:4.3bsd:*:*) echo hppa1.0-hp-bsd exit 0 ;; + *9??*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) echo hppa1.1-hp-osf exit 0 ;; @@ -472,6 +527,9 @@ EOF parisc*:Lites*:*:*) echo hppa1.1-hp-lites exit 0 ;; + hppa*:OpenBSD:*:*) + echo hppa-unknown-openbsd + exit 0 ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd exit 0 ;; @@ -504,11 +562,14 @@ EOF CRAY*TS:*:*:*) echo t90-cray-unicos${UNAME_RELEASE} exit 0 ;; + CRAY*T3E:*:*:*) + echo t3e-cray-unicosmk${UNAME_RELEASE} + exit 0 ;; CRAY-2:*:*:*) echo cray2-cray-unicos exit 0 ;; F300:UNIX_System_V:*:*) - FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit 0 ;; @@ -521,16 +582,22 @@ EOF hp300:OpenBSD:*:*) echo m68k-unknown-openbsd${UNAME_RELEASE} exit 0 ;; - sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} - exit 0 ;; i?86:BSD/386:*:* | i?86:BSD/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; *:BSD/OS:*:*) echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit 0 ;; *:FreeBSD:*:*) + if test -x /usr/bin/objformat; then + if test "elf" = "`/usr/bin/objformat`"; then + echo ${UNAME_MACHINE}-unknown-freebsdelf`echo ${UNAME_RELEASE}|sed -e 's/[-_].*//'` + exit 0 + fi + fi echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit 0 ;; *:NetBSD:*:*) @@ -548,6 +615,15 @@ EOF i*:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; p*:CYGWIN*:*) echo powerpcle-unknown-cygwin exit 0 ;; @@ -561,12 +637,14 @@ EOF # uname on the ARM produces all sorts of strangeness, and we need to # filter it out. case "$UNAME_MACHINE" in + armv*) UNAME_MACHINE=$UNAME_MACHINE ;; arm* | sa110*) UNAME_MACHINE="arm" ;; esac # The BFD linker knows what the default object file format is, so - # first see if it will tell us. - ld_help_string=`ld --help 2>&1` + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + ld_help_string=`cd /; ld --help 2>&1` ld_supported_emulations=`echo $ld_help_string \ | sed -ne '/supported emulations:/!d s/[ ][ ]*/ /g @@ -577,12 +655,42 @@ EOF i?86linux) echo "${UNAME_MACHINE}-pc-linux-aout" ; exit 0 ;; i?86coff) echo "${UNAME_MACHINE}-pc-linux-coff" ; exit 0 ;; sparclinux) echo "${UNAME_MACHINE}-unknown-linux-aout" ; exit 0 ;; + armlinux) echo "${UNAME_MACHINE}-unknown-linux-aout" ; exit 0 ;; m68klinux) echo "${UNAME_MACHINE}-unknown-linux-aout" ; exit 0 ;; - elf32ppc) echo "powerpc-unknown-linux" ; exit 0 ;; + elf32ppc) + # Determine Lib Version + cat >$dummy.c < +#if defined(__GLIBC__) +extern char __libc_version[]; +extern char __libc_release[]; +#endif +main(argc, argv) + int argc; + char *argv[]; +{ +#if defined(__GLIBC__) + printf("%s %s\n", __libc_version, __libc_release); +#else + printf("unkown\n"); +#endif + return 0; +} +EOF + LIBC="" + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null + if test "$?" = 0 ; then + ./$dummy | grep 1\.99 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f $dummy.c $dummy + echo powerpc-unknown-linux-${LIBC} ; exit 0 ;; esac if test "${UNAME_MACHINE}" = "alpha" ; then - sed 's/^ //' <dummy.s + sed 's/^ //' <$dummy.s .globl main .ent main main: @@ -600,9 +708,9 @@ EOF .end main EOF LIBC="" - ${CC-cc} dummy.s -o dummy 2>/dev/null + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null if test "$?" = 0 ; then - ./dummy + ./$dummy case "$?" in 7) UNAME_MACHINE="alpha" @@ -621,20 +729,21 @@ EOF ;; esac - objdump --private-headers dummy | \ + objdump --private-headers $dummy | \ grep ld.so.1 > /dev/null if test "$?" = 0 ; then LIBC="-libc1" fi - fi - rm -f dummy.s dummy - echo ${UNAME_MACHINE}-unknown-linux${LIBC} ; exit 0 + fi + rm -f $dummy.s $dummy + echo ${UNAME_MACHINE}-unknown-linux{LIBC} ; exit 0 elif test "${UNAME_MACHINE}" = "mips" ; then - cat >dummy.c <$dummy.c </dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0 - rm -f dummy.c dummy + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy else + # Either a pre-BFD a.out linker (linux-oldld) + # or one that does not give us useful --help. + # GCC wants to distinguish between linux-oldld and linux-aout. + # If ld does not provide *any* "supported emulations:" + # that means it is oldld. + echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" + test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-oldld" && exit 0 + case "${UNAME_MACHINE}" in i?86) VENDOR=pc; @@ -655,8 +772,32 @@ EOF VENDOR=unknown; ;; esac - echo ${UNAME_MACHINE}-${VENDOR}-linux - exit 0 + # Determine whether the default compiler is a.out or elf + cat >$dummy.c < +#ifdef __cplusplus + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif +#ifdef __ELF__ +# ifdef __GLIBC__ +# if __GLIBC__ >= 2 + printf ("%s-${VENDOR}-linux\n", argv[1]); +# else + printf ("%s-${VENDOR}-linux-libc1\n", argv[1]); +# endif +# else + printf ("%s-${VENDOR}-linux-libc1\n", argv[1]); +# endif +#else + printf ("%s-${VENDOR}-linux-aout\n", argv[1]); +#endif + return 0; +} +EOF + $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy "${UNAME_MACHINE}" && rm $dummy.c $dummy && exit 0 + rm -f $dummy.c $dummy fi ;; # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions # are messed up and put the nodename in both sysname and nodename. @@ -678,6 +819,14 @@ EOF echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} fi exit 0 ;; + i?86:*:5:7*) + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent.*II' >/dev/null) && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) && UNAME_MACHINE=i585 + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}${UNAME_VERSION}-sysv${UNAME_RELEASE} + exit 0 ;; i?86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null) && UNAME_MACHINE=i486 (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ && UNAME_MACHINE=i586 + (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 echo ${UNAME_MACHINE}-pc-sco$UNAME_REL else echo ${UNAME_MACHINE}-pc-sysv32 @@ -740,7 +893,7 @@ EOF mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit 0 ;; - i?86:LynxOS:2.*:*) + i?86:LynxOS:2.*:* | i?86:LynxOS:3.[01]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit 0 ;; TSUNAMI:LynxOS:2.*:*) @@ -752,6 +905,9 @@ EOF SM[BE]S:UNIX_SV:*:*) echo mips-dde-sysv${UNAME_RELEASE} exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; RM*:SINIX-*:*:*) echo mips-sni-sysv4 exit 0 ;; @@ -782,7 +938,7 @@ EOF news*:NEWS-OS:*:6*) echo mips-sony-newsos6 exit 0 ;; - R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R4000:UNIX_SV:*:*) + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then echo mips-nec-sysv`echo ${UNAME_RELEASE} | sed -n 's/\([.0-9]*\).*/\1/p'` else @@ -801,27 +957,24 @@ EOF BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit 0 ;; - - *:Rhapsody:*:*) - arch=`/usr/bin/arch` - case "$arch" in - ppc) - echo powerpc-apple-rhapsody${UNAME_RELEASE} - ;; - i[3456]86) - echo i386-apple-rhapsody${UNAME_RELEASE} - ;; - *) - echo $arch-apple-rhapsody${UNAME_RELEASE} - ;; - esac + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} exit 0 ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 #echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 -cat >dummy.c <$dummy.c < # include @@ -863,7 +1016,6 @@ main () printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); else printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); #endif @@ -923,8 +1075,8 @@ main () } EOF -${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0 -rm -f dummy.c dummy +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm $dummy.c $dummy && exit 0 +rm -f $dummy.c $dummy # Apollos put the system type in the environment. diff --git a/config.sub b/config.sub index aa2241272b..3c591de61b 100644 --- a/config.sub +++ b/config.sub @@ -1,6 +1,6 @@ #! /bin/sh # Configuration validation subroutine script, version 1.1. -# Copyright (C) 1991, 92-97, 1998 Free Software Foundation, Inc. +# Copyright (C) 1991, 92-97, 1998, 1999 Free Software Foundation, Inc. # This file is (in principle) common to ALL GNU software. # The presence of a machine in this file suggests that SOME GNU software # can handle that machine. It does not imply ALL GNU software can. @@ -68,7 +68,7 @@ esac # Here we must recognize all the valid KERNEL-OS combinations. maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - linux-gnu*) + linux*) os=-$maybe_os basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` ;; @@ -98,11 +98,21 @@ case $os in os= basic_machine=$1 ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=vxworks + basic_machine=$1 + ;; -hiux*) os=-hiuxwe2 ;; -sco5) - os=sco3.2v5 + os=-sco3.2v5 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; -sco4) @@ -121,6 +131,9 @@ case $os in os=-sco3.2v2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; -isc) os=-isc2.2 basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` @@ -151,14 +164,21 @@ case $basic_machine in # Some are omitted here because they have special meanings below. tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ | arme[lb] | pyramid | mn10200 | mn10300 | tron | a29k \ - | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w \ - | alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \ - | i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \ - | mips64 | mipsel | mips64el | mips64orion | mips64orionel \ - | mipstx39 | mipstx39el \ - | sparc | sparclet | sparclite | sparc64 | v850) + | 580 | i960 | h8300 \ + | hppa | hppa1.0 | hppa1.1 | hppa2.0 | hppa2.0w | hppa2.0n \ + | alpha | alphaev[4-7] | alphaev56 | alphapca5[67] \ + | we32k | ns16k | clipper | i370 | sh | powerpc | powerpcle \ + | 1750a | dsp16xx | pdp11 | mips16 | mips64 | mipsel | mips64el \ + | mips64orion | mips64orionel | mipstx39 | mipstx39el \ + | mips64vr4300 | mips64vr4300el | mips64vr4100 | mips64vr4100el \ + | mips64vr5000 | miprs64vr5000el \ + | sparc | sparclet | sparclite | sparc64 | sparcv9 | v850 | c4x \ + | thumb | d10v) basic_machine=$basic_machine-unknown ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | z8k | v70 | h8500 | w65) + ;; + # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. @@ -177,24 +197,41 @@ case $basic_machine in vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \ | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ - | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \ - | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* \ - | alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \ - | ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | h8500-* | i960-* \ + | xmp-* | ymp-* \ + | hppa-* | hppa1.0-* | hppa1.1-* | hppa2.0-* | hppa2.0w-* | hppa2.0n-* \ + | alpha-* | alphaev[4-7]-* | alphaev56-* | alphapca5[67]-* \ + | we32k-* | cydra-* | ns16k-* | pn-* | np1-* | xps100-* \ + | clipper-* | orion-* \ | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ - | sparc64-* | mips64-* | mipsel-* \ - | mips64el-* | mips64orion-* | mips64orionel-* \ + | sparc64-* | sparcv9-* | sparc86x-* | mips16-* | mips64-* | mipsel-* \ + | mips64el-* | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* | mips64vr4300-* | mips64vr4300el-* \ | mipstx39-* | mipstx39el-* \ - | f301-*) + | f301-* | armv*-* | t3e-* \ + | m88110-* | m680[01234]0-* | m683?2-* | m68360-* | z8k-* | d10v-* \ + | thumb-* | v850-* | d30v-* | tic30-* | c30-* ) ;; # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) basic_machine=m68000-att ;; 3b*) basic_machine=we32k-att ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; alliant | fx80) basic_machine=fx80-alliant ;; @@ -224,6 +261,10 @@ case $basic_machine in basic_machine=m68k-apollo os=-sysv ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; aux) basic_machine=m68k-apple os=-aux @@ -300,6 +341,10 @@ case $basic_machine in encore | umax | mmax) basic_machine=ns32k-encore ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; fx2800) basic_machine=i860-alliant ;; @@ -318,6 +363,14 @@ case $basic_machine in basic_machine=h8300-hitachi os=-hms ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; harris) basic_machine=m88k-harris os=-sysv3 @@ -333,13 +386,30 @@ case $basic_machine in basic_machine=m68k-hp os=-hpux ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; hp9k2[0-9][0-9] | hp9k31[0-9]) basic_machine=m68000-hp ;; hp9k3[2-9][0-9]) basic_machine=m68k-hp ;; - hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7) + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) basic_machine=hppa1.1-hp ;; hp9k8[0-9][0-9] | hp8[0-9][0-9]) @@ -348,6 +418,14 @@ case $basic_machine in hppa-next) os=-nextstep3 ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; i370-ibm* | ibm*) basic_machine=i370-ibm os=-mvs @@ -369,6 +447,22 @@ case $basic_machine in basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + i386-go32 | go32) + basic_machine=i386-unknown + os=-go32 + ;; + i386-mingw32 | mingw32) + basic_machine=i386-unknown + os=-mingw32 + ;; iris | iris4d) basic_machine=mips-sgi case $os in @@ -397,6 +491,10 @@ case $basic_machine in miniframe) basic_machine=m68000-convergent ;; + *mint | *MiNT) + basic_machine=m68k-atari + os=-mint + ;; mipsel*-linux*) basic_machine=mipsel-unknown os=-linux @@ -411,10 +509,26 @@ case $basic_machine in mips3*) basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + msdos) + basic_machine=i386-unknown + os=-msdos + ;; ncr3000) basic_machine=i486-ncr os=-sysv4 ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-corel + os=-linux + ;; news | news700 | news800 | news900) basic_machine=m68k-sony os=-newsos @@ -427,6 +541,10 @@ case $basic_machine in basic_machine=mips-sony os=-newsos ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; next | m*-next ) basic_machine=m68k-next case $os in @@ -452,9 +570,25 @@ case $basic_machine in basic_machine=i960-intel os=-nindy ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; np1) basic_machine=np1-gould ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; pa-hitachi) basic_machine=hppa1.1-hitachi os=-hiuxwe2 @@ -472,19 +606,19 @@ case $basic_machine in pc532 | pc532-*) basic_machine=ns32k-pc532 ;; - pentium | p5 | k5 | nexen) + pentium | p5 | k5 | k6 | nexen) basic_machine=i586-pc ;; - pentiumpro | p6 | k6 | 6x86) + pentiumpro | p6 | 6x86) basic_machine=i686-pc ;; pentiumii | pentium2) basic_machine=i786-pc ;; - pentium-* | p5-* | k5-* | nexen-*) + pentium-* | p5-* | k5-* | k6-* | nexen-*) basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` ;; - pentiumpro-* | p6-* | k6-* | 6x86-*) + pentiumpro-* | p6-* | 6x86-*) basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-*) @@ -508,12 +642,20 @@ case $basic_machine in ps2) basic_machine=i386-ibm ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; rm[46]00) basic_machine=mips-siemens ;; rtpc | rtpc-*) basic_machine=romp-ibm ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; sequent) basic_machine=i386-sequent ;; @@ -521,6 +663,10 @@ case $basic_machine in basic_machine=sh-hitachi os=-hms ;; + sparclite-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; sps7) basic_machine=m68k-bull os=-sysv2 @@ -528,6 +674,13 @@ case $basic_machine in spur) basic_machine=spur-unknown ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; sun2) basic_machine=m68000-sun ;; @@ -572,6 +725,10 @@ case $basic_machine in basic_machine=i386-sequent os=-dynix ;; + t3e) + basic_machine=t3e-cray + os=-unicos + ;; tx39) basic_machine=mipstx39-unknown ;; @@ -589,6 +746,10 @@ case $basic_machine in basic_machine=a29k-nyu os=-sym1 ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; vaxv) basic_machine=vax-dec os=-sysv @@ -612,6 +773,14 @@ case $basic_machine in basic_machine=a29k-wrs os=-vxworks ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; xmp) basic_machine=xmp-cray os=-unicos @@ -619,6 +788,10 @@ case $basic_machine in xps | xps100) basic_machine=xps100-honeywell ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; none) basic_machine=none-none os=-none @@ -626,6 +799,15 @@ case $basic_machine in # Here we handle the default manufacturer of certain CPU types. It is in # some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; mips) if [ x$os = x-linux ]; then basic_machine=mips-unknown @@ -648,7 +830,7 @@ case $basic_machine in we32k) basic_machine=we32k-att ;; - sparc) + sparc | sparcv9) basic_machine=sparc-sun ;; cydra) @@ -660,6 +842,16 @@ case $basic_machine in orion105) basic_machine=clipper-highlevel ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + c4x*) + basic_machine=c4x-none + os=-coff + ;; *) echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 exit 1 @@ -674,10 +866,6 @@ case $basic_machine in *-commodore*) basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` ;; - human) - basic_machine=m68k-sharp - os=-human - ;; *) ;; esac @@ -703,9 +891,7 @@ case $os in os=-sysv4.2uw ;; -gnu/linux*) - os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` - ;; - -os2_emx) + os=`echo $os | sed -e 's|gnu/linux|linux|'` ;; # First accept the basic system types. # The portable systems comes first. @@ -719,13 +905,21 @@ case $os in | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ - | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux* | -uxpv* | -beos* | -rhapsody* ) + | -mingw32* | -linux* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -openstep* | -oskit*) # Remember, each alternative MUST END IN *, to match a version number. ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; -sunos5*) os=`echo $os | sed -e 's|sunos5|solaris2|'` ;; @@ -747,6 +941,9 @@ case $os in -acis*) os=-aos ;; + -386bsd) + os=-bsd + ;; -ctix* | -uts*) os=-sysv ;; @@ -778,9 +975,18 @@ case $os in # This must come after -sysvr4. -sysv*) ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; -xenix) os=-xenix ;; + -*mint | -*MiNT) + os=-mint + ;; -uxpds) os=-uxpds ;; @@ -814,6 +1020,9 @@ case $basic_machine in *-acorn) os=-riscix1.2 ;; + arm*-corel) + os=-linux + ;; arm*-semi) os=-aout ;; @@ -835,6 +1044,15 @@ case $basic_machine in # default. # os=-sunos4 ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; *-tti) # must be before sparc entry or we get the wrong os. os=-sysv3 ;; @@ -847,6 +1065,15 @@ case $basic_machine in *-ibm) os=-aix ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; *-hp) os=-hpux ;; @@ -910,6 +1137,18 @@ case $basic_machine in f301-fujitsu) os=-uxpv ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; *) os=-none ;; @@ -931,9 +1170,15 @@ case $basic_machine in -aix*) vendor=ibm ;; + -beos*) + vendor=be + ;; -hpux*) vendor=hp ;; + -mpeix*) + vendor=hp + ;; -hiux*) vendor=hitachi ;; @@ -961,6 +1206,15 @@ case $basic_machine in -aux*) vendor=apple ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -*MiNT) + vendor=atari + ;; esac basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` ;; diff --git a/config_s.dj b/config_s.dj index 7ba18e4376..6f77b7f738 100644 --- a/config_s.dj +++ b/config_s.dj @@ -32,7 +32,7 @@ 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%@LIBOBJS@% crypt.o flock.o snprintf.o%g s%@ALLOCA@%%g s%@DEFAULT_KCODE@%%g s%@EXEEXT@%.exe%g diff --git a/configure b/configure index 462280501c..580d62b241 100644 --- a/configure +++ b/configure @@ -1175,13 +1175,64 @@ else fi +# checks for UNIX variants that set C preprocessor variables +ac_safe=`echo "minix/config.h" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for minix/config.h""... $ac_c" 1>&6 +echo "configure:1182: 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:1192: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 + MINIX=yes +else + echo "$ac_t""no" 1>&6 +MINIX= +fi + +if test "$MINIX" = yes; then + cat >> confdefs.h <<\EOF +#define _POSIX_SOURCE 1 +EOF + + cat >> confdefs.h <<\EOF +#define _POSIX_1_SOURCE 2 +EOF + + cat >> confdefs.h <<\EOF +#define _MINIX 1 +EOF + +fi + + echo $ac_n "checking for Cygwin environment""... $ac_c" 1>&6 -echo "configure:1180: checking for Cygwin environment" >&5 +echo "configure:1231: 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 +if { (eval echo configure:1247: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_cygwin=yes else @@ -1209,19 +1260,19 @@ 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 +echo "configure:1264: 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 +if { (eval echo configure:1276: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_mingw32=yes else @@ -1240,7 +1291,7 @@ 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 +echo "configure:1295: checking for executable suffix" >&5 if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1250,7 +1301,7 @@ 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 + if { (eval echo configure:1305: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; }; then for file in conftest.*; do case $file in *.c | *.o | *.obj) ;; @@ -1271,13 +1322,13 @@ 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 +echo "configure:1326: 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 +if { (eval echo configure:1332: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then for ac_file in conftest.*; do case $ac_file in *.c) ;; @@ -1295,64 +1346,13 @@ 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: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: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* - eval "ac_cv_header_$ac_safe=yes" -else - echo "$ac_err" >&5 - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - eval "ac_cv_header_$ac_safe=no" -fi -rm -f conftest* -fi -if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then - echo "$ac_t""yes" 1>&6 - MINIX=yes -else - echo "$ac_t""no" 1>&6 -MINIX= -fi - -if test "$MINIX" = yes; then - cat >> confdefs.h <<\EOF -#define _POSIX_SOURCE 1 -EOF - - cat >> confdefs.h <<\EOF -#define _POSIX_1_SOURCE 2 -EOF - - cat >> confdefs.h <<\EOF -#define _MINIX 1 -EOF - -fi - - echo $ac_n "checking size of int""... $ac_c" 1>&6 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 if test "$cross_compiling" = yes; then - { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } + ac_cv_sizeof_int=4 else cat > conftest.$ac_ext <&6 else if test "$cross_compiling" = yes; then - { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } + ac_cv_sizeof_short=2 else cat > conftest.$ac_ext <&6 else if test "$cross_compiling" = yes; then - { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } + ac_cv_sizeof_long=4 else cat > conftest.$ac_ext <&6 else if test "$cross_compiling" = yes; then - { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } + ac_cv_sizeof_voidp=4 else cat > conftest.$ac_ext <&6 else if test "$cross_compiling" = yes; then - { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } + ac_cv_sizeof_float=4 else cat > conftest.$ac_ext <&6 else if test "$cross_compiling" = yes; then - { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } + ac_cv_sizeof_double=8 else cat > conftest.$ac_ext <&6 -echo "configure:1742: checking for crypt in -lcrypt" >&5 +echo "configure:1745: 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 @@ -1746,7 +1749,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:1764: \"$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 @@ -1785,7 +1788,7 @@ else fi echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 -echo "configure:1789: checking for dlopen in -ldl" >&5 +echo "configure:1792: 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 @@ -1793,7 +1796,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:1811: \"$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,7 +1835,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:1836: checking for shl_load in -ldld" >&5 +echo "configure:1839: 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 @@ -1840,7 +1843,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:1858: \"$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 @@ -1879,7 +1882,7 @@ else fi # Dynamic linking for HP-UX echo $ac_n "checking for setlocale in -lxpg4""... $ac_c" 1>&6 -echo "configure:1883: checking for setlocale in -lxpg4" >&5 +echo "configure:1886: 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 @@ -1887,7 +1890,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:1905: \"$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 @@ -1931,12 +1934,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:1935: checking for $ac_hdr that defines DIR" >&5 +echo "configure:1938: 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> @@ -1944,7 +1947,7 @@ int main() { DIR *dirp = 0; ; return 0; } EOF -if { (eval echo configure:1948: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1951: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* eval "ac_cv_header_dirent_$ac_safe=yes" else @@ -1969,7 +1972,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:1973: checking for opendir in -ldir" >&5 +echo "configure:1976: 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 @@ -1977,7 +1980,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:1995: \"$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 @@ -2010,7 +2013,7 @@ fi else echo $ac_n "checking for opendir in -lx""... $ac_c" 1>&6 -echo "configure:2014: checking for opendir in -lx" >&5 +echo "configure:2017: 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 @@ -2018,7 +2021,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:2036: \"$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 @@ -2052,12 +2055,12 @@ fi fi echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:2056: checking for ANSI C header files" >&5 +echo "configure:2059: 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 @@ -2065,7 +2068,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:2069: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2072: \"$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* @@ -2082,7 +2085,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 @@ -2100,7 +2103,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 @@ -2121,7 +2124,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -2132,7 +2135,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:2136: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2139: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -2156,12 +2159,12 @@ EOF fi 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 +echo "configure:2163: 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 @@ -2177,7 +2180,7 @@ 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 +if { (eval echo configure:2184: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_sys_wait_h=yes else @@ -2199,21 +2202,21 @@ 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 + syscall.h pwd.h a.out.h utime.h memory.h direct.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:2207: checking for $ac_hdr" >&5 +echo "configure:2210: 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:2217: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2220: \"$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* @@ -2241,12 +2244,12 @@ done echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 -echo "configure:2245: checking for uid_t in sys/types.h" >&5 +echo "configure:2248: 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 @@ -2275,12 +2278,12 @@ EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:2279: checking for size_t" >&5 +echo "configure:2282: 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 @@ -2308,12 +2311,12 @@ EOF fi echo $ac_n "checking for st_blksize in struct stat""... $ac_c" 1>&6 -echo "configure:2312: checking for st_blksize in struct stat" >&5 +echo "configure:2315: 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 @@ -2321,7 +2324,7 @@ int main() { struct stat s; s.st_blksize; ; return 0; } EOF -if { (eval echo configure:2325: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2328: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_st_blksize=yes else @@ -2343,12 +2346,12 @@ fi save_LIBOJBS="$LIBOBJS" echo $ac_n "checking for st_blocks in struct stat""... $ac_c" 1>&6 -echo "configure:2347: checking for st_blocks in struct stat" >&5 +echo "configure:2350: 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 @@ -2356,7 +2359,7 @@ int main() { struct stat s; s.st_blocks; ; return 0; } EOF -if { (eval echo configure:2360: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2363: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_st_blocks=yes else @@ -2380,12 +2383,12 @@ fi LIBOBJS="$save_LIBOBJS" echo $ac_n "checking for st_rdev in struct stat""... $ac_c" 1>&6 -echo "configure:2384: checking for st_rdev in struct stat" >&5 +echo "configure:2387: 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 @@ -2393,7 +2396,7 @@ int main() { struct stat s; s.st_rdev; ; return 0; } EOF -if { (eval echo configure:2397: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2400: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_st_rdev=yes else @@ -2415,7 +2418,7 @@ fi echo $ac_n "checking type of array argument to getgroups""... $ac_c" 1>&6 -echo "configure:2419: checking type of array argument to getgroups" >&5 +echo "configure:2422: 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 @@ -2423,7 +2426,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:2455: \"$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 @@ -2462,7 +2465,7 @@ fi if test $ac_cv_type_getgroups = cross; then cat > conftest.$ac_ext < EOF @@ -2486,12 +2489,12 @@ EOF echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 -echo "configure:2490: checking return type of signal handlers" >&5 +echo "configure:2493: 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 @@ -2508,7 +2511,7 @@ int main() { int i; ; return 0; } EOF -if { (eval echo configure:2512: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2515: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void else @@ -2529,19 +2532,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:2533: checking for working alloca.h" >&5 +echo "configure:2536: 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)); +void *p = alloca(2 * sizeof(int)); ; return 0; } EOF -if { (eval echo configure:2545: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:2548: \"$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 @@ -2562,12 +2565,12 @@ EOF fi echo $ac_n "checking for alloca""... $ac_c" 1>&6 -echo "configure:2566: checking for alloca" >&5 +echo "configure:2569: 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:2602: \"$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 @@ -2627,12 +2630,12 @@ EOF echo $ac_n "checking whether alloca needs Cray hooks""... $ac_c" 1>&6 -echo "configure:2631: checking whether alloca needs Cray hooks" >&5 +echo "configure:2634: 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:2661: checking for $ac_func" >&5 +echo "configure:2664: 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:2692: \"$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 @@ -2712,7 +2715,7 @@ done fi echo $ac_n "checking stack direction for C alloca""... $ac_c" 1>&6 -echo "configure:2716: checking stack direction for C alloca" >&5 +echo "configure:2719: 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 @@ -2720,7 +2723,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:2746: \"$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 @@ -2761,12 +2764,12 @@ EOF fi echo $ac_n "checking for pid_t""... $ac_c" 1>&6 -echo "configure:2765: checking for pid_t" >&5 +echo "configure:2768: 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 @@ -2795,17 +2798,17 @@ fi ac_safe=`echo "vfork.h" | sed 'y%./+-%__p_%'` echo $ac_n "checking for vfork.h""... $ac_c" 1>&6 -echo "configure:2799: checking for vfork.h" >&5 +echo "configure:2802: 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:2809: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:2812: \"$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* @@ -2830,18 +2833,18 @@ else fi echo $ac_n "checking for working vfork""... $ac_c" 1>&6 -echo "configure:2834: checking for working vfork" >&5 +echo "configure:2837: 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:2840: checking for vfork" >&5 +echo "configure:2843: 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:2871: \"$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 @@ -2886,7 +2889,7 @@ fi ac_cv_func_vfork_works=$ac_cv_func_vfork else cat > conftest.$ac_ext < @@ -2981,7 +2984,7 @@ main() { } } EOF -if { (eval echo configure:2985: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2988: \"$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 @@ -3004,7 +3007,7 @@ EOF fi echo $ac_n "checking for 8-bit clean memcmp""... $ac_c" 1>&6 -echo "configure:3008: checking for 8-bit clean memcmp" >&5 +echo "configure:3011: 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 @@ -3012,7 +3015,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:3029: \"$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 @@ -3041,15 +3044,15 @@ test $ac_cv_func_memcmp_clean = no && LIBOBJS="$LIBOBJS memcmp.${ac_objext}" for ac_func in dup2 memmove mkdir strcasecmp strncasecmp strerror strftime\ strchr strstr strtoul strdup crypt flock vsnprintf\ - fnmatch isinf isnan finite + isinf isnan finite do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3048: checking for $ac_func" >&5 +echo "configure:3051: 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:3079: \"$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 @@ -3105,12 +3108,12 @@ for ac_func in fmod killpg drand48 random wait4 waitpid syscall getcwd\ dlopen sigprocmask sigaction _setjmp setsid do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:3109: checking for $ac_func" >&5 +echo "configure:3112: 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:3140: \"$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 @@ -3158,12 +3161,12 @@ fi done 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 +echo "configure:3165: 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 @@ -3171,7 +3174,7 @@ int main() { struct tm *tp; tp->tm_sec; ; return 0; } EOF -if { (eval echo configure:3175: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3178: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm=time.h else @@ -3192,12 +3195,12 @@ EOF fi echo $ac_n "checking for tm_zone in struct tm""... $ac_c" 1>&6 -echo "configure:3196: checking for tm_zone in struct tm" >&5 +echo "configure:3199: 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> @@ -3205,7 +3208,7 @@ int main() { struct tm tm; tm.tm_zone; ; return 0; } EOF -if { (eval echo configure:3209: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3212: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm_zone=yes else @@ -3225,12 +3228,12 @@ EOF else echo $ac_n "checking for tzname""... $ac_c" 1>&6 -echo "configure:3229: checking for tzname" >&5 +echo "configure:3232: 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. */ @@ -3240,7 +3243,7 @@ int main() { atoi(*tzname); ; return 0; } EOF -if { (eval echo configure:3244: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:3247: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_var_tzname=yes else @@ -3263,14 +3266,14 @@ 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:3277: \"$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 @@ -3290,7 +3293,7 @@ EOF else echo $ac_n "checking for BSD signal semantics""... $ac_c" 1>&6 -echo "configure:3294: checking for BSD signal semantics" >&5 +echo "configure:3297: 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 @@ -3298,7 +3301,7 @@ else rb_cv_bsd_signal=no else cat > conftest.$ac_ext < @@ -3320,7 +3323,7 @@ main() } EOF -if { (eval echo configure:3324: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:3327: \"$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 @@ -3344,7 +3347,7 @@ EOF fi echo $ac_n "checking whether getpgrp takes no argument""... $ac_c" 1>&6 -echo "configure:3348: checking whether getpgrp takes no argument" >&5 +echo "configure:3351: 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 @@ -3352,7 +3355,7 @@ else { echo "configure: error: cannot check getpgrp if 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:3414: \"$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 @@ -3431,7 +3434,7 @@ EOF fi echo $ac_n "checking whether setpgrp takes no argument""... $ac_c" 1>&6 -echo "configure:3435: checking whether setpgrp takes no argument" >&5 +echo "configure:3438: 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 @@ -3439,7 +3442,7 @@ else { echo "configure: error: cannot check setpgrp if 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:3466: \"$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 @@ -3484,7 +3487,7 @@ fi echo $ac_n "checking for working strtod""... $ac_c" 1>&6 -echo "configure:3488: checking for working strtod" >&5 +echo "configure:3491: 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 @@ -3492,7 +3495,7 @@ else rb_cv_func_strtod=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:3529: \"$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 @@ -3540,14 +3543,14 @@ 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:3544: checking whether byte ordering is bigendian" >&5 +echo "configure:3547: 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 @@ -3558,11 +3561,11 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:3562: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3565: \"$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 @@ -3573,7 +3576,7 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:3577: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3580: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes else @@ -3593,7 +3596,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:3613: \"$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 @@ -3630,18 +3633,18 @@ EOF fi echo $ac_n "checking for working const""... $ac_c" 1>&6 -echo "configure:3634: checking for working const" >&5 +echo "configure:3637: 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 <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3691: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_const=yes else @@ -3705,14 +3708,14 @@ EOF fi echo $ac_n "checking whether char is unsigned""... $ac_c" 1>&6 -echo "configure:3709: checking whether char is unsigned" >&5 +echo "configure:3712: 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:3751: \"$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 @@ -3769,7 +3772,7 @@ fi echo $ac_n "checking whether right shift preserve sign bit""... $ac_c" 1>&6 -echo "configure:3773: checking whether right shift preserve sign bit" >&5 +echo "configure:3776: 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 @@ -3777,7 +3780,7 @@ else 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:3796: \"$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 @@ -3806,7 +3809,7 @@ fi echo "$ac_t""$rb_cv_rshift_sign" 1>&6 if test "$rb_cv_rshift_sign" = yes; then cat >> confdefs.h <<\EOF -#define RSHIFT(x,y) ((x)>>y) +#define RSHIFT(x,y) ((x)>>(int)y) EOF else @@ -3817,19 +3820,19 @@ EOF fi echo $ac_n "checking count field in FILE structures""... $ac_c" 1>&6 -echo "configure:3821: checking count field in FILE structures" >&5 +echo "configure:3824: 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:3833: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3836: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* rb_cv_fcnt="_cnt" else @@ -3839,14 +3842,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:3850: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3853: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* rb_cv_fcnt="__cnt" else @@ -3857,14 +3860,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:3868: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3871: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* rb_cv_fcnt="_r" else @@ -3875,14 +3878,14 @@ 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:3886: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:3889: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* rb_cv_fcnt="readCount" else @@ -3893,14 +3896,14 @@ 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 +if { (eval echo configure:3907: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* rb_cv_fcnt="_rcount" else @@ -3931,19 +3934,23 @@ if test "${with_default_kcode+set}" = set; then utf8) cat >> confdefs.h <<\EOF #define DEFAULT_KCODE KCODE_UTF8 EOF -;; + + DEFAULT_KCODE="KCODE_UTF8";; euc) cat >> confdefs.h <<\EOF #define DEFAULT_KCODE KCODE_EUC EOF -;; + + DEFAULT_KCODE="KCODE_EUC";; sjis) cat >> confdefs.h <<\EOF #define DEFAULT_KCODE KCODE_SJIS EOF -;; + + DEFAULT_KCODE="KCODE_SJIS";; none) cat >> confdefs.h <<\EOF #define DEFAULT_KCODE KCODE_NONE EOF -;; + + DEFAULT_KCODE="KCODE_NONE";; *) echo "configure: warning: $withval is not valid kcode; ignored" 1>&2;; esac fi @@ -3963,10 +3970,8 @@ fi -case "$host_os" in - linux*) - echo $ac_n "checking whether ELF binaries are produced""... $ac_c" 1>&6 -echo "configure:3970: checking whether ELF binaries are produced" >&5 +echo $ac_n "checking whether ELF binaries are produced""... $ac_c" 1>&6 +echo "configure:3975: 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 @@ -3974,7 +3979,7 @@ else 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:4003: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then rb_cv_binary_elf=yes else @@ -4009,12 +4014,30 @@ fi fi echo "$ac_t""$rb_cv_binary_elf" 1>&6 + +if test "$rb_cv_binary_elf" = yes; then + cat >> confdefs.h <<\EOF +#define USE_ELF 1 +EOF + +fi + +case "$host_os" in + linux*) if test "$rb_cv_binary_elf" = no; then with_dln_a_out=yes host_os=${host_os}-a_out else LDFLAGS="-rdynamic" fi;; +netbsd*) + if [ "`$CC -dM -E - &6 -echo "configure:4028: checking whether OS depend dynamic link works" >&5 +echo "configure:4051: checking whether OS depend dynamic link works" >&5 if test "$GCC" = yes; then case "$host_os" in nextstep*) ;; @@ -4075,16 +4098,17 @@ echo "configure:4028: checking whether OS depend dynamic link works" >&5 linux*) LDSHARED="$CC -shared" rb_cv_dlopen=yes ;; freebsd*) LDSHARED="$CC -shared" - if test -x /usr/bin/objformat && \ - test `/usr/bin/objformat` = "elf" ; then + if test "$rb_cv_binary_elf" = yes; 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 -shared" + netbsd*) LDSHARED="ld -shared" + if test "$rb_cv_binary_elf" = yes; then + LDFLAGS="-export-dynamic" + fi rb_cv_dlopen=yes ;; openbsd*) LDSHARED="ld -Bforcearchive -Bshareable" rb_cv_dlopen=yes ;; @@ -4093,7 +4117,7 @@ echo "configure:4028: checking whether OS depend dynamic link works" >&5 rb_cv_dlopen=yes ;; esac ;; bsdi*) LDSHARED="ld -shared" - LDFLAGS="-rdynamic -Wl,-rpath,/usr/local/lib/ruby/1.4/i386-bsdi4.0" + LDFLAGS='-rdynamic -Wl,-rpath,$(prefix)/lib/ruby/$(MAJOR).$(MINOR)/i386-bsdi4.0' rb_cv_dlopen=yes ;; nextstep*) LDSHARED='cc -r -nostdlib' LDFLAGS="-u libsys_s" @@ -4110,6 +4134,7 @@ echo "configure:4028: checking whether OS depend dynamic link works" >&5 aix*) LDSHARED='/usr/ccs/bin/ld' XLDFLAGS='-Wl,-bE:ruby.imp' DLDFLAGS='-eInit_$(TARGET) -bI:$(topdir)/ruby.imp -bM:SRE -T512 -H512 -lc' + LDFLAGS="-brtl" rb_cv_dlopen=yes ;; human*) DLDFLAGS='' @@ -4141,12 +4166,12 @@ if test "$ac_cv_header_a_out_h" = yes; then if test "$with_dln_a_out" = yes || test "$rb_cv_dlopen" = unknown; then cat confdefs.h > config.h echo $ac_n "checking whether matz's dln works""... $ac_c" 1>&6 -echo "configure:4145: checking whether matz's dln works" >&5 +echo "configure:4170: 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:4185: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* rb_cv_dln_a_out=yes else @@ -4218,9 +4243,9 @@ EOF #define DLEXT ".dll" EOF ;; - os2_emx) DLEXT=o + os2_emx*) DLEXT=dll cat >> confdefs.h <<\EOF -#define DLEXT ".so" +#define DLEXT ".dll" EOF ;; *) DLEXT=so @@ -4263,7 +4288,7 @@ fi case "$host_os" in human*) echo $ac_n "checking for _harderr in -lsignal""... $ac_c" 1>&6 -echo "configure:4267: checking for _harderr in -lsignal" >&5 +echo "configure:4292: 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 @@ -4271,7 +4296,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:4311: \"$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 @@ -4310,7 +4335,7 @@ else fi echo $ac_n "checking for hmemset in -lhmem""... $ac_c" 1>&6 -echo "configure:4314: checking for hmemset in -lhmem" >&5 +echo "configure:4339: 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 @@ -4318,7 +4343,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:4358: \"$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 @@ -4356,15 +4381,15 @@ else echo "$ac_t""no" 1>&6 fi - for ac_func in select + for ac_func in select gettimeofday do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:4363: checking for $ac_func" >&5 +echo "configure:4388: 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:4416: \"$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 @@ -4412,7 +4437,7 @@ fi done echo $ac_n "checking whether PD libc _dtos18 fail to convert big number""... $ac_c" 1>&6 -echo "configure:4416: checking whether PD libc _dtos18 fail to convert big number" >&5 +echo "configure:4441: 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 @@ -4420,7 +4445,7 @@ else rb_cv_missing__dtos18=no else cat > conftest.$ac_ext < @@ -4432,7 +4457,7 @@ main () } EOF -if { (eval echo configure:4436: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4461: \"$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 @@ -4454,7 +4479,7 @@ EOF fi echo $ac_n "checking whether PD libc fconvert fail to round""... $ac_c" 1>&6 -echo "configure:4458: checking whether PD libc fconvert fail to round" >&5 +echo "configure:4483: 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 @@ -4462,7 +4487,7 @@ else rb_cv_missing_fconvert=no else cat > conftest.$ac_ext < @@ -4475,7 +4500,7 @@ main () } EOF -if { (eval echo configure:4479: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:4504: \"$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 @@ -4497,13 +4522,13 @@ EOF fi LIBOBJS="$LIBOBJS x68.o" - CFLAGS="$CFLAGS -fansi-only -cc1-stack=196608 -cpp-stack=2694144" + CFLAGS="$CFLAGS -fansi-only -cc1-stack=262144 -cpp-stack=2694144" EXEEXT=.x OBJEXT=o setup=Setup.x68 ;; os2_emx) - LIBOBJS="$LIBOBJS os2.o" + LIBOBJS="$LIBOBJS os2.$OBJEXT" setup=Setup.emx ;; cygwin*) @@ -4524,6 +4549,7 @@ if test "$fat_binary" = yes ; then CFLAGS="$CFLAGS $ARCH_FLAG" fi +FIRSTMAKEFILE="" LIBRUBY_A='lib$(RUBY_INSTALL_NAME).a' LIBRUBY='$(LIBRUBY_A)' LIBRUBYARG='$(LIBRUBY_A)' @@ -4540,6 +4566,7 @@ if test "$host_os" = "beos"; then ;; i586*) LDFLAGS="$LDFLAGS -L." + FIRSTMAKEFILE=GNUmakefile:beos/GNUmakefile.in ;; *) echo EXPORTS > ruby.def @@ -4548,7 +4575,6 @@ 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)' @@ -4568,23 +4594,23 @@ if test "$enable_shared" = 'yes'; then LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).so' ;; linux*) - XLDFLAGS='-Wl,-rpath,${prefix}/lib':/usr/lib:/lib + LIBRUBY_DLDFLAGS='-Wl,-soname,lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR)' LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).so' ;; freebsd*) LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR)$(MINOR)' - if test "$rb_cv_freebsd_elf" != "yes" ; then + if test "$rb_cv_binary_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 + if test "$rb_cv_binary_elf" = yes; then # ELF platforms + LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR) lib$(RUBY_INSTALL_NAME).so' + else + LIBRUBY_ALIASES= # a.out platforms + fi ;; solaris*) XLDFLAGS='-R${prefix}/lib' diff --git a/configure.in b/configure.in index 00b6ff12ce..2d7157340a 100644 --- a/configure.in +++ b/configure.in @@ -77,18 +77,18 @@ AC_CHECK_PROGS(AR, ar aal, ar) 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_EXEEXT +AC_OBJEXT + +AC_CHECK_SIZEOF(int, 4) +AC_CHECK_SIZEOF(short, 2) +AC_CHECK_SIZEOF(long, 4) +AC_CHECK_SIZEOF(void*, 4) +AC_CHECK_SIZEOF(float, 4) +AC_CHECK_SIZEOF(double, 8) AC_CACHE_CHECK(for prototypes, rb_cv_have_prototypes, [AC_TRY_COMPILE([int foo(int x) { return 0; }], [return foo(10);], @@ -140,9 +140,12 @@ case "$host_os" in nextstep*) ;; openstep*) ;; rhapsody*) ;; -human*) ;; +human*) ac_cv_func_getpgrp_void=yes;; beos*) ;; cygwin*) ;; +os2_emx*) LIBS="-lm $LIBS" + ac_cv_lib_xpg4_setlocale=no + ac_cv_lib_dir_opendir=no;; *) LIBS="-lm $LIBS";; esac AC_CHECK_LIB(crypt, crypt) @@ -156,7 +159,7 @@ AC_HEADER_STDC 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) + syscall.h pwd.h a.out.h utime.h memory.h direct.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_TYPE_UID_T @@ -175,7 +178,7 @@ AC_FUNC_VFORK AC_FUNC_MEMCMP AC_REPLACE_FUNCS(dup2 memmove mkdir strcasecmp strncasecmp strerror strftime\ strchr strstr strtoul strdup crypt flock vsnprintf\ - fnmatch isinf isnan finite) + 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\ @@ -253,7 +256,7 @@ test $rb_cv_func_strtod = no && LIBOBJS="$LIBOBJS strtod.o" AC_C_BIGENDIAN AC_C_CONST -AC_CHAR_UNSIGNED +AC_C_CHAR_UNSIGNED AC_CACHE_CHECK(whether right shift preserve sign bit, rb_cv_rshift_sign, [AC_TRY_RUN([ @@ -269,7 +272,7 @@ main() 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)) + AC_DEFINE(RSHIFT(x,y), ((x)>>(int)y)) else AC_DEFINE(RSHIFT(x,y), (((x)<0) ? ~((~(x))>>y) : (x)>>y)) fi @@ -309,10 +312,14 @@ 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);; + utf8) AC_DEFINE(DEFAULT_KCODE, KCODE_UTF8) + DEFAULT_KCODE="KCODE_UTF8";; + euc) AC_DEFINE(DEFAULT_KCODE, KCODE_EUC) + DEFAULT_KCODE="KCODE_EUC";; + sjis) AC_DEFINE(DEFAULT_KCODE, KCODE_SJIS) + DEFAULT_KCODE="KCODE_SJIS";; + none) AC_DEFINE(DEFAULT_KCODE, KCODE_NONE) + DEFAULT_KCODE="KCODE_NONE";; *) AC_MSG_WARN($withval is not valid kcode; ignored);; esac]) @@ -326,10 +333,8 @@ AC_ARG_WITH(dln-a-out, AC_SUBST(XLDFLAGS)dnl -case "$host_os" in - linux*) - AC_CACHE_CHECK(whether ELF binaries are produced, rb_cv_binary_elf, - [AC_TRY_RUN([ +AC_CACHE_CHECK(whether ELF binaries are produced, rb_cv_binary_elf, +[AC_TRY_RUN([ /* Test for whether ELF binaries are produced */ #include #include @@ -346,15 +351,30 @@ main() { exit(0); /* succeed (yes, it's ELF) */ } ], - rb_cv_binary_elf=yes, - rb_cv_binary_elf=no, - rb_cv_binary_elf=yes)]) +rb_cv_binary_elf=yes, +rb_cv_binary_elf=no, +rb_cv_binary_elf=yes)]) + +if test "$rb_cv_binary_elf" = yes; then + AC_DEFINE(USE_ELF) +fi + +case "$host_os" in + linux*) if test "$rb_cv_binary_elf" = no; then with_dln_a_out=yes host_os=${host_os}-a_out else LDFLAGS="-rdynamic" fi;; +netbsd*) + if [[ "`$CC -dM -E - &1 | grep "GNU ld" > /dev/null || LDSHARED="ld -Bshareable" fi rb_cv_dlopen=yes ;; - netbsd*) LDSHARED="ld -shared" + netbsd*) LDSHARED="ld -shared" + if test "$rb_cv_binary_elf" = yes; then + LDFLAGS="-export-dynamic" + fi rb_cv_dlopen=yes ;; openbsd*) LDSHARED="ld -Bforcearchive -Bshareable" rb_cv_dlopen=yes ;; @@ -437,7 +458,7 @@ if test "$with_dln_a_out" != yes; then rb_cv_dlopen=yes ;; esac ;; bsdi*) LDSHARED="ld -shared" - LDFLAGS="-rdynamic -Wl,-rpath,/usr/local/lib/ruby/1.4/i386-bsdi4.0" + LDFLAGS='-rdynamic -Wl,-rpath,$(prefix)/lib/ruby/$(MAJOR).$(MINOR)/i386-bsdi4.0' rb_cv_dlopen=yes ;; nextstep*) LDSHARED='cc -r -nostdlib' LDFLAGS="-u libsys_s" @@ -454,6 +475,7 @@ if test "$with_dln_a_out" != yes; then aix*) LDSHARED='/usr/ccs/bin/ld' XLDFLAGS='-Wl,-bE:ruby.imp' DLDFLAGS='-eInit_$(TARGET) -bI:$(topdir)/ruby.imp -bM:SRE -T512 -H512 -lc' + LDFLAGS="-brtl" rb_cv_dlopen=yes ;; human*) DLDFLAGS='' @@ -520,8 +542,8 @@ else AC_DEFINE(DLEXT, ".bundle");; cygwin*) DLEXT=dll AC_DEFINE(DLEXT, ".dll");; - os2_emx) DLEXT=o - AC_DEFINE(DLEXT, ".so");; + os2_emx*) DLEXT=dll + AC_DEFINE(DLEXT, ".dll");; *) DLEXT=so AC_DEFINE(DLEXT, ".so");; esac @@ -559,7 +581,7 @@ case "$host_os" in human*) AC_CHECK_LIB(signal, _harderr) AC_CHECK_LIB(hmem, hmemset) - AC_CHECK_FUNCS(select) + AC_CHECK_FUNCS(select gettimeofday) AC_CACHE_CHECK(whether PD libc _dtos18 fail to convert big number, rb_cv_missing__dtos18, [AC_TRY_RUN( @@ -598,14 +620,14 @@ rb_cv_missing_fconvert=yes, rb_cv_missing_fconvert=no, rb_cv_missing_fconvert=no AC_DEFINE(MISSING_FCONVERT) fi LIBOBJS="$LIBOBJS x68.o" - CFLAGS="$CFLAGS -fansi-only -cc1-stack=196608 -cpp-stack=2694144" + CFLAGS="$CFLAGS -fansi-only -cc1-stack=262144 -cpp-stack=2694144" EXEEXT=.x OBJEXT=o setup=Setup.x68 ;; dnl OS/2 environment w/ Autoconf 2.1x for EMX os2_emx) - LIBOBJS="$LIBOBJS os2.o" + LIBOBJS="$LIBOBJS os2.$OBJEXT" setup=Setup.emx ;; cygwin*) @@ -626,6 +648,7 @@ if test "$fat_binary" = yes ; then CFLAGS="$CFLAGS $ARCH_FLAG" fi +FIRSTMAKEFILE="" LIBRUBY_A='lib$(RUBY_INSTALL_NAME).a' LIBRUBY='$(LIBRUBY_A)' LIBRUBYARG='$(LIBRUBY_A)' @@ -642,6 +665,7 @@ if test "$host_os" = "beos"; then ;; i586*) LDFLAGS="$LDFLAGS -L." + FIRSTMAKEFILE=GNUmakefile:beos/GNUmakefile.in ;; *) echo EXPORTS > ruby.def @@ -650,7 +674,6 @@ 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)' @@ -667,23 +690,23 @@ if test "$enable_shared" = 'yes'; then LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).so' ;; linux*) - XLDFLAGS='-Wl,-rpath,${prefix}/lib':/usr/lib:/lib + LIBRUBY_DLDFLAGS='-Wl,-soname,lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR)' LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR).$(MINOR) lib$(RUBY_INSTALL_NAME).so' ;; freebsd*) LIBRUBY_SO='lib$(RUBY_INSTALL_NAME).so.$(MAJOR)$(MINOR)' - if test "$rb_cv_freebsd_elf" != "yes" ; then + if test "$rb_cv_binary_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 + if test "$rb_cv_binary_elf" = yes; then # ELF platforms + LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).so.$(MAJOR) lib$(RUBY_INSTALL_NAME).so' + else + LIBRUBY_ALIASES= # a.out platforms + fi ;; solaris*) XLDFLAGS='-R${prefix}/lib' diff --git a/cygwin/GNUmakefile.in b/cygwin/GNUmakefile.in index 970e90e24a..fb30e09ea1 100644 --- a/cygwin/GNUmakefile.in +++ b/cygwin/GNUmakefile.in @@ -5,5 +5,5 @@ 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 + $(LDSHARED) $(DLDFLAGS) -o $(RUBYCWDLL) --output-lib=$(LIBRUBY_SO) --dllname=$(RUBYCWDLL) -Wl,-e,__cygwin_noncygwin_dll_entry@12 --add-stdcall-alias $(OBJS) dmyext.o nm --extern-only $(OBJS) dmyext.o | sed -n '/^........ [CD] _\(.*\)$$/s//#define \1 (*__imp_\1)/p' >import.h diff --git a/dir.c b/dir.c index 31116a9fff..8b7f95785b 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-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -47,12 +47,6 @@ # endif #endif -#ifdef HAVE_FNMATCH_H -#include -#else -#include "missing/fnmatch.h" -#endif - #include #ifdef USE_CWGUSI # include @@ -66,6 +60,167 @@ char *getenv(); char *strchr _((char*,char)); #endif +#include + +#define FNM_NOESCAPE 0x01 +#define FNM_PATHNAME 0x02 +#define FNM_PERIOD 0x04 +#define FNM_NOCASE 0x08 + +#define FNM_NOMATCH 1 +#define FNM_ERROR 2 + +#define downcase(c) (nocase && isupper(c) ? tolower(c) : (c)) + +#if defined DOSISH +#define isdirsep(c) ((c) == '/' || (c) == '\\') +static char * +find_dirsep(s) + char *s; +{ + while (*s) { + if (isdirsep(*s)) + return s; + s++; + } + return 0; +} +#else +#define isdirsep(c) ((c) == '/') +#define find_dirsep(s) strchr(s, '/') +#endif + +static char * +range(pat, test, flags) + char *pat; + char test; + int flags; +{ + int not, ok = 0; + int nocase = flags & FNM_NOCASE; + int escape = !(flags & FNM_NOESCAPE); + + not = *pat == '!' || *pat == '^'; + if (not) + pat++; + + test = downcase(test); + + while (*pat) { + int cstart, cend; + cstart = cend = *pat++; + if (cstart == ']') + return ok == not ? 0 : pat; + else if (escape && cstart == '\\') + cstart = cend = *pat++; + if (*pat == '-' && pat[1] != ']') { + if (escape && pat[1] == '\\') + pat++; + cend = pat[1]; + if (!cend) + return 0; + pat += 2; + } + if (downcase(cstart) <= test && test <= downcase(cend)) + ok = 1; + } + return 0; +} + +#define PERIOD(s) (period && *(s) == '.' && \ + ((s) == string || pathname && isdirsep(*(s)))) +static int +fnmatch(pat, string, flags) + char *pat; + char *string; + int flags; +{ + int c; + int test; + char *s = string; + int escape = !(flags & FNM_NOESCAPE); + int pathname = flags & FNM_PATHNAME; + int period = flags & FNM_PERIOD; + int nocase = flags & FNM_NOCASE; + + while (c = *pat++) { + switch (c) { + case '?': + if (!*s || pathname && isdirsep(*s) || PERIOD(s)) + return FNM_NOMATCH; + s++; + break; + case '*': + while ((c = *pat++) == '*') + ; + + if (PERIOD(s)) + return FNM_NOMATCH; + + if (!c) { + if (pathname && find_dirsep(s)) + return FNM_NOMATCH; + else + return 0; + } + else if (pathname && isdirsep(c)) { + s = find_dirsep(s); + if (s) + break; + return FNM_NOMATCH; + } + + test = escape && c == '\\' ? *pat : c; + test = downcase(test); + pat--; + while (*s) { + if ((c == '[' || downcase(*s) == test) && + !fnmatch(pat, s, flags & ~FNM_PERIOD)) + return 0; + else if (pathname && isdirsep(*s)) + break; + s++; + } + return FNM_NOMATCH; + + case '[': + if (!*s || pathname && isdirsep(*s) || PERIOD(s)) + return FNM_NOMATCH; + pat = range(pat, *s, flags); + if (!pat) + return FNM_NOMATCH; + s++; + break; + + case '\\': + if (escape +#if defined DOSISH + && *pat && strchr("*?[\\", *pat) +#endif + ) { + c = *pat; + if (!c) + c = '\\'; + else + pat++; + } + /* FALLTHROUGH */ + + default: +#if defined DOSISH + if (pathname && isdirsep(c) && isdirsep(*s)) + ; + else +#endif + if(downcase(c) != downcase(*s)) + return FNM_NOMATCH; + s++; + break; + } + } + return !*s ? 0 : FNM_NOMATCH; +} + VALUE rb_cDir; static void @@ -355,7 +510,7 @@ extract_path(p, pend) len = pend - p; alloc = ALLOC_N(char, len+1); memcpy(alloc, p, len); - if (len > 0 && pend[-1] == '/') { + if (len > 1 && pend[-1] == '/') { alloc[len-1] = 0; } else { @@ -421,11 +576,12 @@ glob(path, func, arg) break; } magic = extract_elem(p); +#define BASE (*base && !(*base == '/' && !base[1])) + 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); + sprintf(fix, "%s%s%s", base, (BASE)?"/":"", dp->d_name); if (!m) { (*func)(fix, arg); free(fix); diff --git a/dln.c b/dln.c index e6c7adde70..10ea423643 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-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -80,7 +80,7 @@ int eaccess(); #endif #ifndef FUNCNAME_PATTERN -# if defined(__hp9000s300) || (defined(__NetBSD__) && (!defined(__alpha__) && !defined(__mips__))) || defined(__BORLANDC__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) || defined(NeXT) || defined(__WATCOMC__) || defined(__APPLE__) +# if defined(__hp9000s300) || (defined(__NetBSD__) && !defined(__ELF__)) || defined(__BORLANDC__) || (defined(__FreeBSD__) && __FreeBSD__ < 3) || defined(__OpenBSD__) || defined(NeXT) || defined(__WATCOMC__) || defined(__APPLE__) # define FUNCNAME_PATTERN "_Init_%.200s" # else # define FUNCNAME_PATTERN "Init_%.200s" diff --git a/enum.c b/enum.c index dc7e2112a4..3ad7e107e2 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-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -33,11 +33,11 @@ grep_i(i, arg) } static VALUE -grep_iter_i(i, pat) - VALUE i, pat; +grep_iter_i(i, arg) + VALUE i, *arg; { - if (RTEST(rb_funcall(pat, id_eqq, 1, i))) { - rb_yield(i); + if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) { + rb_ary_push(arg[1], rb_yield(i)); } return Qnil; } @@ -46,19 +46,16 @@ static VALUE enum_grep(obj, pat) VALUE obj, pat; { + VALUE tmp, arg[2]; + + arg[0] = pat; arg[1] = tmp = rb_ary_new(); if (rb_iterator_p()) { - rb_iterate(rb_each, obj, grep_iter_i, pat); - return obj; + rb_iterate(rb_each, obj, grep_iter_i, (VALUE)arg); } else { - VALUE tmp, arg[2]; - - 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; } + return tmp; } struct find_arg { @@ -201,7 +198,7 @@ min_i(i, min) *min = i; else { cmp = rb_funcall(i, id_cmp, 1, *min); - if (FIX2LONG(cmp) < 0) + if (NUM2LONG(cmp) < 0) *min = i; } return Qnil; @@ -217,7 +214,7 @@ min_ii(i, min) *min = i; else { cmp = rb_yield(rb_assoc_new(i, *min)); - if (FIX2LONG(cmp) < 0) + if (NUM2LONG(cmp) < 0) *min = i; } return Qnil; @@ -243,7 +240,7 @@ max_i(i, max) *max = i; else { cmp = rb_funcall(i, id_cmp, 1, *max); - if (FIX2LONG(cmp) > 0) + if (NUM2LONG(cmp) > 0) *max = i; } return Qnil; @@ -259,7 +256,7 @@ max_ii(i, max) *max = i; else { cmp = rb_yield(rb_assoc_new(i, *max)); - if (FIX2LONG(cmp) > 0) + if (NUM2LONG(cmp) > 0) *max = i; } return Qnil; diff --git a/error.c b/error.c index 6a48210b4e..f528eccacd 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-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -26,6 +26,13 @@ int sys_nerr = 256; #endif +#if defined __CYGWIN__ +# include +# if (CYGWIN_VERSION_API_MAJOR > 0) || (CYGWIN_VERSION_API_MINOR >= 8) +# define sys_nerr _sys_nerr +# endif +#endif + int ruby_nerrs; static void @@ -34,14 +41,20 @@ err_snprintf(buf, len, fmt, args) int len; va_list args; { + int n; + if (!ruby_sourcefile) { vsnprintf(buf, len, fmt, args); + return; + } + else if (ruby_sourceline == 0) { + n = snprintf(buf, len, "%s: ", ruby_sourcefile); } else { - int n = snprintf(buf, len, "%s:%d: ", ruby_sourcefile, ruby_sourceline); - if (len > n) { - vsnprintf((char*)buf+n, len-n, fmt, args); - } + n = snprintf(buf, len, "%s:%d: ", ruby_sourcefile, ruby_sourceline); + } + if (len > n) { + vsnprintf((char*)buf+n, len-n, fmt, args); } } @@ -373,6 +386,7 @@ check_backtrace(bt) static VALUE exc_set_backtrace(exc, bt) VALUE exc; + VALUE bt; { return rb_iv_set(exc, "bt", check_backtrace(bt)); } @@ -432,7 +446,7 @@ static const syserr_index_entry syserr_index[]= { static VALUE *syserr_list; #endif -#ifndef NT +#if !defined NT && !defined sys_nerr extern int sys_nerr; #endif diff --git a/eval.c b/eval.c index f225bf47bd..ccdf11530e 100644 --- a/eval.c +++ b/eval.c @@ -6,7 +6,7 @@ $Date$ created at: Thu Jun 10 14:22:17 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -147,6 +147,7 @@ search_method(klass, id, origin) { NODE *body; + if (!klass) return 0; while (!st_lookup(RCLASS(klass)->m_tbl, id, &body)) { klass = RCLASS(klass)->super; if (!klass) return 0; @@ -292,10 +293,15 @@ rb_enable_super(klass, name) ID mid = rb_intern(name); body = search_method(klass, mid, &origin); - if (!body || !body->nd_body || origin != klass) { + if (!body) { print_undef(klass, mid); } - body->nd_noex &= ~NOEX_UNDEF; + if (!body->nd_body) { + remove_method(klass, mid); + } + else { + body->nd_noex &= ~NOEX_UNDEF; + } } static void @@ -550,14 +556,27 @@ dvar_asgn(id, value, push) struct RVarmap *vars = ruby_dyna_vars; while (vars) { - if (push && vars->id == 0) break; + if (push && vars->id == 0) { + rb_dvar_push(id, value); + return; + } if (vars->id == id) { vars->val = value; return; } vars = vars->next; } + + vars = 0; + if (ruby_dyna_vars && ruby_dyna_vars->id == 0) { + vars = ruby_dyna_vars; + ruby_dyna_vars = ruby_dyna_vars->next; + } rb_dvar_push(id, value); + if (vars) { + vars->next = ruby_dyna_vars; + ruby_dyna_vars = vars; + } } void @@ -1511,6 +1530,7 @@ is_defined(self, node, buf) case NODE_SUPER: case NODE_ZSUPER: if (ruby_frame->last_func == 0) return 0; + else if (ruby_frame->last_class == 0) return 0; else if (rb_method_boundp(RCLASS(ruby_frame->last_class)->super, ruby_frame->last_func, 0)) { if (nd_type(node) == NODE_SUPER) { @@ -1698,6 +1718,7 @@ call_trace_func(event, file, line, self, id, klass) struct FRAME *prev; char *file_save = ruby_sourcefile; int line_save = ruby_sourceline; + VALUE srcfile; if (!trace_func) return; @@ -1707,7 +1728,7 @@ call_trace_func(event, file, line, self, id, klass) prev = ruby_frame; PUSH_FRAME(); - *ruby_frame = *_frame.prev; + *ruby_frame = *prev; ruby_frame->prev = prev; if (file) { @@ -1721,8 +1742,9 @@ call_trace_func(event, file, line, self, id, klass) } PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { + srcfile = rb_str_new2(ruby_sourcefile?ruby_sourcefile:"(ruby)"); proc_call(trace, rb_ary_new3(6, rb_str_new2(event), - rb_str_new2(ruby_sourcefile), + srcfile, INT2FIX(ruby_sourceline), INT2FIX(id), self?rb_f_binding(self):Qnil, @@ -3113,6 +3135,8 @@ rb_f_raise(argc, argv) VALUE *argv; { VALUE mesg; + ID exception; + int n; mesg = Qnil; switch (argc) { @@ -3125,17 +3149,24 @@ rb_f_raise(argc, argv) mesg = rb_exc_new3(rb_eRuntimeError, argv[0]); break; } - mesg = rb_funcall(argv[0], rb_intern("exception"), 0, 0); - break; - case 3: + n = 0; + goto exception_call; + case 2: - mesg = rb_funcall(argv[0], rb_intern("exception"), 1, argv[1]); + case 3: + n = 1; + exception_call: + exception = rb_intern("exception"); + if (!rb_respond_to(argv[0], exception)) { + rb_raise(rb_eTypeError, "exception class/object expected"); + } + mesg = rb_funcall(argv[0], exception, n, argv[1]); break; default: rb_raise(rb_eArgError, "wrong # of arguments"); break; } - if (!NIL_P(mesg)) { + if (argc > 0) { if (!rb_obj_is_kind_of(mesg, rb_eException)) rb_raise(rb_eTypeError, "exception object expected"); set_backtrace(mesg, (argc>2)?argv[2]:Qnil); @@ -3595,12 +3626,13 @@ rb_f_missing(argc, argv, obj) volatile VALUE d = 0; char *format = 0; char *desc = ""; + const char *mname; char *file = ruby_sourcefile; int line = ruby_sourceline; - if (argc == 0) rb_raise(rb_eArgError, "no id given"); - - id = FIX2INT(argv[0]); + if (argc == 0 || (id = NUM2INT(argv[0]), mname = rb_id2name(id)) == 0) { + rb_raise(rb_eArgError, "no id given"); + } argc--; argv++; switch (TYPE(obj)) { @@ -3628,8 +3660,6 @@ rb_f_missing(argc, argv, obj) format = "protected method `%s' called for %s%s%s"; } else if (last_call_status & CSTAT_VCALL) { - const char *mname = rb_id2name(id); - if (('a' <= mname[0] && mname[0] <= 'z') || mname[0] == '_') { format = "undefined local variable or method `%s' for %s%s%s"; } @@ -3648,7 +3678,7 @@ rb_f_missing(argc, argv, obj) PUSH_FRAME(); /* fake frame */ *ruby_frame = *_frame.prev->prev; - rb_raise(rb_eNameError, format, rb_id2name(id), + rb_raise(rb_eNameError, format, mname, desc, desc[0]=='#'?"":":", desc[0]=='#'?"":rb_class2name(CLASS_OF(obj))); POP_FRAME(); @@ -4148,6 +4178,27 @@ rb_funcall3(recv, mid, argc, argv) return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 0); } +VALUE +rb_call_super(argc, argv) + int argc; + VALUE *argv; +{ + VALUE result; + + if (ruby_frame->last_class == 0) { + rb_raise(rb_eNameError, "superclass method `%s' must be enabled by rb_enable_super()", + rb_id2name(ruby_frame->last_func)); + } + + PUSH_ITER(ruby_iter->iter?ITER_PRE:ITER_NOT); + result = rb_call(RCLASS(ruby_frame->last_class)->super, + ruby_frame->self, ruby_frame->last_func, + argc, argv, 3); + POP_ITER(); + + return result; +} + static VALUE backtrace(lev) int lev; @@ -4369,7 +4420,7 @@ rb_f_eval(argc, argv, self) VALUE *argv; VALUE self; { - VALUE src, scope, vfile, vline; + VALUE src, scope, vfile, vline, val; char *file = "(eval)"; int line = 1; @@ -4383,6 +4434,19 @@ rb_f_eval(argc, argv, self) } Check_SafeStr(src); + if (NIL_P(scope) && ruby_frame->prev) { + struct FRAME *prev; + VALUE val; + + prev = ruby_frame; + PUSH_FRAME(); + *ruby_frame = *prev->prev; + ruby_frame->prev = prev; + val = eval(self, src, scope, file, line); + POP_FRAME(); + + return val; + } return eval(self, src, scope, file, line); } @@ -4618,7 +4682,7 @@ find_file(file) 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); + rb_raise(rb_eSecurityError, "loading from unsafe path %s", path); } } else { @@ -4636,6 +4700,7 @@ rb_load(fname, wrap) int state; char *file; volatile ID last_func; + volatile VALUE wrapper = 0; VALUE self = ruby_top_self; TMP_PROTECT; @@ -4652,9 +4717,11 @@ rb_load(fname, wrap) PUSH_VARS(); PUSH_CLASS(); + wrapper = ruby_wrapper; if (!wrap) { rb_secure(4); /* should alter global state */ ruby_class = rb_cObject; + ruby_wrapper = 0; } else { /* load in anonymous module as toplevel */ @@ -4664,6 +4731,7 @@ rb_load(fname, wrap) } PUSH_FRAME(); ruby_frame->last_func = 0; + ruby_frame->last_class = 0; ruby_frame->self = ruby_top_self; ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,ruby_class,0,0); PUSH_SCOPE(); @@ -4701,7 +4769,7 @@ rb_load(fname, wrap) POP_FRAME(); POP_CLASS(); POP_VARS(); - ruby_wrapper = 0; + ruby_wrapper = wrapper; if (ruby_nerrs > 0) { ruby_nerrs = 0; rb_exc_raise(ruby_errinfo); @@ -4812,6 +4880,7 @@ rb_f_require(obj, fname) ext = strrchr(buf, '.'); strcpy(ext, DLEXT); file = feature = buf; + if (rb_provided(feature)) return Qfalse; } file = find_file(file); if (file) goto load_dyna; @@ -5174,7 +5243,8 @@ struct end_proc_data { VALUE data; struct end_proc_data *next; }; -static struct end_proc_data *end_proc_data; + +static struct end_proc_data *end_procs, *ephemeral_end_procs; void rb_set_end_proc(func, data) @@ -5182,12 +5252,31 @@ rb_set_end_proc(func, data) VALUE data; { struct end_proc_data *link = ALLOC(struct end_proc_data); + struct end_proc_data **list; - link->next = end_proc_data; + if (ruby_wrapper) list = &ephemeral_end_procs; + else list = &end_procs; + link->next = *list; link->func = func; link->data = data; - rb_global_variable(&link->data); - end_proc_data = link; + *list = link; +} + +void +rb_mark_end_proc() +{ + struct end_proc_data *link; + + link = end_procs; + while (link) { + rb_gc_mark(link->data); + link = link->next; + } + link = ephemeral_end_procs; + while (link) { + rb_gc_mark(link->data); + link = link->next; + } } static void @@ -5220,17 +5309,20 @@ rb_f_at_exit() void rb_exec_end_proc() { - struct end_proc_data *link = end_proc_data; - struct end_proc_data *tmp; + struct end_proc_data *link; int status; + link = end_procs; while (link) { rb_protect((VALUE(*)())link->func, link->data, &status); - tmp = link->next; + link = link->next; + } + while (ephemeral_end_procs) { + link = ephemeral_end_procs; + ephemeral_end_procs = link->next; + rb_protect((VALUE(*)())link->func, link->data, &status); free(link); - link = tmp; } - end_proc_data = 0; } void @@ -5310,6 +5402,7 @@ Init_eval() rb_define_global_function("untrace_var", rb_f_untrace_var, -1); rb_define_global_function("set_trace_func", set_trace_func, 1); + rb_global_variable(&trace_func); rb_define_virtual_variable("$SAFE", safe_getter, safe_setter); } @@ -5475,6 +5568,7 @@ rb_f_binding(self) frame_dup(&data->frame); if (ruby_frame->prev) { data->frame.last_func = ruby_frame->prev->last_func; + data->frame.last_class = ruby_frame->prev->last_class; } if (data->iter) { @@ -5549,6 +5643,7 @@ proc_s_new(klass) data->orig_thread = rb_thread_current(); data->iter = data->prev?Qtrue:Qfalse; + data->tag = 0; /* should not point into stack */ frame_dup(&data->frame); if (data->iter) { blk_copy_prev(data); @@ -5589,6 +5684,7 @@ proc_call(proc, args) VALUE proc, args; /* OK */ { struct BLOCK * volatile old_block; + struct BLOCK _block; struct BLOCK *data; volatile VALUE result = Qnil; int state; @@ -5600,7 +5696,8 @@ proc_call(proc, args) /* PUSH BLOCK from data */ old_block = ruby_block; - ruby_block = data; + _block = *data; + ruby_block = &_block; PUSH_ITER(ITER_CUR); ruby_frame->iter = ITER_CUR; @@ -5625,6 +5722,7 @@ proc_call(proc, args) } PUSH_TAG(PROT_NONE); + _block.tag = prot_tag; state = EXEC_TAG(); if (state == 0) { proc_set_safe_level(proc); @@ -5667,7 +5765,7 @@ proc_arity(proc) int n; Data_Get_Struct(proc, struct BLOCK, data); - if (data->var == 0) return FIX2INT(-1); + if (data->var == 0) return INT2FIX(-1); switch (nd_type(data->var)) { default: return INT2FIX(-2); @@ -5690,6 +5788,7 @@ block_pass(self, node) { VALUE block = rb_eval(self, node->nd_body); struct BLOCK * volatile old_block; + struct BLOCK _block; struct BLOCK *data; volatile VALUE result = Qnil; int state; @@ -5712,11 +5811,13 @@ block_pass(self, node) /* PUSH BLOCK from data */ old_block = ruby_block; - ruby_block = data; + _block = *data; + ruby_block = &_block; PUSH_ITER(ITER_PRE); ruby_frame->iter = ITER_PRE; PUSH_TAG(PROT_NONE); + _block.tag = prot_tag; state = EXEC_TAG(); if (state == 0) { proc_set_safe_level(block); @@ -5724,26 +5825,36 @@ block_pass(self, node) } POP_TAG(); POP_ITER(); - if (ruby_block->tag->dst == state) { - state &= TAG_MASK; - orphan = 2; + if (_block.tag->dst == state) { + if (orphan) { + state &= TAG_MASK; + } + else { + struct BLOCK *ptr = old_block; + + while (ptr) { + if (ptr->scope == _block.scope) { + ptr->tag->dst = state; + break; + } + ptr = ptr->prev; + } + } } ruby_block = old_block; safe_level = safe; if (state) { - if (orphan == 2) {/* escape from orphan procedure */ - switch (state) { - case TAG_BREAK: - rb_raise(rb_eLocalJumpError, "break from proc-closure"); - break; - case TAG_RETRY: - rb_raise(rb_eLocalJumpError, "retry from proc-closure"); - break; - case TAG_RETURN: - rb_raise(rb_eLocalJumpError, "return from proc-closure"); - break; - } + switch (state) { + case TAG_BREAK: + rb_raise(rb_eLocalJumpError, "break from proc-closure"); + break; + case TAG_RETRY: + rb_raise(rb_eLocalJumpError, "retry from proc-closure"); + break; + case TAG_RETURN: + rb_raise(rb_eLocalJumpError, "return from proc-closure"); + break; } JUMP_TAG(state); } @@ -5861,7 +5972,7 @@ method_arity(method) body = body->nd_head; if (!body) return INT2FIX(0); n = body->nd_cnt; - if (body->nd_rest) n = -n-1; + if (body->nd_rest >= 0) n = -n-1; return INT2FIX(n); } } @@ -5937,7 +6048,7 @@ Init_Proc() rb_define_global_function("lambda", rb_f_lambda, 0); rb_define_global_function("binding", rb_f_binding, 0); rb_cBinding = rb_define_class("Binding", rb_cObject); - rb_undef_method(CLASS_OF(rb_cMethod), "new"); + rb_undef_method(CLASS_OF(rb_cBinding), "new"); rb_define_method(rb_cBinding, "clone", bind_clone, 0); rb_cMethod = rb_define_class("Method", rb_cObject); @@ -6013,7 +6124,6 @@ struct thread { VALUE klass; VALUE wrapper; - VALUE trace; int flags; /* misc. states (vmode/rb_trap_immediate/raised) */ char *file; @@ -6152,6 +6262,21 @@ rb_thread_check(data) return (thread_t)RDATA(data)->data; } +static int th_raise_argc; +static VALUE th_raise_argv[2]; +static char *th_raise_file; +static int th_raise_line; +static VALUE th_cmd; +static int th_sig; +static char *th_signm; + +#define RESTORE_NORMAL 1 +#define RESTORE_FATAL 2 +#define RESTORE_INTERRUPT 3 +#define RESTORE_TRAP 4 +#define RESTORE_RAISE 5 +#define RESTORE_SIGNAL 6 + static void rb_thread_save_context(th) thread_t th; @@ -6185,11 +6310,45 @@ rb_thread_save_context(th) th->last_match = rb_backref_get(); th->safe = safe_level; - th->trace = trace_func; th->file = ruby_sourcefile; th->line = ruby_sourceline; } +static int +thread_switch(n) + int n; +{ + switch (n) { + case 0: + return 0; + case RESTORE_FATAL: + JUMP_TAG(TAG_FATAL); + break; + case RESTORE_INTERRUPT: + rb_interrupt(); + break; + case RESTORE_TRAP: + rb_trap_eval(th_cmd, th_sig); + errno = EINTR; + break; + case RESTORE_RAISE: + ruby_frame->last_func = 0; + ruby_sourcefile = th_raise_file; + ruby_sourceline = th_raise_line; + rb_f_raise(th_raise_argc, th_raise_argv); + break; + case RESTORE_SIGNAL: + rb_raise(rb_eSignal, "SIG%s", th_signm); + break; + case RESTORE_NORMAL: + default: + return 1; + } +} + +#define THREAD_SAVE_CONTEXT(th) \ + (rb_thread_save_context(th),thread_switch(setjmp((th)->context))) + static void rb_thread_restore_context _((thread_t,int)); static void @@ -6203,21 +6362,6 @@ stack_extend(th, exit) rb_thread_restore_context(th, exit); } -static int th_raise_argc; -static VALUE th_raise_argv[2]; -static char *th_raise_file; -static int th_raise_line; -static VALUE th_cmd; -static int th_sig; -static 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) thread_t th; @@ -6252,7 +6396,6 @@ rb_thread_restore_context(th, exit) rb_last_status = th->last_status; safe_level = th->safe; - trace_func = th->trace; ruby_sourcefile = th->file; ruby_sourceline = th->line; @@ -6264,35 +6407,7 @@ rb_thread_restore_context(th, exit) rb_lastline_set(tmp->last_line); rb_backref_set(tmp->last_match); - switch (ex) { - case RESTORE_FATAL: - JUMP_TAG(TAG_FATAL); - break; - - case RESTORE_INTERRUPT: - rb_interrupt(); - break; - - case RESTORE_TRAP: - rb_trap_eval(th_cmd, th_sig); - errno = EINTR; - break; - - case RESTORE_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); - } + longjmp(tmp->context, ex); } static void @@ -6441,7 +6556,7 @@ rb_thread_schedule() th->wait_for &= ~WAIT_TIME; th->status = THREAD_RUNNABLE; num_waiting_on_timer--; - next = th; + if (!next) next = th; } else if (th->delay < delay) { delay = th->delay; } @@ -6526,8 +6641,7 @@ rb_thread_schedule() /* context switch */ if (curr == curr_thread) { - rb_thread_save_context(curr); - if (setjmp(curr->context)) { + if (THREAD_SAVE_CONTEXT(curr)) { return; } } @@ -7029,15 +7143,13 @@ rb_thread_create_0(fn, arg, klass) #endif FL_SET(ruby_scope, SCOPE_SHARED); - rb_thread_save_context(curr_thread); - if (setjmp(curr_thread->context)) { + if (THREAD_SAVE_CONTEXT(curr_thread)) { return thread; } PUSH_TAG(PROT_THREAD); if ((state = EXEC_TAG()) == 0) { - rb_thread_save_context(th); - if (setjmp(th->context) == 0) { + if (THREAD_SAVE_CONTEXT(th) == 0) { curr_thread = th; th->result = (*fn)(arg, th); } @@ -7191,8 +7303,7 @@ rb_thread_interrupt() if (curr_thread == main_thread) { rb_interrupt(); } - rb_thread_save_context(curr_thread); - if (setjmp(curr_thread->context)) { + if (THREAD_SAVE_CONTEXT(curr_thread)) { return; } curr_thread = main_thread; @@ -7210,8 +7321,7 @@ rb_thread_signal_raise(sig) rb_raise(rb_eSignal, "SIG%s", sig); } rb_thread_ready(main_thread); - rb_thread_save_context(curr_thread); - if (setjmp(curr_thread->context)) { + if (THREAD_SAVE_CONTEXT(curr_thread)) { return; } th_signm = sig; @@ -7231,8 +7341,7 @@ rb_thread_trap_eval(cmd, sig) return; } rb_thread_ready(main_thread); - rb_thread_save_context(curr_thread); - if (setjmp(curr_thread->context)) { + if (THREAD_SAVE_CONTEXT(curr_thread)) { return; } th_cmd = cmd; @@ -7254,9 +7363,9 @@ rb_thread_raise(argc, argv, thread) rb_f_raise(argc, argv); } - if (curr_thread->status != THREAD_KILLED) + if (!curr_thread->status != THREAD_KILLED) rb_thread_save_context(curr_thread); - if (setjmp(curr_thread->context)) { + if (thread_switch(setjmp(curr_thread->context))) { return thread; } @@ -7277,10 +7386,13 @@ static int rb_thread_loading(feature) const char *feature; { - if (!rb_provided(feature)) return Qfalse; /* need to load */ if (!loading_tbl) { loading_tbl = st_init_strtable(); } + if (!rb_provided(feature)) { + st_insert(loading_tbl, feature, 0); + return Qfalse; /* need to load */ + } while (st_lookup(loading_tbl, feature, 0)) { CHECK_INTS; rb_thread_schedule(); @@ -7293,7 +7405,7 @@ rb_thread_loading_done(feature) const char *feature; { if (loading_tbl) { - st_delete(loading_tbl, feature, 0); + st_delete(loading_tbl, &feature, 0); } } @@ -7380,8 +7492,7 @@ rb_callcc(self) for (tag=prot_tag; tag; tag=tag->prev) { scope_dup(tag->scope); } - rb_thread_save_context(th); - if (setjmp(th->context)) { + if (THREAD_SAVE_CONTEXT(th)) { return th->result; } else { @@ -7489,7 +7600,7 @@ static VALUE catch_i(tag) ID tag; { - return rb_f_catch(0, FIX2INT(tag)); + return rb_funcall(Qnil, rb_intern("catch"), 0, INT2FIX(tag)); } VALUE @@ -7542,7 +7653,7 @@ rb_throw(tag, val) VALUE argv[2]; ID t = rb_intern(tag); - argv[0] = FIX2INT(t); + argv[0] = INT2FIX(t); argv[1] = val; rb_f_throw(2, argv); } diff --git a/ext/Setup.nt b/ext/Setup.nt deleted file mode 100644 index cd7969bb73..0000000000 --- a/ext/Setup.nt +++ /dev/null @@ -1,19 +0,0 @@ -#option nodynamic - -#GD -Win32API -#curses -#dbm -#etc -fcntl -#gdbm -#gtk -marshal -md5 -nkf -#pty -#readline -sdbm -socket -#tcltklib -#tk diff --git a/ext/Win32API/Win32API.c b/ext/Win32API/Win32API.c index 9f75653132..433d13abeb 100644 --- a/ext/Win32API/Win32API.c +++ b/ext/Win32API/Win32API.c @@ -52,13 +52,10 @@ Win32API_initialize(self, dllname, proc, import, export) int len; int ex; - hdll = GetModuleHandle(RSTRING(dllname)->ptr); - if (!hdll) { - hdll = LoadLibrary(RSTRING(dllname)->ptr); - if (!hdll) - rb_raise(rb_eRuntimeError, "LoadLibrary: %s\n", RSTRING(dllname)->ptr); - Data_Wrap_Struct(self, 0, Win32API_FreeLibrary, hdll); - } + hdll = LoadLibrary(RSTRING(dllname)->ptr); + if (!hdll) + rb_raise(rb_eRuntimeError, "LoadLibrary: %s\n", RSTRING(dllname)->ptr); + rb_iv_set(self, "__hdll__", Data_Wrap_Struct(self, 0, Win32API_FreeLibrary, hdll)); hproc = GetProcAddress(hdll, RSTRING(proc)->ptr); if (!hproc) { str = rb_str_new3(proc); @@ -68,9 +65,9 @@ Win32API_initialize(self, dllname, proc, import, export) rb_raise(rb_eRuntimeError, "GetProcAddress: %s or %s\n", RSTRING(proc)->ptr, RSTRING(str)->ptr); } - rb_iv_set(self, "__dll__", INT2NUM((int)hdll)); + rb_iv_set(self, "__dll__", UINT2NUM((unsigned long)hdll)); rb_iv_set(self, "__dllname__", dllname); - rb_iv_set(self, "__proc__", INT2NUM((int)hproc)); + rb_iv_set(self, "__proc__", UINT2NUM((unsigned long)hproc)); a_import = rb_ary_new(); ptr = RARRAY(import)->ptr; @@ -124,7 +121,7 @@ Win32API_Call(argc, argv, obj) ApiVoid *ApiFunctionVoid; ApiInteger *ApiFunctionInteger; - long lParam; + long lParam; char *pParam; VALUE Return; @@ -140,11 +137,11 @@ Win32API_Call(argc, argv, obj) obj_proc = rb_iv_get(obj, "__proc__"); - ApiFunction = (FARPROC)NUM2INT(obj_proc); + ApiFunction = (FARPROC)NUM2ULONG(obj_proc); obj_import = rb_iv_get(obj, "__import__"); obj_export = rb_iv_get(obj, "__export__"); - nimport = RARRAY(obj_import)->len; + nimport = RARRAY(obj_import)->len; texport = FIX2INT(obj_export); if (items != nimport) @@ -159,13 +156,13 @@ Win32API_Call(argc, argv, obj) switch (timport) { case _T_NUMBER: case _T_INTEGER: - lParam = NUM2INT(rb_ary_entry(args, i)); + lParam = NUM2ULONG(rb_ary_entry(args, i)); #if defined(_MSC_VER) || defined(__LCC__) _asm { mov eax, lParam push eax } -#elif defined(__CYGWIN32__) || defined(__MINGW32__) +#elif defined(__CYGWIN__) || defined(__MINGW32__) asm volatile ("pushl %0" :: "g" (lParam)); #else #error @@ -173,15 +170,21 @@ Win32API_Call(argc, argv, obj) break; case _T_POINTER: str = rb_ary_entry(args, i); - Check_Type(str, T_STRING); - rb_str_modify(str); - pParam = RSTRING(str)->ptr; + if (NIL_P(str)) { + pParam = 0; + } else if (FIXNUM_P(str)){ + pParam = (char *)NUM2ULONG(str); + } else { + Check_Type(str, T_STRING); + rb_str_modify(str); + pParam = RSTRING(str)->ptr; + } #if defined(_MSC_VER) || defined(__LCC__) _asm { - mov eax, dword ptr pParam + mov eax, pParam push eax } -#elif defined(__CYGWIN32__) || defined(__MINGW32__) +#elif defined(__CYGWIN__) || defined(__MINGW32__) asm volatile ("pushl %0" :: "g" (pParam)); #else #error @@ -189,7 +192,6 @@ Win32API_Call(argc, argv, obj) break; } } - } switch (texport) { diff --git a/ext/Win32API/depend b/ext/Win32API/depend deleted file mode 100644 index b224bb66c9..0000000000 --- a/ext/Win32API/depend +++ /dev/null @@ -1 +0,0 @@ -Win32API.o : Win32API.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h diff --git a/ext/curses/MANIFEST b/ext/curses/MANIFEST index db5e54ffe8..e1a25d962d 100644 --- a/ext/curses/MANIFEST +++ b/ext/curses/MANIFEST @@ -1,5 +1,6 @@ MANIFEST curses.c +depend extconf.rb hello.rb rain.rb diff --git a/ext/curses/curses.c b/ext/curses/curses.c index 202a0f9244..b0e2ef5bc7 100644 --- a/ext/curses/curses.c +++ b/ext/curses/curses.c @@ -407,50 +407,50 @@ curses_cols() /*-------------------------- class Window --------------------------*/ -/* def new(lines, cols, top, left) */ +/* def new(h, w, top, left) */ static VALUE -window_s_new(class, lines, cols, top, left) +window_s_new(class, h, w, top, left) VALUE class; - VALUE lines; - VALUE cols; + VALUE h; + VALUE w; VALUE top; VALUE left; { - VALUE w; + VALUE win; WINDOW *window; VALUE args[4]; - window = newwin(NUM2INT(lines), NUM2INT(cols), NUM2INT(top), NUM2INT(left)); + window = newwin(NUM2INT(h), NUM2INT(w), NUM2INT(top), NUM2INT(left)); wclear(window); - w = prep_window(class, window); - args[0] = lines; args[1] = cols; args[2] = top; args[3] = left; - rb_obj_call_init(w, 4, args); + win = prep_window(class, window); + args[0] = h; args[1] = w; args[2] = top; args[3] = left; + rb_obj_call_init(win, 4, args); - return w; + return win; } -/* def subwin(lines, cols, top, left) */ +/* def subwin(h, w, top, left) */ static VALUE -window_subwin(obj, lines, cols, top, left) +window_subwin(obj, h, w, top, left) VALUE obj; - VALUE lines; - VALUE cols; + VALUE h; + VALUE w; VALUE top; VALUE left; { struct windata *winp; WINDOW *window; - VALUE w; + VALUE win; VALUE args[4]; GetWINDOW(obj, winp); - window = subwin(winp->window, NUM2INT(lines), NUM2INT(cols), + window = subwin(winp->window, NUM2INT(h), NUM2INT(w), NUM2INT(top), NUM2INT(left)); - w = prep_window(cWindow, window); - args[0] = lines; args[1] = cols; args[2] = top; args[3] = left; - rb_obj_call_init(w, 4, args); + win = prep_window(cWindow, window); + args[0] = h; args[1] = w; args[2] = top; args[3] = left; + rb_obj_call_init(win, 4, args); - return w; + return win; } /* def close */ diff --git a/ext/curses/depend b/ext/curses/depend new file mode 100644 index 0000000000..ecb79e512d --- /dev/null +++ b/ext/curses/depend @@ -0,0 +1 @@ +curses.o: curses.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h diff --git a/ext/dbm/extconf.rb b/ext/dbm/extconf.rb index 55dadc2601..f47287c03e 100644 --- a/ext/dbm/extconf.rb +++ b/ext/dbm/extconf.rb @@ -1,9 +1,10 @@ require 'mkmf' dir_config("dbm") -if have_library("gdbm", "dbm_open") - gdbm = true -end +#if have_library("gdbm", "dbm_open") +# gdbm = true +#end + gdbm = false gdbm or have_library("db", "dbm_open") or have_library("dbm", "dbm_open") have_header("cdefs.h") if have_header("ndbm.h") and have_func("dbm_open") diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in index 3e3ec3992e..20da2a4e47 100644 --- a/ext/extmk.rb.in +++ b/ext/extmk.rb.in @@ -500,7 +500,7 @@ def extmake(target) $objs = nil $local_flags = "" case RUBY_PLATFORM - when /cygwin|beos|openstep|nextstep|rhapsody/ + when /cygwin|beos|openstep|nextstep|rhapsody|i386-os2_emx/ $libs = "" when /mswin32/ $LIBEXT = "lib" diff --git a/ext/kconv/kconv.c b/ext/kconv/kconv.c new file mode 100644 index 0000000000..969c2cb504 --- /dev/null +++ b/ext/kconv/kconv.c @@ -0,0 +1,2017 @@ +/** Network Kanji Filter. (PDS Version) +************************************************************************ +** Copyright (C) 1987, Fujitsu LTD. (Itaru ICHIKAWA) +** 連絡先: (株)富士通研究所 ソフト3研 市川 至 +** (E-Mail Address: ichikawa@flab.fujitsu.co.jp) +** Copyright (C) 1996 +** 連絡先: 琉球大学情報工学科 河野 真治 mine/X0208 support +** (E-Mail Address: kono@ie.u-ryukyu.ac.jp) +** 連絡先: COW for DOS & Win16 & Win32 & OS/2 +** (E-Mail Address: GHG00637@niftyserve.or.jp) +** 営利を目的としない限り、このソースのいかなる +** 複写,改変,修正も許諾します。その際には、この部分を残すこと。 +** このプログラムについては特に何の保証もしない、悪しからず。 +** Everyone is permitted to do anything on this program +** including copying, modifying, improving +** as long as you don't try to make money off it, +** or pretend that you wrote it. +** i.e., the above copyright notice has to appear in all copies. +** THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE. +***********************************************************************/ + +/*********************************************************************** +** 1996/03/10 modified for Kconv - by Ikuo Nakagawa +***********************************************************************/ +/*********************************************************************** +** 1996/12/18 modified for kconv(ruby) - by matz@ruby.club.or.jp +***********************************************************************/ + +static char *CopyRight = + "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa),1996 S. Kono, COW"; +static char *Version = + "1.62"; +static char *Patchlevel = + "5/9612/Shinji Kono, COW matz"; + +#include "ruby.h" + +/* +** +** +** +** USAGE: nkf [flags] [file] +** +** Flags: +** b Output is bufferred (DEFAULT) +** u Output is unbufferred +** +** t no operation +** +** j Outout code is JIS 7 bit (DEFAULT SELECT) +** s Output code is MS Kanji (DEFAULT SELECT) +** e Output code is AT&T JIS (DEFAULT SELECT) +** l Output code is JIS 7bit and ISO8859-1 Latin-1 +** +** m MIME conversion for ISO-2022-JP +** i_ Output sequence to designate JIS-kanji (DEFAULT_J) +** o_ Output sequence to designate single-byte roman characters (DEFAULT_R) +** +** r {de/en}crypt ROT13/47 +** +** v display Version +** +** T Text mode output (for MS-DOS) +** +** x Do not convert X0201 kana into X0208 +** Z Convert X0208 alphabet to ASCII +** +** f60 fold option +** +** m MIME decode +** B try to fix broken JIS, missing Escape +** B[1-9] broken level +** +** O Output to 'nkf.out' file +** d Delete \r in line feed +** c Add \r in line feed +**/ +/******************************/ +/* デフォルトの出力コード選択 */ +/* Select DEFAULT_CODE */ +#define DEFAULT_CODE_JIS +/* #define DEFAULT_CODE_SJIS */ +/* #define DEFAULT_CODE_EUC */ +/******************************/ + +/* for Kconv: _AUTO, _EUC, _SJIS, _JIS */ +#define _AUTO 0 +#define _JIS 1 +#define _EUC 2 +#define _SJIS 3 +#define _BINARY 4 +#define _NOCONV 4 +#define _UNKNOWN _AUTO + +#if (defined(__TURBOC__) || defined(LSI_C)) && !defined(MSDOS) +#define MSDOS +#endif + +#include + +#if defined(MSDOS) || defined(__OS2__) +#include +#include +#include +#endif + +#ifdef MSDOS +#ifdef LSI_C +#define setbinmode(fp) fsetbin(fp) +#else /* Microsoft C, Turbo C */ +#define setbinmode(fp) setmode(fileno(fp), O_BINARY) +#endif +#else /* UNIX,OS/2 */ +#define setbinmode(fp) +#endif + +#ifdef _IOFBF /* SysV and MSDOS */ +#define setvbuffer(fp, buf, size) setvbuf(fp, buf, _IOFBF, size) +#else /* BSD */ +#define setvbuffer(fp, buf, size) setbuffer(fp, buf, size) +#endif + +/*Borland C++ 4.5 EasyWin*/ +#if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */ +#define EASYWIN +#include +#endif + +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +/* state of output_mode and input_mode */ + +#define ASCII 0 +#define X0208 1 +#define X0201 2 +#define NO_X0201 3 +#define JIS_INPUT 4 +#define SJIS_INPUT 5 +#define LATIN1_INPUT 6 +#define FIXED_MIME 7 +#define DOUBLE_SPACE -2 + +#define NL 0x0a +#define ESC 0x1b +#define SP 0x20 +#define AT 0x40 +#define SSP 0xa0 +#define DEL 0x7f +#define SI 0x0f +#define SO 0x0e +#define SSO 0x8e + +#define HOLD_SIZE 32 +#define IOBUF_SIZE 16384 + +#define DEFAULT_J 'B' +#define DEFAULT_R 'B' + +#define SJ0162 0x00e1 /* 01 - 62 ku offset */ +#define SJ6394 0x0161 /* 63 - 94 ku offset */ + + +/* MIME preprocessor */ + +#define _GETC() (inlen-- ? (int)(*inptr++) : EOF) +#define _UNGETC(c) (inlen++, *--inptr = (c)) +#define PUTCHAR(c) (outlen + 1 < outsiz ? \ + ((outptr[outlen++] = (c)), (outptr[outlen] = '\0')) : EOF) +#define GETC() ((!mime_mode)?_GETC():mime_getc()) +#define UNGETC(c) ((!mime_mode)?_UNGETC(c):mime_ungetc(c)) + +#ifdef EASYWIN /*Easy Win */ +extern POINT _BufferSize; +#endif + +/* buffers */ + +static unsigned char hold_buf[HOLD_SIZE*2]; +static int hold_count; +static unsigned char *inptr; +static int inlen; +static char *outptr; +static int outsiz; +static int outlen; + +/* MIME preprocessor fifo */ + +#define MIME_BUF_SIZE (1024) /* 2^n ring buffer */ +#define MIME_BUF_MASK (MIME_BUF_SIZE-1) +#define Fifo(n) mime_buf[(n)&MIME_BUF_MASK] +static unsigned char mime_buf[MIME_BUF_SIZE]; +static unsigned int mime_top = 0; +static unsigned int mime_last = 0; /* decoded */ +static unsigned int mime_input = 0; /* undecoded */ + +/* flags */ +static int unbuf_f = FALSE; +static int estab_f = FALSE; +static int rot_f = FALSE; /* rot14/43 mode */ +static int input_f = FALSE; /* non fixed input code */ +static int alpha_f = FALSE; /* convert JIx0208 alphbet to ASCII */ +static int mime_f = FALSE; /* convert MIME B base64 or Q */ +static int mimebuf_f = FALSE; /* MIME buffered input */ +static int broken_f = FALSE; /* convert ESC-less broken JIS */ +static int iso8859_f = FALSE; /* ISO8859 through */ +#if defined(MSDOS) || defined(__OS2__) +static int x0201_f = TRUE; /* Assume JISX0201 kana */ +#else +static int x0201_f = NO_X0201; /* Assume NO JISX0201 */ +#endif + +/* X0208 -> ASCII converter */ + +static int c1_return; + +/* fold parameter */ +static int line = 0; /* chars in line */ +static int prev = 0; +static int fold_f = FALSE; +static int fold_len = 0; + +/* options */ +static char kanji_intro = DEFAULT_J, + ascii_intro = DEFAULT_R; + +/* Folding */ + +#define FOLD_MARGIN 10 +#define DEFAULT_FOLD 60 + +/* Global states */ +static int output_mode = ASCII, /* output kanji mode */ + input_mode = ASCII, /* input kanji mode */ + shift_mode = FALSE; /* TRUE shift out, or X0201 */ +static int mime_mode = FALSE; /* MIME mode B base64, Q hex */ + +/* X0208 -> ASCII translation table */ +/* X0201 / X0208 conversion tables */ + +/* X0201 kana conversion table */ +/* 90-9F A0-DF */ +static unsigned char cv[]= { +0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57, +0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21, +0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29, +0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43, +0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26, +0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d, +0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35, +0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d, +0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46, +0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c, +0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52, +0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e, +0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62, +0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69, +0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d, +0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c, +0x00,0x00}; + + +/* X0201 kana conversion table for daguten */ +/* 90-9F A0-DF */ +static unsigned char dv[]= { +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e, +0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36, +0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e, +0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47, +0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53, +0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00}; + +/* X0201 kana conversion table for han-daguten */ +/* 90-9F A0-DF */ +static unsigned char ev[]= { +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54, +0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00}; + + +/* X0208 kigou conversion table */ +/* 0x8140 - 0x819e */ +static unsigned char fv[] = { +0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a, +0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00, +0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f, +0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27, +0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d, +0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00, +0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +} ; + + +/* This converts =?ISO-2022-JP?B?HOGE HOGE?= */ + +static unsigned char *mime_pattern[] = { + (unsigned char *)"\075?ISO-8859-1?Q?", + (unsigned char *)"\075?ISO-2022-JP?B?", + (unsigned char *)"\075?ISO-2022-JP?Q?", + NULL +}; + +static int mime_encode[] = { + 'Q', 'B', 'Q', + 0 +}; + +static int add_cr = FALSE; +static int del_cr = FALSE; + +static void (*iconv) _((register int c2,register int c1)); /* s_iconv or oconv */ +static void (*oconv) _((register int c2,register int c1)); /* [ejs]_oconv */ +static int do_kconv _((VALUE, VALUE, int out_code, int in_code)); +static void h_conv _((register int c2,register int c1)); +static int push_hold_buf _((int c2,int c1)); +static void s_iconv _((register int c2,register int c1)); +static void e_oconv _((register int c2,register int c1)); +static void s_oconv _((register int c2,register int c1)); +static void j_oconv _((register int c2,register int c1)); +static int fold _((register int c2,register int c1)); +static int pre_convert _((register int c1,register int c2)); +static int mime_begin _((void)); +static int mime_getc _((void)); +static int mime_ungetc _((unsigned int c)); +static int mime_integrity _((unsigned char *p)); +static int base64decode _((int c)); + +#ifdef notdef +main (argc, argv) + int argc; + char **argv; +{ + register FILE *fin; + register char *cp; + +#ifdef EASYWIN /*Easy Win */ + _BufferSize.y = 400;/*Set Scroll Buffer Size*/ +#endif +#ifdef DEFAULT_CODE_JIS + oconv = j_oconv; /* DEFAULT Code is JIS */ +#endif +#ifdef DEFAULT_CODE_SJIS + oconv = s_oconv; /* DEFAULT Code is S-JIS */ +#endif +#ifdef DEFAULT_CODE_EUC + oconv = e_oconv; /* DEFAULT Code is EUC */ +#endif + + for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) { + cp = *argv; + while (*cp) { + switch (*cp++) { + case 'b': /* buffered mode */ + unbuf_f = FALSE; + continue; + case 'u': /* non bufferd mode */ + unbuf_f = TRUE; + continue; + case 'j': /* JIS output */ + case 'n': + oconv = j_oconv; + continue; + case 'e': /* AT&T EUC output */ + oconv = e_oconv; + continue; + case 's': /* SJIS output */ + oconv = s_oconv; + continue; + case 'l': /* ISO8859 Latin-1 support, no conversion */ + iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */ + input_f = LATIN1_INPUT; + continue; + case 'i': /* Kanji IN ESC-$-@/B */ + if(*cp=='@'||*cp=='B') + kanji_intro = *cp++; + continue; + case 'o': /* ASCII IN ESC-(-J/B */ + if(*cp=='J'||*cp=='B'||*cp=='H') + ascii_intro = *cp++; + continue; + case 'r': + rot_f = TRUE; + continue; +#if defined(MSDOS) || defined(__OS2__) + case 'T': + binmode_f = FALSE; + continue; +#endif + case 'v': + usage(); + exit(1); + break; + /* Input code assumption */ + case 'J': /* JIS input */ + case 'E': /* AT&T EUC input */ + input_f = JIS_INPUT; + continue; + case 'S': /* MS Kanji input */ + input_f = SJIS_INPUT; + if(x0201_f==NO_X0201) x0201_f=TRUE; + continue; + case 'Z': /* Convert X0208 alphabet to asii */ + /* bit:0 Convert X0208 + bit:1 Convert Kankaku to one space + bit:2 Convert Kankaku to two spaces + */ + if('9'>= *cp && *cp>='0') + alpha_f |= 1<<(*cp++ -'0'); + else + alpha_f |= TRUE; + continue; + case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */ + x0201_f = FALSE; /* No X0201->X0208 conversion */ + /* accept X0201 + ESC-(-I in JIS, EUC, MS Kanji + SI/SO in JIS, EUC, MS Kanji + SSO in EUC, JIS, not in MS Kanji + MS Kanji (0xa0-0xdf) + output X0201 + ESC-(-I in JIS (0x20-0x5f) + SSO in EUC (0xa0-0xdf) + 0xa0-0xd in MS Kanji (0xa0-0xdf) + */ + continue; + case 'X': /* Assume X0201 kana */ + /* Default value is NO_X0201 for EUC/MS-Kanji mix */ + x0201_f = TRUE; + continue; + case 'f': /* folding -f60 or -f */ + fold_f = TRUE; + fold_len = atoi(cp); + if(!(0= *cp && *cp>='0') + broken_f |= 1<<(*cp++ -'0'); + else + broken_f |= TRUE; + continue; + case 'O':/* for Output file */ + file_out = TRUE; + continue; + case 'c':/* add cr code */ + add_cr = TRUE; + continue; + case 'd':/* delete cr code */ + del_cr = TRUE; + continue; + default: + /* bogus option but ignored */ + continue; + } + } + } + + if(iso8859_f && (oconv != j_oconv || !x0201_f )) { + fprintf(stderr,"Mixed ISO8859/JISX0201/SJIS/EUC output is not allowed.\n"); + exit(1); + } + + if(binmode_f == TRUE) +#ifdef __OS2__ + if(freopen("","wb",stdout) == NULL) + return (-1); +#else + setbinmode(stdout); +#endif + + if(unbuf_f) + setbuf (stdout, (char *) NULL); + else + setvbuffer (stdout, stdobuf, IOBUF_SIZE); + + if(argc == 0) { + if(binmode_f == TRUE) +#ifdef __OS2__ + if(freopen("","rb",stdin) == NULL) return (-1); +#else + setbinmode(stdin); +#endif + setvbuffer (stdin, stdibuf, IOBUF_SIZE); + convert (stdin); + } else { + while (argc--) { + if((fin = fopen (*argv++, "r")) == NULL) { + perror (*--argv); + return (-1); + } else { +/* reopen file for stdout */ + if(file_out == TRUE){ + if(argc == 1 ) { + if(freopen(*argv++, "w", stdout) == NULL) { + perror (*--argv); + return (-1); + } + argc--; + } else { + if(freopen("nkf.out", "w", stdout) == NULL) { + perror (*--argv); + return (-1); + } + } + if(binmode_f == TRUE) { +#ifdef __OS2__ + if(freopen("","wb",stdout) == NULL) + return (-1); +#else + setbinmode(stdout); +#endif + } + } + if(binmode_f == TRUE) +#ifdef __OS2__ + if(freopen("","rb",fin) == NULL) + return (-1); +#else + setbinmode(fin); +#endif + setvbuffer (fin, stdibuf, IOBUF_SIZE); + convert (fin); + fclose (fin); + } + } + } +#ifdef EASYWIN /*Easy Win */ + if(file_out == FALSE) + scanf("%d",&end_check); + else + fclose(stdout); +#else /* for Other OS */ + if(file_out == TRUE) + fclose(stdout); +#endif + return (0); +} +#endif /* notdef */ + +static int +do_kconv(in, out, out_code, in_code) + VALUE in, out; + int out_code, in_code; +{ + register int c1, c2; + + c2 = 0; + + inptr = (unsigned char *)RSTRING(in)->ptr; /* input buffer */ + inlen = RSTRING(in)->len; /* input buffer size*/ + outptr = RSTRING(out)->ptr; /* output buffer */ + outsiz = RSTRING(out)->len; /* output buffer size */ + outlen = 0; /* current length of output string */ + + if (inlen <= 0) { + return 0; + } + *outptr = '\0'; + + x0201_f = TRUE; /* don't assume JISX0201 kana */ + rot_f = FALSE; /* rot14/43 mode */ + input_f = FALSE; /* non fixed input code */ + alpha_f = FALSE; /* convert JISX0208 alphbet to ASCII */ + mime_f = TRUE; /* convert MIME base64 */ + broken_f = FALSE; /* convert ESC-less broken JIS */ + + switch (out_code) { + case _SJIS: + oconv = s_oconv; + break; + case _EUC: + oconv = e_oconv; + break; + default: + oconv = j_oconv; + break; + } + + switch (in_code) { + case _SJIS: + input_f = SJIS_INPUT; + x0201_f = TRUE; + break; + case _EUC: + case _JIS: + input_f = JIS_INPUT; + break; + default: + input_f = FALSE; + break; + } + + if(input_f == JIS_INPUT || input_f == LATIN1_INPUT) { + estab_f = TRUE; iconv = oconv; + } else if(input_f == SJIS_INPUT) { + estab_f = TRUE; iconv = s_iconv; + } else { + estab_f = FALSE; iconv = oconv; + } + input_mode = ASCII; + output_mode = ASCII; + shift_mode = FALSE; + mime_mode = FALSE; + +#define NEXT continue /* no output, get next */ +#define SEND ; /* output c1 and c2, get next */ +#define LAST break /* end of loop, go closing */ + + while ((c1 = GETC()) != EOF) { + if(!c2 && !input_mode && c1 DEL) { + /* in case of 8th bit is on */ + if(!estab_f) { + /* in case of not established yet */ + if(c1 > SSP) { + /* It is still ambiguious */ + h_conv (c2, c1); + c2 = 0; + NEXT; + } else if(c1 < AT) { + /* ignore bogus code */ + c2 = 0; + NEXT; + } else { + /* established */ + /* it seems to be MS Kanji */ + estab_f = TRUE; + iconv = s_iconv; + SEND; + } + } else + /* in case of already established */ + if(c1 < AT) { + /* ignore bogus code */ + c2 = 0; + NEXT; + } else + SEND; + } else + /* 7 bit code */ + /* it might be kanji shitfted */ + if((c1 == DEL) || (c1 <= SP)) { + /* ignore bogus first code */ + c2 = 0; + NEXT; + } else + SEND; + } else { + /* first byte */ + if(c1 > DEL) { + /* 8 bit code */ + if(!estab_f && !iso8859_f) { + /* not established yet */ + if(c1 < SSP) { + /* it seems to be MS Kanji */ + estab_f = TRUE; + iconv = s_iconv; + } else if(c1 < 0xe0) { + /* it seems to be EUC */ + estab_f = TRUE; + iconv = oconv; + } else { + /* still ambiguious */ + } + c2 = c1; + NEXT; + } else { /* estab_f==TRUE */ + if(iso8859_f) { + SEND; + } else if(SSP<=c1 && c1<0xe0 && iconv == s_iconv) { + /* SJIS X0201 Case... */ + /* This is too arrogant, but ... */ + if(x0201_f==NO_X0201) { + iconv = oconv; + c2 = c1; + NEXT; + } else + if(x0201_f) { + if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) { + /* look ahead for X0201/X0208conversion */ + if((c2 = GETC()) == EOF) { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + LAST; + } else if(c2==(0xde)) { /* 濁点 */ + (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]); + c2=0; + NEXT; + } else if(c2==(0xdf)&&ev[(c1-SSP)*2]) { + /* 半濁点 */ + (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]); + c2=0; + NEXT; + } + UNGETC(c2); c2 = 0; + } + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + NEXT; + } else + SEND; + } else if(c1==SSO && iconv != s_iconv) { + /* EUC X0201 Case */ + /* This is too arrogant + if(x0201_f == NO_X0201) { + estab_f = FALSE; + c2 = 0; + NEXT; + } */ + c1 = GETC(); /* skip SSO */ + euc_1byte_check: + if(x0201_f && SSP<=c1 && c1<0xe0) { + if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) { + if((c2 = GETC()) == EOF) { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + LAST; + } + /* forward lookup 濁点/半濁点 */ + if(c2 != SSO) { + UNGETC(c2); c2 = 0; + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + NEXT; + } else if((c2 = GETC()) == EOF) { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + (*oconv)(0,SSO); + LAST; + } else if(c2==(0xde)) { /* 濁点 */ + (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]); + c2=0; + NEXT; + } else if(c2==(0xdf)&&ev[(c1-SSP)*2]) { + /* 半濁点 */ + (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]); + c2=0; + NEXT; + } else { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + /* we have to check this c2 */ + /* and no way to push back SSO */ + c1 = c2; c2 = 0; + goto euc_1byte_check; + } + } + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + NEXT; + } else + SEND; + } else if(c1 < SSP && iconv != s_iconv) { + /* strange code in EUC */ + iconv = s_iconv; /* try SJIS */ + c2 = c1; + NEXT; + } else { + /* already established */ + c2 = c1; + NEXT; + } + } + } else if((c1 > SP) && (c1 != DEL)) { + /* in case of Roman characters */ + if(shift_mode) { + c1 |= 0x80; + /* output 1 shifted byte */ + if(x0201_f && (!iso8859_f||input_mode==X0201) && + SSP<=c1 && c1<0xe0 ) { + if(dv[(c1-SSP)*2]||ev[(c1-SSP)*2]) { + if((c2 = GETC()) == EOF) { + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + LAST; + } else if(c2==(0xde&0x7f)) { /* 濁点 */ + (*oconv)(dv[(c1-SSP)*2],dv[(c1-SSP)*2+1]); + c2=0; + NEXT; + } else if(c2==(0xdf&0x7f)&&ev[(c1-SSP)*2]) { + /* 半濁点 */ + (*oconv)(ev[(c1-SSP)*2],ev[(c1-SSP)*2+1]); + c2=0; + NEXT; + } + UNGETC(c2); c2 = 0; + } + (*oconv)(cv[(c1-SSP)*2],cv[(c1-SSP)*2+1]); + NEXT; + } else + SEND; + } else if(c1 == '(' && broken_f && input_mode == X0208 + && !mime_mode ) { + /* Try to recover missing escape */ + if((c1 = GETC()) == EOF) { + (*oconv) (0, '('); + LAST; + } else { + if(c1 == 'B' || c1 == 'J' || c1 == 'H') { + input_mode = ASCII; shift_mode = FALSE; + NEXT; + } else { + (*oconv) (0, '('); + /* do not modify various input_mode */ + /* It can be vt100 sequence */ + SEND; + } + } + } else if(input_mode == X0208) { + /* in case of Kanji shifted */ + c2 = c1; + NEXT; + /* goto next_byte */ + } else if(c1 == '=' && mime_f && !mime_mode ) { + if((c1 = _GETC()) == EOF) { + (*oconv) (0, '='); + LAST; + } else if(c1 == '?') { + /* =? is mime conversion start sequence */ + if(mime_begin() == EOF) /* check in detail */ + LAST; + else + NEXT; + } else { + (*oconv) (0, '='); + _UNGETC(c1); + NEXT; + } + } else if(c1 == '$' && broken_f && !mime_mode) { + /* try to recover missing escape */ + if((c1 = GETC()) == EOF) { + (*oconv) (0, '$'); + LAST; + } else if(c1 == '@'|| c1 == 'B') { + /* in case of Kanji in ESC sequence */ + input_mode = X0208; + shift_mode = FALSE; + NEXT; + } else { + /* sorry */ + (*oconv) (0, '$'); + (*oconv) (0, c1); + NEXT; + } + } else + SEND; + } else if(c1 == SI) { + shift_mode = FALSE; + NEXT; + } else if(c1 == SO) { + shift_mode = TRUE; + NEXT; + } else if(c1 == ESC ) { + if((c1 = GETC()) == EOF) { + (*oconv) (0, ESC); + LAST; + } else if(c1 == '$') { + if((c1 = GETC()) == EOF) { + (*oconv) (0, ESC); + (*oconv) (0, '$'); + LAST; + } else if(c1 == '@'|| c1 == 'B') { + /* This is kanji introduction */ + input_mode = X0208; + shift_mode = FALSE; + NEXT; + } else if(broken_f&0x2) { + input_mode = X0208; + shift_mode = FALSE; + NEXT; + } else { + (*oconv) (0, ESC); + (*oconv) (0, '$'); + (*oconv) (0, c1); + NEXT; + } + } else if(c1 == '(') { + if((c1 = GETC()) == EOF) { + (*oconv) (0, ESC); + (*oconv) (0, '('); + LAST; + } else { + if(c1 == 'I') { + /* This is X0201 kana introduction */ + input_mode = X0201; shift_mode = X0201; + NEXT; + } else if(c1 == 'B' || c1 == 'J' || c1 == 'H') { + /* This is X0208 kanji introduction */ + input_mode = ASCII; shift_mode = FALSE; + NEXT; + } else if(broken_f&0x2) { + input_mode = ASCII; shift_mode = FALSE; + NEXT; + } else { + (*oconv) (0, ESC); + (*oconv) (0, '('); + /* maintain various input_mode here */ + SEND; + } + } + } else { + /* lonely ESC */ + (*oconv) (0, ESC); + SEND; + } + } else if(c1 == NL && broken_f&4) { + input_mode = ASCII; + SEND; + } else + SEND; + } + /* send: */ + if(input_mode == X0208) + (*oconv) (c2, c1); /* this is JIS, not SJIS/EUC case */ + else + (*iconv) (c2, c1); /* can be EUC/SJIS */ + c2 = 0; + continue; + /* goto next_word */ + } + + /* epilogue */ + (*iconv) (EOF, 0); + return outlen; +} + + +static void +h_conv (c2, c1) + register int c1, + c2; +{ + register int wc; + + + /** it must NOT be in the kanji shifte sequence */ + /** it must NOT be written in JIS7 */ + /** and it must be after 2 byte 8bit code */ + + hold_count = 0; + push_hold_buf (c2, c1); + c2 = 0; + + while ((c1 = GETC()) != EOF) { + if(c2) { + /* second byte */ + if(!estab_f) { + /* not established */ + if(c1 > SSP) { + /* it is still ambiguious yet */ + SEND; + } else if(c1 < AT) { + /* ignore bogus first byte */ + c2 = 0; + SEND; + } else { + /* now established */ + /* it seems to be MS Kanji */ + estab_f = TRUE; + iconv = s_iconv; + SEND; + } + } else + SEND; + } else { + /* First byte */ + if(c1 > DEL) { + /* 8th bit is on */ + if(c1 < SSP) { + /* it seems to be MS Kanji */ + estab_f = TRUE; + iconv = s_iconv; + } else if(c1 < 0xe0) { + /* it seems to be EUC */ + estab_f = TRUE; + iconv = oconv; + } else { + /* still ambiguious */ + } + c2 = c1; + NEXT; + } else + /* 7 bit code , then send without any process */ + SEND; + } + /* send: */ + if((push_hold_buf (c2, c1) == EOF) || estab_f) + break; + c2 = 0; + continue; + } + + /** now, + ** 1) EOF is detected, or + ** 2) Code is established, or + ** 3) Buffer is FULL (but last word is pushed) + ** + ** in 1) and 3) cases, we continue to use + ** Kanji codes by oconv and leave estab_f unchanged. + **/ + + for (wc = 0; wc < hold_count; wc += 2) { + c2 = hold_buf[wc]; + c1 = hold_buf[wc+1]; + (*iconv) (c2, c1); + } + return; +} + + + +static int +push_hold_buf (c2, c1) + int c2, + c1; +{ + if(hold_count >= HOLD_SIZE*2) + return (EOF); + hold_buf[hold_count++] = c2; + hold_buf[hold_count++] = c1; + return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count); +} + + +static void +s_iconv (c2, c1) + register int c2, + c1; +{ + if((c2 == EOF) || (c2 == 0)) { + /* NOP */ + } else { + c2 = c2 + c2 - ((c2 <= 0x9f) ? SJ0162 : SJ6394); + if(c1 < 0x9f) + c1 = c1 - ((c1 > DEL) ? SP : 0x1f); + else { + c1 = c1 - 0x7e; + c2++; + } + } + (*oconv) (c2, c1); +} + + +static void +e_oconv (c2, c1) + register int c2, + c1; +{ + c2 = pre_convert(c1,c2); c1 = c1_return; + if(fold_f) { + switch(fold(c2,c1)) { + case '\n': + if(add_cr == TRUE) { + PUTCHAR('\r'); + c1 = '\n'; + } + PUTCHAR('\n'); + break; + case 0: return; + case '\r': + c1 = '\n'; c2 = 0; + break; + case '\t': + case ' ': + c1 = ' '; c2 = 0; + break; + } + } + if(c2==DOUBLE_SPACE) { + PUTCHAR(' '); PUTCHAR(' '); + return; + } + if(c2 == EOF) + return; + else if(c2 == 0 && (c1&0x80)) { + PUTCHAR(SSO); PUTCHAR(c1); + } else if(c2 == 0) { + if(c1 == '\n' && add_cr == TRUE) + PUTCHAR('\r'); + if(c1 != '\r') + PUTCHAR(c1); + else if(del_cr == FALSE) + PUTCHAR(c1); + } else { + if((c1<0x20 || 0x7e> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1))); + PUTCHAR((c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e))); + } +} + +static void +j_oconv (c2, c1) + register int c2, + c1; +{ + c2 = pre_convert(c1,c2); c1 = c1_return; + if(fold_f) { + switch(fold(c2,c1)) { + case '\n': + if(output_mode) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR(ascii_intro); + } + if(add_cr == TRUE) { + PUTCHAR('\r'); + c1 = '\n'; + } + PUTCHAR('\n'); + output_mode = ASCII; + break; + case '\r': + c1 = '\n'; c2 = 0; + break; + case '\t': + case ' ': + c1 = ' '; c2 = 0; + break; + case 0: return; + } + } + if(c2 == EOF) { + if(output_mode) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR(ascii_intro); + } + } else if(c2 == 0 && (c1 & 0x80)) { + if(input_mode==X0201 || !iso8859_f) { + if(output_mode!=X0201) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR('I'); + output_mode = X0201; + } + c1 &= 0x7f; + } else { + /* iso8859 introduction, or 8th bit on */ + /* Can we convert in 7bit form using ESC-'-'-A ? + Is this popular? */ + } + PUTCHAR(c1); + } else if(c2 == 0) { + if(output_mode) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR(ascii_intro); + output_mode = ASCII; + } + if(c1 == '\n' && add_cr == TRUE) + PUTCHAR('\r'); + if(c1 != '\r') + PUTCHAR(c1); + else if(del_cr == FALSE) + PUTCHAR(c1); + } else if(c2 == DOUBLE_SPACE) { + if(output_mode) { + PUTCHAR(ESC); + PUTCHAR('('); + PUTCHAR(ascii_intro); + output_mode = ASCII; + } + PUTCHAR(' '); + if(c1 == '\n' && add_cr == TRUE) + PUTCHAR('\r'); + if(c1 != '\r') + PUTCHAR(c1); + else if(del_cr == FALSE) + PUTCHAR(c1); + } else { + if(output_mode != X0208) { + PUTCHAR(ESC); + PUTCHAR('$'); + PUTCHAR(kanji_intro); + output_mode = X0208; + } + if(c1<0x20 || 0x7e0x80 Japanese (X0208/X0201) + <0x80 ASCII + \n new line + ' ' space + + This fold algorthm does not preserve heading space in a line. + This is the main difference from fmt. +*/ + +static int +fold(c2,c1) +register int c2,c1; +{ + int prev0; + if(c1=='\r') + return 0; /* ignore cr */ + if(c1== 8) { + if(line>0) line--; + return 1; + } + if(c2==EOF && line != 0) /* close open last line */ + return '\n'; + /* new line */ + if(c1=='\n') { + if(prev == c1) { /* duplicate newline */ + if(line) { + line = 0; + return '\n'; /* output two newline */ + } else { + line = 0; + return 1; + } + } else { + if(prev&0x80) { /* Japanese? */ + prev = c1; + return 0; /* ignore given single newline */ + } else if(prev==' ') { + return 0; + } else { + prev = c1; + if(++line<=fold_len) + return ' '; + else { + line = 0; + return '\r'; /* fold and output nothing */ + } + } + } + } + if(c1=='\f') { + prev = '\n'; + if(line==0) + return 1; + line = 0; + return '\n'; /* output newline and clear */ + } + /* X0208 kankaku or ascii space */ + if( (c2==0&&c1==' ')|| + (c2==0&&c1=='\t')|| + (c2==DOUBLE_SPACE)|| + (c2=='!'&& c1=='!')) { + if(prev == ' ') { + return 0; /* remove duplicate spaces */ + } + prev = ' '; + if(++line<=fold_len) + return ' '; /* output ASCII space only */ + else { + prev = ' '; line = 0; + return '\r'; /* fold and output nothing */ + } + } + prev0 = prev; /* we still need this one... , but almost done */ + prev = c1; + if(c2 || (SSP<=c1 && c1<=0xdf)) + prev |= 0x80; /* this is Japanese */ + line += (c2==0)?1:2; + if(line<=fold_len) { /* normal case */ + return 1; + } + if(line>=fold_len+FOLD_MARGIN) { /* too many kinsou suspension */ + line = (c2==0)?1:2; + return '\n'; /* We can't wait, do fold now */ + } + /* simple kinsoku rules return 1 means no folding */ + if(c2==0) { + if(c1==0xde) return 1; /* ゛*/ + if(c1==0xdf) return 1; /* ゜*/ + if(c1==0xa4) return 1; /* 。*/ + if(c1==0xa3) return 1; /* ,*/ + if(c1==0xa1) return 1; /* 」*/ + if(c1==0xb0) return 1; /* - */ + if(SSP<=c1 && c1<=0xdf) { /* X0201 */ + line = 1; + return '\n';/* add one new line before this character */ + } + /* fold point in ASCII { [ ( */ + if(( c1!=')'&& + c1!=']'&& + c1!='}'&& + c1!='.'&& + c1!=','&& + c1!='!'&& + c1!='?'&& + c1!='/'&& + c1!=':'&& + c1!=';')&& + ((prev0=='\n')|| (prev0==' ')|| /* ignored new line */ + (prev0&0x80)) /* X0208 - ASCII */ + ) { + line = 1; + return '\n';/* add one new line before this character */ + } + return 1; /* default no fold in ASCII */ + } else { + if(c2=='!') { + if(c1=='"') return 1; /* 、 */ + if(c1=='#') return 1; /* 。 */ + if(c1=='$') return 1; /* , */ + if(c1=='%') return 1; /* . */ + if(c1=='\'') return 1; /* + */ + if(c1=='(') return 1; /* ; */ + if(c1==')') return 1; /* ? */ + if(c1=='*') return 1; /* ! */ + if(c1=='+') return 1; /* ゛ */ + if(c1==',') return 1; /* ゜ */ + } + line = 2; + return '\n'; /* add one new line before this character */ + } +} + +static int +pre_convert(c1,c2) +register int c1,c2; +{ + if(c2) c1 &= 0x7f; + c1_return = c1; + if(c2==EOF) return c2; + c2 &= 0x7f; + if(rot_f) { + if(c2) { + c1 = rot47(c1); + c2 = rot47(c2); + } else { + if(!(c1 & 0x80)) + c1 = rot13(c1); + } + c1_return = c1; + } + /* JISX0208 Alphabet */ + if(alpha_f && c2 == 0x23 ) return 0; + /* JISX0208 Kigou */ + if(alpha_f && c2 == 0x21 ) { + if(0x21==c1) { + if(alpha_f&0x2) { + c1_return = ' '; + return 0; + } else if(alpha_f&0x4) { + c1_return = ' '; + return DOUBLE_SPACE; + } else { + return c2; + } + } else if(0x20' ';i++) { /* start at =? */ + if( ((r[i] = c1 = _GETC())==EOF) || nkf_toupper(c1) != p[i] ) { + /* pattern fails, try next one */ + q = p; + while (p = mime_pattern[++j]) { + for(k=2;k i */ + if(p[k]!=q[k]) break; + if(k==i && nkf_toupper(c1)==p[k]) break; + } + if(p) continue; /* found next one, continue */ + /* all fails, output from recovery buffer */ + _UNGETC(c1); + for(j=0;j> 4) & 0x03); + if(c2 != '=') { + Fifo(mime_last++) = cc; + cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f); + if(c3 != '=') { + Fifo(mime_last++) = cc; + cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f); + if(c4 != '=') + Fifo(mime_last++) = cc; + } + } else { + return c1; + } + return Fifo(mime_top++); +} + +static int +mime_ungetc(c) +unsigned int c; +{ + Fifo(mime_last++) = c; + return c; +} + + +static int +mime_integrity(p) +unsigned char *p; +{ + int c,d; + unsigned int q; + /* In buffered mode, read until =? or NL or buffer full + */ + mime_input = mime_top; + mime_last = mime_top; + while(*p) Fifo(mime_input++) = *p++; + d = 0; + q = mime_input; + while((c=_GETC())!=EOF) { + if(((mime_input-mime_top)&MIME_BUF_MASK)==0) break; + if(c=='=' && d=='?') { + /* checked. skip header, start decode */ + Fifo(mime_input++) = c; + mime_input = q; + return 1; + } + if(!( (c=='+'||c=='/'|| c=='=' || c=='?' || + ('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9')))) + break; + /* Should we check length mod 4? */ + Fifo(mime_input++) = c; + d=c; + } + /* In case of Incomplete MIME, no MIME decode */ + Fifo(mime_input++) = c; + mime_last = mime_input; /* point undecoded buffer */ + mime_mode = 1; /* no decode on Fifo last in mime_getc */ + return 1; +} + +static int +base64decode(c) + int c; +{ + int i; + if(c > '@') + if(c < '[') + i = c - 'A'; /* A..Z 0-25 */ + else + i = c - 'G' /* - 'a' + 26 */ ; /* a..z 26-51 */ + else if(c > '/') + i = c - '0' + '4' /* - '0' + 52 */ ; /* 0..9 52-61 */ + else if(c == '+') + i = '>' /* 62 */ ; /* + 62 */ + else + i = '?' /* 63 */ ; /* / 63 */ + return (i); +} + +#ifdef notdef +int +usage() +{ + fprintf(stderr,"USAGE: nkf(nkf32,wnkf,nkf2) -[flags] [in file] .. [out file for -O flag]\n"); + fprintf(stderr,"Flags:\n"); + fprintf(stderr,"b,u Output is bufferred (DEFAULT),Output is unbufferred\n"); +#ifdef DEFAULT_CODE_SJIS + fprintf(stderr,"j,s,e Outout code is JIS 7 bit, Shift JIS (DEFAULT), AT&T JIS (EUC)\n"); +#endif +#ifdef DEFAULT_CODE_JIS + fprintf(stderr,"j,s,e Outout code is JIS 7 bit (DEFAULT), Shift JIS, AT&T JIS (EUC)\n"); +#endif +#ifdef DEFAULT_CODE_EUC + fprintf(stderr,"j,s,e Outout code is JIS 7 bit, Shift JIS, AT&T JIS (EUC) (DEFAULT)\n"); +#endif + fprintf(stderr,"J,S,E Input assumption is JIS 7 bit , Shift JIS, AT&T JIS (EUC)\n"); + fprintf(stderr,"t no conversion\n"); + fprintf(stderr,"i_ Output sequence to designate JIS-kanji (DEFAULT B)\n"); + fprintf(stderr,"o_ Output sequence to designate ASCII (DEFAULT B)\n"); + fprintf(stderr,"r {de/en}crypt ROT13/47\n"); + fprintf(stderr,"v Show this usage\n"); + fprintf(stderr,"m[BQ] MIME decode [B:base64 stream,Q:quoted stream]\n"); + fprintf(stderr,"l ISO8859-1 (Latin-1) support\n"); + fprintf(stderr,"f Folding: -f60 or -f\n"); + fprintf(stderr,"Z[0-2] Convert X0208 alphabet to ASCII 1: Kankaku to space,2: 2 spaces\n"); + fprintf(stderr,"X,x Assume X0201 kana in MS-Kanji, -x preserves X0201\n"); + fprintf(stderr,"B[0-2] Broken input 0: missing ESC,1: any X on ESC-[($]-X,2: ASCII on NL\n"); +#ifdef MSDOS + fprintf(stderr,"T Text mode output\n"); +#endif + fprintf(stderr,"O Output to File (DEFAULT 'nkf.out')\n"); + fprintf(stderr,"d,c Delete \\r in line feed, Add \\r in line feed\n"); + fprintf(stderr,"Network Kanji Filter Version %s (%s) " +#if defined(MSDOS) && !defined(_Windows) + "for DOS" +#endif +#if !defined(__WIN32__) && defined(_Windows) + "for Win16" +#endif +#if defined(__WIN32__) && defined(_Windows) + "for Win32" +#endif +#ifdef __OS2__ + "for OS/2" +#endif + ,Version,Patchlevel); + fprintf(stderr,"\n%s\n",CopyRight); + return 0; +} +#endif /* notdef */ + +static VALUE +kconv_kconv(argc, argv) + int argc; + VALUE *argv; +{ + VALUE src, dst; + VALUE in, out; + int in_code, out_code; + char *codename = 0; + + rb_scan_args(argc, argv, "12", &src, &out, &in); + Check_Type(src, T_STRING); + + if (NIL_P(out)) { + codename = rb_get_kcode(); + goto codeselect; + } + else if (TYPE(out) == T_STRING) { + codename = RSTRING(out)->ptr; + codeselect: + switch (codename[0]) { + case 'E': case 'e': + out_code = _EUC; + break; + case 'S': case 's': + out_code = _SJIS; + break; + case 'J': case 'j': + default: + out_code = _JIS; + break; + } + } + else { + out_code = NUM2INT(out); + if (out_code == _NOCONV) return (VALUE)src; + } + if (NIL_P(in)) { + in_code = _AUTO; + } + else if (TYPE(in) == T_STRING) { + switch (RSTRING(in)->ptr[0]) { + case 'E': case 'e': + in_code = _EUC; + break; + case 'S': case 's': + in_code = _SJIS; + break; + case 'J': case 'j': + in_code = _JIS; + break; + default: + in_code = _AUTO; + break; + } + } + else { + in_code = NUM2INT(in); + if (in_code == _NOCONV) return (VALUE)src; + } + + dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */ + RSTRING(dst)->len = do_kconv(src, dst, out_code, in_code); + + return dst; +} + +static VALUE +kconv_tojis(obj, src) + VALUE obj, src; +{ + VALUE dst; + + Check_Type(src, T_STRING); + + dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */ + RSTRING(dst)->len = do_kconv(src, dst, _JIS, _AUTO); + + return dst; +} + +static VALUE +kconv_toeuc(obj, src) + VALUE obj, src; +{ + VALUE dst; + + Check_Type(src, T_STRING); + + dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */ + RSTRING(dst)->len = do_kconv(src, dst, _EUC, _AUTO); + + return (VALUE)dst; +} + +static VALUE +kconv_tosjis(obj, src) + VALUE obj, src; +{ + VALUE dst; + + Check_Type(src, T_STRING); + + dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */ + RSTRING(dst)->len = do_kconv(src, dst, _SJIS, _AUTO); + + return dst; +} + +/* + * Character code detection - Algorithm described in: + * Ken Lunde. `Understanding Japanese Information Processing' + * O'Reilly & Associates, Sebastopol, CA. + */ + +static VALUE +kconv_guess(obj, src) + VALUE obj, src; +{ + unsigned char *p; + unsigned char *pend; + int sequence_counter = 0; + + Check_Type(src, T_STRING); + + p = RSTRING(src)->ptr; + pend = p + RSTRING(src)->len; + +#define INCR do {\ + p++;\ + if (p==pend) return INT2FIX(_UNKNOWN);\ + sequence_counter++;\ + if (sequence_counter % 2 == 1 && *p != 0xa4)\ + sequence_counter = 0;\ + if (6 <= sequence_counter) {\ + sequence_counter = 0;\ + return INT2FIX(_EUC);\ + }\ +} while (0) + + if (*p == 0xa4) + sequence_counter = 1; + + while (p= 0x40) { + if (*p >= 0x81) { + if (*p <= 0x8d || (0x8f <= *p && *p <= 0x9f)) { + return INT2FIX(_SJIS); + } + else if (0xfd <= *p && *p <= 0xfe) { + return INT2FIX(_EUC); + } + } + INCR; + } + } + else if (*p <= 0x9f) { + return INT2FIX(_SJIS); + } + } + else if (0xf0 <= *p && *p <= 0xfe) { + return INT2FIX(_EUC); + } + else if (0xe0 <= *p && *p <= 0xef) { + INCR; + if ((0x40 <= *p && *p <= 0x7e) || + (0x80 <= *p && *p <= 0xa0)) { + return INT2FIX(_SJIS); + } + if (0xfd <= *p && *p <= 0xfe) { + return INT2FIX(_EUC); + } + } + INCR; + } + return INT2FIX(_UNKNOWN); +} + +void +Init_kconv() +{ + VALUE mKconv = rb_define_module("Kconv"); + + rb_define_module_function(mKconv, "kconv", kconv_kconv, -1); + rb_define_module_function(mKconv, "tojis", kconv_tojis, 1); + rb_define_module_function(mKconv, "toeuc", kconv_toeuc, 1); + rb_define_module_function(mKconv, "tosjis", kconv_tosjis, 1); + rb_define_module_function(mKconv, "guess", kconv_guess, 1); + + rb_define_const(mKconv, "AUTO", INT2FIX(_AUTO)); + rb_define_const(mKconv, "JIS", INT2FIX(_JIS)); + rb_define_const(mKconv, "EUC", INT2FIX(_EUC)); + rb_define_const(mKconv, "SJIS", INT2FIX(_SJIS)); + rb_define_const(mKconv, "BINARY", INT2FIX(_BINARY)); + rb_define_const(mKconv, "NOCONV", INT2FIX(_NOCONV)); + rb_define_const(mKconv, "UNKNOWN", INT2FIX(_UNKNOWN)); +} + +/** + ** パッチ制作者 + ** void@merope.pleiades.or.jp (Kusakabe Youichi) + ** NIDE Naoyuki + ** ohta@src.ricoh.co.jp (Junn Ohta) + ** inouet@strl.nhk.or.jp (Tomoyuki Inoue) + ** kiri@pulser.win.or.jp (Tetsuaki Kiriyama) + ** Kimihiko Sato + ** a_kuroe@kuroe.aoba.yokohama.jp (Akihiko Kuroe) + ** kono@ie.u-ryukyu.ac.jp (Shinji Kono) + ** GHG00637@nifty-serve.or.jp (COW) + ** j_kuro@pluto.ai.kyutech.ac.jp (Jun Kuroda) + ** + ** 最終更新日 + ** 1996.12.18 + **/ + +/* end */ diff --git a/ext/nkf/depend b/ext/nkf/depend index 645bc869c8..13e32e6074 100644 --- a/ext/nkf/depend +++ b/ext/nkf/depend @@ -1 +1 @@ -nkf.o : nkf.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h nkf1.7/nkf.c +nkf.o : nkf.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h $(srcdir)/nkf1.7/nkf.c diff --git a/ext/nkf/nkf.c b/ext/nkf/nkf.c index 80d0d2e4be..b59688cb03 100644 --- a/ext/nkf/nkf.c +++ b/ext/nkf/nkf.c @@ -31,14 +31,12 @@ rb_nkf_putchar(c) { if (output_ctr >= o_len) { o_len += incsize; - rb_str_cat(dst, "", incsize); + rb_str_cat(dst, 0, incsize); + output = RSTRING(dst)->ptr; incsize *= 2; } - output[output_ctr++] = c; -/* -printf("[[%c][%c][%d]]\n", c, output[output_ctr - 1], output_ctr); -*/ + return c; } @@ -51,6 +49,7 @@ rb_nkf_kconv(obj, opt, src) { int i; char *opt_ptr, *opt_end; + volatile VALUE v; reinit(); opt_ptr = str2cstr(opt, &i); @@ -66,7 +65,8 @@ rb_nkf_kconv(obj, opt, src) input_ctr = 0; input = str2cstr(src, &i_len); - dst = rb_str_new(0, i_len*3 + 10); /* large enough? */ + dst = rb_str_new(0, i_len*3 + 10); + v = dst; output_ctr = 0; output = RSTRING(dst)->ptr; @@ -78,18 +78,8 @@ rb_nkf_kconv(obj, opt, src) } kanji_convert(NULL); - if (output_ctr > 0) output_ctr--; - if (output[output_ctr] == '\0') { -/* -printf("([%c][%d])\n", output[output_ctr], output_ctr); -*/ - RSTRING(dst)->len = output_ctr; - } else { -/* -printf("<[%c][%d]>\n", output[output_ctr], output_ctr); -*/ - RSTRING(dst)->len = output_ctr + 1; - } + RSTRING(dst)->ptr[output_ctr] = '\0'; + RSTRING(dst)->len = output_ctr; return dst; } diff --git a/ext/pty/MANIFEST b/ext/pty/MANIFEST index 5e5af7dd6b..f46d611e5b 100644 --- a/ext/pty/MANIFEST +++ b/ext/pty/MANIFEST @@ -3,6 +3,7 @@ README README.expect README.expect.jp README.jp +depend expect_sample.rb extconf.rb lib/expect.rb diff --git a/ext/pty/depend b/ext/pty/depend new file mode 100644 index 0000000000..888be6c301 --- /dev/null +++ b/ext/pty/depend @@ -0,0 +1 @@ +pty.o: pty.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h diff --git a/ext/pty/pty.c b/ext/pty/pty.c index 98be9044b7..b8c4e9acae 100644 --- a/ext/pty/pty.c +++ b/ext/pty/pty.c @@ -282,7 +282,9 @@ establishShell(shellname, info) dup2(slave,2); close(slave); +#if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRESUID) seteuid(getuid()); +#endif argc = 0; for (i = 0; shellname[i];) { diff --git a/ext/readline/MANIFEST b/ext/readline/MANIFEST index f73a899abb..f8bfd1ea2c 100644 --- a/ext/readline/MANIFEST +++ b/ext/readline/MANIFEST @@ -1,4 +1,5 @@ MANIFEST README +depend extconf.rb readline.c diff --git a/ext/readline/depend b/ext/readline/depend new file mode 100644 index 0000000000..6570c5a036 --- /dev/null +++ b/ext/readline/depend @@ -0,0 +1 @@ +readline.o: readline.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h diff --git a/ext/sdbm/MANIFEST b/ext/sdbm/MANIFEST index d0ed99ba77..8888e69ad4 100644 --- a/ext/sdbm/MANIFEST +++ b/ext/sdbm/MANIFEST @@ -1,5 +1,6 @@ MANIFEST _sdbm.c +depend extconf.rb init.c sdbm.h diff --git a/ext/sdbm/depend b/ext/sdbm/depend new file mode 100644 index 0000000000..1d8b13d13f --- /dev/null +++ b/ext/sdbm/depend @@ -0,0 +1,2 @@ +_sdbm.o: _sdbm.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h +init.o: init.c $(hdrdir)/ruby.h $(topdir)/config.h $(hdrdir)/defines.h diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb index 47addfeff8..6a2937bb3f 100644 --- a/ext/socket/extconf.rb +++ b/ext/socket/extconf.rb @@ -41,6 +41,7 @@ end $ipv6type = nil $ipv6lib = nil $ipv6libdir = nil +$ipv6trylibc = nil if $ipv6 if egrep_cpp("yes", < @@ -59,6 +60,7 @@ EOF $ipv6type = "kame" $ipv6lib="inet6" $ipv6libdir="/usr/local/v6/lib" + $ipv6trylibc=true $CFLAGS="-DINET6 "+$CFLAGS elsif File.directory? "/usr/inet6" $ipv6type = "linux" @@ -100,7 +102,7 @@ EOF if $ipv6lib if File.directory? $ipv6libdir and File.exist? "#{$ipv6libdir}/lib#{$ipv6lib}.a" $LOCAL_LIBS = " -L#$ipv6libdir -l#$ipv6lib" - else + elsif !$ipv6trylibc print < #include #include +int +main() +{ + struct sockaddr_storage ss; + + ss.ss_family; + return 0; +} +EOF + $CFLAGS="-DHAVE_SOCKADDR_STORAGE "+$CFLAGS +end + + if try_link(< +#include +#include +#include #include int main() @@ -148,7 +167,6 @@ EOF $CFLAGS="-DHAVE_SA_LEN "+$CFLAGS end -have_header("sys/sysctl.h") have_header("netinet/tcp.h") have_header("netinet/udp.h") @@ -160,6 +178,10 @@ if try_run(< #include +#ifndef AF_LOCAL +#define AF_LOCAL AF_UNIX +#endif + main() { int passive, gaierr, inet4 = 0, inet6 = 0; @@ -176,6 +198,7 @@ main() goto bad; } for (ai = aitop; ai; ai = ai->ai_next) { + if (ai->ai_family == AF_LOCAL) continue; if (ai->ai_addr == NULL || ai->ai_addrlen == 0 || getnameinfo(ai->ai_addr, ai->ai_addrlen, @@ -221,7 +244,9 @@ main() } } - if (inet6 != 2 || inet4 != 2) + if (!(inet4 == 0 || inet4 == 2)) + goto bad; + if (!(inet6 == 0 || inet6 == 2)) goto bad; if (aitop) diff --git a/ext/socket/getaddrinfo.c b/ext/socket/getaddrinfo.c index 501ebd5006..fbedac4cbb 100644 --- a/ext/socket/getaddrinfo.c +++ b/ext/socket/getaddrinfo.c @@ -38,14 +38,10 @@ * - PF_UNSPEC case would be handled in getipnodebyname() with the AI_ALL flag. */ +#include "config.h" #include #ifndef NT #include -#endif -#ifdef HAVE_SYSCTL_H -#include -#endif -#ifndef NT #include #include #include @@ -71,7 +67,6 @@ #include #endif -#include "config.h" #include "addrinfo.h" #include "sockport.h" @@ -135,6 +130,11 @@ static struct afd { #define PTON_MAX 4 #endif +#ifndef INET6 +#ifndef NT +extern int h_errno; +#endif +#endif static int get_name __P((const char *, struct afd *, struct addrinfo **, char *, struct addrinfo *, @@ -580,11 +580,6 @@ get_addr(hostname, af, res, pai, port0) struct afd *afd; int i, error = 0, h_error; char *ap; -#ifndef INET6 -#ifndef NT - extern int h_errno; -#endif -#endif top = NULL; sentinel.ai_next = NULL; diff --git a/ext/socket/getnameinfo.c b/ext/socket/getnameinfo.c index cb65e4c070..774177c8c1 100644 --- a/ext/socket/getnameinfo.c +++ b/ext/socket/getnameinfo.c @@ -34,6 +34,7 @@ * but INRIA implementation returns EAI_xxx defined for getaddrinfo(). */ +#include "config.h" #include #ifndef NT #include @@ -60,10 +61,15 @@ #include #endif -#include "config.h" #include "addrinfo.h" #include "sockport.h" +#ifndef INET6 +#ifndef NT +extern int h_errno; +#endif +#endif + #define SUCCESS 0 #define ANY 0 #define YES 1 @@ -149,9 +155,6 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) int h_error; char numserv[512]; char numaddr[512]; -#ifndef NT - extern int h_errno; -#endif if (sa == NULL) return ENI_NOSOCKET; diff --git a/ext/socket/socket.c b/ext/socket/socket.c index a1d707122e..43bde950f4 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -16,10 +16,10 @@ #ifndef NT #include #include -#ifdef NETINET_TCP +#ifdef HAVE_NETINET_TCP_H # include #endif -#ifdef NETINET_UDP +#ifdef HAVE_NETINET_UDP_H # include #endif #include @@ -81,10 +81,27 @@ int Rconnect(); #define INET_SERVER 1 #define INET_SOCKS 2 -#ifndef INET6 -# undef ss_family -# define sockaddr_storage sockaddr -# define ss_family sa_family +#ifndef HAVE_SOCKADDR_STORAGE +/* + * RFC 2553: protocol-independent placeholder for socket addresses + */ +#define _SS_MAXSIZE 128 +#define _SS_ALIGNSIZE (sizeof(double)) +#define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof(unsigned char) * 2) +#define _SS_PAD2SIZE (_SS_MAXSIZE - sizeof(unsigned char) * 2 - \ + _SS_PAD1SIZE - _SS_ALIGNSIZE) + +struct sockaddr_storage { +#ifdef HAVE_SA_LEN + unsigned char ss_len; /* address length */ + unsigned char ss_family; /* address family */ +#else + unsigned short ss_family; +#endif + char __ss_pad1[_SS_PAD1SIZE]; + double __ss_align; /* force desired structure storage alignment */ + char __ss_pad2[_SS_PAD2SIZE]; +}; #endif #ifdef NT @@ -93,16 +110,12 @@ sock_finalize(fptr) OpenFile *fptr; { SOCKET s; - extern int errno; if (!fptr->f) return; - - myfdclose(fptr->f); - if(fptr->f2) myfdclose(fptr->f); -/* - s = get_osfhandle(fileno(fptr->f)); + s = get_osfhandle(fileno(fptr->f)); + myfdclose(fptr->f); + if (fptr->f2) myfdclose(fptr->f2); closesocket(s); -*/ } #endif @@ -378,8 +391,8 @@ s_recv(sock, argc, argv, from) GetOpenFile(sock, fptr); fd = fileno(fptr->f); rb_thread_wait_fd(fd); - TRAP_BEG; retry: + TRAP_BEG; RSTRING(str)->len = recvfrom(fd, RSTRING(str)->ptr, RSTRING(str)->len, flags, (struct sockaddr*)buf, &alen); TRAP_END; @@ -498,6 +511,7 @@ ip_addrsetup(host, port) long i = NUM2LONG(host); mkinetaddr(htonl(i), hbuf, sizeof(hbuf)); + hostp = hbuf; } else { char *name = STR2CSTR(host); @@ -508,11 +522,14 @@ ip_addrsetup(host, port) else if (name[0] == '<' && strcmp(name, "") == 0) { mkinetaddr(INADDR_BROADCAST, hbuf, sizeof(hbuf)); } + else if (strlen(name) > sizeof(hbuf)-1) { + rb_raise(rb_eSocket, "hostname too long (%d)", strlen(name)); + } else { strcpy(hbuf, name); } + hostp = hbuf; } - hostp = hbuf; if (NIL_P(port)) { portp = 0; } @@ -529,6 +546,9 @@ ip_addrsetup(host, port) hints.ai_socktype = SOCK_DGRAM; error = getaddrinfo(hostp, portp, &hints, &res); if (error) { + if (hostp && hostp[strlen(hostp)-1] == '\n') { + rb_raise(rb_eSocket, "newline at the end of hostname"); + } rb_raise(rb_eSocket, "%s", gai_strerror(error)); } @@ -890,7 +910,9 @@ tcp_s_gethostbyname(obj, host) struct sockaddr_in6 sin6; MEMZERO(&sin6, struct sockaddr_in6, 1); sin6.sin6_family = AF_INET; +#ifdef SIN6_LEN sin6.sin6_len = sizeof(sin6); +#endif memcpy((char *) &sin6.sin6_addr, *pch, h->h_length); h = gethostbyaddr((char *)&sin6.sin6_addr, sizeof(sin6.sin6_addr), diff --git a/ext/tcltklib/extconf.rb b/ext/tcltklib/extconf.rb index e1086855ba..713cc811e5 100644 --- a/ext/tcltklib/extconf.rb +++ b/ext/tcltklib/extconf.rb @@ -21,6 +21,7 @@ def find_tcl(tcllib) find_library(tcllib, func, *paths) else find_library("tcl", func, *paths) or + find_library("tcl8.2", func, *paths) or find_library("tcl8.0", func, *paths) or find_library("tcl7.6", func, *paths) end @@ -33,6 +34,7 @@ def find_tk(tklib) find_library(tklib, func, *paths) else find_library("tk", func, *paths) or + find_library("tk8.2", func, *paths) or find_library("tk8.0", func, *paths) or find_library("tk4.2", func, *paths) end diff --git a/ext/tk/lib/tk.rb b/ext/tk/lib/tk.rb index f831dbc78a..c344a2bf8e 100644 --- a/ext/tk/lib/tk.rb +++ b/ext/tk/lib/tk.rb @@ -196,7 +196,9 @@ module TkComm def _get_eval_string(str) return nil if str == None - if str.kind_of?(Hash) + if str.kind_of?(String) + # do nothing + elsif str.kind_of?(Hash) str = hash_kv(str).join(" ") elsif str.kind_of?(Array) str = array2tk_list(str) @@ -235,7 +237,7 @@ module TkComm return format("rb_out %s", id); end def uninstall_cmd(id) - id = $1 if /rb_out (c\d+)/ + id = $1 if /rb_out (c\d+)/ =~ id Tk_CMDTBL[id] = nil end private :install_cmd, :uninstall_cmd @@ -347,15 +349,6 @@ module TkComm def _bind_append(what, context, cmd, args=nil) _bind_core('+', what, context, cmd, args) end - private :install_bind, :tk_event_sequence, :_bind_core, :_bind, :_bind_append - - def bind_all(context, cmd=Proc.new, args=nil) - _bind(['bind', 'all'], context, cmd, args) - end - - def bind_append_all(context, cmd=Proc.new, args=nil) - _bind_append(['bind', 'all'], context, cmd, args) - end def _bindinfo(what, context=nil) if context @@ -372,11 +365,33 @@ module TkComm } end end + private :install_bind, :tk_event_sequence, + :_bind_core, :_bind, :_bind_append, :_bindinfo + + def bind(tagOrClass, context, cmd=Proc.new, args=nil) + _bind(["bind", tagOrClass], context, cmd, args) + end + + def bind_append(tagOrClass, context, cmd=Proc.new, args=nil) + _bind_append(["bind", tagOrClass], context, cmd, args) + end def bindinfo(tagOrClass, context=nil) _bindinfo(['bind', tagOrClass], context) end + def bind_all(context, cmd=Proc.new, args=nil) + _bind(['bind', 'all'], context, cmd, args) + end + + def bind_append_all(context, cmd=Proc.new, args=nil) + _bind_append(['bind', 'all'], context, cmd, args) + end + + def bindinfo_all(context=nil) + _bindinfo(['bind', 'all'], context) + end + def pack(*args) TkPack.configure *args end @@ -401,14 +416,14 @@ module TkCore INTERP = TclTkIp.new - INTERP._invoke("proc", "rb_out", "args", "if {[set st [catch {ruby [format \"TkCore.callback %%Q!%s!\" $args]} ret]] != 0} {return -code $st $ret} {return $ret}") + INTERP._invoke("proc", "rb_out", "args", "if {[set st [catch {ruby [format \"TkCore.callback %%Q!%s!\" $args]} ret]] != 0} {if {[regsub -all {!} $args {\\!} newargs] == 0} {return -code $st $ret} {if {[set st [catch {ruby [format \"TkCore.callback %%Q!%s!\" $newargs]} ret]] != 0} {return -code $st $ret} {return $ret}}} {return $ret}") def callback_break - raise TkCallbackBreak, "Tk callback returns 'break' status" + fail TkCallbackBreak, "Tk callback returns 'break' status" end def callback_continue - raise TkCallbackContinue, "Tk callback returns 'continue' status" + fail TkCallbackContinue, "Tk callback returns 'continue' status" end def after(ms, cmd=Proc.new) @@ -514,8 +529,8 @@ module TkCore args.unshift "unknown" res = INTERP._invoke(*args) rescue - raise unless /^invalid command/ =~ $! - raise err + fail unless /^invalid command/ =~ $! + fail err end end if INTERP._return_value() != 0 @@ -570,13 +585,39 @@ module Tk def yscrollcommand(cmd=Proc.new) configure_cmd 'yscrollcommand', cmd end + def xview(*index) + v = tk_send('xview', *index) + list(v) if index.size == 0 + end + def yview(*index) + v = tk_send('yview', *index) + list(v) if index.size == 0 + end + def xscrollbar(bar=nil) + if bar + @xscrollbar = bar + @xscrollbar.orient 'horizontal' + self.xscrollcommand {|arg| @xscrollbar.set *arg} + @xscrollbar.command {|arg| self.xview *arg} + end + @xscrollbar + end + def yscrollbar(bar=nil) + if bar + @yscrollbar = bar + @yscrollbar.orient 'vertical' + self.yscrollcommand {|arg| @yscrollbar.set *arg} + @yscrollbar.command {|arg| self.yview *arg} + end + @yscrollbar + end end module Wm include TkComm def aspect(*args) - w = window(tk_call('wm', 'grid', path, *args)) - w.split.collect{|s|s.to_i} if args.length == 0 + w = tk_call('wm', 'aspect', path, *args) + list(w) if args.length == 0 end def client(name=None) tk_call 'wm', 'client', path, name @@ -594,17 +635,18 @@ module Tk tk_call 'wm', 'focusmodel', path, *args end def frame - tk_call 'wm', 'frame', path + tk_call('wm', 'frame', path) end def geometry(*args) - list(tk_call('wm', 'geometry', path, *args)) + tk_call('wm', 'geometry', path, *args) end def grid(*args) w = tk_call('wm', 'grid', path, *args) list(w) if args.size == 0 end def group(*args) - tk_call 'wm', 'group', path, *args + w = tk_call 'wm', 'group', path, *args + window(w) if args.size == 0 end def iconbitmap(*args) tk_call 'wm', 'iconbitmap', path, *args @@ -628,7 +670,7 @@ module Tk end def maxsize(*args) w = tk_call('wm', 'maxsize', path, *args) - list(w) if not args.size == 0 + list(w) if args.size == 0 end def minsize(*args) w = tk_call('wm', 'minsize', path, *args) @@ -661,7 +703,7 @@ module Tk end end def sizefrom(*args) - list(tk_call('wm', 'sizefrom', path, *args)) + tk_call('wm', 'sizefrom', path, *args) end def state tk_call 'wm', 'state', path @@ -670,7 +712,7 @@ module Tk tk_call 'wm', 'title', path, *args end def transient(*args) - tk_call 'wm', 'transient', path, *args + window(tk_call 'wm', 'transient', path, *args) end def withdraw tk_call 'wm', 'withdraw', path @@ -678,6 +720,46 @@ module Tk end end +module TkBindCore + def bind(context, cmd=Proc.new, args=nil) + Tk.bind(to_eval, context, cmd, args) + end + + def bind_append(context, cmd=Proc.new, args=nil) + Tk.bind_append(to_eval, context, cmd, args) + end + + def bindinfo(context=nil) + Tk.bindinfo(to_eval, context) + end +end + +class TkBindTag + include TkBindCore + + BTagID_TBL = {} + Tk_BINDTAG_ID = ["btag00000"] + + def TkBindTag.id2obj(id) + BTagID_TBL[id]? BTagID_TBL[id]: id + end + + def initialize(*args) + @id = Tk_BINDTAG_ID[0] + Tk_BINDTAG_ID[0] = Tk_BINDTAG_ID[0].succ + BTagID_TBL[@id] = self + bind(*args) if args != [] + end + + def to_eval + @id + end + + def inspect + format "#", @id + end +end + class TkVariable include Tk extend TkCore @@ -730,7 +812,7 @@ class TkVariable INTERP._eval(format('global %s; set %s', @id, @id)) rescue if INTERP._eval(format('global %s; array exists %s', @id, @id)) != "1" - raise + fail else Hash[*tk_split_simplelist(INTERP._eval(format('global %s; array get %s', @id, @id)))] @@ -744,7 +826,7 @@ class TkVariable INTERP._eval(format('global %s; set %s %s', @id, @id, s)) rescue if INTERP._eval(format('global %s; array exists %s', @id, @id)) != "1" - raise + fail else if val == [] INTERP._eval(format('global %s; unset %s; set %s(0) 0; unset %s(0)', @@ -761,7 +843,7 @@ class TkVariable INTERP._eval(format('global %s; unset %s; array set %s %s', @id, @id, @id, s)) else - raise + fail end end end @@ -790,7 +872,7 @@ class TkVariable end def inspect - format "", @id + format "#", @id end def ==(other) @@ -1063,19 +1145,19 @@ module TkWinfo include Tk extend Tk def TkWinfo.atom(name) - tk_call 'winfo', name + number(tk_call 'winfo', 'atom', name) end def winfo_atom(name) TkWinfo.atom name end def TkWinfo.atomname(id) - tk_call 'winfo', id + tk_call 'winfo', 'atomname', id end def winfo_atomname(id) TkWinfo.atomname id end def TkWinfo.cells(window) - number(tk_call('winfo', window.path)) + number(tk_call('winfo', 'cells', window.path)) end def winfo_cells TkWinfo.cells self @@ -1093,6 +1175,12 @@ module TkWinfo def winfo_classname TkWinfo.classname self end + def TkWinfo.colormapfull(window) + bool(tk_call('winfo', 'colormapfull', window.path)) + end + def winfo_colormapfull + TkWinfo.colormapfull self + end def TkWinfo.containing(rootX, rootY) path = tk_call('winfo', 'containing', rootX, rootY) window(path) @@ -1119,7 +1207,7 @@ module TkWinfo TkWinfo.fpixels self, number end def TkWinfo.geometry(window) - list(tk_call('winfo', 'geometry', window.path)) + tk_call('winfo', 'geometry', window.path) end def winfo_geometry TkWinfo.geometry self @@ -1131,15 +1219,15 @@ module TkWinfo TkWinfo.height self end def TkWinfo.id(window) - number(tk_call('winfo', 'id', window.path)) + tk_call('winfo', 'id', window.path) end def winfo_id TkWinfo.id self end def TkWinfo.interps(window=nil) if window - tk_split_simplelist(tk_call('winfo', '-displayof', window.path, - 'interps')) + tk_split_simplelist(tk_call('winfo', 'interps', + '-displayof', window.path)) else tk_split_simplelist(tk_call('winfo', 'interps')) end @@ -1153,8 +1241,14 @@ module TkWinfo def winfo_mapped? TkWinfo.mapped? self end + def TkWinfo.manager(window) + tk_call('winfo', 'manager', window.path) + end + def winfo_manager + TkWinfo.manager self + end def TkWinfo.appname(window) - bool(tk_call('winfo', 'name', window.path)) + tk_call('winfo', 'name', window.path) end def winfo_appname TkWinfo.appname self @@ -1255,6 +1349,12 @@ module TkWinfo def winfo_screenwidth TkWinfo.screenwidth self end + def TkWinfo.server(window) + tk_call 'winfo', 'server', window.path + end + def winfo_server + TkWinfo.server self + end def TkWinfo.toplevel(window) window(tk_call('winfo', 'toplevel', window.path)) end @@ -1267,7 +1367,24 @@ module TkWinfo def winfo_visual TkWinfo.visual self end - def TkWinfo.vrootheigh(window) + def TkWinfo.visualid(window) + tk_call 'winfo', 'visualid', window.path + end + def winfo_visualid + TkWinfo.visualid self + end + def TkWinfo.visualsavailable(window, includeids=false) + if includeids + v = tk_call('winfo', 'visualsavailable', window.path, "includeids") + else + v = tk_call('winfo', 'visualsavailable', window.path) + end + list(v) + end + def winfo_visualsavailable(includeids=false) + TkWinfo.visualsavailable self, includeids + end + def TkWinfo.vrootheight(window) number(tk_call('winfo', 'vrootheight', window.path)) end def winfo_vrootheight @@ -1452,24 +1569,20 @@ module TkTreatFont alias fontobj font_configinfo def font_configure(slot) - if (fnt = slot['font']) - slot['font'] = nil + if (fnt = slot.delete('font')) if fnt.kind_of? TkFont return fnt.call_font_configure(self.path, self.path,'configure',slot) else latinfont_configure(fnt) if fnt end end - if (ltn = slot['latinfont']) - slot['latinfont'] = nil + if (ltn = slot.delete('latinfont')) latinfont_configure(ltn) if ltn end - if (ltn = slot['asciifont']) - slot['asciifont'] = nil + if (ltn = slot.delete('asciifont')) latinfont_configure(ltn) if ltn end - if (knj = slot['kanjifont']) - slot['kanjifont'] = nil + if (knj = slot.delete('kanjifont')) kanjifont_configure(knj) if knj end @@ -1544,6 +1657,7 @@ end class TkObjectptr); } else { + tainted = 1; #ifdef HAVE_GETCWD getcwd(buf, MAXPATHLEN); #else @@ -1122,7 +1126,7 @@ rb_file_s_expand_path(argc, argv) p = &buf[strlen(buf)]; while (p > buf && *(p - 1) == '/') p--; } - else if (isdirsep(*s)) { + else { while (*s && isdirsep(*s)) { *p++ = '/'; s++; @@ -1144,7 +1148,8 @@ rb_file_s_expand_path(argc, argv) } else { *++p = '.'; - *++p = '.'; + do *++p = '.'; while (*++s == '.'); + --s; } break; case '/': @@ -1172,7 +1177,9 @@ rb_file_s_expand_path(argc, argv) if (p == buf || !isdirsep(*p)) p++; *p = '\0'; - return rb_tainted_str_new2(buf); + fname = rb_str_new2(buf); + if (tainted) OBJ_TAINT(fname); + return fname; } static int @@ -1203,7 +1210,7 @@ rb_file_s_basename(argc, argv) int argc; VALUE *argv; { - VALUE fname, fext; + VALUE fname, fext, basename; char *name, *p, *ext; int f; @@ -1224,7 +1231,9 @@ rb_file_s_basename(argc, argv) f = rmext(p, ext); if (f) return rb_str_new(p, f); } - return rb_tainted_str_new2(p); + basename = rb_str_new2(p); + if (OBJ_TAINTED(fname)) OBJ_TAINT(basename); + return basename; } static VALUE @@ -1232,6 +1241,7 @@ rb_file_s_dirname(obj, fname) VALUE obj, fname; { char *name, *p; + VALUE dirname; name = STR2CSTR(fname); p = strrchr(name, '/'); @@ -1240,7 +1250,9 @@ rb_file_s_dirname(obj, fname) } if (p == name) p++; - return rb_tainted_str_new(name, p - name); + dirname = rb_str_new(name, p - name); + if (OBJ_TAINTED(fname)) OBJ_TAINT(dirname); + return dirname; } static VALUE diff --git a/gc.c b/gc.c index ed159a7ffd..879adf27e9 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-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -50,7 +50,6 @@ 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 * @@ -115,12 +114,11 @@ xrealloc(ptr, size) return mem; } -static void +void xfree(x) void *x; { - free_called++; - free(x); + if (x) free(x); } #endif @@ -242,8 +240,8 @@ add_heap() /* Realloc heaps */ heaps_length += HEAPS_INCREMENT; heaps = (heaps_used>0)? - (RVALUE**)realloc(heaps, heaps_length*sizeof(RVALUE)): - (RVALUE**)malloc(heaps_length*sizeof(RVALUE)); + (RVALUE**)realloc(heaps, heaps_length*sizeof(RVALUE*)): + (RVALUE**)malloc(heaps_length*sizeof(RVALUE*)); if (heaps == 0) rb_fatal("can't alloc memory"); } @@ -370,7 +368,7 @@ rb_mark_tbl(tbl) static int mark_hashentry(key, value) - ID key; + VALUE key; VALUE value; { rb_gc_mark(key); @@ -860,6 +858,9 @@ _rb_setjmp: movem.l d3-d7/a3-a5,(a0) moveq.l #0,d0 rts"); +#ifdef setjmp +#undef setjmp +#endif #else #if defined(DJGPP) typedef unsigned long rb_jmp_buf[6]; @@ -893,6 +894,11 @@ rb_gc() jmp_buf save_regs_gc_mark; #ifdef C_ALLOCA VALUE stack_end; + alloca(0); +# define STACK_END (&stack_end) +#else + VALUE *stack_end = alloca(1); +# define STACK_END (stack_end) #endif alloc_objects = 0; @@ -901,10 +907,6 @@ rb_gc() if (during_gc) return; during_gc++; -#ifdef C_ALLOCA - alloca(0); -#endif - /* mark frame stack */ for (frame = ruby_frame; frame; frame = frame->prev) { rb_gc_mark_frame(frame); @@ -924,18 +926,14 @@ rb_gc() /* This assumes that all registers are saved into the jmp_buf */ setjmp(save_regs_gc_mark); mark_locations_array((VALUE*)save_regs_gc_mark, sizeof(save_regs_gc_mark) / sizeof(VALUE *)); -#ifdef C_ALLOCA - rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)&stack_end); -#else - rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)alloca(1)); -#endif + rb_gc_mark_locations(rb_gc_stack_start, (VALUE*)STACK_END); #if defined(THINK_C) || defined(__human68k__) #ifndef __human68k__ mark_locations_array((VALUE*)((char*)save_regs_gc_mark+2), sizeof(save_regs_gc_mark) / sizeof(VALUE *)); #endif rb_gc_mark_locations((VALUE*)((char*)rb_gc_stack_start + 2), - (VALUE*)((char*)&stack_end + 2)); + (VALUE*)((char*)STACK_END + 2)); #endif rb_gc_mark_threads(); @@ -943,6 +941,7 @@ rb_gc() for (list = Global_List; list; list = list->next) { rb_gc_mark(*list->varptr); } + rb_mark_end_proc(); rb_gc_mark_global_tbl(); rb_mark_tbl(rb_class_tbl); diff --git a/hash.c b/hash.c index a0d11c06dd..f3be774e67 100644 --- a/hash.c +++ b/hash.c @@ -6,7 +6,7 @@ $Date$ created at: Mon Nov 22 18:51:18 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -79,19 +79,17 @@ static int rb_any_cmp(a, b) VALUE a, b; { + VALUE args[2]; if (FIXNUM_P(a)) { if (FIXNUM_P(b)) return a != b; } else if (TYPE(a) == T_STRING) { if (TYPE(b) == T_STRING) return rb_str_cmp(a, b); } - else { - VALUE args[2]; - args[0] = a; - args[1] = b; - return !rb_with_disable_interrupt(eql, (VALUE)args); - } + args[0] = a; + args[1] = b; + return !rb_with_disable_interrupt(eql, (VALUE)args); } static int @@ -690,10 +688,9 @@ rb_hash_inspect(hash) } static VALUE -hash_to_s(hash) +to_s_hash(hash) VALUE hash; { - if (rb_inspecting_p(hash)) return rb_str_new2("{...}"); return rb_ary_to_s(rb_hash_to_a(hash)); } @@ -701,8 +698,10 @@ static VALUE rb_hash_to_s(hash) VALUE hash; { + VALUE str; + if (rb_inspecting_p(hash)) return rb_str_new2("{...}"); - return rb_protect_inspect(hash_to_s, hash, 0); + return rb_protect_inspect(to_s_hash, hash, 0); } static VALUE @@ -1368,7 +1367,7 @@ env_index(dmy, value) char *s = strchr(*env, '=')+1; if (s) { if (strncmp(s, RSTRING(value)->ptr, strlen(s)) == 0) { - return rb_tainted_str_new(*env, s-*env); + return rb_tainted_str_new(*env, s-*env-1); } } env++; diff --git a/inits.c b/inits.c index fdc49f0f4b..5c2dba552c 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-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ diff --git a/instruby.rb b/instruby.rb index 52c7c2397f..3222f72194 100644 --- a/instruby.rb +++ b/instruby.rb @@ -15,12 +15,17 @@ if ENV["prefix"] else prefix = CONFIG["prefix"] end + ruby_install_name = CONFIG["ruby_install_name"] +version = "/"+CONFIG["MAJOR"]+"."+CONFIG["MINOR"] +arch = "/"+CONFIG["arch"] + 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"] +rubylibdir = destdir+CONFIG["prefix"]+"/lib/ruby"+version +archlibdir = rubylibdir+arch +sitelibdir = destdir+CONFIG["prefix"]+"/lib/site_ruby"+version +sitearchlibdir = sitelibdir+arch mandir = destdir+CONFIG["mandir"] + "/man1" wdir = Dir.getwd @@ -47,17 +52,17 @@ if File.exist? CONFIG["LIBRUBY_SO"] 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 +File.makedirs rubylibdir, true +File.makedirs archlibdir, true +File.makedirs sitelibdir, true +File.makedirs sitearchlibdir, true if RUBY_PLATFORM =~ /cygwin/ and File.exist? "import.h" - File.install "import.h", archdir, 0644, true + File.install "import.h", archlibdir, 0644, true end if RUBY_PLATFORM =~ /-aix/ - File.install "ruby.imp", archdir, 0644, true + File.install "ruby.imp", archlibdir, 0644, true end Dir.chdir "ext" @@ -66,26 +71,26 @@ Dir.chdir CONFIG["srcdir"] Find.find("lib") do |f| next unless /\.rb$/ =~ f - dir = pkglibdir+"/"+File.dirname(f[4..-1]) + dir = rubylibdir+"/"+File.dirname(f[4..-1]) File.makedirs dir, true unless File.directory? dir File.install f, dir, 0644, true end for f in Dir["*.h"] - File.install f, archdir, 0644, true + File.install f, archlibdir, 0644, true end if RUBY_PLATFORM =~ /mswin32/ - File.makedirs archdir + "/win32", true - File.install "win32/win32.h", archdir + "/win32", 0644, true + File.makedirs archlibdir + "/win32", true + File.install "win32/win32.h", archlibdir + "/win32", 0644, true if File.exist? wdir+'/rubymw.lib' - File.install wdir+'/rubymw.lib', archdir, 0644, true + File.install wdir+'/rubymw.lib', archlibdir, 0644, true end end -File.install wdir+'/'+CONFIG['LIBRUBY_A'], archdir, 0644, true +File.install wdir+'/'+CONFIG['LIBRUBY_A'], archlibdir, 0644, true File.makedirs mandir, true File.install "ruby.1", mandir, 0644, true Dir.chdir wdir -File.install "config.h", archdir, 0644, true -File.install "rbconfig.rb", archdir, 0644, true +File.install "config.h", archlibdir, 0644, true +File.install "rbconfig.rb", archlibdir, 0644, true # vi:set sw=2: diff --git a/intern.h b/intern.h index 4bfefa2fd1..06a7b83994 100644 --- a/intern.h +++ b/intern.h @@ -57,7 +57,7 @@ VALUE rb_big_and _((VALUE, VALUE)); VALUE rb_big_or _((VALUE, VALUE)); VALUE rb_big_xor _((VALUE, VALUE)); VALUE rb_big_lshift _((VALUE, VALUE)); -VALUE rb_big_rand _((VALUE)); +VALUE rb_big_rand _((VALUE, double)); /* class.c */ VALUE rb_class_new _((VALUE)); VALUE rb_singleton_class_new _((VALUE)); @@ -82,7 +82,7 @@ VALUE rb_singleton_class _((VALUE)); /* enum.c */ VALUE rb_enum_length _((VALUE)); /* error.c */ -extern int ruby_nerrs; +EXTERN int ruby_nerrs; VALUE rb_exc_new _((VALUE, const char*, long)); VALUE rb_exc_new2 _((VALUE, const char*)); VALUE rb_exc_new3 _((VALUE, VALUE)); @@ -121,6 +121,7 @@ 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_mark_end_proc _((void)); void rb_gc_mark_threads _((void)); void rb_thread_start_timer _((void)); void rb_thread_stop_timer _((void)); @@ -210,6 +211,12 @@ VALUE rb_Array _((VALUE)); /* parse.y */ extern int ruby_sourceline; extern char *ruby_sourcefile; +#define yyparse rb_yyparse +#define yylex rb_yylex +#define yyerror rb_yyerror +#define yylval rb_yylval +#define yychar rb_yychar +#define yydebug rb_yydebug int yyparse _((void)); ID rb_id_attrset _((ID)); void rb_parser_append_print _((void)); @@ -308,6 +315,7 @@ VALUE rb_f_untrace_var _((int, VALUE*)); VALUE rb_gvar_set2 _((const char*, VALUE)); VALUE rb_f_global_variables _((void)); void rb_alias_variable _((ID, ID)); +struct st_table* rb_generic_ivar_table _((VALUE)); void rb_clone_generic_ivar _((VALUE,VALUE)); void rb_mark_generic_ivar _((VALUE)); void rb_mark_generic_ivar_tbl _((void)); diff --git a/io.c b/io.c index c1c7d511db..1ea7df8c74 100644 --- a/io.c +++ b/io.c @@ -6,7 +6,7 @@ $Date$ created at: Fri Oct 15 18:08:59 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -426,7 +426,7 @@ read_all(port) TRAP_BEG; n = fread(RSTRING(str)->ptr+bytes, 1, siz-bytes, fptr->f); TRAP_END; - if (n == 0) { + if (n == 0 && bytes == 0) { if (feof(fptr->f)) return Qnil; rb_sys_fail(fptr->path); } @@ -452,15 +452,17 @@ io_fread(ptr, len, f) int c; while (n--) { + if (!READ_DATA_PENDING(f)) { + rb_thread_wait_fd(fileno(f)); + } + TRAP_BEG; c = getc(f); + TRAP_END; if (c == EOF) { *ptr = '\0'; break; } *ptr++ = c; - if (!READ_DATA_PENDING(f)) { - rb_thread_wait_fd(fileno(f)); - } } return len - n - 1; @@ -482,11 +484,15 @@ io_read(argc, argv, io) } len = NUM2INT(length); + if (len < 0) { + rb_raise(rb_eArgError, "negative length %d given", len); + } GetOpenFile(io, fptr); rb_io_check_readable(fptr); if (feof(fptr->f)) return Qnil; str = rb_str_new(0, len); + if (len == 0) return str; READ_CHECK(fptr->f); n = io_fread(RSTRING(str)->ptr, len, fptr->f); @@ -951,7 +957,7 @@ rb_io_close(io) { OpenFile *fptr; - GetOpenFile(io, fptr); + fptr = RFILE(io)->fptr; rb_io_fptr_close(fptr); if (fptr->pid) { rb_syswait(fptr->pid); @@ -1088,7 +1094,7 @@ VALUE rb_io_binmode(io) VALUE io; { -#if defined(NT) || defined(DJGPP) || defined(__CYGWIN32__)\ +#if defined(NT) || defined(DJGPP) || defined(__CYGWIN__)\ || defined(__human68k__) || defined(USE_CWGUSI) || defined(__EMX__) OpenFile *fptr; @@ -1250,6 +1256,9 @@ rb_fopen(fname, mode) rb_sys_fail(fname); } } +#ifdef __human68k__ + fmode(file, _IOTEXT); +#endif return file; } @@ -1334,7 +1343,7 @@ rb_file_sysopen(fname, flags, mode) return rb_file_sysopen_internal(rb_cFile, fname, flags, mode); } -#if defined (NT) || defined(DJGPP) || defined(__CYGWIN32__) || defined(__human68k__) +#if defined (NT) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) static struct pipe_list { OpenFile *fptr; struct pipe_list *next; @@ -1393,7 +1402,7 @@ static void pipe_finalize(fptr) OpenFile *fptr; { -#if !defined (__CYGWIN32__) +#if !defined (__CYGWIN__) if (fptr->f != NULL) { pclose(fptr->f); } @@ -1444,7 +1453,8 @@ pipe_open(pname, mode) pipe_add_fptr(fptr); if (modef & FMODE_READABLE) fptr->f = f; if (modef & FMODE_WRITABLE) { - fptr->f2 = f; + if (fptr->f) fptr->f2 = f; + else fptr->f = f; rb_io_synchronized(fptr); } return (VALUE)port; @@ -1524,7 +1534,7 @@ pipe_open(pname, mode) if (fptr->f) fptr->f2 = f; else fptr->f = f; } -#if defined (__CYGWIN32__) +#if defined (__CYGWIN__) fptr->finalize = pipe_finalize; pipe_add_fptr(fptr); #endif @@ -1578,8 +1588,8 @@ rb_file_s_open(argc, argv, klass) path = RSTRING(fname)->ptr; if (FIXNUM_P(vmode)) { - int flags = FIX2INT(vmode); - int fmode = NIL_P(perm) ? 0666 : FIX2INT(perm); + int flags = NUM2INT(vmode); + int fmode = NIL_P(perm) ? 0666 : NUM2INT(perm); file = rb_file_sysopen_internal(klass, path, flags, fmode); } @@ -1619,7 +1629,7 @@ rb_f_open(argc, argv) mode = "r"; } else if (FIXNUM_P(pmode)) { - mode = rb_io_flags_mode(FIX2INT(pmode)); + mode = rb_io_flags_mode(NUM2INT(pmode)); } else { int len; @@ -2283,13 +2293,13 @@ next_argv() fstat(fileno(fr), &st); if (*ruby_inplace_mode) { str = rb_str_new2(fn); -#if defined(MSDOS) || defined(__CYGWIN32__) || defined(NT) +#if defined(MSDOS) || defined(__CYGWIN__) || defined(NT) ruby_add_suffix(str, ruby_inplace_mode); #else rb_str_cat(str, ruby_inplace_mode, strlen(ruby_inplace_mode)); #endif -#if defined(MSDOS) || defined(__BOW__) || defined(__CYGWIN32__) || defined(NT) || defined(__human68k__) || defined(__EMX__) +#if defined(MSDOS) || defined(__BOW__) || defined(__CYGWIN__) || defined(NT) || defined(__human68k__) || defined(__EMX__) (void)fclose(fr); (void)unlink(RSTRING(str)->ptr); (void)rename(fn, RSTRING(str)->ptr); @@ -2304,7 +2314,7 @@ next_argv() #endif } else { -#if !defined(MSDOS) && !defined(__BOW__) && !defined(__CYGWIN32__) && !defined(NT) && !defined(__human68k__) +#if !defined(MSDOS) && !defined(__BOW__) && !defined(__CYGWIN__) && !defined(NT) && !defined(__human68k__) if (unlink(fn) < 0) { rb_warn("Can't remove %s: %s, skipping file", fn, strerror(errno)); @@ -2316,7 +2326,7 @@ next_argv() #endif } fw = rb_fopen(fn, "w"); -#if !defined(MSDOS) && !defined(__CYGWIN32__) && !(NT) && !defined(__human68k__) && !defined(USE_CWGUSI) && !defined(__BEOS__) && !defined(__EMX__) +#if !defined(MSDOS) && !defined(__CYGWIN__) && !(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) { @@ -2359,7 +2369,7 @@ rb_f_gets_internal(argc, argv) if (TYPE(current_file) != T_FILE) { line = rb_funcall3(current_file, rb_intern("gets"), argc, argv); } - if (argc == 0 && rb_rs == rb_default_rs) { + else if (argc == 0 && rb_rs == rb_default_rs) { line = rb_io_gets(current_file); } else { @@ -2623,7 +2633,7 @@ rb_io_ctl(io, req, arg, io_p) int io_p; { #if !defined(MSDOS) && !defined(__human68k__) - int cmd = NUM2INT(req); + int cmd = NUM2ULONG(req); OpenFile *fptr; int len = 0; int fd; @@ -2669,7 +2679,7 @@ rb_io_ctl(io, req, arg, io_p) fd = fileno(fptr->f); #ifdef HAVE_FCNTL TRAP_BEG; -# ifdef USE_CWGUSI +# if defined(USE_CWGUSI) || defined(__CYGWIN__) retval = io_p?ioctl(fd, cmd, (void*) narg):fcntl(fd, cmd, narg); # else retval = io_p?ioctl(fd, cmd, narg):fcntl(fd, cmd, narg); @@ -3066,6 +3076,8 @@ argf_eof() { if (init_p == 0 && !next_argv()) return Qtrue; + if (next_p == -1) + return Qtrue; if (TYPE(current_file) != T_FILE) { return argf_forward(); } @@ -3250,9 +3262,9 @@ Init_IO() rb_define_method(rb_cIO, "flush", rb_io_flush, 0); rb_define_method(rb_cIO, "tell", rb_io_tell, 0); rb_define_method(rb_cIO, "seek", rb_io_seek, 2); - rb_define_const(rb_cIO, "SEEK_SET", SEEK_SET); - rb_define_const(rb_cIO, "SEEK_CUR", SEEK_CUR); - rb_define_const(rb_cIO, "SEEK_END", SEEK_END); + rb_define_const(rb_cIO, "SEEK_SET", INT2FIX(SEEK_SET)); + rb_define_const(rb_cIO, "SEEK_CUR", INT2FIX(SEEK_CUR)); + rb_define_const(rb_cIO, "SEEK_END", INT2FIX(SEEK_END)); rb_define_method(rb_cIO, "rewind", rb_io_rewind, 0); rb_define_method(rb_cIO, "pos", rb_io_tell, 0); rb_define_method(rb_cIO, "pos=", rb_io_set_pos, 1); @@ -3330,7 +3342,7 @@ Init_IO() rb_define_virtual_variable("$-i", opt_i_get, opt_i_set); -#if defined (NT) || defined(DJGPP) || defined(__CYGWIN32__) || defined(__human68k__) +#if defined (NT) || defined(DJGPP) || defined(__CYGWIN__) || defined(__human68k__) atexit(pipe_atexit); #endif diff --git a/lib/complex.rb b/lib/complex.rb index 0af8c20b89..56dd040ac1 100644 --- a/lib/complex.rb +++ b/lib/complex.rb @@ -20,7 +20,7 @@ # Complex::/ # Complex::** # Complex::% -# Complex::divmod +# Complex::divmod -- obsolete # Complex::abs # Complex::abs2 # Complex::arg @@ -51,6 +51,12 @@ def Complex(a, b = 0) if a.kind_of?(Complex) and b == 0 a + elsif b.kind_of?(Complex) + if a.kind_of?(Complex) + Complex(a.real-b.image, a.image + b.real) + else + Complex(a-b.image, b.real) + end elsif b == 0 and defined? Complex::Unify a else @@ -181,18 +187,18 @@ class Complex < Numeric end end - def divmod(other) - if other.kind_of?(Complex) - rdiv, rmod = @real.divmod(other.real) - idiv, imod = @image.divmod(other.image) - return Complex(rdiv, idiv), Complex(rmod, rdiv) - elsif Complex.generic?(other) - Complex(@real.divmod(other), @image.divmod(other)) - else - x , y = other.coerce(self) - x.divmod(y) - end - end +# def divmod(other) +# if other.kind_of?(Complex) +# rdiv, rmod = @real.divmod(other.real) +# idiv, imod = @image.divmod(other.image) +# return Complex(rdiv, idiv), Complex(rmod, rmod) +# elsif Complex.generic?(other) +# Complex(@real.divmod(other), @image.divmod(other)) +# else +# x , y = other.coerce(self) +# x.divmod(y) +# end +# end def abs Math.sqrt!((@real*@real + @image*@image).to_f) diff --git a/lib/debug.rb b/lib/debug.rb index d2f1da83ff..f257e0c777 100644 --- a/lib/debug.rb +++ b/lib/debug.rb @@ -25,6 +25,8 @@ class DEBUGGER__ @last_file = nil @last = [nil, nil] @scripts = {} + @no_step = nil + @finish_pos = 0 end DEBUG_LAST_CMD = [] @@ -254,9 +256,13 @@ class DEBUGGER__ STDOUT.printf "#%d %s\n", frame_pos, info when /^fi(?:nish)?$/ - @finish_pos = @frames.size - frame_pos - frame_pos = 0 - return + if frame_pos == 0 + STDOUT.print "\"finish\" not meaningful in the outermost frame.\n" + else + @finish_pos = @frames.size - frame_pos + frame_pos = 0 + return + end when /^q(?:uit)?$/ input = readline("really quit? (y/n) ", false) @@ -383,10 +389,10 @@ class DEBUGGER__ @frames.unshift binding when 'return', 'end' + @frames.shift if @frames.size == @finish_pos @stop_next = 1 end - @frames.shift when 'raise' excn_handle(file, line, id, binding) diff --git a/lib/find.rb b/lib/find.rb index 3f1b82d2b3..9fb012902c 100644 --- a/lib/find.rb +++ b/lib/find.rb @@ -16,8 +16,10 @@ module Find d = Dir.open(file) begin for f in d - next if f =~ /^\.\.?$/ - if file == "/" then + next if f =~ /\A\.\.?\z/ + if File::ALT_SEPARATOR and file =~ /^([\/\\]|[A-Za-z]:[\/\\]?)$/ then + f = file + f + elsif file == "/" then f = "/" + f else f = file + "/" + f diff --git a/lib/ftplib.rb b/lib/ftplib.rb index 9336e0a8c2..0b90749274 100644 --- a/lib/ftplib.rb +++ b/lib/ftplib.rb @@ -1,639 +1,14 @@ -## ftplib.rb +# +# ftplib.rb +# -# Author: Shugo Maeda -# Version: $Revision: 1.7 $ +$stderr.puts 'Warning: ftplib.rb is obsolute: use net/ftp' -## Code: +require 'net/ftp' -require "socket" -require "monitor" - -class FTPError < StandardError; end -class FTPReplyError < FTPError; end -class FTPTempError < FTPError; end -class FTPPermError < FTPError; end -class FTPProtoError < FTPError; end - -class FTP - - RCS_ID = %q$Id: ftplib.rb,v 1.7 1998/04/13 12:34:24 shugo Exp shugo $ - - include MonitorMixin - - FTP_PORT = 21 - CRLF = "\r\n" - - attr_accessor :passive, :return_code, :debug_mode - attr_reader :welcome, :lastresp - - def FTP.open(host, user = nil, passwd = nil, acct = nil) - new(host, user, passwd, acct) - end - - def initialize(host = nil, user = nil, passwd = nil, acct = nil) - super - @passive = false - @return_code = "\n" - @debug_mode = false - if host - connect(host) - if user - login(user, passwd, acct) - end - end - end - - def open_socket(host, port) - if defined? SOCKSsocket and ENV["SOCKS_SERVER"] - @passive = true - return SOCKSsocket.open(host, port) - else - return TCPsocket.open(host, port) - end - end - private :open_socket - - def connect(host, port = FTP_PORT) - if @debug_mode - print "connect: ", host, ", ", port, "\n" - end - synchronize do - @sock = open_socket(host, port) - voidresp - end - end - - def sanitize(s) - if s =~ /^PASS /i - return s[0, 5] + "*" * (s.length - 5) - else - return s - end - end - private :sanitize - - def putline(line) - if @debug_mode - print "put: ", sanitize(line), "\n" - end - line = line + CRLF - @sock.write(line) - end - private :putline - - def getline - line = @sock.readline # if get EOF, raise EOFError - if line[-2, 2] == CRLF - line = line[0 .. -3] - elsif line[-1] == ?\r or - line[-1] == ?\n - line = line[0 .. -2] - end - if @debug_mode - print "get: ", sanitize(line), "\n" - end - return line - end - private :getline - - def getmultiline - line = getline - buff = line - if line[3] == ?- - code = line[0, 3] - begin - line = getline - buff << "\n" << line - end until line[0, 3] == code and line[3] != ?- - end - return buff << "\n" - end - private :getmultiline - - def getresp - resp = getmultiline - @lastresp = resp[0, 3] - c = resp[0] - case c - when ?1, ?2, ?3 - return resp - when ?4 - raise FTPTempError, resp - when ?5 - raise FTPPermError, resp - else - raise FTPProtoError, resp - end - end - private :getresp - - def voidresp - resp = getresp - if resp[0] != ?2 - raise FTPReplyError, resp - end - end - private :voidresp - - def sendcmd(cmd) - synchronize do - putline(cmd) - return getresp - end - end - - def voidcmd(cmd) - synchronize do - putline(cmd) - voidresp - end - end - - def sendport(host, port) - 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(@sock.addr[3], 0) - port = sock.addr[1] - host = TCPsocket.getaddress(@sock.addr[2]) - resp = sendport(host, port) - return sock - 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 = makepasv - conn = open_socket(host, port) - resp = sendcmd(cmd) - if resp[0] != ?1 - raise FTPReplyError, resp - end - else - sock = makeport - resp = sendcmd(cmd) - if resp[0] != ?1 - raise FTPReplyError, resp - end - conn = sock.accept - end - return conn - end - private :transfercmd - - def getaddress - thishost = Socket.gethostname - if not thishost.index(".") - thishost = Socket.gethostbyname(thishost)[0] - end - if ENV.has_key?("LOGNAME") - realuser = ENV["LOGNAME"] - elsif ENV.has_key?("USER") - realuser = ENV["USER"] - else - realuser = "anonymous" - end - return realuser + "@" + thishost - end - private :getaddress - - def login(user = "anonymous", passwd = nil, acct = nil) - if user == "anonymous" and passwd == nil - passwd = getaddress - end - - resp = "" - synchronize do - resp = sendcmd('USER ' + user) - if resp[0] == ?3 - resp = sendcmd('PASS ' + passwd) - end - if resp[0] == ?3 - resp = sendcmd('ACCT ' + acct) - end - end - if resp[0] != ?2 - raise FTPReplyError, resp - end - @welcome = resp - end - - def retrbinary(cmd, blocksize, callback = Proc.new) - synchronize do - voidcmd("TYPE I") - conn = transfercmd(cmd) - loop do - data = conn.read(blocksize) - break if data == nil - callback.call(data) - end - conn.close - voidresp - end - end - - def retrlines(cmd, callback = nil) - if iterator? - callback = Proc.new - elsif not callback.is_a?(Proc) - callback = Proc.new {|line| print line, "\n"} - end - synchronize do - voidcmd("TYPE A") - conn = transfercmd(cmd) - loop do - line = conn.gets - break if line == nil - if line[-2, 2] == CRLF - line = line[0 .. -3] - elsif line[-1] == ?\n - line = line[0 .. -2] - end - callback.call(line) - end - conn.close - voidresp - end - end - - def storbinary(cmd, file, blocksize, callback = nil) - if iterator? - callback = Proc.new - end - use_callback = callback.is_a?(Proc) - synchronize do - voidcmd("TYPE I") - conn = transfercmd(cmd) - loop do - buf = file.read(blocksize) - break if buf == nil - conn.write(buf) - callback.call(buf) if use_callback - end - conn.close - voidresp - end - end - - def storlines(cmd, file, callback = nil) - if iterator? - callback = Proc.new - end - use_callback = callback.is_a?(Proc) - synchronize do - voidcmd("TYPE A") - conn = transfercmd(cmd) - loop do - buf = file.gets - break if buf == nil - if buf[-2, 2] != CRLF - buf = buf.chop + CRLF - end - conn.write(buf) - callback.call(buf) if use_callback - end - conn.close - voidresp - end - end - - def getbinaryfile(remotefile, localfile, blocksize, callback = nil) - if iterator? - callback = Proc.new - end - use_callback = callback.is_a?(Proc) - f = open(localfile, "w") - begin - f.binmode - retrbinary("RETR " + remotefile, blocksize) do |data| - f.write(data) - callback.call(data) if use_callback - end - ensure - f.close - end - end - - def gettextfile(remotefile, localfile, callback = nil) - if iterator? - callback = Proc.new - end - use_callback = callback.is_a?(Proc) - f = open(localfile, "w") - begin - retrlines("RETR " + remotefile) do |line| - line = line + @return_code - f.write(line) - callback.call(line) if use_callback - end - ensure - f.close - end - end - - def putbinaryfile(localfile, remotefile, blocksize, callback = nil) - if iterator? - callback = Proc.new - end - use_callback = callback.is_a?(Proc) - f = open(localfile) - begin - f.binmode - storbinary("STOR " + remotefile, f, blocksize) do |data| - callback.call(data) if use_callback - end - ensure - f.close - end - end - - def puttextfile(localfile, remotefile, callback = nil) - if iterator? - callback = Proc.new - end - use_callback = callback.is_a?(Proc) - f = open(localfile) - begin - storlines("STOR " + remotefile, f) do |line| - callback.call(line) if use_callback - end - ensure - f.close - end - end - - def acct(account) - cmd = "ACCT " + account - voidcmd(cmd) - end - - def nlst(dir = nil) - cmd = "NLST" - if dir - cmd = cmd + " " + dir - end - files = [] - retrlines(cmd) do |line| - files.push(line) - end - return files - end - - def list(*args, &block) - cmd = "LIST" - args.each do |arg| - cmd = cmd + " " + arg - end - if block - retrlines(cmd, &block) - else - lines = [] - retrlines(cmd) do |line| - lines << line - end - return lines - end - end - alias ls list - alias dir list - - def rename(fromname, toname) - resp = sendcmd("RNFR " + fromname) - if resp[0] != ?3 - raise FTPReplyError, resp - end - voidcmd("RNTO " + toname) - end - - def delete(filename) - resp = sendcmd("DELE " + filename) - if resp[0, 3] == "250" - return - elsif resp[0] == ?5 - raise FTPPermError, resp - else - raise FTPReplyError, resp - end - end - - def chdir(dirname) - if dirname == ".." - begin - voidcmd("CDUP") - return - rescue FTPPermError - if $![0, 3] != "500" - raise FTPPermError, $! - end - end - end - cmd = "CWD " + dirname - voidcmd(cmd) - end - - def size(filename) - voidcmd("TYPE I") - resp = sendcmd("SIZE " + filename) - if resp[0, 3] != "213" - raise FTPReplyError, resp - end - return resp[3..-1].strip - end - - MDTM_REGEXP = /^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/ - - def mtime(filename, local = false) - str = mdtm(filename) - ary = str.scan(MDTM_REGEXP)[0].collect {|i| i.to_i} - return local ? Time.local(*ary) : Time.gm(*ary) - end - - def mkdir(dirname) - resp = sendcmd("MKD " + dirname) - return parse257(resp) - end - - def rmdir(dirname) - voidcmd("RMD " + dirname) - end - - def pwd - resp = sendcmd("PWD") - return parse257(resp) - end - alias getdir pwd - - def system - resp = sendcmd("SYST") - if resp[0, 3] != "215" - raise FTPReplyError, resp - end - return resp[4 .. -1] - end - - def abort - line = "ABOR" + CRLF - print "put: ABOR\n" if @debug_mode - @sock.send(line, Socket::MSG_OOB) - resp = getmultiline - unless ["426", "226", "225"].include?(resp[0, 3]) - raise FTPProtoError, resp - end - return resp - end - - def status - line = "STAT" + CRLF - print "put: STAT\n" if @debug_mode - @sock.send(line, Socket::MSG_OOB) - return getresp - end - - def mdtm(filename) - resp = sendcmd("MDTM " + filename) - if resp[0, 3] == "213" - return resp[3 .. -1].strip - end - end - - def help(arg = nil) - cmd = "HELP" - if arg - cmd = cmd + " " + arg - end - sendcmd(cmd) - end - - def quit - voidcmd("QUIT") - end - - def close - @sock.close if @sock and not @sock.closed? - end - - def closed? - @sock == nil or @sock.closed? - end - - def parse227(resp) - if resp[0, 3] != "227" - raise FTPReplyError, resp - end - left = resp.index("(") - right = resp.index(")") - if left == nil or right == nil - raise FTPProtoError, resp - end - numbers = resp[left + 1 .. right - 1].split(",") - if numbers.length != 6 - raise FTPProtoError, resp - end - host = numbers[0, 4].join(".") - port = (numbers[4].to_i << 8) + numbers[5].to_i - return host, port - 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 - end - if resp[3, 2] != ' "' - return "" - end - dirname = "" - i = 5 - n = resp.length - while i < n - c = resp[i, 1] - i = i + 1 - if c == '"' - if i > n or resp[i, 1] != '"' - break - end - i = i + 1 - end - dirname = dirname + c - end - return dirname - end - private :parse257 -end - -## ftplib.rb ends here +FTP = ::Net::FTP +FTPError = ::Net::FTPError +FTPReplyError = ::Net::FTPReplyError +FTPTempError = ::Net::FTPTempError +FTPPermError = ::Net::FTPPermError +FTPProtoError = ::Net::FTPProtoError diff --git a/lib/getoptlong.rb b/lib/getoptlong.rb index 82cccf43b9..5dd444adcd 100644 --- a/lib/getoptlong.rb +++ b/lib/getoptlong.rb @@ -1,5 +1,5 @@ # -*- Ruby -*- -# Copyright (C) 1998 Motoyuki Kasahara +# Copyright (C) 1998, 1999, 2000 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 @@ -232,7 +232,7 @@ class GetoptLong # Termintate option processing. # def terminate - return if @status == STATUS_TERMINATED + return nil if @status == STATUS_TERMINATED raise RuntimeError, "an error has occured" if @error != nil @status = STATUS_TERMINATED @@ -293,12 +293,12 @@ class GetoptLong # Get next option name and its argument as an array. # def get - name, argument = nil, '' + option_name, option_argument = nil, '' # # Check status. # - return if @error != nil + return nil if @error != nil case @status when STATUS_YET @status = STATUS_STARTED @@ -310,7 +310,7 @@ class GetoptLong # Get next option argument. # if 0 < @rest_singles.length - $_ = '-' + @rest_singles + argument = '-' + @rest_singles elsif (ARGV.length == 0) terminate return nil @@ -322,22 +322,22 @@ class GetoptLong terminate return nil end - $_ = ARGV.shift + argument = ARGV.shift elsif @ordering == REQUIRE_ORDER if (ARGV[0] !~ /^-./) terminate return nil end - $_ = ARGV.shift + argument = ARGV.shift else - $_ = ARGV.shift + argument = ARGV.shift end # # Check the special argument `--'. # `--' indicates the end of the option list. # - if $_ == '--' && @rest_singles.length == 0 + if argument == '--' && @rest_singles.length == 0 terminate return nil end @@ -345,87 +345,88 @@ class GetoptLong # # Check for long and short options. # - if /^(--[^=]+)/ && @rest_singles.length == 0 + if argument =~ /^(--[^=]+)/ && @rest_singles.length == 0 # # This is a long style option, which start with `--'. # pattern = $1 if @canonical_names.include?(pattern) - name = pattern + option_name = pattern else # - # The option `name' is not registered in `@canonical_names'. + # The option `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 + option_name = key match_count += 1 end end if 2 <= match_count - set_error(AmbigousOption, "option `#{$_}' is ambiguous") + set_error(AmbigousOption, "option `#{argument}' is ambiguous") elsif match_count == 0 - set_error(InvalidOption, "unrecognized option `#{$_}'") + set_error(InvalidOption, "unrecognized option `#{argument}'") end end # # Check an argument to the option. # - if @argument_flags[name] == REQUIRED_ARGUMENT - if /=(.*)$/ - argument = $1 + if @argument_flags[option_name] == REQUIRED_ARGUMENT + if argument =~ /=(.*)$/ + option_argument = $1 elsif 0 < ARGV.length - argument = ARGV.shift + option_argument = ARGV.shift else - set_error(MissingArgument, "option `#{$_}' requires an argument") + set_error(MissingArgument, + "option `#{argument}' requires an argument") end - elsif @argument_flags[name] == OPTIONAL_ARGUMENT - if /=(.*)$/ - argument = $1 + elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT + if argument =~ /=(.*)$/ + option_argument = $1 elsif 0 < ARGV.length && ARGV[0] !~ /^-./ - argument = ARGV.shift + option_argument = ARGV.shift else - argument = '' + option_argument = '' end - elsif /=(.*)$/ + elsif argument =~ /=(.*)$/ set_error(NeedlessArgument, - "option `#{name}' doesn't allow an argument") + "option `#{option_name}' doesn't allow an argument") end - elsif /^(-(.))(.*)/ + elsif argument =~ /^(-(.))(.*)/ # # 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 + option_name, ch, @rest_singles = $1, $2, $3 - if @canonical_names.include?(name) + if @canonical_names.include?(option_name) # - # The option `name' is found in `@canonical_names'. + # The option `option_name' is found in `@canonical_names'. # Check its argument. # - if @argument_flags[name] == REQUIRED_ARGUMENT + if @argument_flags[option_name] == REQUIRED_ARGUMENT if 0 < @rest_singles.length - argument = @rest_singles + option_argument = @rest_singles @rest_singles = '' elsif 0 < ARGV.length - argument = ARGV.shift + option_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 + elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT if 0 < @rest_singles.length - argument = @rest_singles + option_argument = @rest_singles @rest_singles = '' elsif 0 < ARGV.length && ARGV[0] !~ /^-./ - argument = ARGV.shift + option_argument = ARGV.shift else - argument = '' + option_argument = '' end end else @@ -444,10 +445,10 @@ class GetoptLong # This is a non-option argument. # Only RETURN_IN_ORDER falled into here. # - return '', $_ + return '', argument end - return @canonical_names[name], argument + return @canonical_names[option_name], option_argument end # @@ -460,9 +461,9 @@ class GetoptLong # def each loop do - name, argument = get_option - break if name == nil - yield name, argument + option_name, option_argument = get_option + break if option_name == nil + yield option_name, option_argument end end diff --git a/lib/mkmf.rb b/lib/mkmf.rb index 5df77bd3ab..f510e9c509 100644 --- a/lib/mkmf.rb +++ b/lib/mkmf.rb @@ -243,7 +243,7 @@ SRC print "no\n" return false end - header.tr!("a-z./\055", "A-Z___") + header.tr!("a-z\055./", "A-Z___") $defs.push(format("-DHAVE_%s", header)) print "yes\n" return true @@ -367,6 +367,8 @@ CXXFLAGS = $(CFLAGS) DLDFLAGS = #{$DLDFLAGS} #{$LDFLAGS} LDSHARED = #{CONFIG["LDSHARED"]} #{defflag} +RUBY_INSTALL_NAME = #{CONFIG["RUBY_INSTALL_NAME"]} + prefix = #{CONFIG["prefix"]} exec_prefix = #{CONFIG["exec_prefix"]} libdir = #{$libdir} diff --git a/lib/net/ftp.rb b/lib/net/ftp.rb new file mode 100644 index 0000000000..cbb2832a0d --- /dev/null +++ b/lib/net/ftp.rb @@ -0,0 +1,642 @@ +=begin + += net/ftp.rb + +written by Shugo Maeda + +This library is distributed under the terms of the Ruby license. +You can freely distribute/modify this library. + +=end + +require "socket" +require "monitor" + +module Net + + class FTPError < StandardError; end + class FTPReplyError < FTPError; end + class FTPTempError < FTPError; end + class FTPPermError < FTPError; end + class FTPProtoError < FTPError; end + + class FTP + include MonitorMixin + + FTP_PORT = 21 + CRLF = "\r\n" + + attr_accessor :passive, :return_code, :debug_mode + attr_reader :welcome, :lastresp + + def FTP.open(host, user = nil, passwd = nil, acct = nil) + new(host, user, passwd, acct) + end + + def initialize(host = nil, user = nil, passwd = nil, acct = nil) + super + @passive = false + @return_code = "\n" + @debug_mode = false + if host + connect(host) + if user + login(user, passwd, acct) + end + end + end + + def open_socket(host, port) + if defined? SOCKSsocket and ENV["SOCKS_SERVER"] + @passive = true + return SOCKSsocket.open(host, port) + else + return TCPsocket.open(host, port) + end + end + private :open_socket + + def connect(host, port = FTP_PORT) + if @debug_mode + print "connect: ", host, ", ", port, "\n" + end + synchronize do + @sock = open_socket(host, port) + voidresp + end + end + + def sanitize(s) + if s =~ /^PASS /i + return s[0, 5] + "*" * (s.length - 5) + else + return s + end + end + private :sanitize + + def putline(line) + if @debug_mode + print "put: ", sanitize(line), "\n" + end + line = line + CRLF + @sock.write(line) + end + private :putline + + def getline + line = @sock.readline # if get EOF, raise EOFError + if line[-2, 2] == CRLF + line = line[0 .. -3] + elsif line[-1] == ?\r or + line[-1] == ?\n + line = line[0 .. -2] + end + if @debug_mode + print "get: ", sanitize(line), "\n" + end + return line + end + private :getline + + def getmultiline + line = getline + buff = line + if line[3] == ?- + code = line[0, 3] + begin + line = getline + buff << "\n" << line + end until line[0, 3] == code and line[3] != ?- + end + return buff << "\n" + end + private :getmultiline + + def getresp + resp = getmultiline + @lastresp = resp[0, 3] + c = resp[0] + case c + when ?1, ?2, ?3 + return resp + when ?4 + raise FTPTempError, resp + when ?5 + raise FTPPermError, resp + else + raise FTPProtoError, resp + end + end + private :getresp + + def voidresp + resp = getresp + if resp[0] != ?2 + raise FTPReplyError, resp + end + end + private :voidresp + + def sendcmd(cmd) + synchronize do + putline(cmd) + return getresp + end + end + + def voidcmd(cmd) + synchronize do + putline(cmd) + voidresp + end + end + + def sendport(host, port) + 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(@sock.addr[3], 0) + port = sock.addr[1] + host = TCPsocket.getaddress(@sock.addr[2]) + resp = sendport(host, port) + return sock + 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 = makepasv + conn = open_socket(host, port) + resp = sendcmd(cmd) + if resp[0] != ?1 + raise FTPReplyError, resp + end + else + sock = makeport + resp = sendcmd(cmd) + if resp[0] != ?1 + raise FTPReplyError, resp + end + conn = sock.accept + end + return conn + end + private :transfercmd + + def getaddress + thishost = Socket.gethostname + if not thishost.index(".") + thishost = Socket.gethostbyname(thishost)[0] + end + if ENV.has_key?("LOGNAME") + realuser = ENV["LOGNAME"] + elsif ENV.has_key?("USER") + realuser = ENV["USER"] + else + realuser = "anonymous" + end + return realuser + "@" + thishost + end + private :getaddress + + def login(user = "anonymous", passwd = nil, acct = nil) + if user == "anonymous" and passwd == nil + passwd = getaddress + end + + resp = "" + synchronize do + resp = sendcmd('USER ' + user) + if resp[0] == ?3 + resp = sendcmd('PASS ' + passwd) + end + if resp[0] == ?3 + resp = sendcmd('ACCT ' + acct) + end + end + if resp[0] != ?2 + raise FTPReplyError, resp + end + @welcome = resp + end + + def retrbinary(cmd, blocksize, callback = Proc.new) + synchronize do + voidcmd("TYPE I") + conn = transfercmd(cmd) + loop do + data = conn.read(blocksize) + break if data == nil + callback.call(data) + end + conn.close + voidresp + end + end + + def retrlines(cmd, callback = nil) + if iterator? + callback = Proc.new + elsif not callback.is_a?(Proc) + callback = Proc.new {|line| print line, "\n"} + end + synchronize do + voidcmd("TYPE A") + conn = transfercmd(cmd) + loop do + line = conn.gets + break if line == nil + if line[-2, 2] == CRLF + line = line[0 .. -3] + elsif line[-1] == ?\n + line = line[0 .. -2] + end + callback.call(line) + end + conn.close + voidresp + end + end + + def storbinary(cmd, file, blocksize, callback = nil) + if iterator? + callback = Proc.new + end + use_callback = callback.is_a?(Proc) + synchronize do + voidcmd("TYPE I") + conn = transfercmd(cmd) + loop do + buf = file.read(blocksize) + break if buf == nil + conn.write(buf) + callback.call(buf) if use_callback + end + conn.close + voidresp + end + end + + def storlines(cmd, file, callback = nil) + if iterator? + callback = Proc.new + end + use_callback = callback.is_a?(Proc) + synchronize do + voidcmd("TYPE A") + conn = transfercmd(cmd) + loop do + buf = file.gets + break if buf == nil + if buf[-2, 2] != CRLF + buf = buf.chomp + CRLF + end + conn.write(buf) + callback.call(buf) if use_callback + end + conn.close + voidresp + end + end + + def getbinaryfile(remotefile, localfile, blocksize, callback = nil) + if iterator? + callback = Proc.new + end + use_callback = callback.is_a?(Proc) + f = open(localfile, "w") + begin + f.binmode + retrbinary("RETR " + remotefile, blocksize) do |data| + f.write(data) + callback.call(data) if use_callback + end + ensure + f.close + end + end + + def gettextfile(remotefile, localfile, callback = nil) + if iterator? + callback = Proc.new + end + use_callback = callback.is_a?(Proc) + f = open(localfile, "w") + begin + retrlines("RETR " + remotefile) do |line| + line = line + @return_code + f.write(line) + callback.call(line) if use_callback + end + ensure + f.close + end + end + + def putbinaryfile(localfile, remotefile, blocksize, callback = nil) + if iterator? + callback = Proc.new + end + use_callback = callback.is_a?(Proc) + f = open(localfile) + begin + f.binmode + storbinary("STOR " + remotefile, f, blocksize) do |data| + callback.call(data) if use_callback + end + ensure + f.close + end + end + + def puttextfile(localfile, remotefile, callback = nil) + if iterator? + callback = Proc.new + end + use_callback = callback.is_a?(Proc) + f = open(localfile) + begin + storlines("STOR " + remotefile, f) do |line| + callback.call(line) if use_callback + end + ensure + f.close + end + end + + def acct(account) + cmd = "ACCT " + account + voidcmd(cmd) + end + + def nlst(dir = nil) + cmd = "NLST" + if dir + cmd = cmd + " " + dir + end + files = [] + retrlines(cmd) do |line| + files.push(line) + end + return files + end + + def list(*args, &block) + cmd = "LIST" + args.each do |arg| + cmd = cmd + " " + arg + end + if block + retrlines(cmd, &block) + else + lines = [] + retrlines(cmd) do |line| + lines << line + end + return lines + end + end + alias ls list + alias dir list + + def rename(fromname, toname) + resp = sendcmd("RNFR " + fromname) + if resp[0] != ?3 + raise FTPReplyError, resp + end + voidcmd("RNTO " + toname) + end + + def delete(filename) + resp = sendcmd("DELE " + filename) + if resp[0, 3] == "250" + return + elsif resp[0] == ?5 + raise FTPPermError, resp + else + raise FTPReplyError, resp + end + end + + def chdir(dirname) + if dirname == ".." + begin + voidcmd("CDUP") + return + rescue FTPPermError + if $![0, 3] != "500" + raise FTPPermError, $! + end + end + end + cmd = "CWD " + dirname + voidcmd(cmd) + end + + def size(filename) + voidcmd("TYPE I") + resp = sendcmd("SIZE " + filename) + if resp[0, 3] != "213" + raise FTPReplyError, resp + end + return resp[3..-1].strip.to_i + end + + MDTM_REGEXP = /^(\d\d\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)$/ + + def mtime(filename, local = false) + str = mdtm(filename) + ary = str.scan(MDTM_REGEXP)[0].collect {|i| i.to_i} + return local ? Time.local(*ary) : Time.gm(*ary) + end + + def mkdir(dirname) + resp = sendcmd("MKD " + dirname) + return parse257(resp) + end + + def rmdir(dirname) + voidcmd("RMD " + dirname) + end + + def pwd + resp = sendcmd("PWD") + return parse257(resp) + end + alias getdir pwd + + def system + resp = sendcmd("SYST") + if resp[0, 3] != "215" + raise FTPReplyError, resp + end + return resp[4 .. -1] + end + + def abort + line = "ABOR" + CRLF + print "put: ABOR\n" if @debug_mode + @sock.send(line, Socket::MSG_OOB) + resp = getmultiline + unless ["426", "226", "225"].include?(resp[0, 3]) + raise FTPProtoError, resp + end + return resp + end + + def status + line = "STAT" + CRLF + print "put: STAT\n" if @debug_mode + @sock.send(line, Socket::MSG_OOB) + return getresp + end + + def mdtm(filename) + resp = sendcmd("MDTM " + filename) + if resp[0, 3] == "213" + return resp[3 .. -1].strip + end + end + + def help(arg = nil) + cmd = "HELP" + if arg + cmd = cmd + " " + arg + end + sendcmd(cmd) + end + + def quit + voidcmd("QUIT") + end + + def close + @sock.close if @sock and not @sock.closed? + end + + def closed? + @sock == nil or @sock.closed? + end + + def parse227(resp) + if resp[0, 3] != "227" + raise FTPReplyError, resp + end + left = resp.index("(") + right = resp.index(")") + if left == nil or right == nil + raise FTPProtoError, resp + end + numbers = resp[left + 1 .. right - 1].split(",") + if numbers.length != 6 + raise FTPProtoError, resp + end + host = numbers[0, 4].join(".") + port = (numbers[4].to_i << 8) + numbers[5].to_i + return host, port + 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 + end + if resp[3, 2] != ' "' + return "" + end + dirname = "" + i = 5 + n = resp.length + while i < n + c = resp[i, 1] + i = i + 1 + if c == '"' + if i > n or resp[i, 1] != '"' + break + end + i = i + 1 + end + dirname = dirname + c + end + return dirname + end + private :parse257 + end + +end diff --git a/lib/net/http.rb b/lib/net/http.rb new file mode 100644 index 0000000000..4847f88bf7 --- /dev/null +++ b/lib/net/http.rb @@ -0,0 +1,312 @@ +=begin + += net/http.rb + +maintained by Minero Aoki +This file is derived from http-access.rb + +This library is distributed under the terms of the Ruby license. +You can freely distribute/modify this library. + +=end + +require 'net/session' + + +module Net + + +class HTTPError < ProtocolError; end +class HTTPBadResponse < HTTPError; end + + +=begin + += HTTP class + +== Class Methods + +: new( address, port = 80 ) + create new HTTP object. + +: port + returns HTTP default port, 80 + +: command_type + returns Command class, HTTPCommand + + +== Methods + +: get( path, header = nil, ret = '' ) + get data from "path" on connecting host. + "header" is a Hash like { 'Accept' => '*/*', ... }. + The data will be written to "ret" using "<<" method. + This method returns response header (Hash) and "ret". + +: head( path, header = nil ) + get only header from "path" on connecting host. + "header" is a Hash like { 'Accept' => '*/*', ... }. + This method returns header as a Hash like + + { 'content-length' => 'Content-Length: 2554', + 'content-type' => 'Content-Type: text/html', + ... } + +=end + + class HTTP < Protocol + + protocol_param :port, '80' + protocol_param :command_type, '::Net::HTTPCommand' + + + def get( path, u_header = nil, ret = '' ) + header = connecting { + @command.get ret, edit_path(path), u_header + } + return header, ret + end + + def head( path, u_header = nil ) + connecting { + @command.head edit_path(path), u_header + } + end + + + private + + + def connecting + if @socket.closed? then + @socket.reopen + end + header = yield + @socket.close unless keep_alive? header + + header + end + + def keep_alive?( header ) + if str = header[ 'connection' ] then + if /\Aconnection:\s*keep-alive/i === str then + return true + end + else + if @http_version == '1.1' then + return true + end + end + + false + end + + + def do_finish + unless @command.error_occured or @socket.closed? then + head '/', { 'Connection' => 'Close' } + end + end + + + def edit_path( path ) + path + end + + class << self + def Proxy( p_addr, p_port ) + klass = super + klass.module_eval %- + def edit_path( path ) + 'http://' + address + + (@port == #{self.port} ? '' : ':' + @port.to_s) + path + end + - + klass + end + end + + end + + HTTPSession = HTTP + + + class HTTPCommand < Command + + HTTPVersion = '1.1' + + def initialize( sock ) + @http_version = HTTPVersion + + @in_header = {} + @in_header[ 'Host' ] = sock.addr + @in_header[ 'Connection' ] = 'Keep-Alive' + @in_header[ 'Accept' ] = '*/*' + + super sock + end + + + attr :http_version + + def get( ret, path, u_header = nil ) + header = get_response( + sprintf( 'GET %s HTTP/%s', path, HTTPVersion ), u_header ) + + if chunked? header then + clen = read_chunked_body( ret ) + header.delete 'transfer-encoding' + header[ 'content-length' ] = "Content-Length: #{clen}" + else + if clen = content_length( header ) then + @socket.read clen, ret + else + @socket.read_all ret + end + end + + header + end + + + def head( path, u_header = nil ) + get_response sprintf( 'HEAD %s HTTP/%s', path, HTTPVersion ), u_header + end + + + # def put + + # def delete + + # def trace + + # def options + + + private + + + def do_quit + unless @socket.closed? then + @socket.close + end + end + + def get_response( line, u_header ) + @socket.writeline line + write_header u_header + rep = get_reply + header = read_header + reply_must rep, SuccessCode + + header + end + + def get_reply + str = @socket.readline + unless /\AHTTP\/(\d+\.\d+)?\s+(\d\d\d)\s*(.*)\z/i === str then + raise HTTPBadResponse, "wrong status line format: #{str}" + end + @http_version = $1 + status = $2 + discrip = $3 + + klass = case status[0] + when ?1 then + case status[2] + when ?0 then ContinueCode + when ?1 then SuccessCode + else UnknownCode + end + when ?2 then SuccessCode + when ?3 then RetryCode + when ?4 then ServerBusyCode + when ?5 then FatalErrorCode + else UnknownCode + end + klass.new( status, discrip ) + end + + + def content_length( header ) + unless str = header[ 'content-length' ] then + return nil + end + unless /\Acontent-length:\s*(\d+)/i === str then + raise HTTPBadResponse, "content-length format error" + end + $1.to_i + end + + def chunked?( header ) + if str = header[ 'transfer-encoding' ] then + if /\Atransfer-encoding:\s*chunked/i === str then + return true + end + end + + false + end + + + def read_header + header = {} + while true do + line = @socket.readline + break if line.empty? + /\A[^:]+/ === line + nm = $& + nm.strip! + nm.downcase! + header[ nm ] = line + end + + header + end + + def write_header( user ) + if user then + header = @in_header.dup.update user + else + header = @in_header + end + header.each do |n,v| + @socket.writeline n + ': ' + v + end + @socket.writeline '' + + if tmp = header['Connection'] then + /close/i === tmp + else + false + end + end + + def read_chunked_body( ret ) + line = nil + len = nil + total = 0 + + while true do + line = @socket.readline + unless /[0-9a-hA-H]+/ === line then + raise HTTPBadResponse, "chunk size not given" + end + len = $&.hex + break if len == 0 + @socket.read( len, ret ); total += len + @socket.read 2 # \r\n + end + while true do + line = @socket.readline + break if line.empty? + end + + total + end + + end + + +end # module Net diff --git a/lib/net/pop.rb b/lib/net/pop.rb index bd4551571d..0ec2481557 100644 --- a/lib/net/pop.rb +++ b/lib/net/pop.rb @@ -1,8 +1,14 @@ -# -# pop.rb version 1.0.1 -# -# author: Minero Aoki -# +=begin + += net/pop.rb + +written by Minero Aoki + +This library is distributed under the terms of the Ruby license. +You can freely distribute/modify this library. + +=end + require 'net/session' require 'md5' @@ -10,101 +16,250 @@ require 'md5' module Net - class POP3Session < Session - attr :mails +=begin - def each() @mails.each{|m| yield m} end +== Net::POP3 +=== Super Class - private +Net::Protocol + +=== Class Methods + +: new( address = 'localhost', port = 110 ) + This method create a new POP3 object. + This will not open connection yet. + + +=== Methods + +: start( account, password ) + This method start POP3. + +: each{|popmail| ...} + This method is equals to "pop3.mails.each" +: mails + This method returns an array of ((URL:#POPMail)). + This array is renewed when login. - def proto_initialize - @proto_type = POP3Command - @port = 110 - @mails = [].freeze +=end + + class POP3 < Protocol + + protocol_param :port, '110' + protocol_param :command_type, '::Net::POP3Command' + + protocol_param :mail_type, '::Net::POPMail' + + def initialize( addr = nil, port = nil ) + super + @mails = [].freeze end + + attr :mails + + def each + @mails.each {|m| yield m } + end + + + private + def do_start( acnt, pwd ) - @proto.auth( acnt, pwd ) + @command.auth( acnt, pwd ) + t = self.type.mail_type @mails = [] - @proto.list.each_with_index do |size,idx| + @command.list.each_with_index do |size,idx| if size then - @mails.push POPMail.new( idx, size, @proto ) + @mails.push t.new( idx, size, @command ) end end @mails.freeze end + end - def do_finish - @proto.quit - end + POP = POP3 + POPSession = POP3 + POP3Session = POP3 +=begin - class POPMail +== Net::POPMail - def initialize( idx, siz, pro ) - @num = idx - @size = siz - @proto = pro +A class of mail which exists on POP server. - @deleted = false - end +=== Super Class - attr :size +Object - def all( dest = '' ) - @proto.retr( @num, dest ) - end - alias pop all - alias mail all - def top( lines, dest = '' ) - @proto.top( @num, lines, dest ) - end +=== Method - def header( dest = '' ) - top( 0, dest ) - end +: all +: pop +: mail + This method fetches a mail and return it. - def delete - @proto.dele( @num ) - @deleted = true - end - alias delete! delete +: header + This method fetches only mail header. - def deleted? - @deleted - end +: top( lines ) + This method fetches mail header and 'lines' lines body. + +: delete +: delete! + This method deletes mail. + +: size + size of mail(bytes) + +: deleted? + true if mail was deleted + +=end + + class POPMail + + def initialize( n, s, cmd ) + @num = n + @size = s + @command = cmd + @deleted = false end - end + attr :size - class APOPSession < POP3Session + def all( dest = '' ) + @command.retr( @num, dest ) + end + alias pop all + alias mail all - def proto_initialize - super - @proto_type = APOPCommand + def top( lines, dest = '' ) + @command.top( @num, lines, dest ) + end + + def header( dest = '' ) + top( 0, dest ) + end + + def delete + @command.dele( @num ) + @deleted = true + end + alias delete! delete + + def deleted? + @deleted end + def uidl + @command.uidl @num + end + + end + + +=begin + +== Net::APOP + +This class has no new methods. Only way of authetication is changed. + +=== Super Class + +Net::POP3 + +=end + + class APOP < POP3 + + protocol_param :command_type, 'Net::APOPCommand' + end + APOPSession = APOP + + +=begin + +== Net::POP3Command + +POP3 command class. + +=== Super Class + +Net::Command + +=== Class Methods + +: new( socket ) + This method creates new POP3Command object. 'socket' must be ProtocolSocket. + + +=== Methods + +: auth( account, password ) + This method do POP authorization (no RPOP) + In case of failed authorization, raises Protocol::ProtocolError exception. + +: list + a list of mails which existing on server. + The list is an array like "array[ number ] = size". + + ex: + + The list from server is + + 1 2452 + 2 3355 + 4 9842 + : + + then, an array is - POPSession = POP3Session - POP3 = POP3Session + [ nil, 2452, 3355, nil, 9842, ... ] +: quit + This method ends POP using 'QUIT' commmand. + +: rset + This method reset all changes done in current session, + by sending 'RSET' command. + +: top( num, lines = 0 ) + This method gets all mail header and 'lines' lines body + by sending 'TOP' command. 'num' is mail number. + + WARNING: the TOP command is 'Optional' in RFC1939 (POP3) + +: retr( num : Integer ) + This method gets a mail by 'RETR' command. 'num' is mail number. + +: dele( num : Integer ) + This method deletes a mail on server by 'DELE'. + +=end class POP3Command < Command + def initialize( sock ) + super + check_reply SuccessCode + end + + def auth( acnt, pass ) - @socket.writeline( 'USER ' + acnt ) + @socket.writeline 'USER ' + acnt check_reply_auth @socket.writeline( 'PASS ' + pass ) @@ -115,8 +270,7 @@ module Net def list - @socket.writeline( 'LIST' ) - check_reply( SuccessCode ) + getok 'LIST' arr = [] @socket.read_pendlist do |line| @@ -129,40 +283,40 @@ module Net def rset - @socket.writeline( 'RSET' ) - check_reply( SuccessCode ) + getok 'RSET' end def top( num, lines = 0, dest = '' ) - @socket.writeline( sprintf( 'TOP %d %d', num, lines ) ) - check_reply( SuccessCode ) - - return @socket.read_pendstr( dest ) + getok sprintf( 'TOP %d %d', num, lines ) + @socket.read_pendstr( dest ) end def retr( num, dest = '', &block ) - @socket.writeline( sprintf( 'RETR %d', num ) ) - check_reply( SuccessCode ) - - return @socket.read_pendstr( dest, &block ) + getok sprintf( 'RETR %d', num ) + @socket.read_pendstr( dest, &block ) end def dele( num ) - @socket.writeline( sprintf( 'DELE %s', num ) ) - check_reply( SuccessCode ) + getok sprintf( 'DELE %d', num ) end + def uidl( num ) + rep = getok( sprintf 'UIDL %d', num ) + uid = rep.msg.split(' ')[1] + + uid + end + private def do_quit - @socket.writeline( 'QUIT' ) - check_reply( SuccessCode ) + getok 'QUIT' end @@ -190,6 +344,22 @@ module Net end +=begin + +== APOPCommand + +=== Super Class + +POP3Command + +=== Methods + +: auth( account, password ) + This method do authorization by sending 'APOP' command. + If server is not APOP server, this raises Net::ProtoAuthError exception. + On other errors, raises Net::ProtocolError. + +=end class APOPCommand < POP3Command @@ -222,9 +392,4 @@ module Net end - - unless Session::Version == '1.0.1' then - $stderr.puts "WARNING: wrong version of session.rb & pop.rb" - end - end diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb new file mode 100644 index 0000000000..4d80153f2c --- /dev/null +++ b/lib/net/protocol.rb @@ -0,0 +1,724 @@ +=begin + += net/protocol.rb + +written by Minero Aoki + +This library is distributed under the terms of the Ruby license. +You can freely distribute/modify this library. + +=end + + +require 'socket' + + +module Net + + Version = '1.1.8' + +=begin + +== Net::Protocol + +the abstruct class for Internet protocol + +=== Super Class + +Object + +=== Class Methods + +: new( address = 'localhost', port = nil ) + This method Creates a new protocol object. + +: start( address = 'localhost', port = nil, *args ) +: start( address = 'localhost', port = nil, *args ){|proto| .... } + This method creates a new Protocol object and start session. + If you call this method with block, Protocol object give itself + to block and finish session when block returns. + +: Proxy( address, port ) + This method creates a proxy class of its protocol. + Arguments are address/port of proxy host. + + +=== Methods + +: address + the address of connecting server (FQDN). + +: port + connecting port number + +: start( *args ) + This method start protocol. If you call this method when the protocol + is already started, this only returns false without doing anything. + + '*args' are specified in subclasses. + +: finish + This method ends protocol. If you call this method before protocol starts, + it only return false without doing anything. + +: active? + true if session have been started + +=end + + class Protocol + + Version = ::Net::Version + + class << self + + def start( address = 'localhost', port = nil, *args ) + instance = new( address, port ) + + if iterator? then + instance.start( *args ) { yield instance } + else + instance.start *args + instance + end + end + + def Proxy( p_addr, p_port ) + klass = Class.new( self ) + klass.module_eval %- + + def initialize( addr, port ) + @proxyaddr = '#{p_addr}' + @proxyport = '#{p_port}' + super @proxyaddr, @proxyport + @address = addr + @port = port + end + + def connect( addr, port ) + super @proxyaddr, @proxyport + end + private :connect + + attr_reader :proxyaddr, :proxyport + - + def klass.proxy? + true + end + + klass + end + + def proxy? + false + end + + + private + + def protocol_param( name, val ) + module_eval %- + def self.#{name.id2name} + #{val} + end + - + end + + end + + + # + # sub-class requirements + # + # protocol_param command_type + # protocol_param port + # + # private method do_start (optional) + # private method do_finish (optional) + # + + protocol_param :port, 'nil' + protocol_param :command_type, 'nil' + protocol_param :socket_type, '::Net::Socket' + + + def initialize( addr = nil, port = nil ) + @address = addr || 'localhost' + @port = port || self.type.port + + @active = false + @pipe = nil + + @command = nil + @socket = nil + end + + + attr_reader :address, :port, + :command, :socket + + + def start( *args ) + return false if active? + @active = true + + begin + connect @address, @port + do_start *args + yield if iterator? + ensure + finish if iterator? + end + end + + def finish + ret = active? + + do_finish if @command + disconnect + @active = false + + ret + end + + def active? + @active + end + + def set_pipe( arg ) # un-documented + @pipe = arg + end + + + private + + + def do_start + end + + def do_finish + @command.quit + end + + + def connect( addr, port ) + @socket = self.type.socket_type.open( addr, port, @pipe ) + @command = self.type.command_type.new( @socket ) + end + + def disconnect + @command = nil + if @socket and not @socket.closed? then + @socket.close + end + @socket = nil + end + + end + + Session = Protocol + + + + class Command + + def initialize( sock ) + @socket = sock + @error_occured = false + @last_reply = nil + end + + attr_reader :socket, :error_occured, :last_reply + attr_writer :socket + + def quit + if @socket and not @socket.closed? then + do_quit + @error_occured = false + end + end + + + private + + def do_quit + end + + # abstract get_reply() + + def check_reply( *oks ) + @last_reply = get_reply + reply_must( @last_reply, *oks ) + end + + def reply_must( rep, *oks ) + oks.each do |i| + if i === rep then + return rep + end + end + + @error_occured = true + rep.error! @socket.sending + end + + def getok( line, ok = SuccessCode ) + @socket.writeline line + check_reply ok + end + + end + + + class ProtocolError < StandardError ; end + class ProtoSyntaxError < ProtocolError ; end + class ProtoFatalError < ProtocolError ; end + class ProtoUnknownError < ProtocolError ; end + class ProtoServerError < ProtocolError ; end + class ProtoAuthError < ProtocolError ; end + class ProtoCommandError < ProtocolError ; end + class ProtoRetryError < ProtocolError ; end + + class ReplyCode + + class << self + + def error_type( err ) + @err = err + end + + def error!( mes ) + raise @err, mes + end + + end + + def initialize( cod, mes ) + @code = cod + @msg = mes + @data = nil + end + + attr_reader :code, :msg + + def []( key ) + if @data then + @data[key] + else + nil + end + end + + def []=( key, val ) + unless h = @data then + @data = h = {} + end + h[key] = val + end + + + def error!( sending ) + mes = < 512 + end + end + end + + def each_crlf_line2( mid ) + buf = @wbuf + beg = pos = nil + + buf << "\n" unless /\n|\r/o === buf[-1,1] + + beg = 0 + while pos = buf.index( TERMEXP, beg ) do + send mid, buf[ beg, pos - beg ] << CRLF + beg = pos + $&.size + end + end + + + def do_write_beg + @writtensize = 0 + @sending = '' + @wbuf = '' + end + + def do_write_do( arg ) + if @pipe or @sending.size < 128 then + @sending << Net.quote( arg ) + else + @sending << '...' unless @sending[-1] == ?. + end + + s = @socket.write( arg ) + @writtensize += s + s + end + + def do_write_fin + if @pipe then + @pipe << 'write "' + @pipe << @sending + @pipe << "\"\n" + end + + @socket.flush + @writtensize + end + + end + + + def Net.quote( str ) + str = str.gsub( "\n", '\\n' ) + str.gsub!( "\r", '\\r' ) + str.gsub!( "\t", '\\t' ) + str + end + +end # module Net diff --git a/lib/net/session.rb b/lib/net/session.rb index b0977e7e14..7cf423ce3a 100644 --- a/lib/net/session.rb +++ b/lib/net/session.rb @@ -1,82 +1,197 @@ -# -# session.rb version 1.0.1 -# -# author: Minero Aoki -# +=begin -require 'socket' += net/session.rb +written by Minero Aoki -class String +This library is distributed under the terms of the Ruby license. +You can freely distribute/modify this library. - def doquote - str = self.gsub( "\n", '\\n' ) - str.gsub!( "\r", '\\r' ) - str.gsub!( "\t", '\\t' ) - return str - end +=end -end +require 'socket' module Net - DEBUG = $DEBUG - # DEBUG = false + Version = '1.1.4' +=begin - class Session +== Net::Protocol - Version = '1.0.1' +the abstruct class for Internet protocol - def initialize( addr = 'localhost', port = nil ) - proto_initialize - @address = addr - @port = port if port - @active = false - end +=== Super Class + +Object + +=== Constants + +: Version + The version of Session class. It is a string like "1.1.4". + + +=== Class Methods + +: new( address = 'localhost', port = nil ) + This method Creates a new Session object. + +: start( address = 'localhost', port = nil, *args ) +: start( address = 'localhost', port = nil, *args ){|session| .... } + This method creates a new Session object and start session. + If you call this method with block, Session object give itself + to block and finish session when block returns. + +: Proxy( address, port ) + This method creates a proxy class of its protocol. + Arguments are address/port of proxy host. + + +=== Methods + +: address + the address of connecting server (FQDN). + +: port + connecting port number + +: start( *args ) + This method start protocol. If you call this method when the protocol + is already started, this only returns false without doing anything. + + '*args' are specified in subclasses. + +: finish + This method ends protocol. If you call this method before protocol starts, + it only return false without doing anything. + +: active? + true if session have been started + +=end + + class Protocol class << self + def start( address = 'localhost', port = nil, *args ) - inst = new( address, port ) - ret = inst.start( *args ) + instance = new( address, port ) if iterator? then - ret = yield( inst ) - inst.finish + instance.start( *args ) { yield instance } + else + instance.start *args + instance end - return ret end + + def Proxy( p_addr, p_port ) + klass = Class.new( self ) + klass.module_eval %- + + def initialize( addr, port ) + @proxyaddr = '#{p_addr}' + @proxyport = '#{p_port}' + super @proxyaddr, @proxyport + @address = addr + @port = port + end + + def connect( addr, port ) + super @proxyaddr, @proxyport + end + private :connect + + attr :proxyaddr + attr :proxyport + - + def klass.proxy? + true + end + + klass + end + + def proxy? + false + end + + + private + + def protocol_param( name, val ) + module_eval %- + def self.#{name.id2name} + #{val} + end + - + end + + end + + + # + # sub-class requirements + # + # protocol_param command_type + # protocol_param port + # + # private method do_start (optional) + # private method do_finish (optional) + # + + protocol_param :port, 'nil' + protocol_param :command_type, 'nil' + protocol_param :socket_type, '::Net::ProtocolSocket' + + + def initialize( addr = nil, port = nil ) + @address = addr || 'localhost' + @port = port || self.type.port + + @active = false + @pipe = nil + + @command = nil + @socket = nil end attr :address attr :port + attr :command attr :socket - attr :proto_type - attr :proto, true def start( *args ) return false if active? + @active = true - if ProtocolSocket === args[0] then - @socket = args.shift - else - @socket = ProtocolSocket.open( @address, @port ) + begin + connect @address, @port + do_start *args + yield if iterator? + ensure + finish if iterator? end - @proto = @proto_type.new( @socket ) - do_start( *args ) - - @active = true end def finish - if @proto then + if @command then do_finish - @proto = nil + disconnect + end + + if @socket and not @socket.closed? then + @socket.close + @socket = nil + end + + if active? then + @active = false return true else @@ -84,20 +199,72 @@ module Net end end - def active?() @active end + def active? + @active + end + + def set_pipe( arg ) # un-documented + @pipe = arg + end + + + private + + + def do_start + end + + def do_finish + end + + + def connect( addr, port ) + @socket = self.type.socket_type.open( addr, port, @pipe ) + @command = self.type.command_type.new( @socket ) + end + + def disconnect + @command.quit + @command = nil + @socket = nil + end end + Session = Protocol + + +=begin + +== Net::Command + +=== Super Class + +Object + +=== Class Methods + +: new( socket ) + This method create new Command object. 'socket' must be ProtocolSocket. + This method is abstract class. + + +=== Methods +: quit + This method dispatch command which ends the protocol. + +=end class Command def initialize( sock ) @socket = sock - check_reply( SuccessCode ) + @error_occured = false end attr :socket, true + attr :error_occured def quit if @socket and not @socket.closed? then @@ -107,21 +274,31 @@ module Net @socket.close unless @socket.closed? @socket = nil end + @error_occured = false end end private def check_reply( *oks ) - rep = get_reply + reply_must( get_reply, *oks ) + end + + def reply_must( rep, *oks ) oks.each do |i| if i === rep then return rep end end + @error_occured = true rep.error! @socket.sending end + + def getok( line, ok = SuccessCode ) + @socket.writeline line + check_reply ok + end end @@ -133,6 +310,7 @@ module Net class ProtoServerError < ProtocolError ; end class ProtoAuthError < ProtocolError ; end class ProtoCommandError < ProtocolError ; end + class ProtoRetryError < ProtocolError ; end class ReplyCode @@ -145,64 +323,157 @@ module Net attr :msg def error!( sending ) - err, tag = Errors[ self.type ] - mes = sprintf( < [ ProtoUnknownError, 'unknown error' ], - ContinueCode => [ ProtoUnknownError, 'unknown error' ], - ErrorCode => [ ProtocolError, 'protocol error' ], - SyntaxErrorCode => [ ProtoSyntaxError, 'syntax error' ], - FatalErrorCode => [ ProtoFatalError, 'fatal error' ], - ServerBusyCode => [ ProtoServerError, 'probably server busy' ], - UnknownCode => [ ProtoUnknownError, 'unknown error' ] - } + class ContinueCode < SuccessCode + Error = ProtoUnknownError + end + + class ErrorCode < ReplyCode + Error = ProtocolError + end + + class SyntaxErrorCode < ErrorCode + Error = ProtoSyntaxError + end + + class FatalErrorCode < ErrorCode + Error = ProtoFatalError + end + + class ServerBusyCode < ErrorCode + Error = ProtoServerError end + class RetryCode < ReplyCode + Error = ProtoRetryError + end + + class UnknownCode < ReplyCode + Error = ProtoUnknownError + end + + +=begin + +== Net::ProtocolSocket + +=== Super Class + +Object + +=== Class Methods + +: new( address = 'localhost', port = nil ) + This create new ProtocolSocket object, and connect to server. + + +=== Methods + +: close + This method closes socket. + +: address, addr + a FQDN address of server + +: ip_address, ipaddr + an IP address of server + +: port + connecting port number. + +: closed? + true if ProtocolSokcet have been closed already + + +: read( length ) + This method read 'length' bytes and return the string. + +: readuntil( target ) + This method read until find 'target'. Returns read string. + +: readline + read until "\r\n" and returns it without "\r\n". + +: read_pendstr + This method read until "\r\n.\r\n". + At the same time, delete period at line head and final line ("\r\n.\r\n"). + +: read_pendlist +: read_pendlist{|line| .... } + This method read until "\r\n.\r\n". This method resembles to 'read_pendstr', + but 'read_pendlist' don't check period at line head, and returns array which + each element is one line. + + When this method was called with block, evaluate it for each reading a line. + +: write( src ) + This method send 'src'. ProtocolSocket read strings from 'src' by 'each' + iterator. This method returns written bytes. + +: writebin( src ) + This method send 'src'. ProtocolSokcet read string from 'src' by 'each' + iterator. This method returns written bytes. + +: writeline( str ) + This method writes 'str'. There has not to be bare "\r" or "\n" in 'str'. + +: write_pendstr( src ) + This method writes 'src' as a mail. + ProtocolSocket reads strings from 'src' by 'each' iterator. + This returns written bytes. + +=end class ProtocolSocket - def initialize( addr, port ) - @address = addr - @port = port + def initialize( addr, port, pipe = nil ) + @addr = addr + @port = port + @pipe = pipe + @closed = true @ipaddr = '' - @closed = false @sending = '' @buffer = '' @socket = TCPsocket.new( addr, port ) + @closed = false @ipaddr = @socket.addr[3] - - @dout = Net::DEBUG end + attr :pipe, true + class << self alias open new end + def reopen + unless closed? then + @socket.close + @buffer = '' + end + @socket = TCPsocket.new( @addr, @port ) + end + attr :socket, true @@ -211,11 +482,21 @@ MES @closed = true end - def closed?() @closed end + def closed? + @closed + end + + def address + @addr.dup + end + alias addr address - def addr() @address.dup end - def port() @port end - def ipaddr() @ipaddr.dup end + attr :port + + def ip_address + @ipaddr.dup + end + alias ipaddr ip_address attr :sending @@ -226,16 +507,35 @@ MES def read( len, ret = '' ) - rsize = 0 + @pipe << "reading #{len} bytes...\n" if pre = @pipe ; @pipe = nil + rsize = 0 while rsize + @buffer.size < len do - rsize += @buffer.size - ret << fetch_rbuf( @buffer.size ) + rsize += writeinto( ret, @buffer.size ) fill_rbuf end - ret << fetch_rbuf( len - rsize ) + writeinto( ret, len - rsize ) - return ret + @pipe << "read #{len} bytes\n" if @pipe = pre + ret + end + + + def read_all( ret = '' ) + @pipe << "reading all...\n" if pre = @pipe; @pipe = nil + + rsize = 0 + begin + while true do + rsize += writeinto( ret, @buffer.size ) + fill_rbuf + end + rescue EOFError + ; + end + + @pipe << "read #{rsize} bytes\n" if @pipe = pre + ret end @@ -244,19 +544,21 @@ MES fill_rbuf end - return fetch_rbuf( idx + target.size ) + ret = '' + writeinto( ret, idx + target.size ) + ret end def readline ret = readuntil( CRLF ) ret.chop! - return ret + ret end def read_pendstr( dest = '' ) - $stderr.puts "reading pendstr" if pre = @dout ; @dout = false + @pipe << "reading text...\n" if pre = @pipe ; @pipe = nil rsize = 0 @@ -266,12 +568,14 @@ MES dest << str end - $stderr.puts "read pendstr #{rsize} bytes" if @dout = pre - return dest + @pipe << "read #{rsize} bytes\n" if @pipe = pre + dest end def read_pendlist + @pipe << "reading list...\n" if pre = @pipe ; @pipe = nil + arr = [] str = nil call = iterator? @@ -282,7 +586,8 @@ MES yield str if iterator? end - return arr + @pipe << "read #{arr.size} lines\n" if @pipe = pre + arr end @@ -295,22 +600,16 @@ MES @buffer << @socket.sysread( READ_BLOCK ) end - def fetch_rbuf( len ) + def writeinto( ret, len ) bsi = @buffer.size - ret = @buffer[ 0, len ] + ret << @buffer[ 0, len ] @buffer = @buffer[ len, bsi - len ] - if @dout then - $stderr.print 'read "' - debugout ret - $stderr.print "\"\n" - end - return ret + @pipe << %{read "#{Net.quote ret}"\n} if @pipe + len end - ### write - public @@ -319,7 +618,7 @@ MES each_crlf_line( src ) do |line| do_write_do line end - return do_write_fin + do_write_fin end @@ -328,7 +627,7 @@ MES src.each do |bin| do_write_do bin end - return do_write_fin + do_write_fin end @@ -336,13 +635,12 @@ MES do_write_beg do_write_do str do_write_do CRLF - return do_write_fin + do_write_fin end def write_pendstr( src ) - $stderr.puts "writing pendstr from #{src.type}" if pre = @dout - @dout = false + @pipe << "writing text from #{src.type}" if pre = @pipe ; @pipe = nil do_write_beg each_crlf_line( src ) do |line| @@ -352,8 +650,8 @@ MES do_write_do D_CRLF wsize = do_write_fin - $stderr.puts "wrote pendstr #{wsize} bytes" if @dout = pre - return wsize + @pipe << "wrote #{wsize} bytes text" if @pipe = pre + wsize end @@ -363,18 +661,18 @@ MES def each_crlf_line( src ) buf = '' beg = 0 - pos = nil + pos = s = bin = nil - src.each do |b| - buf << b + src.each do |bin| + buf << bin beg = 0 - while (pos = buf.index(TERMEXP, beg)) and (pos < buf.size - 2) do - pos += $&.size - tmp = buf[ beg, pos - beg ] - tmp.chop! - yield tmp << CRLF - beg = pos + while pos = buf.index( TERMEXP, beg ) do + s = $&.size + break if pos + s == buf.size - 1 and buf[-1] == ?\r + + yield buf[ beg, pos - beg ] << CRLF + beg = pos + s end buf = buf[ beg, buf.size - beg ] if beg != 0 end @@ -382,52 +680,49 @@ MES buf << "\n" unless /\n|\r/o === buf[-1,1] beg = 0 - while pos = buf.index(TERMEXP, beg) do - pos += $&.size - tmp = buf[ beg, pos - beg ] - tmp.chop! - yield tmp << CRLF - beg = pos + while pos = buf.index( TERMEXP, beg ) do + yield buf[ beg, pos - beg ] << CRLF + beg = pos + $&.size end end def do_write_beg - $stderr.print 'write "' if @dout - @writtensize = 0 @sending = '' end def do_write_do( arg ) - debugout arg if @dout - - if @sending.size < 128 then - @sending << arg + if @pipe or @sending.size < 128 then + @sending << Net.quote( arg ) else @sending << '...' unless @sending[-1] == ?. end + s = @socket.write( arg ) @writtensize += s - return s + s end def do_write_fin - $stderr.puts if @dout + if @pipe then + @pipe << 'write "' + @pipe << @sending + @pipe << "\"\n" + end @socket.flush - return @writtensize + @writtensize end + end - def debugout( ret ) - while ret and tmp = ret[ 0, 50 ] do - ret = ret[ 50, ret.size - 50 ] - tmp = tmp.inspect - $stderr.print tmp[ 1, tmp.size - 2 ] - end - end + def Net.quote( str ) + str = str.gsub( "\n", '\\n' ) + str.gsub!( "\r", '\\r' ) + str.gsub!( "\t", '\\t' ) + str end -end +end # module Net diff --git a/lib/net/smtp.rb b/lib/net/smtp.rb index 9f534c20c0..7a04aa2aa2 100644 --- a/lib/net/smtp.rb +++ b/lib/net/smtp.rb @@ -1,89 +1,166 @@ -# -# smtp.rb version 1.0.1 -# -# author Minero Aoki -# +=begin + += net/smtp.rb + +written by Minero Aoki + +This library is distributed under the terms of the Ruby license. +You can freely distribute/modify this library. + +=end + require 'net/session' module Net - class SMTPSession < Session - def proto_initialize - @proto_type = SMTPCommand - @port = 25 - end +=begin + +== Net::SMTP + +=== Super Class + +Net::Protocol + +=== Class Methods + +: new( address = 'localhost', port = 25 ) + This method create new SMTP object. + + +=== Methods + +: start( helo_domain = ENV['HOSTNAME'] ) + This method opens TCP connection and start SMTP. + If protocol had been started, do nothing and return false. + +: sendmail( mailsrc, from_domain, to_addrs ) + This method sends 'mailsrc' as mail. SMTPSession read strings + from 'mailsrc' by calling 'each' iterator, and convert them + into "\r\n" terminated string when write. + + Exceptions which SMTP raises are: + * Net::ProtoSyntaxError: syntax error (errno.500) + * Net::ProtoFatalError: fatal error (errno.550) + * Net::ProtoUnknownError: unknown error + * Net::ProtoServerBusy: temporary error (errno.420/450) + +: finish + This method ends SMTP. + If protocol had not started, do nothind and return false. + +=end + + class SMTP < Protocol + + protocol_param :port, '25' + protocol_param :command_type, '::Net::SMTPCommand' + def sendmail( mailsrc, fromaddr, toaddrs ) - @proto.mailfrom( fromaddr ) - @proto.rcpt( toaddrs ) - @proto.data - @proto.sendmail( mailsrc ) + @command.mailfrom fromaddr + @command.rcpt toaddrs + @command.data + @command.sendmail mailsrc end private - def do_start( helodom = nil ) + def do_start( helodom = ENV['HOSTNAME'] ) unless helodom then - helodom = ENV[ 'HOSTNAME' ] + raise ArgumentError, "cannot get hostname" end - @proto.helo( helodom ) - end - - def do_finish - @proto.quit + @command.helo helodom end end - SMTP = SMTPSession + SMTPSession = SMTP + + +=begin + +== Net::SMTPCommand + +=== Super Class + +Net::Command + +=== Class Methods + +: new( socket ) + This method creates new SMTPCommand object, and open SMTP. + + +=== Methods + +: helo( helo_domain ) + This method send "HELO" command and start SMTP. + helo_domain is localhost's FQDN. +: mailfrom( from_addr ) + This method sends "MAIL FROM" command. + from_addr is your mail address(????@????). +: rcpt( to_addrs ) + This method sends "RCPT TO" command. + to_addrs is array of mail address(???@???) of destination. + +: data( mailsrc ) + This method send 'mailsrc' as mail. SMTP reads strings from 'mailsrc' + by calling 'each' iterator. + +: quit + This method sends "QUIT" command and ends SMTP session. + +=end class SMTPCommand < Command + def initialize( sock ) + super + check_reply SuccessCode + end + + def helo( fromdom ) - @socket.writeline( 'HELO ' << fromdom ) - check_reply( SuccessCode ) + getok sprintf( 'HELO %s', fromdom ) end def mailfrom( fromaddr ) - @socket.writeline( 'MAIL FROM:<' + fromaddr + '>' ) - check_reply( SuccessCode ) + getok sprintf( 'MAIL FROM:<%s>', fromaddr ) end def rcpt( toaddrs ) toaddrs.each do |i| - @socket.writeline( 'RCPT TO:<' + i + '>' ) - check_reply( SuccessCode ) + getok sprintf( 'RCPT TO:<%s>', i ) end end def data - @socket.writeline( 'DATA' ) - check_reply( ContinueCode ) + getok 'DATA', ContinueCode end - def sendmail( mailsrc ) - @socket.write_pendstr( mailsrc ) - check_reply( SuccessCode ) + def writemail( mailsrc ) + @socket.write_pendstr mailsrc + check_reply SuccessCode end + alias sendmail writemail private def do_quit - @socket.writeline( 'QUIT' ) - check_reply( SuccessCode ) + getok 'QUIT' end @@ -91,19 +168,19 @@ module Net arr = read_reply stat = arr[0][0,3] - cls = UnknownCode - case stat[0] - when ?2 then cls = SuccessCode - when ?3 then cls = ContinueCode - when ?4 then cls = ServerBusyCode - when ?5 then - case stat[1] - when ?0 then cls = SyntaxErrorCode - when ?5 then cls = FatalErrorCode - end - end - - return cls.new( stat, arr.join('') ) + klass = UnknownCode + klass = case stat[0] + when ?2 then SuccessCode + when ?3 then ContinueCode + when ?4 then ServerBusyCode + when ?5 then + case stat[1] + when ?0 then SyntaxErrorCode + when ?5 then FatalErrorCode + end + end + + klass.new( stat, arr.join('') ) end @@ -120,9 +197,4 @@ module Net end - - unless Session::Version == '1.0.1' then - $stderr.puts "WARNING: wrong version of session.rb & smtp.rb" - end - end diff --git a/lib/net/telnet.rb b/lib/net/telnet.rb new file mode 100644 index 0000000000..4acaaadd3a --- /dev/null +++ b/lib/net/telnet.rb @@ -0,0 +1,749 @@ +=begin +$Date$ + +== SIMPLE TELNET CLIENT LIBRARY + +net/telnet.rb + +Version 1.30 + +Wakou Aoyama + + +=== MAKE NEW TELNET OBJECT + + host = Net::Telnet::new({ + "Binmode" => false, # default: false + "Host" => "localhost", # default: "localhost" + "Output_log" => "output_log", # default: nil (no output) + "Dump_log" => "dump_log", # default: nil (no 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 = Net::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") + # == host.write("string\n") + + +=== 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}) + +if no password prompt. + + host.login("username") + host.login({"Name" => "username", + "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 = Net::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 = Net::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 1.30 + +2000/04/03 18:27:02 + +- telnet.rb --> net/telnet.rb + +=== Version 1.20 + +2000/01/24 17:02:57 + +- respond to "IAC WILL x" with "IAC DONT x" +- respond to "IAC WONT x" with "IAC DONT x" +- better dumplog format + thanks to WATANABE Hirofumi + +=== Version 1.10 + +2000/01/18 17:47:31 + +- bug fix: write method +- respond to "IAC WILL BINARY" with "IAC DO BINARY" + +=== Version 1.00 + +1999/10/04 22:51:26 + +- bug fix: waitfor(preprocess) method + thanks to Shin-ichiro Hara +- add simple support for AO, DM, IP, NOP, SB, SE +- COUTION! TimeOut --> TimeoutError + +=== Version 0.50 + +1999/09/21 21:24:07 + +- add write method + +=== Version 0.40 + +1999/09/17 17:41:41 + +- bug fix: preprocess method + +=== Version 0.30 + +1999/09/14 23:09:05 + +- change prompt check order. + not IO::select([@sock], nil, nil, waittime) and prompt === line + --> prompt === line and not IO::select([@sock], nil, nil, waittime) + +=== Version 0.24 + +1999/09/13 22:28:33 + +- Telnet#login +if ommit password, then not require password prompt. + +=== 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 "timeout" + +module Net + class Telnet < SimpleDelegator + + IAC = 255.chr # "\377" # "\xff" # interpret as command: + DONT = 254.chr # "\376" # "\xfe" # you are not to use option + DO = 253.chr # "\375" # "\xfd" # please, you use option + WONT = 252.chr # "\374" # "\xfc" # I won't use option + WILL = 251.chr # "\373" # "\xfb" # I will use option + SB = 250.chr # "\372" # "\xfa" # interpret as subnegotiation + GA = 249.chr # "\371" # "\xf9" # you may reverse the line + EL = 248.chr # "\370" # "\xf8" # erase the current line + EC = 247.chr # "\367" # "\xf7" # erase the current character + AYT = 246.chr # "\366" # "\xf6" # are you there + AO = 245.chr # "\365" # "\xf5" # abort output--but let prog finish + IP = 244.chr # "\364" # "\xf4" # interrupt process--permanently + BREAK = 243.chr # "\363" # "\xf3" # break + DM = 242.chr # "\362" # "\xf2" # data mark--for connect. cleaning + NOP = 241.chr # "\361" # "\xf1" # nop + SE = 240.chr # "\360" # "\xf0" # end sub negotiation + EOR = 239.chr # "\357" # "\xef" # end of record (transparent mode) + ABORT = 238.chr # "\356" # "\xee" # Abort process + SUSP = 237.chr # "\355" # "\xed" # Suspend process + EOF = 236.chr # "\354" # "\xec" # End of file + SYNCH = 242.chr # "\362" # "\xf2" # for telfunc calls + + OPT_BINARY = 0.chr # "\000" # "\x00" # Binary Transmission + OPT_ECHO = 1.chr # "\001" # "\x01" # Echo + OPT_RCP = 2.chr # "\002" # "\x02" # Reconnection + OPT_SGA = 3.chr # "\003" # "\x03" # Suppress Go Ahead + OPT_NAMS = 4.chr # "\004" # "\x04" # Approx Message Size Negotiation + OPT_STATUS = 5.chr # "\005" # "\x05" # Status + OPT_TM = 6.chr # "\006" # "\x06" # Timing Mark + OPT_RCTE = 7.chr # "\a" # "\x07" # Remote Controlled Trans and Echo + OPT_NAOL = 8.chr # "\010" # "\x08" # Output Line Width + OPT_NAOP = 9.chr # "\t" # "\x09" # Output Page Size + OPT_NAOCRD = 10.chr # "\n" # "\x0a" # Output Carriage-Return Disposition + OPT_NAOHTS = 11.chr # "\v" # "\x0b" # Output Horizontal Tab Stops + OPT_NAOHTD = 12.chr # "\f" # "\x0c" # Output Horizontal Tab Disposition + OPT_NAOFFD = 13.chr # "\r" # "\x0d" # Output Formfeed Disposition + OPT_NAOVTS = 14.chr # "\016" # "\x0e" # Output Vertical Tabstops + OPT_NAOVTD = 15.chr # "\017" # "\x0f" # Output Vertical Tab Disposition + OPT_NAOLFD = 16.chr # "\020" # "\x10" # Output Linefeed Disposition + OPT_XASCII = 17.chr # "\021" # "\x11" # Extended ASCII + OPT_LOGOUT = 18.chr # "\022" # "\x12" # Logout + OPT_BM = 19.chr # "\023" # "\x13" # Byte Macro + OPT_DET = 20.chr # "\024" # "\x14" # Data Entry Terminal + OPT_SUPDUP = 21.chr # "\025" # "\x15" # SUPDUP + OPT_SUPDUPOUTPUT = 22.chr # "\026" # "\x16" # SUPDUP Output + OPT_SNDLOC = 23.chr # "\027" # "\x17" # Send Location + OPT_TTYPE = 24.chr # "\030" # "\x18" # Terminal Type + OPT_EOR = 25.chr # "\031" # "\x19" # End of Record + OPT_TUID = 26.chr # "\032" # "\x1a" # TACACS User Identification + OPT_OUTMRK = 27.chr # "\e" # "\x1b" # Output Marking + OPT_TTYLOC = 28.chr # "\034" # "\x1c" # Terminal Location Number + OPT_3270REGIME = 29.chr # "\035" # "\x1d" # Telnet 3270 Regime + OPT_X3PAD = 30.chr # "\036" # "\x1e" # X.3 PAD + OPT_NAWS = 31.chr # "\037" # "\x1f" # Negotiate About Window Size + OPT_TSPEED = 32.chr # " " # "\x20" # Terminal Speed + OPT_LFLOW = 33.chr # "!" # "\x21" # Remote Flow Control + OPT_LINEMODE = 34.chr # "\"" # "\x22" # Linemode + OPT_XDISPLOC = 35.chr # "#" # "\x23" # X Display Location + OPT_OLD_ENVIRON = 36.chr # "$" # "\x24" # Environment Option + OPT_AUTHENTICATION = 37.chr # "%" # "\x25" # Authentication Option + OPT_ENCRYPT = 38.chr # "&" # "\x26" # Encryption Option + OPT_NEW_ENVIRON = 39.chr # "'" # "\x27" # New Environment Option + OPT_EXOPL = 255.chr # "\377" # "\xff" # Extended-Options-List + + NULL = "\000" + CR = "\015" + LF = "\012" + EOL = CR + LF + v = $-v + $-v = false + VERSION = "1.30" + RELEASE_DATE = "$Date$" + $-v = v + + def initialize(options) + @options = options + @options["Binmode"] = false unless @options.has_key?("Binmode") + @options["Host"] = "localhost" unless @options.has_key?("Host") + @options["Port"] = 23 unless @options.has_key?("Port") + @options["Prompt"] = /[$%#>] \z/n unless @options.has_key?("Prompt") + @options["Telnetmode"] = true unless @options.has_key?("Telnetmode") + @options["Timeout"] = 10 unless @options.has_key?("Timeout") + @options["Waittime"] = 0 unless @options.has_key?("Waittime") + + @telnet_option = { "SGA" => false, "BINARY" => false } + + if @options.has_key?("Output_log") + @log = File.open(@options["Output_log"], 'a+') + @log.sync = true + @log.binmode + end + + if @options.has_key?("Dump_log") + @dumplog = File.open(@options["Dump_log"], 'a+') + @dumplog.sync = true + @dumplog.binmode + def @dumplog.log_dump(dir, x) + len = x.length + addr = 0 + offset = 0 + while 0 < len + if len < 16 + line = x[offset, len] + else + line = x[offset, 16] + end + hexvals = line.unpack('H*')[0] + hexvals.concat ' ' * (32 - hexvals.length) + hexvals = format "%s %s %s %s " * 4, *hexvals.unpack('a2' * 16) + line.gsub! /[\000-\037\177-\377]/n, '.' + printf "%s 0x%5.5x: %s%s\n", dir, addr, hexvals, line + addr += 16 + offset += 16 + len -= 16 + end + print "\n" + end + end + + if @options.has_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.has_key?("Output_log") + @dumplog.log_dump('#', message) if @options.has_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 TimeoutError, "timed-out; opening of the host" + rescue + @log.write($!.to_s + "\n") if @options.has_key?("Output_log") + @dumplog.log_dump('#', $!.to_s + "\n") if @options.has_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.has_key?("Output_log") + @dumplog.log_dump('#', message) if @options.has_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"] + + str.gsub!(/#{IAC}( + [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]| + [#{DO}#{DONT}#{WILL}#{WONT}] + [#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}]| + #{SB}[^#{IAC}]*#{IAC}#{SE} + )/xno){ + if IAC == $1 # handle escaped IAC characters + IAC + elsif AYT == $1 # respond to "IAC AYT" (are you there) + self.write("nobody here but us pigeons" + EOL) + '' + elsif DO[0] == $1[0] # respond to "IAC DO x" + if OPT_BINARY[0] == $1[1] + @telnet_option["BINARY"] = true + self.write(IAC + WILL + OPT_BINARY) + else + self.write(IAC + WONT + $1[1..1]) + end + '' + elsif DONT[0] == $1[0] # respond to "IAC DON'T x" with "IAC WON'T x" + self.write(IAC + WONT + $1[1..1]) + '' + elsif WILL[0] == $1[0] # respond to "IAC WILL x" + if OPT_BINARY[0] == $1[1] + self.write(IAC + DO + OPT_BINARY) + elsif OPT_ECHO[0] == $1[1] + self.write(IAC + DO + OPT_ECHO) + elsif OPT_SGA[0] == $1[1] + @telnet_option["SGA"] = true + self.write(IAC + DO + OPT_SGA) + else + self.write(IAC + DONT + $1[1..1]) + end + '' + elsif WONT[0] == $1[0] # respond to "IAC WON'T x" + if OPT_ECHO[0] == $1[1] + self.write(IAC + DONT + OPT_ECHO) + elsif OPT_SGA[0] == $1[1] + @telnet_option["SGA"] = false + self.write(IAC + DONT + OPT_SGA) + else + self.write(IAC + DONT + $1[1..1]) + end + '' + else + '' + end + } + + str + end # preprocess + + def waitfor(options) + time_out = @options["Timeout"] + waittime = @options["Waittime"] + + if options.kind_of?(Hash) + prompt = if options.has_key?("Match") + options["Match"] + elsif options.has_key?("Prompt") + options["Prompt"] + elsif options.has_key?("String") + Regexp.new( Regexp.quote(options["String"]) ) + end + time_out = options["Timeout"] if options.has_key?("Timeout") + waittime = options["Waittime"] if options.has_key?("Waittime") + else + prompt = options + end + + if time_out == false + time_out = nil + end + + line = '' + buf = '' + rest = '' + until(prompt === line and not IO::select([@sock], nil, nil, waittime)) + unless IO::select([@sock], nil, nil, time_out) + raise TimeoutError, "timed-out; wait for the next data" + end + begin + c = @sock.sysread(1024 * 1024) + @dumplog.log_dump('<', c) if @options.has_key?("Dump_log") + if @options["Telnetmode"] + if Integer(c.rindex(/#{IAC}#{SE}/no)) < + Integer(c.rindex(/#{IAC}#{SB}/no)) + buf = preprocess(rest + c[0 ... c.rindex(/#{IAC}#{SB}/no)]) + rest = c[c.rindex(/#{IAC}#{SB}/no) .. -1] + elsif pt = c.rindex(/#{IAC}[^#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]?\z/no) + buf = preprocess(rest + c[0 ... pt]) + rest = c[pt .. -1] + else + buf = preprocess(c) + rest = '' + end + end + @log.print(buf) if @options.has_key?("Output_log") + line.concat(buf) + yield buf if iterator? + rescue EOFError # End of file reached + if line == '' + line = nil + yield nil if iterator? + end + break + end + end + line + end + + def write(string) + length = string.length + while 0 < length + IO::select(nil, [@sock]) + @dumplog.log_dump('>', string[-length..-1]) if @options.has_key?("Dump_log") + length -= @sock.syswrite(string[-length..-1]) + end + 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 + + self.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.has_key?("Match") + time_out = options["Timeout"] if options.has_key?("Timeout") + else + string = options + end + + 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 = nil) + 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 } + if password + line.concat( cmd({"String" => username, + "Match" => /Password[: ]*\z/n}){|c| yield c } ) + line.concat( cmd(password){|c| yield c } ) + else + line.concat( cmd(username){|c| yield c } ) + end + else + line = waitfor(/login[: ]*\z/n) + if password + line.concat( cmd({"String" => username, + "Match" => /Password[: ]*\z/n}) ) + line.concat( cmd(password) ) + else + line.concat( cmd(username) ) + end + end + line + end + + end +end diff --git a/lib/observer.rb b/lib/observer.rb index 0c74b49750..a91c1e38c3 100644 --- a/lib/observer.rb +++ b/lib/observer.rb @@ -32,7 +32,7 @@ module Observable def notify_observers(*arg) if @observer_state if @observer_peers - for i in @observer_peers + for i in @observer_peers.dup i.update(*arg) end end diff --git a/lib/parsedate.rb b/lib/parsedate.rb index 29b3fa43b9..35fffcfe98 100644 --- a/lib/parsedate.rb +++ b/lib/parsedate.rb @@ -27,7 +27,7 @@ module ParseDate if date.sub!(/(#{DAYPAT})[a-z]*,?/i, ' ') wday = DAYS[$1.downcase] end - if date.sub!(/(\d+):(\d+)(?::(\d+))?(?:\s*(am|pm))?(?:\s+([a-z]{1,4}(?:\s+[a-z]{1,4})?|[-+]\d{4}))?/i, ' ') + if date.sub!(/(\d+):(\d+)(?::(\d+))?(?:\s*(am|pm))?(?:\s+([a-z]{1,4}(?:\s+[a-z]{1,4}|[-+]\d{4})?|[-+]\d{4}))?/i, ' ') hour = $1.to_i min = $2.to_i if $3 diff --git a/lib/pstore.rb b/lib/pstore.rb index 2aa9864b58..97b3794326 100644 --- a/lib/pstore.rb +++ b/lib/pstore.rb @@ -13,6 +13,7 @@ # end require "marshal" +require "ftools" class PStore class Error < StandardError @@ -51,6 +52,10 @@ class PStore in_transaction @table[name] = value end + def delete(name) + in_transaction + @table.delete name + end def roots in_transaction @@ -77,12 +82,19 @@ class PStore raise PStore::Error, "nested transaction" if @transaction begin @transaction = true - value = file = nil - begin - File::open(@filename, "r") do |file| - @table = Marshal.load(file) - end - rescue Errno::ENOENT + value = nil + backup = @filename+"~" + if File::exist?(@filename) + file = File::open(@filename, "r+") + orig = true + else + file = File::open(@filename, "w+") + end + file.flock(File::LOCK_EX) + if orig + File::copy @filename, backup + @table = Marshal::load(file) + else @table = {} end begin @@ -95,16 +107,11 @@ class PStore ensure unless @abort begin - File::rename @filename, @filename+"~" - rescue Errno::ENOENT - no_orig = true - end - begin - File::open(@filename, "w") do |file| - Marshal::dump(@table, file) - end + file.rewind + Marshal::dump(@table, file) rescue - File::rename @filename+"~", @filename unless no_orig + File::rename backup, @filename if File::exist?(backup) + raise end end @abort = false @@ -112,6 +119,7 @@ class PStore ensure @table = nil @transaction = false + file.close if file end value end diff --git a/lib/singleton.rb b/lib/singleton.rb index 8167a01aa8..235ba898fd 100644 --- a/lib/singleton.rb +++ b/lib/singleton.rb @@ -14,9 +14,15 @@ module Singleton def Singleton.append_features(klass) klass.private_class_method(:new) klass.instance_eval %{ + @__instance__ = nil def instance + Thread.critical = true unless @__instance__ - @__instance__ = new + begin + @__instance__ = new + ensure + Thread.critical = false + end end return @__instance__ end diff --git a/lib/telnet.rb b/lib/telnet.rb index b6623513e0..47a0926f8e 100644 --- a/lib/telnet.rb +++ b/lib/telnet.rb @@ -1,11 +1,11 @@ =begin -$Date: 1999/10/04 22:51:26 $ +$Date: 2000/01/24 17:02:57 $ -== SIMPLE TELNET CLIANT LIBRARY +== SIMPLE TELNET CLIENT LIBRARY telnet.rb -Version 1.00 +Version 1.20 Wakou Aoyama @@ -155,6 +155,22 @@ of cource, set sync=true or flush is necessary. == HISTORY +=== Version 1.20 + +2000/01/24 17:02:57 + +- respond to "IAC WILL x" with "IAC DONT x" +- respond to "IAC WONT x" with "IAC DONT x" +- better dumplog format + thanks to WATANABE Hirofumi + +=== Version 1.10 + +2000/01/18 17:47:31 + +- bug fix: write method +- respond to "IAC WILL BINARY" with "IAC DO BINARY" + === Version 1.00 1999/10/04 22:51:26 @@ -338,74 +354,73 @@ if ommit password, then not require password prompt. require "socket" require "delegate" -require "thread" require "timeout" 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 + IAC = 255.chr # "\377" # "\xff" # interpret as command: + DONT = 254.chr # "\376" # "\xfe" # you are not to use option + DO = 253.chr # "\375" # "\xfd" # please, you use option + WONT = 252.chr # "\374" # "\xfc" # I won't use option + WILL = 251.chr # "\373" # "\xfb" # I will use option + SB = 250.chr # "\372" # "\xfa" # interpret as subnegotiation + GA = 249.chr # "\371" # "\xf9" # you may reverse the line + EL = 248.chr # "\370" # "\xf8" # erase the current line + EC = 247.chr # "\367" # "\xf7" # erase the current character + AYT = 246.chr # "\366" # "\xf6" # are you there + AO = 245.chr # "\365" # "\xf5" # abort output--but let prog finish + IP = 244.chr # "\364" # "\xf4" # interrupt process--permanently + BREAK = 243.chr # "\363" # "\xf3" # break + DM = 242.chr # "\362" # "\xf2" # data mark--for connect. cleaning + NOP = 241.chr # "\361" # "\xf1" # nop + SE = 240.chr # "\360" # "\xf0" # end sub negotiation + EOR = 239.chr # "\357" # "\xef" # end of record (transparent mode) + ABORT = 238.chr # "\356" # "\xee" # Abort process + SUSP = 237.chr # "\355" # "\xed" # Suspend process + EOF = 236.chr # "\354" # "\xec" # End of file + SYNCH = 242.chr # "\362" # "\xf2" # for telfunc calls + + OPT_BINARY = 0.chr # "\000" # "\x00" # Binary Transmission + OPT_ECHO = 1.chr # "\001" # "\x01" # Echo + OPT_RCP = 2.chr # "\002" # "\x02" # Reconnection + OPT_SGA = 3.chr # "\003" # "\x03" # Suppress Go Ahead + OPT_NAMS = 4.chr # "\004" # "\x04" # Approx Message Size Negotiation + OPT_STATUS = 5.chr # "\005" # "\x05" # Status + OPT_TM = 6.chr # "\006" # "\x06" # Timing Mark + OPT_RCTE = 7.chr # "\a" # "\x07" # Remote Controlled Trans and Echo + OPT_NAOL = 8.chr # "\010" # "\x08" # Output Line Width + OPT_NAOP = 9.chr # "\t" # "\x09" # Output Page Size + OPT_NAOCRD = 10.chr # "\n" # "\x0a" # Output Carriage-Return Disposition + OPT_NAOHTS = 11.chr # "\v" # "\x0b" # Output Horizontal Tab Stops + OPT_NAOHTD = 12.chr # "\f" # "\x0c" # Output Horizontal Tab Disposition + OPT_NAOFFD = 13.chr # "\r" # "\x0d" # Output Formfeed Disposition + OPT_NAOVTS = 14.chr # "\016" # "\x0e" # Output Vertical Tabstops + OPT_NAOVTD = 15.chr # "\017" # "\x0f" # Output Vertical Tab Disposition + OPT_NAOLFD = 16.chr # "\020" # "\x10" # Output Linefeed Disposition + OPT_XASCII = 17.chr # "\021" # "\x11" # Extended ASCII + OPT_LOGOUT = 18.chr # "\022" # "\x12" # Logout + OPT_BM = 19.chr # "\023" # "\x13" # Byte Macro + OPT_DET = 20.chr # "\024" # "\x14" # Data Entry Terminal + OPT_SUPDUP = 21.chr # "\025" # "\x15" # SUPDUP + OPT_SUPDUPOUTPUT = 22.chr # "\026" # "\x16" # SUPDUP Output + OPT_SNDLOC = 23.chr # "\027" # "\x17" # Send Location + OPT_TTYPE = 24.chr # "\030" # "\x18" # Terminal Type + OPT_EOR = 25.chr # "\031" # "\x19" # End of Record + OPT_TUID = 26.chr # "\032" # "\x1a" # TACACS User Identification + OPT_OUTMRK = 27.chr # "\e" # "\x1b" # Output Marking + OPT_TTYLOC = 28.chr # "\034" # "\x1c" # Terminal Location Number + OPT_3270REGIME = 29.chr # "\035" # "\x1d" # Telnet 3270 Regime + OPT_X3PAD = 30.chr # "\036" # "\x1e" # X.3 PAD + OPT_NAWS = 31.chr # "\037" # "\x1f" # Negotiate About Window Size + OPT_TSPEED = 32.chr # " " # "\x20" # Terminal Speed + OPT_LFLOW = 33.chr # "!" # "\x21" # Remote Flow Control + OPT_LINEMODE = 34.chr # "\"" # "\x22" # Linemode + OPT_XDISPLOC = 35.chr # "#" # "\x23" # X Display Location + OPT_OLD_ENVIRON = 36.chr # "$" # "\x24" # Environment Option + OPT_AUTHENTICATION = 37.chr # "%" # "\x25" # Authentication Option + OPT_ENCRYPT = 38.chr # "&" # "\x26" # Encryption Option + OPT_NEW_ENVIRON = 39.chr # "'" # "\x27" # New Environment Option + OPT_EXOPL = 255.chr # "\377" # "\xff" # Extended-Options-List NULL = "\000" CR = "\015" @@ -413,35 +428,56 @@ class Telnet < SimpleDelegator EOL = CR + LF v = $-v $-v = false - VERSION = "1.00" - RELEASE_DATE = "$Date: 1999/10/04 22:51:26 $" + VERSION = "1.20" + RELEASE_DATE = "$Date: 2000/01/24 17:02:57 $" $-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") + @options["Binmode"] = false unless @options.has_key?("Binmode") + @options["Host"] = "localhost" unless @options.has_key?("Host") + @options["Port"] = 23 unless @options.has_key?("Port") + @options["Prompt"] = /[$%#>] \z/n unless @options.has_key?("Prompt") + @options["Telnetmode"] = true unless @options.has_key?("Telnetmode") + @options["Timeout"] = 10 unless @options.has_key?("Timeout") + @options["Waittime"] = 0 unless @options.has_key?("Waittime") @telnet_option = { "SGA" => false, "BINARY" => false } - if @options.key?("Output_log") + if @options.has_key?("Output_log") @log = File.open(@options["Output_log"], 'a+') @log.sync = true @log.binmode end - if @options.key?("Dump_log") + if @options.has_key?("Dump_log") @dumplog = File.open(@options["Dump_log"], 'a+') @dumplog.sync = true @dumplog.binmode + def @dumplog.log_dump(dir, x) + len = x.length + addr = 0 + offset = 0 + while 0 < len + if len < 16 + line = x[offset, len] + else + line = x[offset, 16] + end + hexvals = line.unpack('H*')[0] + hexvals.concat ' ' * (32 - hexvals.length) + hexvals = format "%s %s %s %s " * 4, *hexvals.unpack('a2' * 16) + line.gsub! /[\000-\037\177-\377]/n, '.' + printf "%s 0x%5.5x: %s%s\n", dir, addr, hexvals, line + addr += 16 + offset += 16 + len -= 16 + end + print "\n" + end end - if @options.key?("Proxy") + if @options.has_key?("Proxy") if @options["Proxy"].kind_of?(Telnet) @sock = @options["Proxy"].sock elsif @options["Proxy"].kind_of?(TCPsocket) @@ -452,8 +488,8 @@ $-v = v 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") + @log.write(message) if @options.has_key?("Output_log") + @dumplog.log_dump('#', message) if @options.has_key?("Dump_log") begin if @options["Timeout"] == false @@ -466,8 +502,8 @@ $-v = v rescue TimeoutError raise TimeoutError, "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") + @log.write($!.to_s + "\n") if @options.has_key?("Output_log") + @dumplog.log_dump('#', $!.to_s + "\n") if @options.has_key?("Dump_log") raise end @sock.sync = true @@ -475,8 +511,8 @@ $-v = v 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") + @log.write(message) if @options.has_key?("Output_log") + @dumplog.log_dump('#', message) if @options.has_key?("Dump_log") end super(@sock) @@ -532,11 +568,15 @@ $-v = v self.write(IAC + WONT + $1[1..1]) '' elsif WILL[0] == $1[0] # respond to "IAC WILL x" - if OPT_ECHO[0] == $1[1] + if OPT_BINARY[0] == $1[1] + self.write(IAC + DO + OPT_BINARY) + elsif OPT_ECHO[0] == $1[1] self.write(IAC + DO + OPT_ECHO) elsif OPT_SGA[0] == $1[1] @telnet_option["SGA"] = true self.write(IAC + DO + OPT_SGA) + else + self.write(IAC + DONT + $1[1..1]) end '' elsif WONT[0] == $1[0] # respond to "IAC WON'T x" @@ -545,6 +585,8 @@ $-v = v elsif OPT_SGA[0] == $1[1] @telnet_option["SGA"] = false self.write(IAC + DONT + OPT_SGA) + else + self.write(IAC + DONT + $1[1..1]) end '' else @@ -560,15 +602,15 @@ $-v = v waittime = @options["Waittime"] if options.kind_of?(Hash) - prompt = if options.key?("Match") + prompt = if options.has_key?("Match") options["Match"] - elsif options.key?("Prompt") + elsif options.has_key?("Prompt") options["Prompt"] - elsif options.key?("String") + elsif options.has_key?("String") Regexp.new( Regexp.quote(options["String"]) ) end - time_out = options["Timeout"] if options.key?("Timeout") - waittime = options["Waittime"] if options.key?("Waittime") + time_out = options["Timeout"] if options.has_key?("Timeout") + waittime = options["Waittime"] if options.has_key?("Waittime") else prompt = options end @@ -586,7 +628,7 @@ $-v = v end begin c = @sock.sysread(1024 * 1024) - @dumplog.print(c) if @options.key?("Dump_log") + @dumplog.log_dump('<', c) if @options.has_key?("Dump_log") if @options["Telnetmode"] if Integer(c.rindex(/#{IAC}#{SE}/no)) < Integer(c.rindex(/#{IAC}#{SB}/no)) @@ -600,7 +642,7 @@ $-v = v rest = '' end end - @log.print(buf) if @options.key?("Output_log") + @log.print(buf) if @options.has_key?("Output_log") line.concat(buf) yield buf if iterator? rescue EOFError # End of file reached @@ -618,7 +660,8 @@ $-v = v length = string.length while 0 < length IO::select(nil, [@sock]) - length -= @sock.syswrite(string) + @dumplog.log_dump('>', string[-length..-1]) if @options.has_key?("Dump_log") + length -= @sock.syswrite(string[-length..-1]) end end @@ -649,8 +692,8 @@ $-v = v if options.kind_of?(Hash) string = options["String"] - match = options["Match"] if options.key?("Match") - time_out = options["Timeout"] if options.key?("Timeout") + match = options["Match"] if options.has_key?("Match") + time_out = options["Timeout"] if options.has_key?("Timeout") else string = options end diff --git a/lib/timeout.rb b/lib/timeout.rb index d4ea758acd..cc2ab5bac5 100644 --- a/lib/timeout.rb +++ b/lib/timeout.rb @@ -25,8 +25,6 @@ class TimeoutErrornum_entries, arg->arg); + st_foreach(tbl, obj_each, arg); + } + else { + w_long(0, arg->arg); + } +} + static void w_object(obj, arg, limit) VALUE obj; @@ -204,9 +224,10 @@ w_object(obj, arg, limit) int limit; { struct dump_call_arg c_arg; + st_table *ivtbl = 0; if (limit == 0) { - rb_raise(rb_eRuntimeError, "exceed depth limit"); + rb_raise(rb_eArgError, "exceed depth limit"); } if (obj == Qnil) { w_byte(TYPE_NIL, arg); @@ -259,20 +280,31 @@ w_object(obj, arg, limit) return; } + if (ivtbl = rb_generic_ivar_table(obj)) { + w_byte(TYPE_IVAR, arg); + } + switch (BUILTIN_TYPE(obj)) { - case T_MODULE: case T_CLASS: + w_byte(TYPE_CLASS, arg); + { + VALUE path = rb_class_path(obj); + w_bytes(RSTRING(path)->ptr, RSTRING(path)->len, arg); + } + break; + + case T_MODULE: w_byte(TYPE_MODULE, arg); { VALUE path = rb_class_path(obj); w_bytes(RSTRING(path)->ptr, RSTRING(path)->len, arg); } - return; + break; case T_FLOAT: w_byte(TYPE_FLOAT, arg); w_float(RFLOAT(obj)->value, arg); - return; + break; case T_BIGNUM: w_byte(TYPE_BIGNUM, arg); @@ -288,20 +320,20 @@ w_object(obj, arg, limit) d++; } } - return; + break; case T_STRING: w_uclass(obj, rb_cString, arg); w_byte(TYPE_STRING, arg); w_bytes(RSTRING(obj)->ptr, RSTRING(obj)->len, arg); - return; + break; case T_REGEXP: w_uclass(obj, rb_cRegexp, arg); w_byte(TYPE_REGEXP, arg); w_bytes(RREGEXP(obj)->str, RREGEXP(obj)->len, arg); w_byte(rb_reg_options(obj), arg); - return; + break; case T_ARRAY: w_uclass(obj, rb_cArray, arg); @@ -320,9 +352,17 @@ w_object(obj, arg, limit) case T_HASH: w_uclass(obj, rb_cHash, arg); - w_byte(TYPE_HASH, arg); + if (!NIL_P(RHASH(obj)->ifnone)) { + w_byte(TYPE_HASH_DEF, arg); + } + else { + w_byte(TYPE_HASH, arg); + } w_long(RHASH(obj)->tbl->num_entries, arg); st_foreach(RHASH(obj)->tbl, hash_each, &c_arg); + if (!NIL_P(RHASH(obj)->ifnone)) { + w_object(RHASH(obj)->ifnone, arg, limit); + } break; case T_STRUCT: @@ -357,13 +397,7 @@ w_object(obj, arg, limit) } path = rb_class2name(klass); w_unique(path, arg); - if (ROBJECT(obj)->iv_tbl) { - w_long(ROBJECT(obj)->iv_tbl->num_entries, arg); - st_foreach(ROBJECT(obj)->iv_tbl, obj_each, &c_arg); - } - else { - w_long(0, arg); - } + w_ivar(ROBJECT(obj)->iv_tbl, &c_arg); } break; @@ -373,6 +407,9 @@ w_object(obj, arg, limit) break; } } + if (ivtbl) { + w_ivar(ivtbl, &c_arg); + } } static VALUE @@ -449,10 +486,12 @@ struct load_arg { FILE *fp; char *ptr, *end; st_table *symbol; - st_table *data; + VALUE data; VALUE proc; }; +static VALUE r_object _((struct load_arg *arg)); + static int r_byte(arg) struct load_arg *arg; @@ -602,24 +641,49 @@ r_regist(v, arg) if (arg->proc) { rb_funcall(arg->proc, rb_intern("call"), 1, v); } - st_insert(arg->data, arg->data->num_entries, v); + rb_hash_aset(arg->data, INT2FIX(RHASH(arg->data)->tbl->num_entries), v); return v; } +static void +r_ivar(obj, arg) + VALUE obj; + struct load_arg *arg; +{ + int len; + + len = r_long(arg); + if (len > 0) { + while (len--) { + ID id = r_symbol(arg); + VALUE val = r_object(arg); + rb_ivar_set(obj, id, val); + } + } +} + static VALUE r_object(arg) struct load_arg *arg; { VALUE v; int type = r_byte(arg); + long id; switch (type) { case TYPE_LINK: - if (st_lookup(arg->data, r_long(arg), &v)) { - return v; + id = r_long(arg); + v = rb_hash_aref(arg->data, INT2FIX(id)); + if (NIL_P(v)) { + rb_raise(rb_eArgError, "dump format error (unlinked)"); } - rb_raise(rb_eArgError, "dump format error (unlinked)"); - break; + return v; + break; + + case TYPE_IVAR: + v = r_object(arg); + r_ivar(v, arg); + return v; case TYPE_UCLASS: { @@ -703,6 +767,7 @@ r_object(arg) } case TYPE_HASH: + case TYPE_HASH_DEF: { int len = r_long(arg); @@ -713,6 +778,9 @@ r_object(arg) VALUE value = r_object(arg); rb_hash_aset(v, key, value); } + if (type == TYPE_HASH_DEF) { + RHASH(v)->ifnone = r_object(arg); + } return v; } @@ -768,28 +836,46 @@ r_object(arg) case TYPE_OBJECT: { VALUE klass; - int len; klass = rb_path2class(r_unique(arg)); - len = r_long(arg); v = rb_obj_alloc(klass); r_regist(v, arg); - if (len > 0) { - while (len--) { - ID id = r_symbol(arg); - VALUE val = r_object(arg); - rb_ivar_set(v, id, val); - } - } + r_ivar(v, arg); return v; } break; + case TYPE_MODULE_OLD: + { + char *buf; + r_bytes(buf, arg); + return r_regist(rb_path2class(buf), arg); + } + + case TYPE_CLASS: + { + VALUE c; + + char *buf; + r_bytes(buf, arg); + c = rb_path2class(buf); + if (TYPE(c) != T_CLASS) { + rb_raise(rb_eTypeError, "%s is not a class", buf); + } + return r_regist(c, arg); + } + case TYPE_MODULE: { + VALUE m; + char *buf; r_bytes(buf, arg); - return rb_path2class(buf); + m = rb_path2class(buf); + if (TYPE(m) != T_CLASS) { + rb_raise(rb_eTypeError, "%s is not a module", buf); + } + return r_regist(m, arg); } default: @@ -811,7 +897,6 @@ load_ensure(arg) struct load_arg *arg; { st_free_table(arg->symbol); - st_free_table(arg->data); return 0; } @@ -837,7 +922,7 @@ marshal_load(argc, argv) int len; arg.fp = 0; - arg.ptr = str2cstr(port, &len); + arg.ptr = rb_str2cstr(port, &len); arg.end = arg.ptr + len; } else { @@ -846,11 +931,13 @@ marshal_load(argc, argv) major = r_byte(&arg); if (major == MARSHAL_MAJOR) { + volatile VALUE hash; /* protect from GC */ + if (r_byte(&arg) != MARSHAL_MINOR) { rb_warn("Old marshal file format (can be read)"); } arg.symbol = st_init_numtable(); - arg.data = st_init_numtable(); + arg.data = hash = rb_hash_new(); if (NIL_P(proc)) arg.proc = 0; else arg.proc = proc; v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg); diff --git a/math.c b/math.c index 978a23c73c..39bc48aa1c 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-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ diff --git a/misc/inf-ruby.el b/misc/inf-ruby.el index eaa904951c..f192147a37 100644 --- a/misc/inf-ruby.el +++ b/misc/inf-ruby.el @@ -18,7 +18,7 @@ ;;; "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)) +;;; (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. @@ -35,9 +35,12 @@ ;;; HISTORY ;;; senda - 8 Apr 1998: Created. ;;; $Log$ +;;; Revision 1.2.2.1 1999/12/01 09:24:48 matz +;;; 19991201 +;;; ;;; 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 ;;; diff --git a/misc/ruby-mode.el b/misc/ruby-mode.el index 50e4f50e87..75efbf012b 100644 --- a/misc/ruby-mode.el +++ b/misc/ruby-mode.el @@ -180,12 +180,8 @@ The variable ruby-indent-level controls the amount of indentation. (back-to-indentation) (setq top (current-column)) (skip-chars-backward " \t") - (cond - ((>= x shift) + (if (>= shift top) (setq shift (- shift top)) (setq shift 0)) - ((>= shift top) - (setq shift (- shift top))) - (t (setq shift 0))) (if (and (bolp) (= x top)) (move-to-column (+ x shift)) @@ -669,7 +665,6 @@ An end of a defun is found by moving forward from the beginning of one." "return" "then" "throw" - "self" "super" "unless" "undef" @@ -681,8 +676,8 @@ An end of a defun is found by moving forward from the beginning of one." "\\)\\>[^_]") 2) ;; variables - '("\\b\\(nil\\|self\\|true\\|false\\)\\b" - 1 font-lock-variable-name-face) + '("\\(^\\|[^_:.@$]\\|\\.\\.\\)\\b\\(nil\\|self\\|true\\|false\\)\\b[^_]" + 2 font-lock-variable-name-face) ;; variables '("[$@].\\(\\w\\|_\\)*" 0 font-lock-variable-name-face) diff --git a/missing/file.h b/missing/file.h index 79f5f65f5d..2d491d0fc1 100644 --- a/missing/file.h +++ b/missing/file.h @@ -1,31 +1,22 @@ /* This is file FILE.H */ -/* -** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954 -** -** This file is distributed under the terms listed in the document -** "copying.dj", available from DJ Delorie at the address above. -** A copy of "copying.dj" should accompany this file; if not, a copy -** should be available from where this file was obtained. This file -** may not be distributed without a verbatim copy of "copying.dj". -** -** This file is distributed WITHOUT ANY WARRANTY; without even the implied -** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -*/ #ifndef _FILE_H_ #define _FILE_H_ #include -#define L_SET 0 -#define L_CURR 1 -#define L_INCR 1 -#define L_XTND 2 - +#ifndef L_SET +# define L_SET 0 /* seek from beginning. */ +# define L_CURR 1 /* seek from current position. */ +# define L_INCR 1 /* ditto. */ +# define L_XTND 2 /* seek from end. */ +#endif -#define F_OK 0 /* does file exist */ -#define X_OK 1 /* is it executable by caller */ -#define W_OK 2 /* is it writable by caller */ -#define R_OK 4 /* is it readable by caller */ +#ifndef R_OK +# define R_OK 4 /* test whether readable. */ +# define W_OK 2 /* test whether writable. */ +# define X_OK 1 /* test whether execubale. */ +# define F_OK 0 /* test whether exist. */ +#endif #endif diff --git a/missing/flock.c b/missing/flock.c index a4a9544b56..0eaa8d8fdb 100644 --- a/missing/flock.c +++ b/missing/flock.c @@ -78,6 +78,54 @@ flock(fd, operation) } return i; } +#elif defined HAVE_FCNTL && defined HAVE_FCNTL_H + +/* These are the flock() constants. Since this sytems doesn't have + flock(), the values of the constants are probably not available. +*/ +# ifndef LOCK_SH +# define LOCK_SH 1 +# endif +# ifndef LOCK_EX +# define LOCK_EX 2 +# endif +# ifndef LOCK_NB +# define LOCK_NB 4 +# endif +# ifndef LOCK_UN +# define LOCK_UN 8 +# endif + +#include +#include +#include + +int +flock(fd, operation) + int fd; + int operation; +{ + struct flock lock; + + switch (operation & ~LOCK_NB) { + case LOCK_SH: + lock.l_type = F_RDLCK; + break; + case LOCK_EX: + lock.l_type = F_WRLCK; + break; + case LOCK_UN: + lock.l_type = F_UNLCK; + break; + default: + errno = EINVAL; + return -1; + } + lock.l_whence = SEEK_SET; + lock.l_start = lock.l_len = 0L; + + return fcntl(fd, (operation & LOCK_NB) ? F_SETLK : F_SETLKW, &lock); +} #else int flock(fd, operation) diff --git a/missing/fnmatch.c b/missing/fnmatch.c deleted file mode 100644 index 4cf746118a..0000000000 --- a/missing/fnmatch.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * 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 deleted file mode 100644 index 773851625a..0000000000 --- a/missing/fnmatch.h +++ /dev/null @@ -1,57 +0,0 @@ -/*- - * 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/isnan.c b/missing/isnan.c index 96bb93ba6a..3c56765807 100644 --- a/missing/isnan.c +++ b/missing/isnan.c @@ -1,3 +1,15 @@ +#ifdef _MSC_VER + +#include +int +isnan(n) + double n; +{ + return _isnan(n); +} + +#else + static int double_ne(); int @@ -14,3 +26,4 @@ double_ne(n1, n2) { return n1 != n2; } +#endif diff --git a/missing/strtod.c b/missing/strtod.c index e052cbc067..fdccd48081 100644 --- a/missing/strtod.c +++ b/missing/strtod.c @@ -6,8 +6,13 @@ * 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. + * Permission to use, copy, modify, and distribute this + * software and its documentation for any purpose and without + * fee is hereby granted, provided that the above copyright + * notice appear in all copies. The University of California + * makes no representations about the suitability of this + * software for any purpose. It is provided "as is" without + * express or implied warranty. * * RCS: @(#) $Id$ */ diff --git a/missing/x68.c b/missing/x68.c index dbfe662874..9a8f0a2a9c 100644 --- a/missing/x68.c +++ b/missing/x68.c @@ -18,6 +18,7 @@ link(const char *src, const char *dst) return symlink(src, dst); } +#ifndef HAVE_GETTIMEOFDAY #include #include @@ -34,3 +35,4 @@ gettimeofday(struct timeval *tv, struct timezone *tz) return 0; } +#endif diff --git a/node.h b/node.h index 4add37b47c..c223b78ff7 100644 --- a/node.h +++ b/node.h @@ -6,13 +6,17 @@ $Date$ created at: Fri May 28 15:14:02 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ #ifndef NODE_H #define NODE_H +#if defined(__cplusplus) +extern "C" { +#endif + enum node_type { NODE_METHOD, NODE_FBODY, @@ -310,9 +314,6 @@ typedef struct RNode { #define NEW_PREEXE(b) NEW_SCOPE(b) #define NEW_POSTEXE() rb_node_newnode(NODE_POSTEXE,0,0,0) -NODE *rb_node_newnode(); -VALUE rb_method_booundp(); - #define NOEX_PUBLIC 0 #define NOEX_UNDEF 1 #define NOEX_CFUNC 1 @@ -331,4 +332,8 @@ VALUE rb_gvar_get _((struct global_entry *)); VALUE rb_gvar_set _((struct global_entry *, VALUE)); VALUE rb_gvar_defined _((struct global_entry *)); +#if defined(__cplusplus) +} /* extern "C" { */ +#endif + #endif diff --git a/numeric.c b/numeric.c index d1c016e708..b21b17407e 100644 --- a/numeric.c +++ b/numeric.c @@ -6,7 +6,7 @@ $Date$ created at: Fri Aug 13 18:33:09 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -43,8 +43,8 @@ num_coerce(x, y) VALUE x, y; { if (CLASS_OF(x) == CLASS_OF(y)) - return rb_assoc_new(x, y); - return rb_assoc_new(rb_Float(x), rb_Float(y)); + return rb_assoc_new(y, x); + return rb_assoc_new(rb_Float(y), rb_Float(x)); } static VALUE @@ -330,8 +330,7 @@ flo_modulo(x, y, modulo) result = value1 - value2 * value; } #endif - if (modulo && - (RFLOAT(x)->value < 0.0) != (result < 0.0) && result != 0.0) { + if (modulo && value*result<0.0) { result += value; } return rb_float_new(result); @@ -1169,12 +1168,10 @@ fix_rshift(x, y) long i, val; i = NUM2LONG(y); - if (i < sizeof(long) * 8) { - val = RSHIFT(FIX2LONG(x), i); - return INT2FIX(val); - } - - return INT2FIX(0); + if (i < 0) + return fix_lshift(x, INT2FIX(-i)); + val = RSHIFT(FIX2LONG(x), i); + return INT2FIX(val); } static VALUE diff --git a/object.c b/object.c index 9c5163a248..2c594ec0e7 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-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -565,6 +565,7 @@ rb_mod_cmp(mod, arg) static VALUE rb_module_s_new(klass) + VALUE klass; { VALUE mod = rb_module_new(); diff --git a/pack.c b/pack.c index 999f93a0e7..83b83fbc41 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-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ diff --git a/parse.y b/parse.y index 5e516d2751..ff94cca7b2 100644 --- a/parse.y +++ b/parse.y @@ -330,21 +330,31 @@ stmt : block_call | stmt kWHILE_MOD expr { value_expr($3); - if (nd_type($1) == NODE_BEGIN) { - $$ = NEW_WHILE(cond($3), $1->nd_body, 0); + if ($1) { + if (nd_type($1) == NODE_BEGIN) { + $$ = NEW_WHILE(cond($3), $1->nd_body, 0); + } + else { + $$ = NEW_WHILE(cond($3), $1, 1); + } } else { - $$ = NEW_WHILE(cond($3), $1, 1); + $$ = 0; } } | stmt kUNTIL_MOD expr { value_expr($3); - if (nd_type($1) == NODE_BEGIN) { - $$ = NEW_UNTIL(cond($3), $1->nd_body, 0); + if ($1) { + if (nd_type($1) == NODE_BEGIN) { + $$ = NEW_UNTIL(cond($3), $1->nd_body, 0); + } + else { + $$ = NEW_UNTIL(cond($3), $1, 1); + } } else { - $$ = NEW_UNTIL(cond($3), $1, 1); + $$ = 0; } } | klBEGIN @@ -517,6 +527,10 @@ mlhs_node : variable { $$ = attrset($1, $3); } + | primary tCOLON2 tIDENTIFIER + { + $$ = attrset($1, $3); + } | backref { rb_backref_error($1); @@ -535,6 +549,10 @@ lhs : variable { $$ = attrset($1, $3); } + | primary tCOLON2 tIDENTIFIER + { + $$ = attrset($1, $3); + } | backref { rb_backref_error($1); @@ -573,8 +591,7 @@ undef_list : fitem $$ = block_append($1, NEW_UNDEF($4)); } -op : tDOT2 { $$ = tDOT2; } - | '|' { $$ = '|'; } +op : '|' { $$ = '|'; } | '^' { $$ = '^'; } | '&' { $$ = '&'; } | tCMP { $$ = tCMP; } @@ -669,6 +686,17 @@ arg : lhs '=' arg $$ = NEW_OP_ASGN2($1, $3, $4, $5); fixpos($$, $1); } + | primary tCOLON2 tIDENTIFIER tOP_ASGN arg + { + if ($4 == tOROP) { + $4 = 0; + } + else if ($4 == tANDOP) { + $4 = 1; + } + $$ = NEW_OP_ASGN2($1, $3, $4, $5); + fixpos($$, $1); + } | backref tOP_ASGN arg { rb_backref_error($1); @@ -708,23 +736,23 @@ arg : lhs '=' arg } | tUPLUS arg { - if (nd_type($2) == NODE_LIT) { + if ($2 && nd_type($2) == NODE_LIT) { $$ = $2; } else { - $$ = call_op($2, tUPLUS, 0); + $$ = call_op($2, tUPLUS, 0, 0); } } | tUMINUS arg { - if (nd_type($2) == NODE_LIT && FIXNUM_P($2->nd_lit)) { + if ($2 && nd_type($2) == NODE_LIT && FIXNUM_P($2->nd_lit)) { long i = FIX2LONG($2->nd_lit); $2->nd_lit = INT2FIX(-i); $$ = $2; } else { - $$ = call_op($2, tUMINUS, 0); + $$ = call_op($2, tUMINUS, 0, 0); } } | arg '|' arg @@ -786,7 +814,7 @@ arg : lhs '=' arg } | '~' arg { - $$ = call_op($2, '~', 0); + $$ = call_op($2, '~', 0, 0); } | arg tLSHFT arg { @@ -1516,7 +1544,11 @@ f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg $$ = NEW_ARGS(0, 0, -1); } -f_norm_arg : tIDENTIFIER +f_norm_arg : tCONSTANT + { + yyerror("formal argument must not be constant"); + } + | tIDENTIFIER { if (!is_local_id($1)) yyerror("formal argument must be local variable"); @@ -3236,8 +3268,8 @@ yylex() } else { result = tIDENTIFIER; - if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) { - if ((c = nextc()) == '=' && !peek('=')) { + if (lex_state == EXPR_FNAME) { + if ((c = nextc()) == '=' && !peek('=') && !peek('~')) { tokadd(c); } else { @@ -3394,9 +3426,16 @@ rb_str_extend(list, term) tokadd(c); goto loop_again; case '\\': - c = read_escape(); - tokadd(c); - goto loop_again; + c = nextc(); + if (c == -1) return (NODE*)-1; + if (c == term) { + tokadd(c); + } + else { + tokadd('\\'); + tokadd(c); + } + break; case '{': if (brace != -1) nest++; case '\"': diff --git a/prec.c b/prec.c index e4e116c347..43739bd9bd 100644 --- a/prec.c +++ b/prec.c @@ -6,7 +6,7 @@ $Date$ created at: Tue Jan 26 02:40:41 1999 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto *************************************************/ diff --git a/process.c b/process.c index d5c2d5eb8a..7d79a1d5c2 100644 --- a/process.c +++ b/process.c @@ -6,7 +6,7 @@ $Date$ created at: Tue Aug 10 14:30:50 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -195,10 +195,11 @@ rb_f_waitpid(obj, vpid, vflags) int pid, flags, status; if (NIL_P(vflags)) flags = 0; - else flags = FIX2UINT(vflags); + else flags = NUM2UINT(vflags); - if ((pid = rb_waitpid(FIX2UINT(vpid), flags, &status)) < 0) + if ((pid = rb_waitpid(NUM2INT(vpid), flags, &status)) < 0) rb_sys_fail(0); + if (pid == 0) return Qnil; return INT2FIX(pid); } @@ -600,6 +601,13 @@ rb_f_system(argc, argv) VALUE cmd; int state; + fflush(stdout); + fflush(stderr); + if (argc == 0) { + rb_last_status = INT2FIX(0); + rb_raise(rb_eArgError, "wrong # of arguments"); + } + if (TYPE(argv[0]) == T_ARRAY) { if (RARRAY(argv[0])->len != 2) { rb_raise(rb_eArgError, "wrong first argument"); @@ -619,6 +627,11 @@ rb_f_system(argc, argv) VALUE cmd; int state; + if (argc == 0) { + rb_last_status = INT2FIX(0); + rb_raise(rb_eArgError, "wrong # of arguments"); + } + if (TYPE(argv[0]) == T_ARRAY) { if (RARRAY(argv[0])->len != 2) { rb_raise(rb_eArgError, "wrong first argument"); @@ -644,7 +657,7 @@ rb_f_system(argc, argv) fflush(stderr); if (argc == 0) { rb_last_status = INT2FIX(0); - return INT2FIX(0); + rb_raise(rb_eArgError, "wrong # of arguments"); } if (TYPE(argv[0]) == T_ARRAY) { @@ -667,7 +680,7 @@ rb_f_system(argc, argv) #if defined(USE_CWGUSI) rb_notimplement(); #else - volatile VALUE prog = 0; + volatile VALUE prog = 0; int pid; int i; @@ -675,7 +688,7 @@ rb_f_system(argc, argv) fflush(stderr); if (argc == 0) { rb_last_status = INT2FIX(0); - return INT2FIX(0); + rb_raise(rb_eArgError, "wrong # of arguments"); } if (TYPE(argv[0]) == T_ARRAY) { @@ -791,7 +804,7 @@ proc_setpgrp(argc, argv) rb_scan_args(argc, argv, "0"); if (setpgrp() < 0) rb_sys_fail(0); #endif - return Qnil; + return INT2FIX(0); #else rb_notimplement(); #endif @@ -822,7 +835,7 @@ proc_setpgid(obj, pid, pgrp) ipgrp = NUM2INT(pgrp); if (setpgid(ipid, ipgrp) < 0) rb_sys_fail(0); - return Qnil; + return INT2FIX(0); #else rb_notimplement(); #endif diff --git a/random.c b/random.c index e977094eaa..36ffd699e0 100644 --- a/random.c +++ b/random.c @@ -6,7 +6,7 @@ $Date$ created at: Fri Dec 24 16:39:21 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -76,47 +76,57 @@ void srand48 _((long)); #endif /* not HAVE_DRAND48 */ -#ifdef HAVE_RANDOM static int first = 1; +#ifdef HAVE_RANDOM static char state[256]; #endif -static VALUE -rb_f_srand(argc, argv, obj) - int argc; - VALUE *argv; - VALUE obj; +static int +rand_init(seed) + long seed; { - VALUE seed; int old; - static int saved_seed; - - if (rb_scan_args(argc, argv, "01", &seed) == 0) { - static int n = 0; - struct timeval tv; - - gettimeofday(&tv, 0); - seed = tv.tv_sec ^ tv.tv_usec ^ getpid() ^ n++; - } - else { - seed = NUM2UINT(seed); - } + static unsigned int saved_seed; #ifdef HAVE_RANDOM if (first == 1) { initstate(1, state, sizeof state); - first = 0; } else { setstate(state); } #endif + first = 0; SRANDOM(seed); old = saved_seed; saved_seed = seed; - return rb_int2inum(old); + return old; +} + +static VALUE +rb_f_srand(argc, argv, obj) + int argc; + VALUE *argv; + VALUE obj; +{ + VALUE a; + unsigned int seed, old; + + if (rb_scan_args(argc, argv, "01", &a) == 0) { + static int n = 0; + struct timeval tv; + + gettimeofday(&tv, 0); + seed = tv.tv_sec ^ tv.tv_usec ^ getpid() ^ n++; + } + else { + seed = NUM2UINT(a); + } + old = rand_init(seed); + + return rb_uint2inum(old); } static VALUE @@ -125,14 +135,19 @@ rb_f_rand(obj, vmax) { long val, max; + if (first) { + struct timeval tv; + + gettimeofday(&tv, 0); + rand_init(tv.tv_sec ^ tv.tv_usec ^ getpid()); + } switch (TYPE(vmax)) { - case T_BIGNUM: - return rb_big_rand(vmax); - case T_FLOAT: - if (RFLOAT(vmax)->value > LONG_MAX || RFLOAT(vmax)->value < LONG_MIN) - return rb_big_rand(rb_dbl2big(RFLOAT(vmax)->value)); - break; + if (RFLOAT(vmax)->value <= LONG_MAX && RFLOAT(vmax)->value >= LONG_MIN) + break; + /* fall through */ + case T_BIGNUM: + return rb_big_rand(vmax, RANDOM_NUMBER); } max = NUM2LONG(vmax); diff --git a/range.c b/range.c index b1925e9929..ff455e4a96 100644 --- a/range.c +++ b/range.c @@ -6,7 +6,7 @@ $Date$ created at: Thu Aug 19 17:46:47 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ diff --git a/re.c b/re.c index ac73732d39..8052189e08 100644 --- a/re.c +++ b/re.c @@ -5,7 +5,7 @@ $Author$ created at: Mon Aug 9 18:24:49 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -182,6 +182,21 @@ kcode_reset_option() } } +int +rb_mbclen2(c, re) + unsigned char c; + VALUE re; +{ + int len; + + if (!FL_TEST(re, KCODE_FIXED)) + return mbclen(c); + kcode_set_option(re); + len = mbclen(c); + kcode_reset_option(); + return len; +} + extern int ruby_in_compile; static void @@ -260,9 +275,8 @@ static VALUE rb_reg_source(re) VALUE re; { - VALUE str = rb_str_new(0,0); - rb_reg_expr_str(str, RREGEXP(re)->str,RREGEXP(re)->len); - + VALUE str = rb_str_new(RREGEXP(re)->str,RREGEXP(re)->len); + if (OBJ_TAINTED(re)) OBJ_TAINT(str); return str; } @@ -538,6 +552,7 @@ rb_reg_search(reg, str, pos, reverse) } result = re_search(RREGEXP(reg)->ptr,RSTRING(str)->ptr,RSTRING(str)->len, pos, range, regs); + if (FL_TEST(reg, KCODE_FIXED)) kcode_reset_option(); @@ -710,7 +725,7 @@ static VALUE match_string(match) VALUE match; { - return rb_str_dup(RMATCH(match)->str); + return RMATCH(match)->str; /* str is frozen */ } VALUE rb_cRegexp; @@ -1263,7 +1278,9 @@ Init_Regexp() rb_global_variable(®_cache); rb_global_variable(&matchcache); - rb_cMatch = rb_define_class("MatchingData", rb_cData); + rb_cMatch = rb_define_class("MatchingData", rb_cObject); + rb_undef_method(CLASS_OF(rb_cMatch), "new"); + rb_define_method(rb_cMatch, "clone", match_clone, 0); rb_define_method(rb_cMatch, "size", match_size, 0); rb_define_method(rb_cMatch, "length", match_size, 0); diff --git a/re.h b/re.h index dc4cd17354..c4a63e1ff0 100644 --- a/re.h +++ b/re.h @@ -6,7 +6,7 @@ $Date$ created at: Thu Sep 30 14:18:32 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -36,4 +36,7 @@ VALUE rb_reg_regsub _((VALUE, VALUE, struct re_registers *)); int rb_kcode _((void)); extern int ruby_ignorecase; + +int rb_mbclen2 _((unsigned char, VALUE)); +#define mbclen2(c,re) rb_mbclen2((c),(re)) #endif diff --git a/regex.c b/regex.c index fd8a447b05..0ecd457b52 100644 --- a/regex.c +++ b/regex.c @@ -48,13 +48,6 @@ # include #endif -#if defined(STDC_HEADERS) -# include -#else -/* We need this for `regex.h', and perhaps for the Emacs include files. */ -# include -#endif - #ifndef __STDC__ # define volatile #endif @@ -1055,7 +1048,7 @@ calculate_must_string(start, end) return must; } -static int +static unsigned int read_backslash(c) int c; { @@ -1087,6 +1080,47 @@ read_backslash(c) return c; } +static unsigned int +read_special(p, pend, pp) + const char *p, *pend, **pp; +{ + int c; + + PATFETCH_RAW(c); + switch (c) { + case 'M': + PATFETCH_RAW(c); + if (c != '-') return -1; + PATFETCH_RAW(c); + *pp = p; + if (c == '\\') { + return read_special(p, pend, pp) | 0x80; + } + else if (c == -1) return ~0; + else { + return ((c & 0xff) | 0x80); + } + + case 'C': + PATFETCH_RAW(c); + if (c != '-') return ~0; + case 'c': + PATFETCH_RAW(c); + *pp = p; + if (c == '\\') { + c = read_special(p, pend, pp); + } + else if (c == '?') return 0177; + else if (c == -1) return ~0; + return c & 0x9f; + default: + return read_backslash(c); + } + + end_of_pattern: + return ~0; +} + /* re_compile_pattern takes a regular-expression string and converts it into a buffer full of byte commands for matching. @@ -1406,7 +1440,8 @@ re_compile_pattern(pattern, size, bufp) case 'W': for (c = 0; c < (1 << BYTEWIDTH); c++) { if (SYNTAX(c) != Sword && - (current_mbctype || SYNTAX(c) != Sword2)) + (current_mbctype && !re_mbctab[c] || + !current_mbctype && SYNTAX(c) != Sword2)) SET_LIST_BIT(c); } last = -1; @@ -1457,6 +1492,16 @@ re_compile_pattern(pattern, size, bufp) had_num_literal = 1; break; + case 'M': + case 'C': + case 'c': + p0 = --p; + c = read_special(p, pend, &p0); + if (c > 255) goto invalid_escape; + p = p0; + had_num_literal = 1; + break; + default: c = read_backslash(c); if (ismbchar(c)) { @@ -2143,6 +2188,16 @@ re_compile_pattern(pattern, size, bufp) BUFPUSH(c1); break; + case 'M': + case 'C': + case 'c': + p0 = --p; + c = read_special(p, pend, &p0); + if (c > 255) goto invalid_escape; + p = p0; + had_num_literal = 1; + goto numeric_char; + default: c = read_backslash(c); goto normal_char; @@ -2305,6 +2360,9 @@ re_compile_pattern(pattern, size, bufp) nested_meta: FREE_AND_RETURN(stackb, "nested *?+ in regexp"); + + invalid_escape: + FREE_AND_RETURN(stackb, "Invalid escape character syntax"); } void @@ -2898,11 +2956,12 @@ re_compile_fastmap(bufp) c = beg + 1; } - for (j = c; j < (1 << BYTEWIDTH); j++) + for (j = c; j < (1 << BYTEWIDTH); j++) { if (num_literal) fastmap[j] = 1; if (ismbchar(j)) fastmap[j] = 1; + } } break; @@ -4099,9 +4158,10 @@ re_match(bufp, string_arg, size, pos, regs) case jump: p1++; EXTRACT_NUMBER_AND_INCR (mcnt, p1); + + if (mcnt >= 0) break; /* should be backward jump */ p1 += mcnt; - if (p1 >= pend) break; if (( is_a_jump_n && (enum regexpcode)*p1 == succeed_n) || (!is_a_jump_n && (enum regexpcode)*p1 == on_failure_jump)) { if (failed_paren) { diff --git a/ruby.c b/ruby.c index 0b4d486ec8..e36e585b85 100644 --- a/ruby.c +++ b/ruby.c @@ -6,7 +6,7 @@ $Date$ created at: Tue Aug 10 12:47:31 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -176,8 +176,11 @@ rubylib_mangle(s, l) strcpy(ret + newl, s + oldl); return ret; } +#define rubylib_mangled_path(s, l) rb_str_new2(rubylib_mangle((s), (l))) +#define rubylib_mangled_path2(s) rb_str_new2(rubylib_mangle((s), 0)) #else -#define rubylib_mangle(s, l) (s) +#define rubylib_mangled_path(s, l) rb_str_new((s), (l)) +#define rubylib_mangled_path2(s) rb_str_new2(s) #endif static void @@ -202,18 +205,18 @@ addpath(path) while (*p) { while (*p == sep) p++; if (s = strchr(p, sep)) { - rb_ary_push(ary, rb_str_new(rubylib_mangle(p, (int)(s-p)), (int)(s-p))); + rb_ary_push(ary, rubylib_mangled_path(p, (int)(s-p))); p = s + 1; } else { - rb_ary_push(ary, rb_str_new2(rubylib_mangle(p, 0))); + rb_ary_push(ary, rubylib_mangled_path2(p)); break; } } rb_load_path = rb_ary_plus(ary, rb_load_path); } else { - rb_ary_unshift(rb_load_path, rb_str_new2(rubylib_mangle(path, 0))); + rb_ary_unshift(rb_load_path, rubylib_mangled_path2(path)); } } @@ -389,7 +392,10 @@ proc_options(argcp, argvp) s = argv[1]; argc--,argv++; } - if (*s && chdir(s) < 0) { + if (!s || !*s) { + rb_fatal("Can't chdir"); + } + if (chdir(s) < 0) { rb_fatal("Can't chdir to %s", s); } break; @@ -677,7 +683,11 @@ load_file(fname, script) } } } - else if (!NIL_P(c)) { + else if (NIL_P(c)) { + rb_io_close(f); + return; + } + else { rb_io_ungetc(f, c); } } diff --git a/ruby.h b/ruby.h index 765fd75ee8..fe24da344d 100644 --- a/ruby.h +++ b/ruby.h @@ -5,7 +5,7 @@ $Author$ created at: Thu Jun 10 14:26:32 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto *************************************************/ @@ -89,7 +89,7 @@ extern "C" { ---->> ruby requires sizeof(void*) == sizeof(long) to be compiled. <<---- #endif typedef unsigned long VALUE; -typedef unsigned int ID; +typedef unsigned long ID; #ifdef __STDC__ # include @@ -117,6 +117,8 @@ typedef unsigned int ID; #define INT2FIX(i) (VALUE)(((long)(i))<<1 | FIXNUM_FLAG) VALUE rb_int2inum _((long)); #define INT2NUM(v) rb_int2inum(v) +VALUE rb_uint2inum _((unsigned long)); +#define UINT2NUM(v) rb_uint2inum(v) #define FIX2LONG(x) RSHIFT((long)x,1) #define FIX2ULONG(x) (((unsigned long)(x))>>1) diff --git a/rubyio.h b/rubyio.h index f4b72781e5..145b420696 100644 --- a/rubyio.h +++ b/rubyio.h @@ -6,7 +6,7 @@ $Date$ created at: Fri Nov 12 16:47:09 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ diff --git a/rubytest.rb b/rubytest.rb index 7b886fd3f4..20032e303e 100644 --- a/rubytest.rb +++ b/rubytest.rb @@ -9,6 +9,8 @@ if File.exist? CONFIG['LIBRUBY_SO'] dldpath = "SHLIB_PATH" when /-aix/ dldpath = "LIBPATH" + when /-beos/ + dldpath = "LIBRARY_PATH" else dldpath = "LD_LIBRARY_PATH" end diff --git a/sample/io.rb b/sample/io.rb deleted file mode 100644 index 0b38d2112d..0000000000 --- a/sample/io.rb +++ /dev/null @@ -1,44 +0,0 @@ -# IO test -# usage: ruby io.rb file.. - -home = ENV["HOME"] -home.sub("m", "&&") -print(home, "\n") -print(home.reverse, "\n") - -if File.s("io.rb") - print(File.s("io.rb"), ": io.rb\n") -end - -$/="f\n" -for i in "abc\n\ndef\nghi\n" - print("tt: ", i) -end - -printf("%s:(%d)%s\n", $0, ARGV.length, ARGV[0]) -passwd = open(ARGV[0], "r") -#printf("%s", passwd.find{i|i =~ /\*/}) - -n = 1 -for i in passwd #.grep(/^\*/) - printf("%6d: %s", n, i) - n = n + 1; -end - -fp = open("|-", "r") - -if fp == nil - for i in 1..5 - print(i, "\n") - end -else - for line in fp - print(line) - end -end - -def printUsage() - if $USAGE - apply($USAGE); - end -end diff --git a/sample/mine.rb b/sample/mine.rb index 7d02e5bfc9..8fc27e0c6d 100644 --- a/sample/mine.rb +++ b/sample/mine.rb @@ -81,7 +81,7 @@ class Board elsif y < 0 then 0 elsif y >= @hi then 0 else - @data[x*@wi+y] + @data[y*@wi+x] end end def count(x,y) diff --git a/sample/mpart.rb b/sample/mpart.rb index 6c40d50e18..a88eba0ef6 100644 --- a/sample/mpart.rb +++ b/sample/mpart.rb @@ -31,7 +31,7 @@ for i in ifp = open(basename) end ofp.write(i) line = line + 1 - if line >= lines + if line >= lines and !ifp.eof? ofp.write("END--cut here--cut here\n") ofp.close part = part + 1 diff --git a/sample/rbc.rb b/sample/rbc.rb deleted file mode 100644 index 9f1ab9443d..0000000000 --- a/sample/rbc.rb +++ /dev/null @@ -1,1015 +0,0 @@ -#!/usr/local/bin/ruby -# -# rbc.rb - -# $Release Version: 0.8 $ -# $Revision: 1.8 $ -# $Date: 1998/03/11 05:43:00 $ -# by Keiju ISHITSUKA(Nippon Rational Inc.) -# -# -- -# Usage: -# -# rbc.rb [options] file_name opts -# options: -# -d debug mode (not recommended) -# -f does not read ~/.irbrc -# -m bc mode (rational/matrix calc) -# -r load-module same as `ruby -r' -# --inspect use inspect for result output -# (default for non-bc mode) -# --noinspect does not use inspect for result output -# --noreadline does not use readline library -# (default: try to use readline) -# -# additional private method (as function): -# exit, quit terminate the interpreter -# inspect_mode(sw = nil) toggle inspect mode -# trace_load(sw = nil) change trace mode for file loading using -# load/require. (default: trace-mode on) -# -require "e2mmap.rb" - -$stdout.sync = TRUE - -module BC_APPLICATION__ - RCS_ID='-$Id: rbc.rb,v 1.8 1998/03/11 05:43:00 keiju Exp keiju $-' - - extend Exception2MessageMapper - def_exception :UnrecognizedSwitch, "Unrecognized switch: %s" - - CONFIG = {} - CONFIG[0] = $0 - CONFIG[:USE_READLINE] = TRUE - CONFIG[:LOAD_MODULES] = [] - CONFIG[:INSPECT] = nil - CONFIG[:TRACE_LOAD] = FALSE - CONFIG[:RC] = TRUE - - CONFIG[:DEBUG] = FALSE - - while opt = ARGV.shift - case opt - when "-d" - CONFIG[:DEBUG] = TRUE - when "-m" - CONFIG[:INSPECT] = FALSE if CONFIG[:INSPECT].nil? - require "mathn.rb" - include Math - when "-r" - opt = ARGV.shift - CONFIG[:LOAD_MODULES].push opt if opt - when "-f" - opt = ARGV.shift - CONFIG[:RC] = FALSE - when "--inspect" - CONFIG[:INSPECT] = TRUE - when "--noinspect" - CONFIG[:INSPECT] = FALSE - when "--noreadline" - CONFIG[:USE_READLINE] = FALSE - when /^-/ - # print UnrecognizedSwitch.inspect, "\n" - BC_APPLICATION__.fail UnrecognizedSwitch, opt - else - CONFIG[:USE_READLINE] = FALSE - $0 = opt - break - end - end - CONFIG[:INSPECT] = TRUE if CONFIG[:INSPECT].nil? - - PROMPTi = "rbc%d> " - PROMPTs = "rbc%d%s " - PROMPTe = "rbc%d* " - - class BC - def initialize - lex_init - end - - def eval_input(io, cont, bind) - line = '' - @io = io - @ltype = nil - @quoted = nil - @indent = 0 - @lex_state = EXPR_BEG - - @io.prompt = format(PROMPTi, @indent) - - loop do - @continue = FALSE - l = @io.gets - - unless l - break if line == '' - else - line = line + l - - lex(l) if l != "\n" - print @quoted.inspect, "\n" if CONFIG[:DEBUG] - if @ltype - @io.prompt = format(PROMPTs, @indent, @ltype) - next - elsif @continue - @io.prompt = format(PROMPTe, @indent) - next - elsif @indent > 0 - @io.prompt = format(PROMPTi, @indent) - next - end - end - - if line != "\n" - begin - if CONFIG[:INSPECT] - print((cont._=eval(line, bind)).inspect, "\n") - else - print((cont._=eval(line, bind)), "\n") - end - rescue - # $! = 'exception raised' unless $! - # print "ERR: ", $!, "\n" - $! = RuntimeError.new("exception raised") unless $! - print $!.type, ": ", $!, "\n" - end - end - break if not l - line = '' - indent = 0 - @io.prompt = format(PROMPTi, indent) - end - print "\n" - end - - EXPR_BEG = :EXPR_BEG - EXPR_MID = :EXPR_MID - EXPR_END = :EXPR_END - EXPR_ARG = :EXPR_ARG - EXPR_FNAME = :EXPR_FNAME - - CLAUSE_STATE_TRANS = { - "alias" => EXPR_FNAME, - "and" => EXPR_BEG, - "begin" => EXPR_BEG, - "case" => EXPR_BEG, - "class" => EXPR_BEG, - "def" => EXPR_FNAME, - "defined?" => EXPR_END, - "do" => EXPR_BEG, - "else" => EXPR_BEG, - "elsif" => EXPR_BEG, - "end" => EXPR_END, - "ensure" => EXPR_BEG, - "for" => EXPR_BEG, - "if" => EXPR_BEG, - "in" => EXPR_BEG, - "module" => EXPR_BEG, - "nil" => EXPR_END, - "not" => EXPR_BEG, - "or" => EXPR_BEG, - "rescue" => EXPR_MID, - "return" => EXPR_MID, - "self" => EXPR_END, - "super" => EXPR_END, - "then" => EXPR_BEG, - "undef" => EXPR_FNAME, - "unless" => EXPR_BEG, - "until" => EXPR_BEG, - "when" => EXPR_BEG, - "while" => EXPR_BEG, - "yield" => EXPR_END - } - - ENINDENT_CLAUSE = [ - "case", "class", "def", "do", "for", "if", - "module", "unless", "until", "while", "begin" #, "when" - ] - DEINDENT_CLAUSE = ["end" #, "when" - ] - - PARCENT_LTYPE = { - "q" => "\'", - "Q" => "\"", - "x" => "\`", - "r" => "\/" - } - - PARCENT_PAREN = { - "{" => "}", - "[" => "]", - "<" => ">", - "(" => ")" - } - - def lex_init() - @OP = Trie.new - @OP.def_rules("\0", "\004", "\032"){} - @OP.def_rules(" ", "\t", "\f", "\r", "\13") do - @space_seen = TRUE - next - end - @OP.def_rule("#") do - |op, rests| - @ltype = "#" - identify_comment(rests) - end - @OP.def_rule("\n") do - print "\\n\n" if CONFIG[:DEBUG] - if @lex_state == EXPR_BEG || @lex_state == EXPR_FNAME - @continue = TRUE - else - @lex_state = EXPR_BEG - end - end - @OP.def_rules("*", "*=", "**=", "**") {@lex_state = EXPR_BEG} - @OP.def_rules("!", "!=", "!~") {@lex_state = EXPR_BEG} - @OP.def_rules("=", "==", "===", "=~", "<=>") {@lex_state = EXPR_BEG} - @OP.def_rules("<", "<=", "<<") {@lex_state = EXPR_BEG} - @OP.def_rules(">", ">=", ">>") {@lex_state = EXPR_BEG} - @OP.def_rules("'", '"') do - |op, rests| - @ltype = op - @quoted = op - identify_string(rests) - end - @OP.def_rules("`") do - |op, rests| - if @lex_state != EXPR_FNAME - @ltype = op - @quoted = op - identify_string(rests) - end - end - @OP.def_rules('?') do - |op, rests| - @lex_state = EXPR_END - identify_question(rests) - end - @OP.def_rules("&", "&&", "&=", "|", "||", "|=") do - @lex_state = EXPR_BEG - end - @OP.def_rule("+@", proc{@lex_state == EXPR_FNAME}) {} - @OP.def_rule("-@", proc{@lex_state == EXPR_FNAME}) {} - @OP.def_rules("+=", "-=") {@lex_state = EXPR_BEG} - @OP.def_rules("+", "-") do - |op, rests| - if @lex_state == EXPR_ARG - if @space_seen and rests[0] =~ /[0-9]/ - identify_number(rests) - else - @lex_state = EXPR_BEG - end - elsif @lex_state != EXPR_END and rests[0] =~ /[0-9]/ - identify_number(rests) - else - @lex_state = EXPR_BEG - end - end - @OP.def_rule(".") do - |op, rests| - @lex_state = EXPR_BEG - if rests[0] =~ /[0-9]/ - rests.unshift op - identify_number(rests) - else - # handle ``obj.if'' and such - identify_identifier(rests, TRUE) - @lex_state = EXPR_ARG - end - end - @OP.def_rules("..", "...") {@lex_state = EXPR_BEG} - - lex_int2 - end - - def lex_int2 - @OP.def_rules("]", "}", ")") do - @lex_state = EXPR_END - @indent -= 1 - end - @OP.def_rule(":") {|op,rests| - identify_identifier(rests, TRUE) - } - @OP.def_rule("::") {|op,rests| - identify_identifier(rests, TRUE); - } - @OP.def_rule("/") do - |op, rests| - if @lex_state == EXPR_BEG || @lex_state == EXPR_MID - @ltype = op - @quoted = op - identify_string(rests) - elsif rests[0] == '=' - rests.shift - @lex_state = EXPR_BEG - elsif @lex_state == EXPR_ARG and @space_seen and rests[0] =~ /\s/ - @ltype = op - @quoted = op - identify_string(rests) - else - @lex_state = EXPR_BEG - end - end - @OP.def_rules("^", "^=") {@lex_state = EXPR_BEG} - @OP.def_rules(",", ";") {@lex_state = EXPR_BEG} - @OP.def_rule("~") {@lex_state = EXPR_BEG} - @OP.def_rule("~@", proc{@lex_state = EXPR_FNAME}) {} - @OP.def_rule("(") do - @lex_state = EXPR_BEG - @indent += 1 - end - @OP.def_rule("[]", proc{@lex_state == EXPR_FNAME}) {} - @OP.def_rule("[]=", proc{@lex_state == EXPR_FNAME}) {} - @OP.def_rule("[") do - @indent += 1 - if @lex_state != EXPR_FNAME - @lex_state = EXPR_BEG - end - end - @OP.def_rule("{") do - @lex_state = EXPR_BEG - @indent += 1 - end - @OP.def_rule('\\') {|op, rests| identify_escape(rests)} #') - @OP.def_rule('%') do - |op, rests| - if @lex_state == EXPR_BEG || @lex_state == EXPR_MID - identify_quotation(rests) - elsif rests[0] == '=' - rests.shift - elsif @lex_state == EXPR_ARG and @space_seen and rests[0] =~ /\s/ - identify_quotation(rests) - else - @lex_state = EXPR_BEG - end - end - @OP.def_rule('$') do #' - |op, rests| - identify_gvar(rests) - end - @OP.def_rule('@') do - |op, rests| - if rests[0] =~ /[\w_]/ - rests.unshift op - identify_identifier(rests) - end - end - @OP.def_rule("def", proc{|op, chrs| /\s/ =~ chrs[0]}) do - |op, rests| - @indent += 1 - @lex_state = EXPR_END - until rests[0] == "\n" or rests[0] == ";" - rests.shift - end - end - @OP.def_rule("") do - |op, rests| - printf "MATCH: start %s: %s\n", op, rests.inspect if CONFIG[:DEBUG] - if rests[0] =~ /[0-9]/ - identify_number(rests) - elsif rests[0] =~ /[\w_]/ - identify_identifier(rests) - end - printf "MATCH: end %s: %s\n", op, rests.inspect if CONFIG[:DEBUG] - end - - p @OP if CONFIG[:DEBUG] - end - - def lex(l) - chrs = l.split(//) - tokens = [] - - case @ltype - when "'", '"', '`', '/' - identify_string(chrs) - return if chrs.empty? - when "#" - identify_comment(chrs) - return - when "=" - if l =~ /^=end/ - $ltype = nil - return - end - else - if l =~ /^=begin/ - $ltype = "=" - return - end - end - - until chrs.empty? - @space_seen = FALSE - printf "perse: %s\n", chrs.join("") if CONFIG[:DEBUG] - @OP.match(chrs) - printf "lex_state: %s continue: %s\n", @lex_state.id2name, @continue if CONFIG[:DEBUG] - end - end - - def identify_gvar(chrs) - @lex_state = EXPR_END - - ch = chrs.shift - case ch - when /[_~*$?!@/\\;,.=:<>"]/ #" - return - - when "-" - ch = chrs.shift - return - - when "&", "`", "'", "+" - return - - when /[1-9]/ - chrs.unshift ch - v = "$" - while (ch = chrs.shift) =~ /[0-9]/ - end - chrs.unshift ch - return - - when /\w/ - chrs.unshift ch - chrs.unshift "$" - identify_identifier(chrs) - return - - else - chrs.unshift ch - return - end - end - - def identify_identifier(chrs, escaped = FALSE) - token = "" - token.concat chrs.shift if chrs[0] =~ /[$@]/ or escaped - while (ch = chrs.shift) =~ /\w|_/ - print ":", ch, ":" if CONFIG[:DEBUG] - token.concat ch - end - chrs.unshift ch - - if ch == "!" or ch == "?" - chrs.shift - token.concat ch - end - # fix token - - if token =~ /^[$@]/ or escaped - @lex_state = EXPR_END - return - end - - print token, "\n" if CONFIG[:DEBUG] - if state = CLAUSE_STATE_TRANS[token] - if @lex_state != EXPR_BEG and token =~ /^(if|unless|while|until)/ - # modifiers - else - if ENINDENT_CLAUSE.include?(token) - @indent += 1 - elsif DEINDENT_CLAUSE.include?(token) - @indent -= 1 - end - end - @lex_state = state - return - end - if @lex_state == EXPR_FNAME - @lex_state = EXPR_END - if chrs[0] == '=' - chrs.shift - end - elsif @lex_state == EXPR_BEG - @lex_state = EXPR_ARG - else - @lex_state = EXPR_END - end - end - - def identify_quotation(chrs) - ch = chrs.shift - if lt = PARCENT_LTYPE[ch] - ch = chrs.shift - else - lt = "\"" - end - if ch !~ /\W/ - chrs.unshift ch - next - end - @ltype = lt - unless @quoted = PARCENT_PAREN[ch] - @quoted = ch - end - identify_string(chrs) - end - - def identify_number(chrs) - @lex_state = EXPR_END - - ch = chrs.shift - case ch - when /0/ - if (ch = chrs[0]) == "x" - chrs.shift - match = /[0-9a-f_]/ - else - match = /[0-7_]/ - end - while ch = chrs.shift - if ch !~ match - chrs.unshift ch - break - end - end - return - end - - while ch = chrs.shift - case ch - when /[0-9]/ - when "e", "E" - # type = FLOAT - unless (ch = chrs.shift) == "+" or ch == "-" - chrs.unshift ch - end - when "." - # type = FLOAT - when "_" - else - chrs.unshift ch - return - end - end - end - - def identify_question(chrs) - @lex_state = EXPR_END - - if chrs.shift == "\\" #" - identify_escape(chrs) - end - end - - def identify_string(chrs) - while ch = chrs.shift - if @quoted == ch - if @ltype == "/" - if chrs[0] =~ /i|o|n|e|s/ - chrs.shift - end - end - @ltype = nil - @quoted = nil - @lex_state = EXPR_END - break - elsif ch == '\\' #' - identify_escape(chrs) - end - end - end - - def identify_comment(chrs) - while ch = chrs.shift - if ch == "\\" #" - identify_escape(chrs) - end - if ch == "\n" - @ltype = nil - chrs.unshift ch - break - end - end - end - - def identify_escape(chrs) - ch = chrs.shift - case ch - when "\n", "\r", "\f" - @continue = TRUE - when "\\", "n", "t", "r", "f", "v", "a", "e", "b" #" - when /[0-7]/ - chrs.unshift ch - 3.times do - ch = chrs.shift - case ch - when /[0-7]/ - when nil - break - else - chrs.unshift ch - break - end - end - when "x" - 2.times do - ch = chrs.shift - case ch - when /[0-9a-fA-F]/ - when nil - break - else - chrs.unshift ch - break - end - end - when "M" - if (ch = chrs.shift) != '-' - chrs.unshift ch - elsif (ch = chrs.shift) == "\\" #" - identify_escape(chrs) - end - return - when "C", "c", "^" - if ch == "C" and (ch = chrs.shift) != "-" - chrs.unshift ch - elsif (ch = chrs.shift) == "\\" #" - identify_escape(chrs) - end - return - end - end - end - - class Trie - extend Exception2MessageMapper - def_exception :ErrNodeNothing, "node nothing" - def_exception :ErrNodeAlreadyExists, "node already exists" - - class Node - # abstract node if postproc is nil. - def initialize(preproc = nil, postproc = nil) - @Tree = {} - @preproc = preproc - @postproc = postproc - end - - attr :preproc, TRUE - attr :postproc, TRUE - - def search(chrs, opt = nil) - return self if chrs.empty? - ch = chrs.shift - if node = @Tree[ch] - node.search(chrs, opt) - else - if opt - chrs.unshift ch - self.create_subnode(chrs) - else - Trie.fail ErrNodeNothing - end - end - end - - def create_subnode(chrs, preproc = nil, postproc = nil) - if chrs.empty? - if @postproc - p node - Trie.fail ErrNodeAlreadyExists - else - print "Warn: change abstruct node to real node\n" if CONFIG[:DEBUG] - @preproc = preproc - @postproc = postproc - end - return self - end - - ch = chrs.shift - if node = @Tree[ch] - if chrs.empty? - if node.postproc - p node - Trie.fail ErrNodeAlreadyExists - else - print "Warn: change abstruct node to real node\n" if CONFIG[:DEBUG] - node.preproc = preproc - node.postproc = postproc - end - else - node.create_subnode(chrs, preproc, postproc) - end - else - if chrs.empty? - node = Node.new(preproc, postproc) - else - node = Node.new - node.create_subnode(chrs, preproc, postproc) - end - @Tree[ch] = node - end - node - end - - def match(chrs, op = "") - print "match>: ", chrs, "op:", op, "\n" if CONFIG[:DEBUG] - if chrs.empty? - if @preproc.nil? || @preproc.call(op, chrs) - printf "op1: %s\n", op if CONFIG[:DEBUG] - @postproc.call(op, chrs) - "" - else - nil - end - else - ch = chrs.shift - if node = @Tree[ch] - if ret = node.match(chrs, op+ch) - return ch+ret - else - chrs.unshift ch - if @postproc and @preproc.nil? || @preproc.call(op, chrs) - printf "op2: %s\n", op.inspect if CONFIG[:DEBUG] - @postproc.call(op, chrs) - return "" - else - return nil - end - end - else - chrs.unshift ch - if @postproc and @preproc.nil? || @preproc.call(op, chrs) - printf "op3: %s\n", op if CONFIG[:DEBUG] - @postproc.call(op, chrs) - return "" - else - return nil - end - end - end - end - end - - def initialize - @head = Node.new("") - end - - def def_rule(token, preproc = nil, postproc = nil) -# print node.inspect, "\n" if CONFIG[:DEBUG] - postproc = proc if iterator? - node = create(token, preproc, postproc) - end - - def def_rules(*tokens) - if iterator? - p = proc - end - for token in tokens - def_rule(token, nil, p) - end - end - - def preporc(token, proc) - node = search(token) - node.preproc=proc - end - - def postproc(token) - node = search(token, proc) - node.postproc=proc - end - - def search(token) - @head.search(token.split(//)) - end - - def create(token, preproc = nil, postproc = nil) - @head.create_subnode(token.split(//), preproc, postproc) - end - - def match(token) - token = token.split(//) if token.kind_of?(String) - ret = @head.match(token) - printf "match end: %s:%s", ret, token.inspect if CONFIG[:DEBUG] - ret - end - - def inspect - format("", @head.inspect) - end - end - - if /^-tt(.*)$/ =~ ARGV[0] -# Tracer.on - case $1 - when "1" - tr = Trie.new - print "0: ", tr.inspect, "\n" - tr.def_rule("=") {print "=\n"} - print "1: ", tr.inspect, "\n" - tr.def_rule("==") {print "==\n"} - print "2: ", tr.inspect, "\n" - - print "case 1:\n" - print tr.match("="), "\n" - print "case 2:\n" - print tr.match("=="), "\n" - print "case 3:\n" - print tr.match("=>"), "\n" - - when "2" - tr = Trie.new - print "0: ", tr.inspect, "\n" - tr.def_rule("=") {print "=\n"} - print "1: ", tr.inspect, "\n" - tr.def_rule("==", proc{FALSE}) {print "==\n"} - print "2: ", tr.inspect, "\n" - - print "case 1:\n" - print tr.match("="), "\n" - print "case 2:\n" - print tr.match("=="), "\n" - print "case 3:\n" - print tr.match("=>"), "\n" - end - exit - end - - module CONTEXT - def _=(value) - CONFIG[:_] = value - eval "_=BC_APPLICATION__::CONFIG[:_]", CONFIG[:BIND] - end - -# def _ -# eval "_", CONFIG[:BIND] -# end - - def quit - exit - end - - def trace_load(opt = nil) - if !opt.nil? - CONFIG[:TRACE_LOAD] = opt - else - CONFIG[:TRACE_LOAD] = !CONFIG[:TRACE_LOAD] - end - print "Switch to load/require #{unless CONFIG[:TRACE_LOAD]; ' non';end} trace mode.\n" - if CONFIG[:TRACE_LOAD] - eval %{ - class << self - alias load rbc_load - alias require rbc_require - end - } - else - eval %{ - class << self - alias load rbc_load_org - alias require rbc_require_org - end - } - end - CONFIG[:TRACE_LOAD] - end - - alias rbc_load_org load - def rbc_load(file_name) - return true if load_sub(file_name) - raise LoadError, "No such file to load -- #{file_name}" - end - - alias rbc_require_org require - def rbc_require(file_name) - rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?") - return false if $".find{|f| f =~ rex} - - case file_name - when /\.rb$/ - if load_sub(file_name) - $".push file_name - return true - end - when /\.(so|o|sl)$/ - rbc_require_org(file_name) - end - - if load_sub(f = file_name + ".rb") - $".push f - return true - end - rbc_require_org(file_name) - end - - def load_sub(fn) - if fn =~ /^#{Regexp.quote(File::Separator)}/ - return false unless File.exist?(fn) - BC.new.eval_input FileInputMethod.new(fn), self, CONFIG[:BIND] - return true - end - - for path in $: - if File.exist?(f = File.join(path, fn)) - BC.new.eval_input FileInputMethod.new(f), self, CONFIG[:BIND] - return true - end - end - return false - end - - def inspect_mode(opt = nil) - if opt - CONFIG[:INSPECT] = opt - else - CONFIG[:INSPECT] = !CONFIG[:INSPECT] - end - print "Switch to#{unless CONFIG[:INSPECT]; ' non';end} inspect mode.\n" - CONFIG[:INSPECT] - end - - def run(bind) - CONFIG[:BIND] = bind - - if CONFIG[:RC] - rc = File.expand_path("~/.irbrc") - if File.exists?(rc) - begin - load rc - rescue - print "load error: #{rc}\n" - print $!.type, ": ", $!, "\n" - for err in $@[0, $@.size - 2] - print "\t", err, "\n" - end - end - end - end - - if CONFIG[:TRACE_LOAD] - trace_load true - end - - for m in CONFIG[:LOAD_MODULES] - begin - require m - rescue - print $@[0], ":", $!.type, ": ", $!, "\n" - end - end - - if !$0.equal?(CONFIG[0]) - io = FileInputMethod.new($0) - elsif defined? Readline - io = ReadlineInputMethod.new - else - io = StdioInputMethod.new - end - - BC.new.eval_input io, self, CONFIG[:BIND] - end - end - - class InputMethod - attr :prompt, TRUE - - def gets - end - public :gets - end - - class StdioInputMethod < InputMethod - def gets - print @prompt - $stdin.gets - end - end - - class FileInputMethod < InputMethod - def initialize(file) - @io = open(file) - end - - def gets - l = @io.gets - print @prompt, l - l - end - end - - if CONFIG[:USE_READLINE] - begin - require "readline" - print "use readline module\n" - class ReadlineInputMethod < InputMethod - include Readline - def gets - if l = readline(@prompt, TRUE) - l + "\n" - else - l - end - end - end - rescue - CONFIG[:USE_READLINE] = FALSE - end - end -end - -extend BC_APPLICATION__::CONTEXT -run(binding) - diff --git a/signal.c b/signal.c index 6489760bc6..f5f8d822d1 100644 --- a/signal.c +++ b/signal.c @@ -298,7 +298,7 @@ posix_signal(signum, handler) sigact.sa_flags |= SA_RESTART; /* SVR4, 4.3+BSD */ #endif #ifdef SA_NOCLDWAIT - if (signum == SIGCHLD && handler == (RETSIGTYPE)SIG_IGN) + if (signum == SIGCHLD && handler == SIG_IGN) sigact.sa_flags |= SA_NOCLDWAIT; #endif sigaction(signum, &sigact, 0); @@ -317,7 +317,7 @@ signal_exec(sig) case SIGINT: rb_thread_interrupt(); break; -#ifndef NT +#if !defined(NT) && !defined(__human68k__) case SIGHUP: #endif #ifdef SIGQUIT @@ -498,7 +498,7 @@ trap(arg) if (func == SIG_DFL) { switch (sig) { case SIGINT: -#ifndef NT +#if !defined(NT) && !defined(__human68k__) case SIGHUP: #endif #ifdef SIGQUIT diff --git a/sprintf.c b/sprintf.c index 3c71e9771f..40d2e04535 100644 --- a/sprintf.c +++ b/sprintf.c @@ -6,7 +6,7 @@ $Date$ created at: Fri Oct 15 10:39:26 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -147,12 +147,13 @@ rb_f_sprintf(argc, argv) char *buf, *p, *end; int blen, bsiz; VALUE result; - int width, prec, flags = FNONE; + int tainted = 0; VALUE tmp; VALUE str; fmt = GETARG(); + if (OBJ_TAINTED(fmt)) tainted = 1; p = str2cstr(fmt, &blen); end = p + blen; blen = 0; @@ -172,6 +173,7 @@ rb_f_sprintf(argc, argv) p = t + 1; /* skip `%' */ width = prec = -1; + retry: switch (*p) { default: @@ -290,6 +292,7 @@ rb_f_sprintf(argc, argv) int len; str = rb_obj_as_string(arg); + if (OBJ_TAINTED(str)) tainted = 1; len = RSTRING(str)->len; if (flags&FPREC) { if (prec < len) { @@ -618,6 +621,7 @@ rb_f_sprintf(argc, argv) result = rb_str_new(buf, blen); free(buf); + if (tainted) OBJ_TAINT(result); return result; } diff --git a/st.c b/st.c index 486b72a434..503686b111 100644 --- a/st.c +++ b/st.c @@ -79,8 +79,8 @@ static long primes[] = { 32 + 5, 64 + 3, 128 + 3, - 256 + 29, - 512 + 17, + 256 + 27, + 512 + 9, 1024 + 9, 2048 + 5, 4096 + 83, diff --git a/string.c b/string.c index f7366cf99a..325c5b515f 100644 --- a/string.c +++ b/string.c @@ -6,7 +6,7 @@ $Date$ created at: Mon Aug 9 17:12:58 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -112,9 +112,10 @@ rb_str_new4(orig) str->ptr = RSTRING(orig)->ptr; RSTRING(orig)->orig = (VALUE)str; str->orig = 0; - if (FL_TEST(str, FL_TAINT)) { + if (FL_TEST(orig, FL_TAINT)) { FL_SET(str, FL_TAINT); } + FL_SET(str, STR_FREEZE); return (VALUE)str; } } @@ -261,9 +262,13 @@ rb_str_times(str, times) long i, len; len = NUM2LONG(times); + if (len == 0) return rb_str_new(0,0); if (len < 0) { rb_raise(rb_eArgError, "negative argument"); } + if (LONG_MAX / len < RSTRING(str)->len) { + rb_raise(rb_eArgError, "argument too big"); + } str2 = rb_str_new(0, RSTRING(str)->len*len); for (i=0; ilen; + if (pos < 0) return Qnil; + } switch (TYPE(sub)) { case T_REGEXP: @@ -756,6 +765,7 @@ rb_str_upto(beg, end, excl) int excl; { VALUE current; + ID succ = rb_intern("succ"); if (TYPE(end) != T_STRING) end = rb_str_to_str(end); @@ -763,7 +773,7 @@ rb_str_upto(beg, end, excl) while (rb_str_cmp(current, end) <= 0) { rb_yield(current); if (!excl && rb_str_equal(current, end)) break; - current = rb_str_succ(current); + current = rb_funcall(current, succ, 0, 0); if (excl && rb_str_equal(current, end)) break; if (RSTRING(current)->len > RSTRING(end)->len) break; @@ -858,7 +868,7 @@ rb_str_replace(str, beg, len, val) if (RSTRING(str)->len < beg && len < 0) { MEMZERO(RSTRING(str)->ptr + RSTRING(str)->len, char, -len); } - memcpy(RSTRING(str)->ptr+beg, RSTRING(val)->ptr, RSTRING(val)->len); + memmove(RSTRING(str)->ptr+beg, RSTRING(val)->ptr, RSTRING(val)->len); RSTRING(str)->len += RSTRING(val)->len - len; RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; } @@ -1041,10 +1051,9 @@ rb_str_sub(argc, argv, str) VALUE *argv; VALUE str; { - VALUE val = rb_str_sub_bang(argc, argv, str = rb_str_dup(str)); - - if (NIL_P(val)) return str; - return val; + str = rb_str_dup(str); + rb_str_sub_bang(argc, argv, str); + return str; } static VALUE @@ -1110,7 +1119,7 @@ rb_str_gsub_bang(argc, argv, str) * Always consume at least one character of the input string * in order to prevent infinite loops. */ - len = mbclen(RSTRING(str)->ptr[END(0)]); + len = mbclen2(RSTRING(str)->ptr[END(0)], pat); if (RSTRING(str)->len > END(0)) { memcpy(bp, RSTRING(str)->ptr+END(0), len); bp += len; @@ -1148,10 +1157,10 @@ rb_str_gsub(argc, argv, str) VALUE *argv; VALUE str; { - VALUE val = rb_str_gsub_bang(argc, argv, str = rb_str_dup(str)); + str = rb_str_dup(str); - if (NIL_P(val)) return str; - return val; + rb_str_gsub_bang(argc, argv, str); + return str; } static VALUE @@ -1193,13 +1202,11 @@ rb_f_sub(argc, argv) int argc; VALUE *argv; { - VALUE line, v; + VALUE str = rb_str_dup(uscore_get()); - line = uscore_get(); - v = rb_str_sub_bang(argc, argv, line = rb_str_dup(line)); - if (NIL_P(v)) return line; - rb_lastline_set(v); - return v; + rb_str_sub_bang(argc, argv, str); + rb_lastline_set(str); + return str; } static VALUE @@ -1215,13 +1222,11 @@ rb_f_gsub(argc, argv) int argc; VALUE *argv; { - VALUE line, v; + VALUE str = rb_str_dup(uscore_get()); - line = uscore_get(); - v = rb_str_gsub_bang(argc, argv, line = rb_str_dup(line)); - if (NIL_P(v)) return line; - rb_lastline_set(v); - return v; + rb_str_gsub_bang(argc, argv, str); + rb_lastline_set(str); + return str; } static VALUE @@ -1343,12 +1348,6 @@ rb_str_inspect(str) *b++ = *p++; } } -#if 0 - else if ((c & 0x80) && rb_kcode() != MBCTYPE_EUC) { - CHECK(1); - *b++ = c; - } -#endif else if (c == '"'|| c == '\\') { CHECK(2); *b++ = '\\'; @@ -1522,10 +1521,9 @@ static VALUE rb_str_upcase(str) VALUE str; { - VALUE val = rb_str_upcase_bang(str = rb_str_dup(str)); - - if (NIL_P(val)) return str; - return val; + str = rb_str_dup(str); + rb_str_upcase_bang(str); + return str; } static VALUE @@ -1556,10 +1554,9 @@ static VALUE rb_str_downcase(str) VALUE str; { - VALUE val = rb_str_downcase_bang(str = rb_str_dup(str)); - - if (NIL_P(val)) return str; - return val; + str = rb_str_dup(str); + rb_str_downcase_bang(str); + return str; } static VALUE @@ -1592,10 +1589,9 @@ static VALUE rb_str_capitalize(str) VALUE str; { - VALUE val = rb_str_capitalize_bang(str = rb_str_dup(str)); - - if (NIL_P(val)) return str; - return val; + str = rb_str_dup(str); + rb_str_capitalize_bang(str); + return str; } static VALUE @@ -1630,10 +1626,9 @@ static VALUE rb_str_swapcase(str) VALUE str; { - VALUE val = rb_str_swapcase_bang(str = rb_str_dup(str)); - - if (NIL_P(val)) return str; - return val; + str = rb_str_dup(str); + rb_str_swapcase_bang(str); + return str; } typedef unsigned char *USTR; @@ -1781,10 +1776,9 @@ static VALUE rb_str_tr(str, src, repl) VALUE str, src, repl; { - VALUE val = tr_trans(str = rb_str_dup(str), src, repl, 0); - - if (NIL_P(val)) return str; - return val; + str = rb_str_dup(str); + tr_trans(str, src, repl, 0); + return str; } static void @@ -1865,10 +1859,9 @@ rb_str_delete(argc, argv, str) VALUE *argv; VALUE str; { - VALUE val = rb_str_delete_bang(argc, argv, str = rb_str_dup(str)); - - if (NIL_P(val)) return str; - return val; + str = rb_str_dup(str); + rb_str_delete_bang(argc, argv, str); + return str; } static VALUE @@ -1926,10 +1919,9 @@ rb_str_squeeze(argc, argv, str) VALUE *argv; VALUE str; { - VALUE val = rb_str_squeeze_bang(argc, argv, str = rb_str_dup(str)); - - if (NIL_P(val)) return str; - return val; + str = rb_str_dup(str); + rb_str_squeeze_bang(argc, argv, str); + return str; } static VALUE @@ -1943,10 +1935,9 @@ static VALUE rb_str_tr_s(str, src, repl) VALUE str, src, repl; { - VALUE val = tr_trans(str = rb_str_dup(str), src, repl, 1); - - if (NIL_P(val)) return str; - return val; + str = rb_str_dup(str); + tr_trans(str, src, repl, 1); + return str; } static VALUE @@ -2069,6 +2060,7 @@ rb_str_split_method(argc, argv, str) if (!NIL_P(limit) && lim <= ++i) break; } end++; + if (ismbchar(*ptr)) {ptr++; end++;} } } } @@ -2082,11 +2074,11 @@ rb_str_split_method(argc, argv, str) regs = RMATCH(rb_backref_get())->regs; if (start == end && BEG(0) == END(0)) { if (last_null == 1) { - rb_ary_push(result, rb_str_substr(str, beg, mbclen(RSTRING(str)->ptr[beg]))); + rb_ary_push(result, rb_str_substr(str, beg, mbclen2(RSTRING(str)->ptr[beg],spat))); beg = start; } else { - start += mbclen(RSTRING(str)->ptr[start]); + start += mbclen2(RSTRING(str)->ptr[start],spat); last_null = 1; continue; } @@ -2234,10 +2226,9 @@ static VALUE rb_str_chop(str) VALUE str; { - VALUE val = rb_str_chop_bang(str = rb_str_dup(str)); - - if (NIL_P(val)) return str; - return val; + str = rb_str_dup(str); + rb_str_chop_bang(str); + return str; } static VALUE @@ -2250,12 +2241,11 @@ rb_f_chop_bang(str) static VALUE rb_f_chop() { - VALUE str = uscore_get(); - VALUE val = rb_str_chop_bang(str = rb_str_dup(str)); + VALUE str = rb_str_dup(uscore_get()); - if (NIL_P(val)) return str; - rb_lastline_set(val); - return val; + rb_str_chop_bang(str); + rb_lastline_set(str); + return str; } static VALUE @@ -2307,10 +2297,9 @@ rb_str_chomp(argc, argv, str) VALUE *argv; VALUE str; { - VALUE val = rb_str_chomp_bang(argc, argv, str = rb_str_dup(str)); - - if (NIL_P(val)) return str; - return val; + str = rb_str_dup(str); + rb_str_chomp_bang(argc, argv, str); + return str; } static VALUE @@ -2326,12 +2315,11 @@ rb_f_chomp(argc, argv) int argc; VALUE *argv; { - VALUE str = uscore_get(); - VALUE val = rb_str_chomp_bang(argc, argv, str = rb_str_dup(str)); + VALUE str = rb_str_dup(uscore_get()); - if (NIL_P(val)) return str; - rb_lastline_set(val); - return val; + rb_str_chomp_bang(argc, argv, str); + rb_lastline_set(str); + return str; } static VALUE @@ -2374,10 +2362,9 @@ static VALUE rb_str_strip(str) VALUE str; { - VALUE val = rb_str_strip_bang(str = rb_str_dup(str)); - - if (NIL_P(val)) return str; - return val; + str = rb_str_dup(str); + rb_str_strip_bang(str); + return str; } static VALUE @@ -2396,7 +2383,7 @@ scan_once(str, pat, start) /* * Always consume at least one character of the input string */ - *start = END(0)+mbclen(RSTRING(str)->ptr[END(0)]); + *start = END(0)+mbclen2(RSTRING(str)->ptr[END(0)],pat); } else { *start = END(0); diff --git a/struct.c b/struct.c index e22c539fac..56710b676f 100644 --- a/struct.c +++ b/struct.c @@ -224,6 +224,7 @@ static VALUE rb_struct_s_def(argc, argv, klass) int argc; VALUE *argv; + VALUE klass; { VALUE name, rest; long i; diff --git a/time.c b/time.c index dd22c499dd..a1774b1371 100644 --- a/time.c +++ b/time.c @@ -6,7 +6,7 @@ $Date$ created at: Tue Dec 28 14:31:59 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -386,7 +386,7 @@ time_cmp(time1, time2) i = FIX2LONG(time2); if (tobj1->tv.tv_sec == i) return INT2FIX(0); if (tobj1->tv.tv_sec > i) return INT2FIX(1); - return FIX2INT(-1); + return INT2FIX(-1); case T_FLOAT: { @@ -399,7 +399,7 @@ time_cmp(time1, time2) return INT2FIX(0); if (tobj1->tv.tv_sec > (time_t)RFLOAT(time2)->value) return INT2FIX(1); - return FIX2INT(-1); + return INT2FIX(-1); } } @@ -408,15 +408,15 @@ time_cmp(time1, time2) if (tobj1->tv.tv_sec == tobj2->tv.tv_sec) { if (tobj1->tv.tv_usec == tobj2->tv.tv_usec) return INT2FIX(0); if (tobj1->tv.tv_usec > tobj2->tv.tv_usec) return INT2FIX(1); - return FIX2INT(-1); + return INT2FIX(-1); } if (tobj1->tv.tv_sec > tobj2->tv.tv_sec) return INT2FIX(1); - return FIX2INT(-1); + return INT2FIX(-1); } i = NUM2LONG(time2); if (tobj1->tv.tv_sec == i) return INT2FIX(0); if (tobj1->tv.tv_sec > i) return INT2FIX(1); - return FIX2INT(-1); + return INT2FIX(-1); } static VALUE diff --git a/top.sed b/top.sed index feef9006ba..40f1316109 100644 --- a/top.sed +++ b/top.sed @@ -33,7 +33,7 @@ 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 vsnprintf.o%g +s%@LIBOBJS@% crypt.o flock.o vsnprintf.o%g s%@ALLOCA@%%g s%@DEFAULT_KCODE@%%g s%@EXEEXT@%.exe%g diff --git a/util.c b/util.c index 04b3dd6dbe..6a792fe4f4 100644 --- a/util.c +++ b/util.c @@ -6,7 +6,7 @@ $Date$ created at: Fri Mar 10 17:22:34 JST 1995 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ diff --git a/util.h b/util.h index 41ce2a5a19..84ad5fcc5f 100644 --- a/util.h +++ b/util.h @@ -6,7 +6,7 @@ $Date$ created at: Thu Mar 9 11:55:53 JST 1995 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ #ifndef UTIL_H diff --git a/variable.c b/variable.c index 7b273933ac..5e041f876d 100644 --- a/variable.c +++ b/variable.c @@ -195,10 +195,20 @@ VALUE rb_path2class(path) const char *path; { + VALUE c; + if (path[0] == '#') { rb_raise(rb_eArgError, "can't retrieve anonymous class %s", path); } - return rb_eval_string(path); + c = rb_eval_string(path); + switch (TYPE(c)) { + case T_MODULE: + case T_CLASS: + break; + default: + rb_raise(rb_eTypeError, "class path %s does not point class", path); + } + return c; } void @@ -694,6 +704,18 @@ rb_alias_variable(name1, name2) static int special_generic_ivar = 0; static st_table *generic_iv_tbl; +st_table* +rb_generic_ivar_table(obj) + VALUE obj; +{ + st_table *tbl; + VALUE val; + + if (!generic_iv_tbl) return 0; + if (!st_lookup(generic_iv_tbl, obj, &tbl)) return 0; + return tbl; +} + static VALUE generic_ivar_get(obj, id) VALUE obj; diff --git a/version.c b/version.c index 6cd9943430..fa27427c67 100644 --- a/version.c +++ b/version.c @@ -6,7 +6,7 @@ $Date$ created at: Thu Sep 30 20:08:01 JST 1993 - Copyright (C) 1993-1999 Yukihiro Matsumoto + Copyright (C) 1993-2000 Yukihiro Matsumoto ************************************************/ @@ -40,6 +40,6 @@ ruby_show_version() void ruby_show_copyright() { - printf("ruby - Copyright (C) 1993-1999 Yukihiro Matsumoto\n"); + printf("ruby - Copyright (C) 1993-2000 Yukihiro Matsumoto\n"); exit(0); } diff --git a/version.h b/version.h index 0d5ed1f1eb..d8736f2680 100644 --- a/version.h +++ b/version.h @@ -1,4 +1,4 @@ -#define RUBY_VERSION "1.4.2" -#define RUBY_RELEASE_DATE "1999-09-18" -#define RUBY_VERSION_CODE 142 -#define RUBY_RELEASE_CODE 19990918 +#define RUBY_VERSION "1.4.4" +#define RUBY_RELEASE_DATE "2000-03-13" +#define RUBY_VERSION_CODE 144 +#define RUBY_RELEASE_CODE 20000313 diff --git a/win32/Makefile b/win32/Makefile index f84c96bc3f..7573ef62cf 100644 --- a/win32/Makefile +++ b/win32/Makefile @@ -18,8 +18,8 @@ LDFLAGS = $(CFLAGS) -Fm #LDFLAGS = $(CFLAGS) -Fm XLDFLAGS = #EXTLIBS = -LIBS = advapi32.lib wsock32.lib $(EXTLIBS) -MISSING = crypt.obj alloca.obj win32.obj fnmatch.obj isinf.obj isnan.obj +LIBS = user32.lib advapi32.lib wsock32.lib $(EXTLIBS) +MISSING = crypt.obj alloca.obj win32.obj isinf.obj isnan.obj LDSHARED = DLDFLAGS = SOLIBS = @@ -166,9 +166,6 @@ isinf.obj: missing/isinf.c isnan.obj: missing/isnan.c $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/isnan.c -fnmatch.obj: missing/fnmatch.c - $(CC) -I. $(CFLAGS) $(CPPFLAGS) -c missing/fnmatch.c - memcmp.obj: missing/memcmp.c $(CC) $(CFLAGS) $(CPPFLAGS) -c missing/memcmp.c diff --git a/win32/config.status b/win32/config.status index 9b959ff4bb..6f77f19b01 100644 --- a/win32/config.status +++ b/win32/config.status @@ -7,7 +7,7 @@ s%@FFLAGS@%%g s%@DEFS@% -DUSE_THREAD -DSIZEOF_INT=4 -DSIZEOF_SHORT=2 -DSIZEOF_LONG=4 -DSIZEOF_VOIDP=4 -DSIZEOF_FLOAT=4 -DSIZEOF_DOUBLE=8 -DHAVE_PROTOTYPES=1 -DHAVE_STDARG_PROTOTYPES=1 -DHAVE_STDLIB_H=1 -DHAVE_LIMITS_H=1 -DHAVE_SYS_FILE_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_ST_RDEV=1 -DGETGROUPS_T=int -DRETSIGTYPE=void -DHAVE_ALLOCA=1 -DHAVE_FMOD=1 -DHAVE_WAITPID=1 -DHAVE_GETCWD=1 -DHAVE_CHSIZE=1 -DHAVE_GETGROUPS=1 -DHAVE_GETLOGIN=1 -DRSHIFT=\(x,y\)\ \(\(x\)\>\>y\) -DFILE_COUNT=_cnt -DDLEXT=\".dll\" -DRUBY_LIB=\"/usr/local/lib/ruby/1.4\" -DRUBY_ARCHLIB=\"/usr/local/lib/ruby/1.4/i386-mswin32\" -DRUBY_PLATFORM=\"i386-mswin32\" %g s%@LDFLAGS@%%g -s%@LIBS@%advapi32.lib wsock32.lib%g +s%@LIBS@%user32.lib advapi32.lib wsock32.lib%g s%@exec_prefix@%${prefix}%g s%@prefix@%/usr/local%g s%@program_transform_name@%s,x,x,%g @@ -35,7 +35,7 @@ s%@RANLIB@%rem%g s%@AR@%lib -nologo%g s%@LN_S@%%g s%@SET_MAKE@%%g -s%@LIBOBJS@% crypt.obj alloca.obj win32.obj fnmatch.obj isinf.obj isnan.obj%g +s%@LIBOBJS@% crypt.obj alloca.obj win32.obj isinf.obj isnan.obj%g s%@ALLOCA@%%g s%@DEFAULT_KCODE@%%g s%@EXEEXT@%.exe%g diff --git a/win32/ruby.def b/win32/ruby.def index 1c79697fd7..97ac63c74b 100644 --- a/win32/ruby.def +++ b/win32/ruby.def @@ -31,6 +31,7 @@ EXPORTS rb_eSystemCallError rb_eZeroDivError rb_mErrno + ruby_nerrs ;eval.c rb_cProc ruby_frame @@ -98,8 +99,6 @@ EXPORTS definekey encrypt crypt -;missing/fnmatch.c - fnmatch ;missing/isinf.c isinf ;missing/isnan.c @@ -134,6 +133,7 @@ EXPORTS mygetservbyname mygetservbyport myget_osfhandle + win32_getcwd win32_getenv ;array.c rb_mem_clear @@ -283,6 +283,7 @@ EXPORTS rb_funcall rb_funcall2 rb_funcall3 + rb_call_super rb_backtrace rb_frame_last_func rb_obj_instance_eval @@ -326,6 +327,7 @@ EXPORTS rb_file_s_expand_path ;gc.c xmalloc + xfree xcalloc xrealloc rb_global_variable @@ -373,7 +375,7 @@ EXPORTS rb_fdopen rb_file_open rb_file_sysopen - rb_io_synchronized + rb_io_synchronized rb_p rb_gets rb_str_setter diff --git a/win32/win32.c b/win32/win32.c index a28006ce86..a1e6d25ff3 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -229,7 +229,6 @@ char *getlogin() struct { int inuse; int pid; - HANDLE oshandle; FILE *pipe; } MyPopenRecord[MYPOPENSIZE]; @@ -495,7 +494,7 @@ mypopen (char *cmd, char *mode) int p[2]; BOOL fRet; - HANDLE hInFile, hOutFile, hStdin, hStdout; + HANDLE hInFile, hOutFile; LPCSTR lpApplicationName = NULL; LPTSTR lpCommandLine; LPTSTR lpCmd2 = NULL; @@ -509,23 +508,11 @@ mypopen (char *cmd, char *mode) sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; - if (!reading) { - FILE *fp; - - fp = (_popen)(cmd, mode); - - MyPopenRecord[slot].inuse = TRUE; - MyPopenRecord[slot].pipe = fp; - MyPopenRecord[slot].pid = -1; - - if (!fp) - rb_fatal("cannot open pipe \"%s\" (%s)", cmd, strerror(errno)); - return fp; - } - fRet = CreatePipe(&hInFile, &hOutFile, &sa, 2048L); - if (!fRet) - rb_fatal("cannot open pipe \"%s\" (%s)", cmd, strerror(errno)); + if (!fRet) { + errno = GetLastError(); + rb_sys_fail("mypopen: CreatePipe"); + } memset(&aStartupInfo, 0, sizeof (STARTUPINFO)); memset(&aProcessInformation, 0, sizeof (PROCESS_INFORMATION)); @@ -533,93 +520,63 @@ mypopen (char *cmd, char *mode) aStartupInfo.dwFlags = STARTF_USESTDHANDLES; if (reading) { - aStartupInfo.hStdInput = GetStdHandle(STD_OUTPUT_HANDLE);//hStdin; - aStartupInfo.hStdError = INVALID_HANDLE_VALUE; - //for save - DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_OUTPUT_HANDLE), - GetCurrentProcess(), &hStdout, - 0, FALSE, DUPLICATE_SAME_ACCESS - ); - //for redirect - DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_INPUT_HANDLE), - GetCurrentProcess(), &hStdin, - 0, TRUE, DUPLICATE_SAME_ACCESS - ); + aStartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); aStartupInfo.hStdOutput = hOutFile; } else { - aStartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); //hStdout; - aStartupInfo.hStdError = INVALID_HANDLE_VALUE; - // for save - DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_INPUT_HANDLE), - GetCurrentProcess(), &hStdin, - 0, FALSE, DUPLICATE_SAME_ACCESS - ); - //for redirect - DuplicateHandle(GetCurrentProcess(), GetStdHandle(STD_OUTPUT_HANDLE), - GetCurrentProcess(), &hStdout, - 0, TRUE, DUPLICATE_SAME_ACCESS - ); - aStartupInfo.hStdInput = hInFile; + aStartupInfo.hStdInput = hInFile; + aStartupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); } + aStartupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); dwCreationFlags = (NORMAL_PRIORITY_CLASS); lpCommandLine = cmd; if (NtHasRedirection(cmd) || isInternalCmd(cmd)) { lpApplicationName = getenv("COMSPEC"); - lpCmd2 = malloc(strlen(lpApplicationName) + 1 + strlen(cmd) + sizeof (" /c ")); - if (lpCmd2 == NULL) - rb_fatal("Mypopen: malloc failed"); + lpCmd2 = xmalloc(strlen(lpApplicationName) + 1 + strlen(cmd) + sizeof (" /c ")); sprintf(lpCmd2, "%s %s%s", lpApplicationName, " /c ", cmd); lpCommandLine = lpCmd2; } fRet = CreateProcess(lpApplicationName, lpCommandLine, &sa, &sa, sa.bInheritHandle, dwCreationFlags, NULL, NULL, &aStartupInfo, &aProcessInformation); + errno = GetLastError(); + + if (lpCmd2) + free(lpCmd2); if (!fRet) { CloseHandle(hInFile); CloseHandle(hOutFile); - rb_fatal("cannot fork for \"%s\" (%s)", cmd, strerror(errno)); + return NULL; } CloseHandle(aProcessInformation.hThread); if (reading) { - HANDLE hDummy; - fd = _open_osfhandle((long)hInFile, (_O_RDONLY | pipemode)); CloseHandle(hOutFile); - DuplicateHandle(GetCurrentProcess(), hStdout, - GetCurrentProcess(), &hDummy, - 0, TRUE, (DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE) - ); } else { - HANDLE hDummy; - - fd = _open_osfhandle((long)hOutFile, (_O_WRONLY | pipemode)); + fd = _open_osfhandle((long)hOutFile, (_O_WRONLY | pipemode)); CloseHandle(hInFile); - DuplicateHandle(GetCurrentProcess(), hStdin, - GetCurrentProcess(), &hDummy, - 0, TRUE, (DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE) - ); } - if (fd == -1) - rb_fatal("cannot open pipe \"%s\" (%s)", cmd, strerror(errno)); - - - if ((fp = (FILE *) fdopen(fd, mode)) == NULL) - return NULL; + if (fd == -1) { + CloseHandle(reading ? hInFile : hOutFile); + CloseHandle(aProcessInformation.hProcess); + rb_sys_fail("mypopen: _open_osfhandle"); + } - if (lpCmd2) - free(lpCmd2); + if ((fp = (FILE *) fdopen(fd, mode)) == NULL) { + _close(fd); + CloseHandle(aProcessInformation.hProcess); + rb_sys_fail("mypopen: fdopen"); + } MyPopenRecord[slot].inuse = TRUE; MyPopenRecord[slot].pipe = fp; - MyPopenRecord[slot].oshandle = (reading ? hInFile : hOutFile); MyPopenRecord[slot].pid = (int)aProcessInformation.hProcess; return fp; } @@ -671,14 +628,13 @@ mypclose(FILE *fp) } } } + CloseHandle((HANDLE)MyPopenRecord[i].pid); #endif - // // close the pipe // - // Closehandle() is done by fclose(). - //CloseHandle(MyPopenRecord[i].oshandle); + fflush(fp); fclose(fp); @@ -1218,12 +1174,6 @@ NtMakeCmdVector (char *cmdline, char ***vec, int InputCmd) // UNIX compatible directory access functions for NT // -// -// File names are converted to lowercase if the -// CONVERT_TO_LOWER_CASE variable is defined. -// - -#define CONVERT_TO_LOWER_CASE #define PATHLEN 1024 // @@ -1246,33 +1196,18 @@ opendir(char *filename) char root[PATHLEN]; char volname[PATHLEN]; DWORD serial, maxname, flags; - BOOL downcase; - char *dummy; // // check to see if we\'ve got a directory // - if (stat (filename, &sbuf) < 0 || - sbuf.st_mode & _S_IFDIR == 0) { + if ((stat (filename, &sbuf) < 0 || + sbuf.st_mode & _S_IFDIR == 0) && + (!isalpha(filename[0]) || filename[1] != ':' || filename[2] != '\0' || + ((1 << (filename[0] & 0x5f) - 'A') & GetLogicalDrives()) == 0)) { return NULL; } - // - // check out the file system characteristics - // - if (GetFullPathName(filename, PATHLEN, root, &dummy)) { - if (dummy = strchr(root, '\\')) - *++dummy = '\0'; - if (GetVolumeInformation(root, volname, PATHLEN, - &serial, &maxname, &flags, 0, 0)) { - downcase = !(flags & FS_CASE_SENSITIVE); - } - } - else { - downcase = TRUE; - } - // // Get us a DIR structure // @@ -1287,7 +1222,7 @@ opendir(char *filename) strcpy(scanname, filename); - if (index("/\\", *(scanname + strlen(scanname) - 1)) == NULL) + if (index("/\\:", *CharPrev(scanname, scanname + strlen(scanname))) == NULL) strcat(scanname, "/*"); else strcat(scanname, "*"); @@ -1309,8 +1244,6 @@ opendir(char *filename) idx = strlen(FindData.cFileName)+1; p->start = ALLOC_N(char, idx); strcpy (p->start, FindData.cFileName); - if (downcase) - strlwr(p->start); p->nfiles++; // @@ -1334,8 +1267,6 @@ opendir(char *filename) rb_fatal ("opendir: malloc failed!\n"); } strcpy(&p->start[idx], FindData.cFileName); - if (downcase) - strlwr(&p->start[idx]); p->nfiles++; idx += len+1; } @@ -1609,7 +1540,7 @@ typedef struct { #endif /* defined (_MT) && !defined (DLL_FOR_WIN32S) */ } ioinfo; -EXTERN_C ioinfo * __pioinfo[]; +EXTERN_C _CRTIMP ioinfo * __pioinfo[]; #define IOINFO_L2E 5 #define IOINFO_ARRAY_ELTS (1 << IOINFO_L2E) @@ -1617,6 +1548,7 @@ EXTERN_C ioinfo * __pioinfo[]; #define _osfile(i) (_pioinfo(i)->osfile) #define FOPEN 0x01 /* file handle open */ +#define FNOINHERIT 0x10 /* file handle opened O_NOINHERIT */ #define FAPPEND 0x20 /* file handle opened O_APPEND */ #define FDEV 0x40 /* file handle refers to device */ #define FTEXT 0x80 /* file handle is in text mode */ @@ -1636,6 +1568,9 @@ my_open_osfhandle(long osfhandle, int flags) if (flags & O_TEXT) fileflags |= FTEXT; + if (flags & O_NOINHERIT) + fileflags |= FNOINHERIT; + /* attempt to allocate a C Runtime file handle */ if ((fh = _alloc_osfhnd()) == -1) { errno = EMFILE; /* too many open files */ @@ -1687,7 +1622,8 @@ myfdopen (int fd, const char *mode) void myfdclose(FILE *fp) { - fclose(fp); + _free_osfhnd(fileno(fp)); + fclose(fp); } @@ -1829,6 +1765,10 @@ myselect (int nfds, fd_set *rd, fd_set *wr, fd_set *ex, if (!NtSocketsInitialized++) { StartSockets(); } + if (nfds == 0 && timeout) { + Sleep(timeout->tv_sec * 1000 + timeout->tv_usec / 1000); + return 0; + } if ((r = select (nfds, rd, wr, ex, timeout)) == SOCKET_ERROR) { errno = WSAGetLastError(); switch (errno) { @@ -2266,7 +2206,7 @@ gettimeofday(struct timeval *tv, struct timezone *tz) } char * -getcwd(buffer, size) +win32_getcwd(buffer, size) char *buffer; int size; { @@ -2281,7 +2221,7 @@ getcwd(buffer, size) return NULL; } - for (bp = buffer; *bp != '\0'; bp++) { + for (bp = buffer; *bp != '\0'; bp = CharNext(bp)) { if (*bp == '\\') { *bp = '/'; } diff --git a/win32/win32.h b/win32/win32.h index 04cb192c43..cbcf4e8117 100644 --- a/win32/win32.h +++ b/win32/win32.h @@ -87,7 +87,7 @@ #undef leave #if defined(__cplusplus) -} +extern "C++" { #endif #include @@ -103,7 +103,7 @@ #include #if defined(__cplusplus) -extern "C" { +} #endif #define UIDTYPE int @@ -387,6 +387,11 @@ extern char *mystrerror(int); #endif #define get_osfhandle myget_osfhandle +#ifdef getcwd +#undef getcwd +#endif +#define getcwd win32_getcwd + #ifdef getenv #undef getenv #endif -- cgit v1.2.3