diff options
author | Yukihiro Matsumoto <[email protected]> | 1997-10-02 17:59:18 +0900 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2019-08-17 22:09:32 +0900 |
commit | 10d21745c8c1c3c78678ea7e0b62c0a7433ccfce (patch) | |
tree | 4e40254178d66c343cae763029131d959518f795 /lib | |
parent | ce930d042913722f209bbd3209b6c90a3c71325f (diff) |
version 1.0-971002v1_0_971002
https://cache.ruby-lang.org/pub/ruby/1.0/ruby-1.0-971002.tar.gz
Thu Oct 2 17:59:18 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-971002
Wed Oct 1 14:01:49 1997 WATANABE Hirofumi <[email protected]>
* ext/marshal/marshal.c (w_byte): argument must be char.
Wed Oct 1 10:30:22 1997 Yukihiro Matsumoto <[email protected]>
* ext/marshal/marshal.c (marshal_dump): try to set binmode.
* ext/marshal/marshal.c (r_object): forgot to re-regist structs in
the object table.
* eval.c (ruby_options): call Init_ext() before any require()
calls by `-r'.
Tue Sep 30 14:51:07 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970930
Fri Sep 30 14:29:22 1997 WATANABE Hirofumi <[email protected]>
* ext/marshal/marshal.c (w_object): marshal dumped core.
Tue Sep 30 10:27:39 1997 Yukihiro Matsumoto <[email protected]>
* sample/test.rb: bignum test suits added.
Mon Sep 29 13:37:58 1997 Yukihiro Matsumoto <[email protected]>
* ruby.c (forbid_setid): forbid some options in suid mode.
Mon Sep 27 09:53:48 1997 EGUCHI Matsumoto <[email protected]>
* bignum.c: modified for speeding.
Fri Sep 26 18:27:59 1997 WATANABE Hirofumi <[email protected]>
* sample/from.rb: some extensions.
Mon Sep 29 13:15:56 1997 Yukihiro Matsumoto <[email protected]>
* parse.y (lhs): no more syntax error on `obj.CONSTANT = value'.
Fri Sep 26 14:41:46 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (ruby_run): deferred calling Init_ext() just before eval_node.
Fri Sep 26 13:27:24 1997 WATANABE Hirofumi <[email protected]>
* io.c (io_isatty): forgot to return TRUE value.
Fri Sep 25 11:10:58 1997 EGUCHI Osamu <[email protected]>
* eval.c: use _setjmp/_longjmp instead of setjmp/longjmp on some
platforms.
Wed Sep 24 17:43:13 1997 Yukihiro Matsumoto <[email protected]>
* string.c (Init_String): String#taint and String#taint? added.
Wed Sep 24 00:57:00 1997 Katsuyuki Okabe <[email protected]>
* X68000 patch.
Tue Sep 23 20:42:30 1997 EGUCHI Osamu <[email protected]>
* parse.y (node_newnode): SEGV on null node setup.
Mon Sep 22 11:22:46 1997 Yukihiro Matsumoto <[email protected]>
* ruby.c (ruby_prog_init): wrong safe condition check.
Sun Sep 21 14:46:02 1997 MAEDA shugo <[email protected]>
* error.c (exc_inspect): garbage added to classpath.
Fri Sep 19 11:49:23 1997 <[email protected]>
* version 1.0-970919
* parse.y (newtok): forgot to adjust buffer size when shrinking
the token buffer.
* enum.c (enum_find): rb_eval_cmd() does not return value.
* io.c (pipe_open): close fds on pipe exec. fcntl(fd, F_SETFD, 1)
no longer used.
Tue Sep 16 17:54:25 1997 Yukihiro Matsumoto <[email protected]>
* file.c (f_test): problem if wrong command specified.
* ruby.c (ruby_prog_init): close stdaux and stdprn for MSDOS.
* ruby.c (ruby_prog_init): should not add path from environment
variable, if ruby is running under seuid.
* process.c (init_ids): check suid check for setuid/seteuid etc.
Mon Sep 15 00:42:04 1997 WATANABE Hirofumi <[email protected]>
* regex.c (re_compile_pattern): \w{3} and \W{3} did not work.
Thu Sep 11 10:31:48 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970911
* ext/socket/socket.c (sock_new): no setbuf() for NT.
* io.c (rb_fopen,rb_fdopen): set close-on-exec for every fd.
Wed Sep 10 15:55:31 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970910
* ext/marshal/marshal.c (r_bytes0): extra big length check.
Tue Sep 9 16:27:14 1997 Yukihiro Matsumoto <[email protected]>
* io.c (pipe_fptr_atexit): clean up popen()'ed fptr.
* error.c (set_syserr): some system has error code that is bigger
than sys_nerr. grrr.
Tue Sep 9 16:27:14 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970909
* error.c (set_syserr): some system has error code that is bigger
than sys_nerr. grrr.
Wed Sep 3 18:11:00 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970903
* eval.c (f_load): expand path if fname begins with `~'.
Mon Sep 1 13:42:48 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_call): alias occured in the module body caused SEGV.
Fri Aug 29 11:10:21 1997 Yukihiro Matsumoto <[email protected]>
* parse.y (yylex): spaces can follow =begin/=end.
* variable.c (find_class_path): look for class_tbl also for
unnamed fundamental classes, such as Object, String, etc.
* variable.c (rb_name_class): can't name class before String class
is initilialized.
* inits.c (rb_call_inits): unrecognized dependency from GC to
Array.
* variable.c (find_class_path): could not find class if Object's
iv_tbl is NULL.
Thu Aug 28 13:12:05 1997 Yukihiro Matsumoto <[email protected]>
* parse.y (yylex): revised `=begin' skip code.
* eval.c (is_defined): separated from rb_eval().
Wed Aug 27 11:32:42 1997 Yukihiro Matsumoto <[email protected]>
* variable.c (fc_i): some classes/modules does not have iv_tbl.
* variable.c (find_class_path): avoid inifinite loop.
Tue Aug 26 13:43:47 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_eval): undef'ing non-existing method will raise
NameError exception.
* object.c (class_s_new): needed to create metaclass too.
* eval.c (error_print): no class name print for anonymous class.
* eval.c (rb_longjmp): proper exception raised if raise() called
without arguments, with $! or $@ set.
* object.c (Init_Object): superclass()'s method argument setting
was wrong again.
Mon Aug 25 11:53:11 1997 Yukihiro Matsumoto <[email protected]>
* sample/ruby-mode.el (ruby-parse-region): auto-indent now
supports "\\" in the strings.
* struct.c (struct_getmember): new API to get member value from C
language side.
Fri Aug 22 14:26:40 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (error_print): modified exception print format.
Thu Aug 21 16:10:58 1997 Yukihiro Matsumoto <[email protected]>
* sample/ruby-mode.el (ruby-calculate-indent): wrong indent level
calculated with keyword operators.
Thu Aug 21 11:55:41 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970821
Thu Aug 21 11:36:58 1997 WATANABE Hirofumi <[email protected]>
* parse.y (arg): ary[0] += 1 cause SEGV
Wed Aug 20 14:24:42 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970820
* eval.c (rb_call): infinite loop bug
Tue Aug 19 00:15:38 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970819
* eval.c (rb_call): did not raise ArgumentError if too many
arguments more than optional arguments (without rest arg).
* eval.c (rb_eval): did not work well for op_asgn2 (attribute
self assignment).
Mon Aug 18 09:25:56 1997 Yukihiro Matsumoto <[email protected]>
* object.c (inspect_i): did not display T_DATA instance variables.
* parse.y: provides more accurate line number information.
* eval.c (thread_value): include value's backtrace information in
the variable `$@'.
* eval.c (f_abort): print backtrace and exit.
Sat Aug 16 00:17:44 1997 Yukihiro Matsumoto <[email protected]>
* object.c (class_s_new): do not make subclass of singleton class.
Fri Aug 15 15:49:46 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (call_trace_func): block context switch in the trace
function.
* eval.c (rb_eval): clear method cache at class extention.
Fri Aug 15 19:40:43 1997 WATANABE Hirofumi <[email protected]>
* ext/socket/socket.c (Init_socket): small typo caused SEGV.
Tue Aug 12 16:02:18 1997 Yukihiro Matsumoto <[email protected]>
* variable.c: option variables: $-0, $-p(readonly), $-v,
$-I(load_path), $-a(readonly), $-K, $-d, $-F, $-i, $-l.
* parse.y (yylex): ignore rd (ruby document) in the code.
Mon Aug 11 12:37:58 1997 Yukihiro Matsumoto <[email protected]>
* re.c (Init_Regexp): $-K as alias to the $KCODE.
* io.c (Init_IO): new virtual variable $-i for the value of -i
option.
* enum.c (Init_Enumerable): include? as alias of member?
Fri Aug 8 11:16:50 1997 Yukihiro Matsumoto <[email protected]>
* io.c (io_foreach): now the record separator can be specified.
* io.c (io_s_readlines): new method to read in whole file (or
command output) from path.
* ext/socket/socket.c (Init_socket): recvfrom did not work.
* ext/socket/socket.c (sock_send): forgot to check nil for false
value.
Thu Aug 7 11:40:01 1997 Yukihiro Matsumoto <[email protected]>
* object.c (Init_Object): remove private_attr/public_attr.
Wed Aug 6 14:21:36 1997 Yukihiro Matsumoto <[email protected]>
* object.c (mod_attr): forgot to check nil for false value.
Mon Aug 4 11:50:28 1997 Yukihiro Matsumoto <[email protected]>
* variable.c (rb_class_path): scan class constants for anonymous
classes/modules to make up pathes.
Wed Jul 30 08:45:12 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_eval): stop to cache const value in nodes.
Sat Jul 26 03:17:22 1997 WATANABE Hirofumi <[email protected]>
* numeric.c (flo_to_s): wrong .0 at end.
Sat Jul 26 00:36:36 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (error_print): always print exception type in the
toplevel exception handler.
* string.c (str_hash): wrong hash value.
Thu Jul 24 11:05:51 1997 Yukihiro Matsumoto <[email protected]>
* string.c (uscore_get): proper error message for unset $_.
Wed Jul 23 09:56:55 1997 Yukihiro Matsumoto <[email protected]>
* object.c (obj_methods): returns list of method names of the
specified object.
* class.c (mod_instance_methods): returns list of method names of
the class instnace.
Fri Jul 11 22:38:55 1997 Yukihiro Matsumoto <[email protected]>
* object.c (class_superclass): returns class's superclass
itself. (1.1)
* object.c (obj_type): returns object's class itself. (1.1)
* class.c (mod_included_modules): list included modules.
* object.c (class_superclass): raises error for Object.
Thu Jul 3 09:54:02 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (SETUP_ARGS): save source position, remove nd_line().
* eval.c (rb_call): replace modulo by bit-masking.
* eval.c (POP_SCOPE): force recycle scope object to reduce gc rate.
* gc.c (obj_free): aboid calling run_final() when no finalizer is set.
* eval.c (PUSH_VARS): do not allocate the dynamic scope's end-mark
object.
Wed Jul 2 14:25:07 1997 KIMURA Koichi <[email protected]>
* Native mswin32 support.
Tue Jul 1 09:59:00 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970701
* parse.y (mrhs): allow rest-star(*) in right hand side.
Tue Jun 24 19:04:31 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970624
Sat Jun 20 22:22:51 1997 Michio "Karl" Jinbo <[email protected]>
* eval.c: freebsd 3.0 <sys/select.h> support.
Fri Jun 20 01:24:45 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970620
* gc.c: eliminate uninitilalized field of Hash, Array etc., to
avoid dumping core.
Thu Jun 19 01:29:44 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970619
* string.c (str_split_method): wrong limit.
Sat Jun 14 01:54:16 1997 Yukihiro Matsumoto <[email protected]>
* class.c (rb_singleton_class): no singleton for special
constants (now raises exception).
* eval.c (ruby_init): cbase in TOPLEVEL_BINDING need to be
initialized.
Sat Jun 14 01:01:16 1997 maeda shugo <[email protected]>
* array.c (sort_2): wrong comparison.
Sat Jun 14 00:53:44 1997 Yukihiro Matsumoto <[email protected]>
* hash.c (hash_foreach): safe iteration.
Fri Jun 13 14:04:56 1997 Michio "Karl" Jinbo <[email protected]>
* configure.in: -Bshareable option for netbsd.
Fri Jun 13 01:16:22 1997 WATANABE Hirofumi <[email protected]>
* io.c (pipe_open): call io_unbuffered() only for writable pipes.
Thu Jun 12 01:14:15 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970612
* ext/socket/socket.c (sock_new): use io_unbuffered().
* ext/marshal/marshal.c (w_long): compact long format, which
supports 64 bit architectures (unless longs are >32 bit size).
* ext/marshal/marshal.c: allows recursive data for marshaling.
* parse.y (rb_intern): raise exception for non-internable string.
* ext/marshal/marshal.c (marshal_load): allows direct loading from
strings.
* ext/marshal/marshal.c (marshal_dump): allows direct dump to strings.
* ext/marshal/marshal.c (marshal_dump): interface changed.
Wed Jun 11 18:26:00 1997 Yukihiro Matsumoto <[email protected]>
* gc.c (rb_newobj): remove needless memset().
Mon Jun 9 13:03:43 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_eval): reduce condition checks from while/until loop.
* eval.c (rb_eval): wrong jump point for `next'.
Fri Jun 6 11:47:39 1997 Yukihiro Matsumoto <[email protected]>
* ruby.c (ruby_set_argv): initialize dln_argv0 for dln_a_out.
* ext/socket/socket.c (open_unix): display path name for exceptions.
* ruby.c (proc_options): option -S did not work well.
Fri May 30 02:14:44 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970530
* eval.c (eval): set $! properly if exception raised in eval().
* io.c (io_write): now handles non T_FILE object.
* io.c (io_defset): $< can be anything which has `write' method.
Thu May 29 15:40:22 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (eval): $@ is always an array (not string).
* pack.c (pack_unpack): avoid corrupting memory for unexpected
input strings.
Wed May 28 12:46:13 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970528
* process.c (rb_waitpid): do not block other threads.
Tue May 27 12:02:31 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (ruby_init): split initialize and processing command line
options.
* ruby.c (ruby_options): ruby_init(0, 0, envp) dumps core.
Tue May 20 18:59:45 1997 Yukihiro Matsumoto <[email protected]>
* variable.c (rb_ivar_set): invalid instance variable access for
built-in object raises TypeError.
Fri May 16 17:32:21 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970516
* dir.c (push_globs): was freeing non heap pointer.
* gc.c: remove some duplicated prototypes.
* ext/kconv/kconv.c: fix prototypes.
Fri May 9 11:38:59 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970509
* gc.c (obj_free): avoid free(NULL).
* eval.c (rb_check_safe_str): argument missing for TypeError().
Thu May 8 01:14:28 1997 Yukihiro Matsumoto <[email protected]>
* file.c (file_s_dirname): need to return "." for path without
slashes.
Wed May 7 19:18:48 1997 Yukihiro Matsumoto <[email protected]>
* process.c (f_fork): child processe does not inherit parent's
itimer setting on linux. call setitimer() again in the child
process.
Sat May 3 02:49:43 1997 Yukihiro Matsumoto <[email protected]>
* ext/curses/curses.c: modified for portability and add to the
standard distribution.
Wed Apr 30 00:34:00 1997 Yukihiro Matsumoto <[email protected]>
* file.c (file_s_size): returns 0 for empty files (not FALSE).
Fri Apr 25 02:17:50 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970425
* eval.c (f_load): free unused name-table.
* eval.c (f_load): copy local variable name-table.
* gc.c (obj_free): avoid free(NULL).
* eval.c (rb_eval): forgot to make link from the scope object to
NODE_SCOPE. It may crash the interpreter.
Thu Apr 24 00:35:09 1997 Yukihiro Matsumoto <[email protected]>
* random.c (f_srand): save old seed anyway. srand() returns no
value on some systems.
* gc.c (obj_free): avoid double free of the local variable name
table.
* parse.y (top_local_setup): modify realloc to handle offset.
Tue Apr 22 12:58:26 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970422
Thu Apr 17 00:40:51 1997 Yukihiro Matsumoto <[email protected]>
* configure.in (rb_cv_bsdpgrp): proper check for BSD
setpgrp/setpgrp.
Wed Apr 16 16:14:02 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (proc_call): proc called in other thread must be orphan.
Tue Apr 15 10:46:31 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970415
* gc.c (obj_free): NODE_SCOPE marked from SCOPE object.
* gc.c (gc_mark): some nodes marked wrong.
* process.c (proc_getpgrp): wrong argument
Fri Apr 14 18:32:42 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970414
Fri Apr 12 01:20:12 1997 Yukihiro Matsumoto <[email protected]>
* ruby.h: String pointer changed to unsigned char.
Fri Apr 11 10:27:29 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970411
* Makefile.in: create libruby.a before linking ruby.
* string.c (str_strip_bang): >0x80 characters for isspace().
* eval.c (proc_call): set safe-level temporally
* eval.c (proc_s_new): save safe-level in the proc context.
* eval.c (rb_eval): no class/module extention in safe mode.
Thu Apr 10 02:10:41 1997 Yukihiro Matsumoto <[email protected]>
* gc.c (gc_mark): remove some pointer checks for speeding up.
* ruby.c (ruby_options): set $0 temporally for -r option.
* eval.c: built-in security feature.
* gc.c (gc_sweep): do not free nodes during compile.
* parse.y (yycompile): set flag when compiling.
Wed Apr 9 10:19:02 1997 Yukihiro Matsumoto <[email protected]>
* ruby.c: forgot to include <ctype.h> for isspace().
* file.c: provide S_ISREG for some platforms.
* io.c (Init_IO): added some $< operations.
* lib/ping.rb: check host upness using TCP echo.
Tue Apr 8 00:10:15 1997 Yukihiro Matsumoto <[email protected]>
* io.c (arg_read): bug with 0 length input.
Mon Apr 7 11:36:16 1997 Yukihiro Matsumoto <[email protected]>
* ext/fcntl/fcntl.c: module for fcntl constants.
* eval.c (rb_alias): bug when original was an alias.
* parse.y (primary): syntax to access singleton class.
* eval.c (mod_public_method): method's to specify visibitily of
the class methods. make_method_{public,private} removed.
Fri Apr 4 21:43:57 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970404
* gc.c (obj_free): finalizer added for experiment.
Thu Apr 3 02:12:31 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_schedule): make Fatal rise on main_thread on
deadlocks.
* eval.c (thread_join): raise ThreadError instead of Fatal, in
case of deadlock.
* regex.c (re_compile_fastmap): uninitialized local variable.
* parse.y (parse_regx): new option //[nes] to specify character
code for regexp literals. Last specified code option is valid.
* re.c (reg_s_new): addtional 3rd argument to specify compiled
regexp's character code.
* re.c (reg_new_1): regexp character code can be specified for
each regexp object.
Wed Apr 2 14:51:06 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_create): handle uncaught throw.
* eval.c (thread_create): halt on some deadlock conditions.
* regex.c (is_in_list): wrong result for non-mbc higher-byte
characters.
* regex.c (re_match): wrong skip for multi-byte characters.
* regex.c (re_compile_fastmap): wrong fastmap in non-mbc mode.
* hash.c (Init_Hash): hash compatible features added to ENV.
Tue Apr 1 15:24:06 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (obj_extend): remove Object#extend as an iterator which
is in experimental state, since it unveils internal singleton
classes.
Mon Mar 31 14:29:39 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970331
Sun Mar 30 19:40:57 1997 WATANABE Hirofumi <[email protected]>
* parse.y (terms): avoided win32 gcc's optimization bug.
Sat Mar 29 11:21:58 1997 Yukihiro Matsumoto <[email protected]>
* struct.c (make_struct): St[val,..] creates new structure.
Fri Mar 28 11:24:51 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (obj_make_private): new method make_method_{public,private}
to change visibility of singleton methods.
* regex.c (re_compile_pattern): enables numeric literal >= 0x80 in
the character class.
* regex.c (re_compile_pattern): enabled numeric literal >= 0x80,
in multibyte mode.
* regex.c (re_compile_fastmap): modified exantn and charset(_not)
to set fastmap for higher bytes properly.
* regex.c (is_in_list): now matches numeric literals.
Thu Mar 27 13:34:20 1997 WATANABE Hirofumi <[email protected]>
* pack.c (pack_unpack): extra null byte after unpacked string.
Wed Mar 26 15:20:34 1997 Yukihiro Matsumoto <[email protected]>
* regex.c (re_compile_pattern): register numbers must be fit in a
byte (0 <= regnum <= 0xff).
* regex.c (re_compile_fastmap): forgot to set mbchar map for
charset_not if RE_MBCTYPE is on.
* regex.c (re_compile_pattern): set list bits for multi-byte
characters for \W, \S, \D in range expression.
* object.c (obj_is_kind_of): defined that nil itself is kind of
nil. TRUE is kind of TRUE, FALSE is kind of FALSE likewise.
This change makes `obj.kind_of?(eval(obj.type))' always true.
Tue Mar 25 14:08:43 1997 Yukihiro Matsumoto <[email protected]>
* lib/English.rb: provides nicer English alias for the variables.
* parse.y (expr): alias $var1 $var2 makes alias of the global
variable.
Mon Mar 24 18:23:20 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970324
Thu Mar 20 22:04:59 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (mod_modfunc): forget to clear method cache.
Wed Mar 19 17:06:55 1997 Yukihiro Matsumoto <[email protected]>
* parse.y (program): set methods' default private/public status
correctly under eval().
* eval.c (eval): set the_class correctly while evaluating string.
Tue Mar 18 12:23:53 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (eval): yield can be called from eval().
* version 1.0-970318
* parse.y (program): regexp in condition expression should do
matching operation with $_.
* re.c (reg_regsub): wrong substitution.
Fri Mar 14 14:36:28 1997 Yukihiro Matsumoto <[email protected]>
* hash.c (hash_invert): returns value to key mapping of the
associative array.
* ext/socket/extconf.rb: set environment variable SOCKS_SERVER to
compile with libsocks.a.
* ext/socket/socket.c (socks_s_open): SOCKSsocket class to access
internet via SOCKS library.
* sprintf.c (f_sprintf): unsigned formats display leading double
dots for imaginary sequence of signed bit to the left.
* sprintf.c (f_sprintf): correct width and precision formatting
for big integers.
* parse.y (yylex): enables negative hex/octal numbers and `_' in
non-decimal numbers.
* sprintf.c (f_sprintf): %u added for unsigned decimal format.
Thu Mar 13 10:24:27 1997 Yukihiro Matsumoto <[email protected]>
* sprintf.c (f_sprintf): wrong output for bignums.
* array.c (ary_reverse_each): iterates in reverse order.
* pack.c (pack_unpack): L unpacked signed long.
* io.c (f_backquote): now returns an empty string for no output.
Wed Mar 12 10:20:30 1997 Yukihiro Matsumoto <[email protected]>
* ext/socks/socks.c: socket module with socks library.
Mon Mar 10 20:44:22 1997 Yukihiro Matsumoto <[email protected]>
* re.c (reg_regsub): \& for substitution. \`, \', and \+ are
avaiable also.
Thu Mar 6 01:47:03 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970306
* sample/rubydb.el (gud): ruby debugger emacs interface
* lib/debug.rb: ruby debugger
* parse.y (exprs): more accurate line number display.
Wed Mar 5 21:31:46 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970305
Tue Mar 4 12:28:32 1997 Yukihiro Matsumoto <[email protected]>
* ruby.c (proc_options): search through RUBYPATH and PATH for
option -S.
Mon Mar 3 22:44:55 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_status): returns nil for exception terminated
threads.
* eval.c (thread_value): re-raise exceptions.
Sat Mar 1 00:59:47 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_eval): restore $! value after rescue clause, to
re-raise exceptions correctly.
Fri Feb 28 16:43:38 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970228
Thu Feb 27 11:23:41 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (rb_yield_0): redo raises exception
* eval.c (thread_schedule): bug in interrupt handling by rescue.
Wed Feb 26 00:55:36 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (eval): forgot to restore dynamic local variable
bindings.
Tue Feb 25 11:22:08 1997 Yukihiro Matsumoto <[email protected]>
* ext/aix_ld.rb: AIX dynamic load support (not tested).
* eval.c (rb_eval): wrong return value for defined? super.
* error.c (exception): more error check.
* re.c (reg_regsub): wrong substitution when sub expanded to null
string.
Fri Feb 21 13:01:47 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970221
* eval.c (f_require): volatile added. register variable was
recycled, so that GC did not mark that variable.
* object.c (Init_Object): forget to mark main object (was mostly
ok, but made trouble with early GC.)
Thu Feb 20 11:50:50 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970220
Thu Feb 20 11:25:50 1997 Yasuo OHBA <[email protected]>
* lib/date.rb: update
Thu Feb 20 08:25:57 1997 Yukihiro Matsumoto <[email protected]>
* parse.y (yylex): forgot tokfix() before rb_intern().
* lib/tk.rb (TkVariable): give up using trace_var.
Wed Feb 19 00:24:35 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970219
* pack.c (pack_pack): packed by null for A specifier. must be
space filled.
* pack.c (pack_unpack): bug in skipping spaces
* gc.c (xmalloc): garbage collect for every 4 Meg. allocation.
* string.c (str_split_method): limit worked wrong way.
* io.c (io_gets_method): misunderstand 0xff in binary files when
$/ == nil.
* re.c (reg_regsub): re-implement.
* ext/socket/socket.c (thread_connect): remove O_NONBLOCK, which
is not defined on some platform like NeXT.
Mon Feb 17 13:08:30 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970217
* object.c (mod_eqq): === extended for subclass check (to use case
as typecase).
Sat Feb 15 02:07:22 1997 Yukihiro Matsumoto <[email protected]>
* regex.c (re_compile_pattern): wrong match backref at end of pattern.
* io.c (arg_read): now works beyond end of file.
Thu Feb 13 16:21:24 1997 Yukihiro Matsumoto <[email protected]>
* parse.y (expr): return/yield now accept normal argument format.
* parse.y (yylex): a star in `yield *x' must not be multiplication
operator.
Wed Feb 12 15:06:44 1997 Yukihiro Matsumoto <[email protected]>
* time.c (time_plus): bug in simple addition.
* eval.c (thread_raise): raise exceptions from outside.
* eval.c (Init_Thread): Thread#alive? -- alias for Thread#status.
Mon Feb 10 00:38:55 1997 Yukihiro Matsumoto <[email protected]>
* ruby.h (Data_Make_Struct): rename macros.
Sun Feb 8 11:48:13 1997 Yukihiro Matsumoto <[email protected]>
* io.c (f_syscall): argument offset was wrong.
Fri Feb 7 18:01:17 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970207
* eval.c: add volatiles to avoid variable crobbering by longjmp().
* eval.c (f_raise): 1st argument can be the GlobalExit object now.
* array.c (ary_unshift): no longer accept more than 2 args.
* eval.c (f_raise): bug if 2nd argument is the exception.
Tue Feb 4 00:37:29 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970204
* eval.c (eval): check compile errors by nerrs.
* eval.c (rb_eval): check syntax error by nerrs, not by the return
value, which may be NULL.
* eval.c (compile): Do not clear errinfo.
Mon Feb 3 10:13:06 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (obj_extend): move real inclusion to Module#extend_object
to allow redfinition.
* object.c (Init_Object): Kernel class is now Module. Object class
became the true root class.
* object.c (obj_inspect): remove useless buffer.
* hash.c (any_cmp): disable interrupts and context switching.
* st.c: remove ALLOW_INTS to disable interrupt during operations.
Fri Jan 31 22:10:08 1997 Yukihiro Matsumoto <[email protected]>
* hash.c (hash_rehash): re-register all key-value.
Thu Jan 30 02:14:49 1997 Yukihiro Matsumoto <[email protected]>
* io.c (io_reopen): re-implement according to clone() way.
* io.c (io_clone): copy IO object.
* struct.c (struct_eql): compare elements by eql?.
* io.c (io_mode_flags): detect "rb", "wb" etc.
* io.h (FMODE_BINMODE): added.
* ext/socket/socket.c (Init_socket): undef BasicSocket.new
* file.c (Init_File): File.new(path[,mode])
* io.c (Init_IO): IO.new(fd[,mode])
* eval.c (rb_method_boundp): forgot to enable priv argument.
* object.c (Init_Object): remove `=~' from Kernel class.
* ext/socket/socket.c (open_inet): initialize sockaddr before
calling bind(2).
* sample/ruby-mode.el (ruby-calculate-indent): skip comment lines
Wed Jan 29 18:43:22 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (Init_Thread): DEFER_INTS during initializing threads.
* hash.c (Init_Hash): Hash#eql? checks for object identity.
* eval.c (thread_set_critical): wrong value assigned.
Mon Jan 27 16:10:51 1997 Yukihiro Matsumoto <[email protected]>
* io.c (io_print): remove print_on().
* eval.c (f_missing): proper error message for undefined method
without argument
Sat Jan 25 23:32:32 1997 Yukihiro Matsumoto <[email protected]>
* string.c (str_sub_s): false alert - sub() does not modify string.
* array.c (ary_times): negative multiplication detected
* string.c (str_times): negative multiplication detected
Fri Jan 24 10:51:39 1997 Yukihiro Matsumoto <[email protected]>
* time.c (time_arg): month -> 0 == "jan" == "1" == "01", little bit
confusing but wanted to conform japanese style.
* version 1.0-970124
Fri Jan 24 09:52:49 1997 WATANABE Hirofumi <[email protected]>
* util.c (_fixpath): supports SJIS filenames on DJGPP.
Thu Jan 23 16:52:06 1997 Yukihiro Matsumoto <[email protected]>
* README.EXT: update. partially translated into English.
* ext/extmk.rb.in: inherit $LDFLAGS to the final link.
* ext/socket/socket.c (Init_socket): add various constants.
Mon Jan 23 11:40:59 1997 WATANABE Hirofumi <[email protected]>
* eval.c (Init_Thread): allocate main_thread first to avoid crash.
Thu Jan 23 02:09:26 1997 Yukihiro Matsumoto <[email protected]>
* gc.c (ObjectSpace): API modified. each_object method will do all
the iteration.
* eval.c (proc_call): wrong return from nested lambda.
* ext/GD/GD.c: debugged.
Wed Jan 22 16:12:25 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970122
* gc.c (gc_mark): forgot to mark match->str.
* ext/GD/GD.c: GD interface module.
* eval.c (PUSH_BLOCK): wrong value pushed as the block level.
Mon Jan 20 14:01:31 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_run): no context switch in the critical section.
Mon Jan 20 09:40:59 1997 WATANABE Hirofumi <[email protected]>
* utils.c: supports 8+3 filenames
Sat Jan 18 01:23:03 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970118
* regex.c (PATFETCH): need cast to unsigned char.
* io.c (io_ctl): bug in case when arg is not a string.
* lib/tk.rb: forgot that Kernel#type returns the class name now.
* regex.c (re_search): "abc\n" =~ "^$" should not match.
Fri Jan 17 12:31:37 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970117
* ruby.c (ruby_options): constant PLATFORM, which is in the {cpu}-{os}
form, defined.
* configure.in: platform infomation embedded in the interpreter.
* regex.c (re_search): /^$/ did not match to "" by wrong exit condition.
* lib/thread.rb: re-write Mutex/Queue based on Thread.critical.
* eval.c (thread_set_critical): remove Thread.exclusive, add
Thread.critical = TRUE/FALSE instead.
* re.c (reg_search): re-compile pattern if needed
* regex.c (PATFETCH): do translate at compile time
Thu Jan 16 00:49:10 1997 Yukihiro Matsumoto <[email protected]>
* gc.c (gc_mark_frame): forgot to mark frame->cbase.
* regex.c (re_compile_pattern): /a$|b)/ causes error.
* regex.c (re_compile_pattern): /(^|b)/ causes error.
* version 1.0-970116
* re.c (Init_Regexp): set RE_CONTEXTUAL_INVALID_OPS flag.
Tue Jan 14 02:09:06 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (proc_call): Proc#callをイテレータとして呼んだ時に対応
* configure.in: nextstep対応?
* eval.c (rb_eval): a[b]=cで無駄な配列を割り当てない
* eval.c (f_send): イテレータとして呼ばれたらイテレータとしてメソッ
ドを呼ぶ.
* string.c (str_new4): match共有用の生成関数
* re.c (reg_search): matchの実体(文字列)をマッチを行った文字列と
copy-on-writeで共有
* string.c (str_hash): toupperをかける条件が違っていた
* array.c (sort_2): FixnumとStringを特別扱いして高速化
Mon Jan 13 11:03:53 1997 Yukihiro Matsumoto <[email protected]>
* eval.c (thread_create): threadが生成されるまで割込みを設定しない
* eval.c (Init_Thread): 割込みタイミングを100msecに
Sat Jan 11 00:17:05 1997 Yukihiro Matsumoto <[email protected]>
* regex.c (re_search): マッチに失敗する場合があった(本当に直ったか?)
* io.c (io_ioctl,io_fcntl): 第2引数を省略可能に
* io.c (io_ioctl,io_fcntl): 戻り値がIOだった.整数(システムコール
の戻り値)を返すようにした.
* io.c (io_ctl): 引数が整数の時に対応
* io.c (io_fcntl): file.cから移動
Fri Jan 10 17:01:47 1997 Yukihiro Matsumoto <[email protected]>
* version 1.0-970110
* ext/socket/socket.c (thread_connect): open(connect(2))で他の
threadをブロックしないように
* eval.c (thread_create): exitでないときにexitだと思い込む
Mon Jan 6 17:42:22 1997 Yukihiro Matsumoto <[email protected]>
* string.c (str_sub_s): 文字列長より長いoffsetの検出
* regex.c (re_search): 空にマッチするパターン後の$で失敗
Thu Jan 2 16:36:23 1997 Yukihiro Matsumoto <[email protected]>
* file.c (file_reopen): Fileのreopen(pathまたはIOで指定).
* io.c (io_reopen): IOのreopen(IOで指定) -- change classつき
Wed Jan 1 11:09:01 1997 Yukihiro Matsumoto <[email protected]>
* io.c (f_select): timeoutでnilを返す
Fri Dec 27 13:06:44 1996 Yukihiro Matsumoto <[email protected]>
* file.c (file_s_open): サブクラスではそのクラスのインスタンスを返
すように.
Fri Dec 27 08:58:27 1996 [email protected]
* numeric.c (flo_to_s): index()を使わない.strstr()に.
Thu Dec 26 01:34:17 1996 Yukihiro Matsumoto <[email protected]>
* lib/tk.rb: placeが使えるように
* pack.c (endian): マクロDYNAMIC_ENDIANを指定すると実行時にendian
を判定するように.
* eval.c (thread_alloc): 初期化忘れのメンバがあった.
Co-authored-by: EGUCHI Matsumoto <[email protected]>
Co-authored-by: EGUCHI Osamu <[email protected]>
Co-authored-by: KIMURA Koichi <[email protected]>
Co-authored-by: Katsuyuki Okabe <[email protected]>
Co-authored-by: MAEDA shugo <[email protected]>
Co-authored-by: Michio "Karl" Jinbo <[email protected]>
Co-authored-by: WATANABE Hirofumi <[email protected]>
Co-authored-by: Yasuo OHBA <[email protected]>
Co-authored-by: maeda shugo <[email protected]>
Co-authored-by: ono <[email protected]>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/English.rb | 28 | ||||
-rw-r--r-- | lib/base64.rb | 47 | ||||
-rw-r--r-- | lib/date.rb | 221 | ||||
-rw-r--r-- | lib/debug.rb | 262 | ||||
-rw-r--r-- | lib/e2mmap.rb | 94 | ||||
-rw-r--r-- | lib/e2mmap1_0.rb | 71 | ||||
-rw-r--r-- | lib/finalize.rb | 205 | ||||
-rw-r--r-- | lib/ftplib.rb | 617 | ||||
-rw-r--r-- | lib/jcode.rb | 35 | ||||
-rw-r--r-- | lib/mathn.rb | 3 | ||||
-rw-r--r-- | lib/matrix.rb | 777 | ||||
-rw-r--r-- | lib/mutex_m.rb | 183 | ||||
-rw-r--r-- | lib/observer.rb | 2 | ||||
-rw-r--r-- | lib/parsedate.rb | 12 | ||||
-rw-r--r-- | lib/ping.rb | 55 | ||||
-rw-r--r-- | lib/safe.rb | 78 | ||||
-rw-r--r-- | lib/sync.rb | 376 | ||||
-rw-r--r-- | lib/thread.rb | 117 | ||||
-rw-r--r-- | lib/thwait.rb | 128 | ||||
-rw-r--r-- | lib/tk.rb | 128 | ||||
-rw-r--r-- | lib/tkcanvas.rb | 21 | ||||
-rw-r--r-- | lib/tkclass.rb | 2 | ||||
-rw-r--r-- | lib/tkcore.rb | 40 | ||||
-rw-r--r-- | lib/tkentry.rb | 15 | ||||
-rw-r--r-- | lib/tkscrollbox.rb | 4 | ||||
-rw-r--r-- | lib/tktext.rb | 46 | ||||
-rw-r--r-- | lib/tkthcore.rb | 33 | ||||
-rw-r--r-- | lib/tracer.rb | 75 |
28 files changed, 3376 insertions, 299 deletions
diff --git a/lib/English.rb b/lib/English.rb new file mode 100644 index 0000000000..c7e13bebe6 --- /dev/null +++ b/lib/English.rb @@ -0,0 +1,28 @@ + +alias $ERROR_INFO $! +alias $ERROR_POSITION $@ +alias $LOADED_FEATURES $" +alias $FS $; +alias $FIELD_SEPARATOR $; +alias $OFS $, +alias $OUTPUT_FIELD_SEPARATOR $, +alias $RS $/ +alias $INPUT_RECORD_SEPARATOR $/ +alias $ORS $\ +alias $OUPUT_RECORD_SEPARATOR $\ +alias $INPUT_LINE_NUMBER $. +alias $NR $. +alias $LAST_READ_LINE $_ +alias $DEFAULT_OUTPUT $> +alias $DEFAULT_INPUT $< +alias $PID $$ +alias $PROCESS_ID $$ +alias $CHILD_STATUS $? +alias $LAST_MATCH_INFO $~ +alias $IGNORECASE $= +alias $PROGRAM_NAME $0 +alias $ARGV $* +alias $MATCH $& +alias $PREMATCH $` +alias $POSTMATCH $' +alias $LAST_PAREN_MATCH $+ diff --git a/lib/base64.rb b/lib/base64.rb index 9bb6487bee..96208a634d 100644 --- a/lib/base64.rb +++ b/lib/base64.rb @@ -1,29 +1,11 @@ def decode64(str) - e = -1; - c = "," - string='' + string = '' for line in str.split("\n") - line.sub!(/=+$/, '') - line.tr! 'A-Za-z0-9+/', "\000-\377" - line.each_byte { |ch| - n +=1 - e +=1 - if e==0 - c = ch << 2 - elsif e==1 - c |= ch >>4 - string += [c].pack('c') - c = ch << 4 - elsif e == 2 - c |= ch >> 2 - string += [c].pack('c'); - c = ch << 6 - elsif e==3 - c |= ch - string += [c].pack('c') - e = -1 - end - } + line.delete!('^A-Za-z0-9+/') # remove non-base64 chars + line.tr!('A-Za-z0-9+/', ' -_') # convert to uuencoded format + len = ["#{32 + line.length * 3 / 4}"].pack("c") + # compute length byte + string += "#{len}#{line}".unpack("u") # uudecode and concatenate end return string end @@ -53,3 +35,20 @@ def decode_b(str) str.gsub!(/\0/, '') j2e(str) end + +def encode64(bin) + encode = "" + pad = 0 + [bin].pack("u").each do |uu| + len = (2 + (uu[0] - 32)* 4) / 3 + encode << uu[1, len].tr('` -_', 'AA-Za-z0-9+/') + pad += uu.length - 2 - len + end + encode + "=" * (pad % 3) +end + +def b64encode(bin, len = 60) + encode64(bin).scan(/.{1,#{len}}/o) do + print $&, "\n" + end +end diff --git a/lib/date.rb b/lib/date.rb new file mode 100644 index 0000000000..260f6e79ec --- /dev/null +++ b/lib/date.rb @@ -0,0 +1,221 @@ +# +# Date.rb - +# $Release Version: $ +# $Revision: 1.2 $ +# $Date: 1997/02/14 11:05:29 $ +# by Yasuo OHBA(SHL Japan Inc. Technology Dept.) +# +# -- +# +# September 1752 +# S M Tu W Th F S +# 1 2 14 15 16 +# 17 18 19 20 21 22 23 +# 24 25 26 27 28 29 30 +# + +class Date + include Comparable + + def initialize(y = 1, m = 1, d = 1) + if y.kind_of?(String) && y.size == 8 + @year = y[0,4].to_i + @month = y[4,2].to_i + @day = y[6,2].to_i + else + if m.kind_of?(String) + ml = {"jan"=>1, "feb"=>2, "mar"=>3, "apr"=>4, "may"=>5, "jun"=>6, "jul"=>7, "aug"=>8, "sep"=>9, "oct"=>10, "nov"=>11, "dec"=>12} + m = ml[m.downcase] + if m.nil? + raise ArgumentError, "Wrong argument. (month)" + end + end + @year = y.to_i + @month = m.to_i + @day = d.to_i + end + _check_date + return self + end + + def year + return @year + end + + def month + return @month + end + + def day + return @day + end + + def period + return Date.period!(@year, @month, @day) + end + + def day_of_week + dl = Date.daylist(@year) + d = Date.jan1!(@year) + for m in 1..(@month - 1) + d += dl[m] + end + d += @day - 1 + if @year == 1752 && @month == 9 && @day >= 14 + d -= (14 - 3) + end + return (d % 7) + end + + Weektag = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"] + def name_of_week + return Weektag[self.day_of_week] + end + + def +(o) + if o.kind_of?(Integer) + d = self.period + o + elsif o.kind_of?(Date) + d = self.period + o.period + else + raise TypeError, "Illegal type. (Integer or Date)" + end + return Date.at(d) + end + + def -(o) + if o.kind_of?(Integer) + d = self.period - o + elsif o.kind_of?(Date) + d = self.period - o.period + else + raise TypeError, "Illegal type. (Integer or Date)" + end + if d <= 0 + raise ArgumentError, "argument out of range. (self > other)" + end + return Date.at(d) + end + + def <=>(o) + if o.kind_of?(Integer) + d = o + elsif o.kind_of?(Date) + d = o.period + else + raise TypeError, "Illegal type. (Integer or Date)" + end + return self.period <=> d + end + + def eql?(o) + self == o + end + + def hash + return @year ^ @month ^ @day + end + + def leapyear? + if Date.leapyear(@year) == 1 + return FALSE + else + return TRUE + end + end + + def _check_date + m = Date.daylist(@year) + if @month < 1 || @month > 12 + raise ArgumentError, "argument(month) out of range." + return nil + end + if @year == 1752 && @month == 9 + if @day >= 3 && @day <= 13 + raise ArgumentError, "argument(1752/09/3-13) out of range." + return nil + end + d = 30 + else + d = m[@month] + end + if @day < 1 || @day > d + raise ArgumentError, "argument(day) out of range." + return nil + end + return self + end + + private :_check_date +end + +def Date.at(d) + mm = 1 + yy = (d / 366.0).to_i + if yy != 0 + dd = d - (Date.period!(yy, 1, 1) - 1) + else + dd = d + yy = 1 + end + dl = Date.daylist(yy) + while dd > dl[mm] + if dd > dl[0] + dd -= dl[0] + yy += 1 + dl = Date.daylist(yy) + else + dd -= dl[mm] + mm += 1 + end + end + if yy == 1752 && mm == 9 && dd >= 3 && dd <= 19 + dd += (14 - 3) # 1752/09/03-19 -> 1752/09/14-30 + end + + return Date.new(yy, mm, dd) +end + +def Date.period!(y, m, d) + p = d + dl = Date.daylist(y) + for mm in 1..(m - 1) + p += dl[mm] + end + p += (y - 1) * 365 + ((y - 1) / 4.0).to_i + if (y - 1) > 1752 + p -= ((y - 1 - 1752) / 100.0).to_i + p += ((y - 1 - 1752) / 400.0).to_i + p -= (14 - 3) + elsif y == 1752 && m == 9 && d >= 14 && d <= 30 + p -= (14 - 3) + end + return p +end + +def Date.leapyear(yy) + return ((Date.jan1!(yy + 1) + 7 - Date.jan1!(yy)) % 7) +end + +def Date.daylist(yy) + case (Date.leapyear(yy)) + when 1 # non-leapyear + return [365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] + when 2 # leapyear + return [366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] + else # 1752 + return [355, 31, 29, 31, 30, 31, 30, 31, 31, 19, 31, 30, 31] + end +end + +def Date.jan1!(y) + d = 4 + y + (y + 3) / 4 + if y > 1800 + d -= (y - 1701) / 100 + d += (y - 1601) / 400 + end + if y > 1752 + d += 3 + end + return (d % 7) +end diff --git a/lib/debug.rb b/lib/debug.rb new file mode 100644 index 0000000000..432c7b4d19 --- /dev/null +++ b/lib/debug.rb @@ -0,0 +1,262 @@ + +class DEBUGGER__ + trap("INT") { DEBUGGER__::CONTEXT.interrupt } + $DEBUG = TRUE + def initialize + @break_points = [] + @stop_next = 1 + @frames = [nil] + @frame_pos = nil + @last_file = nil + @scripts = {} + end + + def interrupt + @stop_next = 1 + end + + def debug_eval(str, binding) + begin + val = eval(str, binding) + val + rescue + at = caller(0) + printf "%s:%s\n", at.shift, $! + for i in at + break if i =~ /`debug_(eval|command)'$/ #` + printf "\tfrom %s\n", i + end + end + end + + def debug_command(file, line, id, binding) + if (ENV['EMACS'] == 't') + printf "\032\032%s:%d:\n", file, line + else + printf "%s:%d:%s", file, line, line_at(file, line) + end + @frames[-1] = binding + STDOUT.print "(rdb:-) " + STDOUT.flush + while input = STDIN.gets + input.chop! + case input + when /^b(reak)?\s+(([^:\n]+:)?.+)/ + pos = $2 + if pos.index ":" + file, pos = pos.split(":") + end + file = File.basename(file) + if pos =~ /^\d+$/ + pname = pos + pos = Integer(pos) + else + pname = pos = pos.intern.id2name + end + printf "Set breakpoint %d at %s:%s\n", @break_points.size, file, pname + @break_points.push [file, pos] + when /^b(reak)?$/, /^info b(reak)?$/ + n = 0 + for f, p in @break_points + printf "%d %s:%s\n", n, f, p + n += 1 + end + when /^del(ete)?(\s+(\d+))?$/ + pos = $3 + unless pos + STDOUT.print "clear all breakpoints? (y/n) " + STDOUT.flush + input = STDIN.gets.chop! + if input == "y" + for n in @break_points.indexes + @break_points[n] = nil + end + end + else + pos = Integer(pos) + if @break_points[pos] + bp = @break_points[pos] + printf "Clear breakpoint %d at %s:%s\n", pos, bp[0], bp[1] + @break_points[pos] = nil + else + printf "Breakpoint %d is not defined\n", pos + end + end + when /^c(ont)?$/ + return + when /^s(tep)?\s*(\d+)?$/ + if $1 + lev = Integer($1) + else + lev = 1 + end + @stop_next = lev + return + when /^n(ext)?\s*(\d+)?$/ + if $1 + lev = Integer($1) + else + lev = 1 + end + @stop_next = lev + @no_step = @frames.size + return + when /^up\s*(\d+)?$/ + if $1 + lev = Integer($1) + else + lev = 1 + end + unless @frame_pos + @frame_pos = @frames.size - 1 + end + @frame_pos -= lev + if @frame_pos < 0 + STDOUT.print "at toplevel\n" + @frame_pos = 0 + else + binding = @frames[@frame_pos] + end + when /^down\s*(\d+)??$/ + if $1 + lev = Integer($1) + else + lev = 1 + end + if lev >= @frames.size or @frame_pos and @frame_pos+lev >= @frames.size + STDOUT.print "at stack bottom\n" + @frame_pos = nil + else + @frame_pos += lev + binding = @frames[@frame_pos] + end + when /^fin(ish)?$/ + @finish_pos = @frames.size + return + when /^q(uit)?$/ + STDOUT.print "really quit? (y/n) " + STDOUT.flush + input = STDIN.gets.chop! + exit if input == "y" + when /^where$/ + at = caller(4) + for i in at + printf " %s\n", i + end + when /^l(ist)?(\s+(.*))?$/ + if $3 + b, e = $3.split(/[-,]/) + b = Integer(b)-1 + if e + e = Integer(e)-1 + else + e = b + 10 + end + end + unless b + b = line - 1 + e = line + 9 + end + p [b,e] + line_at(file, line) + if lines = @scripts[file] and lines != TRUE + n = b+1 + for l in lines[b..e] + printf "%4d %s", n, l + n += 1 + end + else + printf "no sourcefile available for %s\n", file + end + when /^p\s+/ + p debug_eval($', binding) + else + v = debug_eval(input, binding) + p v unless v == nil + end + STDOUT.print "(rdb:-) " + STDOUT.flush + end + end + + def line_at(file, line) + lines = @scripts[file] + if lines + return "\n" if lines == TRUE + line = lines[line-1] + return "\n" unless line + return line + end + begin + f = open(file) + lines = @scripts[file] = f.readlines + rescue + @scripts[file] = TRUE + return "\n" + end + line = lines[line-1] + return "\n" unless line + return line + end + + def debug_funcname(id) + if id == 0 + "toplevel" + else + id.id2name + end + end + + def check_break_points(file, pos, binding, id) + file = File.basename(file) + if @break_points.include? [file, pos] + index = @break_points.index([file, pos]) + printf "Breakpoint %d, %s at %s:%s\n", + index, debug_funcname(id), file, pos + return TRUE + end + return FALSE + end + + def trace_func(event, file, line, id, binding) + if event == 'line' + if @no_step == nil or @no_step >= @frames.size + @stop_next -= 1 + end + if @stop_next == 0 + if [file, line] == @last + @stop_next = 1 + else + @no_step = nil + debug_command(file, line, id, binding) + @last = [file, line] + end + end + if check_break_points(file, line, binding, id) + debug_command(file, line, id, binding) + end + end + if event == 'call' + @frames.push binding + if check_break_points(file, id.id2name, binding, id) + debug_command(file, line, id, binding) + end + end + if event == 'class' + @frames.push binding + end + if event == 'return' or event == 'end' + if @finish_pos == @frames.size + @stop_next = 1 + end + @frames.pop + end + @last_file = file + end + + CONTEXT = new +end + +set_trace_func proc{|event, file, line, id, binding| + DEBUGGER__::CONTEXT.trace_func event, file, line, id, binding +} diff --git a/lib/e2mmap.rb b/lib/e2mmap.rb new file mode 100644 index 0000000000..d10657bbad --- /dev/null +++ b/lib/e2mmap.rb @@ -0,0 +1,94 @@ +# +# e2mmap.rb - for ruby 1.1 +# $Release Version: 1.1$ +# $Revision: 1.4 $ +# $Date: 1997/08/18 07:12:12 $ +# by Keiju ISHITSUKA +# +# -- +# +# +if VERSION < "1.1" + require "e2mmap1_0.rb" +else + + module Exception2MessageMapper + RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/RCS/e2mmap.rb,v 1.4 1997/08/18 07:12:12 keiju Exp keiju $-' + + E2MM = Exception2MessageMapper + + def E2MM.extend_object(cl) + super + cl.bind(self) + end + + # �����Ȥθߴ����Τ���˻Ĥ��Ƥ���. + def E2MM.extend_to(b) + c = eval("self", b) + c.extend(self) + end + +# public :fail + # alias e2mm_fail fail + + def fail(err = nil, *rest) + Exception2MessageMapper.fail Exception2MessageMapper::ErrNotRegisteredException, err.to_s + end + + def bind(cl) + self.module_eval %q^ + E2MM_ErrorMSG = {} + # fail(err, *rest) + # err: �㳰 + # rest: ��å��������Ϥ��ѥ��� + # + def self.fail(err = nil, *rest) + $@ = caller(0) if [email protected]? + if form = E2MM_ErrorMSG[err] + $! = err.new(sprintf(form, *rest)) + # e2mm_fail() + raise() +# elsif self == Exception2MessageMapper +# fail Exception2MessageMapper::ErrNotRegisteredException, err.to_s + else +# print "super\n" + super + end + end + class << self + public :fail + end + + # def_exception(c, m) + # c: exception + # m: message_form + # �㳰c�Υ�å�������m�Ȥ���. + # + def self.def_e2message(c, m) + E2MM_ErrorMSG[c] = m + end + + # def_exception(c, m) + # n: exception_name + # m: message_form + # s: �㳰�����ѡ����饹(�ǥե����: Exception) + # �㳰̾``c''�����㳰�������, ���Υ�å�������m�Ȥ���. + # + #def def_exception(n, m) + def self.def_exception(n, m, s = Exception) + n = n.id2name if n.kind_of?(Fixnum) + e = Class.new(s) + const_set(n, e) + E2MM_ErrorMSG[e] = m + # const_get(:E2MM_ErrorMSG)[e] = m + end + ^ + end + + extend E2MM + def_exception(:ErrNotClassOrModule, "Not Class or Module") + def_exception(:ErrNotRegisteredException, "not registerd exception(%s)") + end +end + diff --git a/lib/e2mmap1_0.rb b/lib/e2mmap1_0.rb new file mode 100644 index 0000000000..c5797fd573 --- /dev/null +++ b/lib/e2mmap1_0.rb @@ -0,0 +1,71 @@ +# +# e2mmap.rb - +# $Release Version: 1.0$ +# $Revision: 1.4 $ +# $Date: 1997/08/18 07:12:12 $ +# by Keiju ISHITSUKA +# +# -- +# +# + +module Exception2MessageMapper + RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/RCS/e2mmap.rb,v 1.4 1997/08/18 07:12:12 keiju Exp keiju $-' + E2MM = Exception2MessageMapper + + def E2MM.extend_to(b) + c = eval("self", b) + c.extend(self) + c.bind(b) + end + + def bind(b) + eval " + @binding = binding + E2MM_ErrorMSG = Hash.new + + # fail(err, *rest) + # err: �㳰 + # rest: ��å��������Ϥ��ѥ��� + # + def fail!(*rest) + super + end + + def fail(err, *rest) + $! = err.new(sprintf(E2MM_ErrorMSG[err], *rest)) + super() + end + + public :fail + # def_exception(c, m) + # c: exception + # m: message_form + # �㳰c�Υ�å�������m�Ȥ���. + # + def def_e2message(c, m) + E2MM_ErrorMSG[c] = m + end + + # def_exception(c, m) + # c: exception_name + # m: message_form + # s: �㳰�����ѡ����饹(�ǥե����: Exception) + # �㳰̾``c''�����㳰�������, ���Υ�å�������m�Ȥ���. + # + def def_exception(c, m) + + c = c.id2name if c.kind_of?(Fixnum) + eval \"class \#{c} < Exception + end + E2MM_ErrorMSG[\#{c}] = '\#{m}' + \", @binding + end +", b + + end + + E2MM.extend_to(binding) + def_exception("ErrNotClassOrModule", "Not Class or Module") +end + diff --git a/lib/finalize.rb b/lib/finalize.rb new file mode 100644 index 0000000000..e934753e19 --- /dev/null +++ b/lib/finalize.rb @@ -0,0 +1,205 @@ +# +# finalize.rb - +# $Release Version: $ +# $Revision: 1.2 $ +# $Date: 1997/07/25 02:43:00 $ +# by Keiju ISHITSUKA(SHL Japan Inc.) +# +# -- +# +# Usage: +# +# add(obj, dependant, method = :finalize, *opt) +# add_dependency(obj, dependant, method = :finalize, *opt) +# ��¸�ط� R_method(obj, dependant) ���ɲ� +# +# delete(obj_or_id, dependant, method = :finalize) +# delete_dependency(obj_or_id, dependant, method = :finalize) +# ��¸�ط� R_method(obj, dependant) �κ�� +# delete_all_dependency(obj_or_id, dependant) +# ��¸�ط� R_*(obj, dependant) �κ�� +# delete_by_dependant(dependant, method = :finalize) +# ��¸�ط� R_method(*, dependant) �κ�� +# delete_all_by_dependant(dependant) +# ��¸�ط� R_*(*, dependant) �κ�� +# delete_all +# ���Ƥΰ�¸�ط��κ��. +# +# finalize(obj_or_id, dependant, method = :finalize) +# finalize_dependency(obj_or_id, dependant, method = :finalize) +# ��¸��Ϣ R_method(obj, dependtant) �Ƿ�Ф��dependant�� +# finalize����. +# finalize_all_dependency(obj_or_id, dependant) +# ��¸��Ϣ R_*(obj, dependtant) �Ƿ�Ф��dependant��finalize����. +# finalize_by_dependant(dependant, method = :finalize) +# ��¸��Ϣ R_method(*, dependtant) �Ƿ�Ф��dependant��finalize����. +# fainalize_all_by_dependant(dependant) +# ��¸��Ϣ R_*(*, dependtant) �Ƿ�Ф��dependant��finalize����. +# finalize_all +# Finalizer����Ͽ��������Ƥ�dependant��finalize���� +# +# safe{..} +# gc����Finalizer����ư����Τ�ߤ��. +# +# + +module Finalizer + RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/RCS/finalize.rb,v 1.2 1997/07/25 02:43:00 keiju Exp keiju $-' + + # @dependency: {id => [[dependant, method, *opt], ...], ...} + + # ��¸�ط� R_method(obj, dependant) ���ɲ� + def add_dependency(obj, dependant, method = :finalize, *opt) + ObjectSpace.call_finalizer(obj) + method = method.id unless method.kind_of?(Fixnum) + assoc = [dependant, method].concat(opt) + if dep = @dependency[obj.id] + dep.push assoc + else + @dependency[obj.id] = [assoc] + end + end + alias add add_dependency + + # ��¸�ط� R_method(obj, dependant) �κ�� + def delete_dependency(id, dependant, method = :finalize) + id = id.id unless id.kind_of?(Fixnum) + method = method.id unless method.kind_of?(Fixnum) + for assoc in @dependency[id] + assoc.delete_if do + |d, m, *o| + d == dependant && m == method + end + @dependency.delete(id) if assoc.empty? + end + end + alias delete delete_dependency + + # ��¸�ط� R_*(obj, dependant) �κ�� + def delete_all_dependency(id, dependant) + id = id.id unless id.kind_of?(Fixnum) + method = method.id unless method.kind_of?(Fixnum) + for assoc in @dependency[id] + assoc.delete_if do + |d, m, *o| + d == dependant + end + @dependency.delete(id) if assoc.empty? + end + end + + # ��¸�ط� R_method(*, dependant) �κ�� + def delete_by_dependant(dependant, method = :finalize) + method = method.id unless method.kind_of?(Fixnum) + for id in @dependency.keys + delete(id, dependant, method) + end + end + + # ��¸�ط� R_*(*, dependant) �κ�� + def delete_all_by_dependant(dependant) + for id in @dependency.keys + delete_all_dependency(id, dependant) + end + end + + # ��¸��Ϣ R_method(obj, dependtant) �Ƿ�Ф��dependant��finalize�� + # ��. + def finalize_dependency(id, dependant, method = :finalize) + id = id.id unless id.kind_of?(Fixnum) + method = method.id unless method.kind_of?(Fixnum) + for assocs in @dependency[id] + assocs.delete_if do + |d, m, *o| + d.send(m, *o) if ret = d == dependant && m == method + ret + end + @dependency.delete(id) if assoc.empty? + end + end + alias finalize finalize_dependency + + # ��¸��Ϣ R_*(obj, dependtant) �Ƿ�Ф��dependant��finalize����. + def finalize_all_dependency(id, dependant) + id = id.id unless id.kind_of?(Fixnum) + method = method.id unless method.kind_of?(Fixnum) + for assoc in @dependency[id] + assoc.delete_if do + |d, m, *o| + d.send(m, *o) if ret = d == dependant + end + @dependency.delete(id) if assoc.empty? + end + end + + # ��¸��Ϣ R_method(*, dependtant) �Ƿ�Ф��dependant��finalize����. + def finalize_by_dependant(dependant, method = :finalize) + method = method.id unless method.kind_of?(Fixnum) + for id in @dependency.keys + finalize(id, dependant, method) + end + end + + # ��¸��Ϣ R_*(*, dependtant) �Ƿ�Ф��dependant��finalize����. + def fainalize_all_by_dependant(dependant) + for id in @dependency.keys + finalize_all_dependency(id, dependant) + end + end + + # Finalizer����Ͽ����Ƥ������Ƥ�dependant��finalize���� + def finalize_all + for id, assocs in @dependency + for dependant, method, *opt in assocs + dependant.send(method, id, *opt) + end + assocs.clear + end + end + + # finalize_* ������˸ƤӽФ�����Υ��ƥ졼�� + def safe + old_status = Thread.critical + Thread.critical = TRUE + ObjectSpace.remove_finalizer(@proc) + yield + ObjectSpace.add_finalizer(@proc) + Thread.critical = old_status + end + + # ObjectSpace#add_finalizer�ؤ���Ͽ�ؿ� + def final_of(id) + if assocs = @dependency.delete(id) + for dependant, method, *opt in assocs + dependant.send(method, id, *opt) + end + end + end + + @dependency = Hash.new + @proc = proc{|id| final_of(id)} + ObjectSpace.add_finalizer(@proc) + + module_function :add + module_function :add_dependency + + module_function :delete + module_function :delete_dependency + module_function :delete_all_dependency + module_function :delete_by_dependant + module_function :delete_all_by_dependant + + module_function :finalize + module_function :finalize_dependency + module_function :finalize_all_dependency + module_function :finalize_by_dependant + module_function :fainalize_all_by_dependant + module_function :finalize_all + + module_function :safe + + module_function :final_of + private_class_method :final_of + +end + diff --git a/lib/ftplib.rb b/lib/ftplib.rb new file mode 100644 index 0000000000..34ee2f8d62 --- /dev/null +++ b/lib/ftplib.rb @@ -0,0 +1,617 @@ +### ftplib.rb -*- Mode: ruby; tab-width: 8; -*- + +## $Revision: 1.5 $ +## $Date: 1997/09/16 08:03:31 $ +## by maeda shugo <[email protected]> + +### Code: + +require "socket" +require "sync" if defined? Thread + +class FTPError < Exception; end +class FTPReplyError < FTPError; end +class FTPTempError < FTPError; end +class FTPPermError < FTPError; end +class FTPProtoError < FTPError; end + +class FTP + + RCS_ID = '$Id: ftplib.rb,v 1.5 1997/09/16 08:03:31 shugo Exp $' + + FTP_PORT = 21 + CRLF = "\r\n" + + attr :passive, TRUE + attr :return_code, TRUE + attr :debug_mode, TRUE + attr :welcome + attr :lastresp + + THREAD_SAFE = defined?(Thread) != FALSE + + if THREAD_SAFE + def synchronize(mode = :EX) + if @sync + @sync.synchronize(mode) do + yield + end + end + end + + def sock_synchronize(mode = :EX) + if @sock + @sock.synchronize(mode) do + yield + end + end + end + else + def synchronize(mode = :EX) + yield + end + + def sock_synchronize(mode = :EX) + yield + end + end + private :sock_synchronize + + 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) + if THREAD_SAFE + @sync = Sync.new + end + @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 + SOCKSsocket.open(host, port) + else + 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) + if THREAD_SAFE + @sock.extend Sync_m + end + voidresp + end + end + + def sanitize(s) + if s =~ /^PASS /i + s[0, 5] + "*" * (s.length - 5) + else + 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 + 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 + 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 + sock_synchronize do + putline(cmd) + getresp + end + end + end + + def voidcmd(cmd) + synchronize do + sock_synchronize do + putline(cmd) + voidresp + end + end + nil + end + + def sendport(host, port) + hbytes = host.split(".") + pbytes = [port / 256, port % 256] + bytes = hbytes + pbytes + cmd = "PORT " + bytes.join(",") + voidcmd(cmd) + end + private :sendport + + def makeport + sock = TCPserver.open(0) + port = sock.addr[1] + host = TCPsocket.getaddress(@sock.addr[2]) + resp = sendport(host, port) + sock + end + private :makeport + + def transfercmd(cmd) + if @passive + host, port = parse227(sendcmd("PASV")) + 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 + 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 + 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) + while TRUE + 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) + while TRUE + 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) + while TRUE + buf = file.read(blocksize) + break if buf == nil + conn.write(buf) + if use_callback + callback.call(buf) + end + 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) + while TRUE + buf = file.gets + break if buf == nil + if buf[-2, 2] != CRLF + if buf[-1] == ?\r or + buf[-1] == ?\n + buf = buf[0 .. -2] + end + buf = buf + CRLF + end + conn.write(buf) + if use_callback + callback.call(buf) + end + 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) + if use_callback + callback.call(data) + end + 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) + if use_callback + callback.call(line) + end + 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| + if use_callback + callback.call(data) + end + 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| + if use_callback + callback.call(line) + end + 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 + files + end + + def list(*args) + cmd = "LIST" + if iterator? + callback = Proc.new + elsif args[-1].is_a?(Proc) + callback = args.pop + else + callback = nil + end + args.each do |arg| + cmd = cmd + " " + arg + end + retrlines(cmd, callback) + 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) + resp = sendcmd("SIZE " + filename) + if resp[0, 3] == "213" + return Integer(resp[3 .. -1].strip) + end + 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 + resp = "" + sock_synchronize do + print "put: ABOR\n" if @debug_mode + @sock.send(line, Socket::MSG_OOB) + resp = getmultiline + end + unless ["426", "226", "225"].include?(resp[0, 3]) + raise FTPProtoError, resp + end + resp + end + + def status + line = "STAT" + CRLF + resp = "" + sock_synchronize do + print "put: STAT\n" if @debug_mode + @sock.send(line, Socket::MSG_OOB) + resp = getresp + end + resp + 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 = (Integer(numbers[4]) << 8) + Integer(numbers[5]) + return host, port + end + private :parse227 + + 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 diff --git a/lib/jcode.rb b/lib/jcode.rb index 5b2289932f..40ab48ddac 100644 --- a/lib/jcode.rb +++ b/lib/jcode.rb @@ -1,15 +1,31 @@ # jcode.rb - ruby code to handle japanese (EUC/SJIS) string +$vsave, $VERBOSE = $VERBOSE, FALSE class String printf STDERR, "feel free for some warnings:\n" if $VERBOSE + def jlength + self.split(//).length + end + alias original_succ succ private :original_succ + def mbchar?(c) + if $KCODE =~ /^s/i + c =~ /[\x81-\x9f\xe0-\xef][\x40-\x7e\x80-\xfc]/n + elsif $KCODE =~ /^e/i + c =~ /[\xa1-\xfe][\xa1-\xfe]/n + else + FALSE + end + end + def succ if self[-2] && self[-2] & 0x80 != 0 s = self.dup s[-1] += 1 + s[-1] += 1 if !mbchar?(s) return s else original_succ @@ -23,8 +39,11 @@ class String tail = self[-2..-1] if tail.length == 2 and tail =~ /^.$/ then if self[0..-2] == to[0..-2] + first = self[-2].chr for c in self[-1] .. to[-1] - yield self[0..-2]+c.chr + if mbchar?(first+c.chr) + yield self[0..-2]+c.chr + end end end else @@ -171,4 +190,18 @@ class String self.dup.tr_s!(from,to) end + alias original_chop! chop! + private :original_chop! + + def chop! + if self =~ /(.)$/ and $1.size == 2 + original_chop! + end + original_chop! + end + + def chop + self.dup.chop! + end end +$VERBOSE = $vsave diff --git a/lib/mathn.rb b/lib/mathn.rb index 359cb45769..fdf27f6771 100644 --- a/lib/mathn.rb +++ b/lib/mathn.rb @@ -2,7 +2,7 @@ # mathn.rb - # $Release Version: 0.5 $ # $Revision: 1.1 $ -# $Date: 1996/11/11 04:25:24 $ +# $Date: 1997/07/03 04:43:47 $ # by Keiju ISHITSUKA(SHL Japan Inc.) # # -- @@ -12,6 +12,7 @@ require "rational.rb" require "complex.rb" +require "matrix.rb" class Integer diff --git a/lib/matrix.rb b/lib/matrix.rb new file mode 100644 index 0000000000..394c66f098 --- /dev/null +++ b/lib/matrix.rb @@ -0,0 +1,777 @@ +#!/usr/local/bin/ruby +# +# matrix.rb - +# $Release Version: 1.0$ +# $Revision: 1.0 $ +# $Date: 97/05/23 11:35:28 $ +# Original Version from Smalltalk-80 version +# on July 23, 1985 at 8:37:17 am +# by Keiju ISHITSUKA +# +# -- +# +# Matrix[[1,2,3], +# : +# [3,4,5]] +# Matrix[row0, +# row1, +# : +# rown] +# +# column: �� +# row: �� +# + +require "e2mmap.rb" + +module ExceptionForMatrix + Exception2MessageMapper.extend_to(binding) + + def_e2message(TypeError, "wrong argument type %s (expected %s)") + def_e2message(ArgumentError, "Wrong # of arguments(%d for %d)") + + def_exception("ErrDimensionMismatch", "\#{self.type} dimemsion mismatch") + def_exception("ErrNotRegular", "Not Regular Matrix") + def_exception("ErrOperationNotDefined", "This operation(%s) can\\'t defined") +end + +class Matrix + RCS_ID='-$Header: ruby-mode,v 1.2 91/04/20 17:24:57 keiju Locked $-' + + include ExceptionForMatrix + + # instance creations + private_class_method :new + + def Matrix.[](*rows) + new(:init_rows, rows, FALSE) + end + + def Matrix.rows(rows, copy = TRUE) + new(:init_rows, rows, copy) + end + + def Matrix.columns(columns) + rows = (0 .. columns[0].size - 1).collect { + |i| + (0 .. columns.size - 1).collect { + |j| + columns[j][i] + } + } + Matrix.rows(rows, FALSE) + end + + def Matrix.diagonal(*values) + size = values.size + rows = (0 .. size - 1).collect { + |j| + row = Array.new(size).fill(0, 0, size) + row[j] = values[j] + row + } + self + rows(rows, FALSE) + end + + def Matrix.scalar(n, value) + Matrix.diagonal(*Array.new(n).fill(value, 0, n)) + end + + def Matrix.identity(n) + Matrix.scalar(n, 1) + end + class << Matrix + alias unit identity + alias I identity + end + + def Matrix.zero(n) + Matrix.scalar(n, 0) + end + + def Matrix.row_vector(row) + case row + when Vector + Matrix.rows([row.to_a], FALSE) + when Array + Matrix.rows([row.dup], FALSE) + else + Matrix.row([[row]], FALSE) + end + end + + def Matrix.column_vector(column) + case column + when Vector + Matrix.columns([column.to_a]) + when Array + Matrix.columns([column]) + else + Matrix.columns([[column]]) + end + end + + # initializing + def initialize(init_method, *argv) + self.send(init_method, *argv) + end + + def init_rows(rows, copy) + if copy + @rows = rows.collect{|row| row.dup} + else + @rows = rows + end + self + end + private :init_rows + + #accessing + def [](i, j) + @rows[i][j] + end + + def row_size + @rows.size + end + + def column_size + @rows[0].size + end + + def row(i) + if iterator? + for e in @rows[i] + yield e + end + else + Vector.elements(@rows[i]) + end + end + + def column(j) + if iterator? + 0.upto(row_size - 1) do + |i| + yield @rows[i][j] + end + else + col = (0 .. row_size - 1).collect { + |i| + @rows[i][j] + } + Vector.elements(col, FALSE) + end + end + + def collect + rows = @rows.collect{|row| row.collect{|e| yield e}} + Matrix.rows(rows, FALSE) + end + alias map collect + + # + # param: (from_row, row_size, from_col, size_col) + # (from_row..to_row, from_col..to_col) + # + def minor(*param) + case param.size + when 2 + from_row = param[0].first + size_row = param[0].size + from_col = param[1].first + size_col = param[1].size + when 4 + from_row = param[0] + size_row = param[1] + from_col = param[2] + size_col = param[3] + else + Matrix.fail ArgumentError, param.inspect + end + + rows = @rows[from_row, size_row].collect{ + |row| + row[from_col, size_col] + } + Matrix.rows(rows, FALSE) + end + + # TESTING + def regular? + square? and rank == column_size + end + + def singular? + not regular? + end + + def square? + column_size == row_size + end + + # ARITHMETIC + + def *(m) #is matrix or vector or number" + case(m) + when Numeric + rows = @rows.collect { + |row| + row.collect { + |e| + e * m + } + } + return Matrix.rows(rows, FALSE) + when Vector + m = Matrix.column_vector(m) + r = self * m + return r.column(0) + when Matrix + Matrix.fail ErrDimensionMismatch if column_size != m.row_size + + rows = (0 .. row_size - 1).collect { + |i| + (0 .. m.column_size - 1).collect { + |j| + vij = 0 + 0.upto(column_size - 1) do + |k| + vij += self[i, k] * m[k, j] + end + vij + } + } + return Matrix.rows(rows, FALSE) + else + x, y = m.coerce(self) + return x * y + end + end + + def +(m) + case m + when Numeric + Matrix.fail ErrOperationNotDefined, "+" + when Vector + m = Matrix.column_vector(m) + when Matrix + else + x, y = m.coerce(self) + return x + y + end + + Matrix.fail ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size + + rows = (0 .. row_size - 1).collect { + |i| + (0 .. column_size - 1).collect { + |j| + self[i, j] + m[i, j] + } + } + Matrix.rows(rows, FALSE) + end + + def -(m) + case m + when Numeric + Matrix.fail ErrOperationNotDefined, "-" + when Vector + m = Matrix.column_vector(m) + when Matrix + else + x, y = m.coerce(self) + return x - y + end + + Matrix.fail ErrDimensionMismatch unless row_size == m.row_size and column_size == m.column_size + + rows = (0 .. row_size - 1).collect { + |i| + (0 .. column_size - 1).collect { + |j| + self[i, j] - m[i, j] + } + } + Matrix.rows(rows, FALSE) + end + + def inverse + Matrix.fail ErrDimensionMismatch unless square? + Matrix.I(row_size).inverse_from(self) + end + alias inv inverse + + def inverse_from(src) + size = row_size - 1 + a = src.to_a + + for k in 0..size + if (akk = a[k][k]) == 0 + i = k + begin + fail ErrNotRegular if (i += 1) > size + end while a[i][k] == 0 + a[i], a[k] = a[k], a[i] + @rows[i], @rows[k] = @rows[k], @rows[i] + akk = a[k][k] + end + + for i in 0 .. size + next if i == k + q = a[i][k] / akk + a[i][k] = 0 + + (k + 1).upto(size) do + |j| + a[i][j] -= a[k][j] * q + end + 0.upto(size) do + |j| + @rows[i][j] -= @rows[k][j] * q + end + end + + (k + 1).upto(size) do + |j| + a[k][j] /= akk + end + 0.upto(size) do + |j| + @rows[k][j] /= akk + end + end + self + end + #alias reciprocal inverse + + def ** (other) + if other.kind_of?(Integer) + x = self + if other <= 0 + x = self.inverse + return Matrix.identity(self.column_size) if other == 0 + other = -other + end + z = x + n = other - 1 + while n != 0 + while (div, mod = n.divmod(2) + mod == 0) + x = x * x + n = div + end + z *= x + n -= 1 + end + z + elsif other.kind_of?(Float) || defined?(Rational) && other.kind_of?(Rational) + fail ErrOperationNotDefined, "**" + else + fail ErrOperationNotDefined, "**" + end + end + + # Matrix functions + + def determinant + return 0 unless square? + + size = row_size - 1 + a = to_a + + det = 1 + k = 0 + begin + if (akk = a[k][k]) == 0 + i = k + begin + return 0 if (i += 1) > size + end while a[i][k] == 0 + a[i], a[k] = a[k], a[i] + akk = a[k][k] + end + (k + 1).upto(size) do + |i| + q = a[i][k] / akk + (k + 1).upto(size) do + |j| + a[i][j] -= a[k][j] * q + end + end + det *= akk + end while (k += 1) <= size + det + end + alias det determinant + + def rank + if column_size > row_size + a = transpose.to_a + else + a = to_a + end + rank = 0 + k = 0 + begin + if (akk = a[k][k]) == 0 + i = -1 + nothing = FALSE + begin + if (i += 1) > column_size - 1 + nothing = TRUE + break + end + end while a[i][k] == 0 + next if nothing + a[i], a[k] = a[k], a[i] + akk = a[k][k] + end + (k + 1).upto(row_size - 1) do + |i| + q = a[i][k] / akk + (k + 1).upto(column_size - 1) do + |j| + a[i][j] -= a[k][j] * q + end + end + rank += 1 + end while (k += 1) <= column_size - 1 + return rank + end + + def trace + tr = 0 + 0.upto(column_size - 1) do + |i| + tr += @rows[i][i] + end + tr + end + alias tr trace + + def transpose + Matrix.columns(@rows) + end + alias t transpose + + # CONVERTING + + def coerce(other) + case other + when Numeric + return Scalar.new(other), self + end + end + + def row_vectors + rows = (0 .. column_size - 1).collect { + |i| + row(i) + } + rows + end + + def column_vectors + columns = (0 .. row_size - 1).collect { + |i| + column(i) + } + columns + end + + def to_a + @rows.collect{|row| row.collect{|e| e}} + end + + def to_f + collect{|e| e.to_f} + end + + def to_i + collect{|e| e.to_i} + end + + def to_r + collect{|e| e.to_r} + end + + # PRINTING + def to_s + "Matrix[" + @rows.collect{ + |row| + "[" + row.collect{|e| e.to_s}.join(", ") + "]" + }.join(", ")+"]" + end + + def inspect + "Matrix"[email protected] + end + + # Private CLASS + + class Scalar < Numeric + include ExceptionForMatrix + + def initialize(value) + @value = value + end + + # ARITHMETIC + def +(other) + case other + when Numeric + Scalar.new(@value + other) + when Vector, Matrix + Scalar.fail WrongArgType, other.type, "Numeric or Scalar" + when Scalar + Scalar.new(@value + other.value) + else + x, y = other.coerce(self) + x + y + end + end + + def -(other) + case other + when Numeric + Scalar.new(@value - other) + when Vector, Matrix + Scalar.fail WrongArgType, other.type, "Numeric or Scalar" + when Scalar + Scalar.new(@value - other.value) + else + x, y = other.coerce(self) + x - y + end + end + + def *(other) + case other + when Numeric + Scalar.new(@value * other) + when Vector, Matrix + other.collect{|e| @value * e} + else + x, y = other.coerce(self) + x * y + end + end + + def / (other) + case other + when Numeric + Scalar.new(@value / other) + when Vector + Scalar.fail WrongArgType, other.type, "Numeric or Scalar or Matrix" + when Matrix + self * _M.inverse + else + x, y = other.coerce(self) + x / y + end + end + + def ** (other) + case other + when Numeric + Scalar.new(@value ** other) + when Vector + Scalar.fail WrongArgType, other.type, "Numeric or Scalar or Matrix" + when Matrix + other.powered_by(self) + else + x, y = other.coerce(self) + x ** y + end + end + end +end + +#---------------------------------------------------------------------- +# +# - +# +#---------------------------------------------------------------------- +class Vector + include ExceptionForMatrix + + + #INSTANCE CREATION + + private_class_method :new + def Vector.[](*array) + new(:init_elements, array, copy = FALSE) + end + + def Vector.elements(array, copy = TRUE) + new(:init_elements, array, copy) + end + + def initialize(method, array, copy) + self.send(method, array, copy) + end + + def init_elements(array, copy) + if copy + @elements = array.dup + else + @elements = array + end + end + + # ACCSESSING + + def [](i) + @elements[i] + end + + def size + @elements.size + end + + # ENUMRATIONS + def each2(v) + Vector.fail ErrDimensionMismatch if size != v.size + 0.upto(size - 1) do + |i| + yield @elements[i], v[i] + end + end + + def collect2(v) + Vector.fail ErrDimensionMismatch if size != v.size + (0 .. size - 1).collect do + |i| + yield @elements[i], v[i] + end + end + + # ARITHMETIC + + def *(x) "is matrix or number" + case x + when Numeric + els = @elements.collect{|e| e * x} + Vector.elements(els, FALSE) + when Matrix + self.covector * x + else + s, x = X.corece(self) + s * x + end + end + + def +(v) + case v + when Vector + Vector.fail ErrDimensionMismatch if size != v.size + els = collect2(v) { + |v1, v2| + v1 + v2 + } + Vector.elements(els, FALSE) + when Matrix + Matrix.column_vector(self) + v + else + s, x = v.corece(self) + s + x + end + end + + def -(v) + case v + when Vector + Vector.fail ErrDimensionMismatch if size != v.size + els = collect2(v) { + |v1, v2| + v1 - v2 + } + Vector.elements(els, FALSE) + when Matrix + Matrix.column_vector(self) - v + else + s, x = v.corece(self) + s - x + end + end + + # VECTOR FUNCTIONS + + def inner_product(v) + Vector.fail ErrDimensionMismatch if size != v.size + + p = 0 + each2(v) { + |v1, v2| + p += v1 * v2 + } + p + end + + def collect + els = @elements.collect { + |v| + yield v + } + Vector.elements(els, FALSE) + end + alias map collect + + def map2(v) + els = collect2(v) { + |v1, v2| + yield v1, v2 + } + Vector.elements(els, FALSE) + end + + def r + v = 0 + for e in @elements + v += e*e + end + return v.sqrt + end + + # CONVERTING + def covector + Matrix.row_vector(self) + end + + def to_a + @elements.dup + end + + def to_f + collect{|e| e.to_f} + end + + def to_i + collect{|e| e.to_i} + end + + def to_r + collect{|e| e.to_r} + end + + def coerce(other) + case other + when Numeric + return Scalar.new(other), self + end + end + + # PRINTING + + def to_s + "Vector[" + @elements.join(", ") + "]" + end + + def inspect + str = "Vector"[email protected] + end +end + diff --git a/lib/mutex_m.rb b/lib/mutex_m.rb new file mode 100644 index 0000000000..823888e72f --- /dev/null +++ b/lib/mutex_m.rb @@ -0,0 +1,183 @@ +# +# mutex_m.rb - +# $Release Version: 2.0$ +# $Revision: 1.2 $ +# $Date: 1997/07/25 02:43:21 $ +# Original from mutex.rb +# by Keiju ISHITSUKA(SHL Japan Inc.) +# +# -- +# Usage: +# require "mutex_m.rb" +# obj = Object.new +# obj.extend Mutex_m +# ... +# ���Mutex��Ʊ���Ȥ��� +# + +require "finalize" + +module Mutex_m + def Mutex_m.extend_object(obj) + if Fixnum === obj or TRUE === obj or FALSE === obj or nil == obj + raise TypeError, "Mutex_m can't extend to this class(#{obj.type})" + else + begin + eval "class << obj + @mu_locked + end" + obj.extend(For_primitive_object) + rescue TypeError + obj.extend(For_general_object) + end + end + end + + def mu_extended + unless (defined? locked? and + defined? lock and + defined? unlock and + defined? try_lock and + defined? synchronize) + eval "class << self + alias locked mu_locked? + alias lock mu_lock + alias unlock mu_unlock + alias try_lock mu_try_lock + alias synchronize mu_synchronize + end" + end + end + + def mu_synchronize + begin + mu_lock + yield + ensure + mu_unlock + end + end + + module For_general_object + include Mutex_m + + def For_general_object.extend_object(obj) + super + obj.mu_extended + end + + def mu_extended + super + @mu_waiting = [] + @mu_locked = FALSE; + end + + def mu_locked? + @mu_locked + end + + def mu_try_lock + result = FALSE + Thread.critical = TRUE + unless @mu_locked + @mu_locked = TRUE + result = TRUE + end + Thread.critical = FALSE + result + end + + def mu_lock + while (Thread.critical = TRUE; @mu_locked) + @mu_waiting.push Thread.current + Thread.stop + end + @mu_locked = TRUE + Thread.critical = FALSE + self + end + + def mu_unlock + return unless @mu_locked + Thread.critical = TRUE + wait = @mu_waiting + @mu_waiting = [] + @mu_locked = FALSE + Thread.critical = FALSE + for w in wait + w.run + end + self + end + + end + + module For_primitive_object + include Mutex_m + Mu_Locked = Hash.new + + def For_primitive_object.extend_object(obj) + super + obj.mu_extended + Finalizer.add(obj, For_primitive_object, :mu_finalize) + end + + def For_primitive_object.mu_finalize(id) + Thread.critical = TRUE + if wait = Mu_Locked.delete(id) + # wait == [] �Ȥ����� GC�����Τ�, for w in wait �ϰ�̣�ʤ�. + Thread.critical = FALSE + for w in wait + w.run + end + else + Thread.critical = FALSE + end + self + end + + def mu_locked? + Mu_Locked.key?(self.id) + end + + def mu_try_lock + Thread.critical = TRUE + if Mu_Locked.key?(self.id) + ret = FALSE + else + Mu_Locked[self.id] = [] + Finalizer.set(self, For_primitive_object, :mu_delete_Locked) + ret = TRUE + end + Thread.critical = FALSE + ret + end + + def mu_lock + while (Thread.critical = TRUE; w = Mu_Locked[self.id]) + w.push Thread.current + Thread.stop + end + Mu_Locked[self.id] = [] + Finalizer.add(self, For_primitive_object, :mu_delete_Locked) + Thread.critical = FALSE + self + end + + def mu_unlock + Thread.critical = TRUE + if wait = Mu_Locked.delete(self.id) + Finalizer.delete(self, For_primitive_object, :mu_finalize) + Thread.critical = FALSE + for w in wait + w.run + end + else + Thread.critical = FALSE + end + self + end + end +end + + diff --git a/lib/observer.rb b/lib/observer.rb index 9a753939a2..b802dac633 100644 --- a/lib/observer.rb +++ b/lib/observer.rb @@ -30,7 +30,7 @@ module Observable @observer_state end def notify_observers(*arg) - if @observer_state + if @observer_peers and @observer_state for i in @observer_peers i.update(*arg) end diff --git a/lib/parsedate.rb b/lib/parsedate.rb index 3f4612ebe5..1c1dda76bc 100644 --- a/lib/parsedate.rb +++ b/lib/parsedate.rb @@ -14,26 +14,26 @@ module ParseDate time = $1 end if date =~ /19(\d\d)/ - year = $1 + year = Integer($1) end if date.sub!(/\s*(\d+)\s+(#{MONTHPAT})\S*\s+/i, ' ') - dayofmonth = $1 + dayofmonth = $1.to_i monthname = $2 elsif date.sub!(/\s*(#{MONTHPAT})\S*\s+(\d+)\s+/i, ' ') monthname = $1 - dayofmonth = $2 + dayofmonth = $2.to_i elsif date.sub!(/\s*(#{MONTHPAT})\S*\s+(\d+)\D+/i, ' ') monthname = $1 - dayofmonth = $2 + dayofmonth = $2.to_i elsif date.sub!(/\s*(\d\d?)\/(\d\d?)/, ' ') month = $1 - dayofmonth = $2 + dayofmonth = $2.to_i end if monthname month = MONTHS[monthname.downcase] end if ! year && date =~ /\d\d/ - year = $& + year = Integer($&) end return year, month, dayofmonth end diff --git a/lib/ping.rb b/lib/ping.rb new file mode 100644 index 0000000000..d742a50f99 --- /dev/null +++ b/lib/ping.rb @@ -0,0 +1,55 @@ +# +# ping.rb -- check a host for upness +# +#= SYNOPSIS +# +# require 'ping' +# print "'jimmy' is alive and kicking\n" if Ping.pingecho('jimmy', 10) ; +# +#= DESCRIPTION +# +# This module contains routines to test for the reachability of remote hosts. +# Currently the only routine implemented is pingecho(). +# +# pingecho() uses a TCP echo (I<not> an ICMP one) to determine if the +# remote host is reachable. This is usually adequate to tell that a remote +# host is available to rsh(1), ftp(1), or telnet(1) onto. +# +#== Parameters +# +# : hostname +# +# The remote host to check, specified either as a hostname or as an +# IP address. +# +# : timeout +# +# The timeout in seconds. If not specified it will default to 5 seconds. +# +#= WARNING +# +# pingecho() uses user-level thread to implement the timeout, so it may block +# for long period if named does not respond for some reason. +# +#=end + +module Ping + require "socket" + def pingecho(host, timeout=5) + begin + x = Thread.current + y = Thread.start { + sleep timeout + x.raise RuntimeError if x.status + } + s = TCPsocket.new(host, "echo") + s.close + return TRUE + rescue + return FALSE; + ensure + Thread.kill y if y.status + end + end + module_function "pingecho" +end diff --git a/lib/safe.rb b/lib/safe.rb deleted file mode 100644 index 7c95555495..0000000000 --- a/lib/safe.rb +++ /dev/null @@ -1,78 +0,0 @@ -# this is a safe-mode for ruby, which is still incomplete. - -unless defined? SecurityError - class SecurityError<Exception - end -end - -module Restricted - - printf STDERR, "feel free for some warnings:\n" if $VERBOSE - module Bastion - include Restricted - extend Restricted - BINDING = binding - def Bastion.to_s; "main" end - end - - class R_File<File - NG_FILE_OP = [] - def R_File.open(*args) - raise SecurityError, "can't use File.open() in safe mode" #' - end - end - - IO = nil - File = R_File - FileTest = nil - Dir = nil - ObjectSpace = nil - - def eval(string) - begin - super(string, Bastion::BINDING) - rescue - $@ = caller - raise - end - end - module_function :eval - - DEFAULT_SECURITY_MANAGER = Object.new - - def Restricted.set_securuty_manager(sec_man) - if @sec_man - raise SecurityError, "cannot change security manager" - end - @sec_man = sec_man - end - - def Restricted.securuty_manager - return @sec_man if @sec_man - return DEFAULT_SECURITY_MANAGER - end - - for cmd in ["test", "require", "load", "open", "system"] - eval format("def DEFAULT_SECURITY_MANAGER.%s(*args) - raise SecurityError, \"can't use %s() in safe mode\" - end", cmd, cmd) #' - eval format("def %s(*args) - Restricted.securuty_manager.%s(*args) - end", cmd, cmd) - end - - def `(arg) #` - Restricted.securuty_manager.send(:`, arg) #`) - end - - def DEFAULT_SECURITY_MANAGER.`(arg) #` - raise SecurityError, "can't use backquote(``) in safe mode" - end -end - -if $DEBUG - p eval("File.open('/dev/null')") - p Restricted.eval("self") - p Restricted.eval("open('/dev/null')") - p Restricted.eval("File.open('/dev/null')") -end diff --git a/lib/sync.rb b/lib/sync.rb new file mode 100644 index 0000000000..fd18291ca9 --- /dev/null +++ b/lib/sync.rb @@ -0,0 +1,376 @@ +# +# sync.rb - ���������2-�ե��������å����饹 +# $Release Version: 0.1$ +# $Revision: 1.3 $ +# $Date: 1997/08/18 07:17:08 $ +# by Keiju ISHITSUKA +# +# -- +# Usage: +# Sync_m, Synchronizer_m +# +# Sync_m#sync_mode +# Sync_m#sync_locked?, locked? +# Sync_m#sync_shared?, shared? +# Sync_m#sync_exclusive?, sync_exclusive? +# Sync_m#sync_try_lock, try_lock +# Sync_m#sync_lock, lock +# Sync_m#sync_unlock, unlock +# +# Sync, Synchronicer: +# include Sync_m +# +# sync = Sync.new +# Sync#mode +# Sync#locked? +# Sync#shared? +# Sync#exclusive? +# Sync#try_lock(mode) -- mode = :EX, :SH, :UN +# Sync#lock(mode) -- mode = :EX, :SH, :UN +# Sync#unlock +# Sync#synchronize(mode) {...} +# +# + +unless defined? Thread + fail "Thread not available for this ruby interpreter" +end + +require "finalize.rb" + +module Sync_m + RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/RCS/sync.rb,v 1.3 1997/08/18 07:17:08 keiju Exp keiju $-' + + UN = :UN + SH = :SH + EX = :EX + + class Err < Exception + def Err.Fail(*opt) + fail self, sprintf(self::Message, *opt) + end + + class UnknownLocker < Err + Message = "Thread(%s) not locked." + def UnknownLocker.Fail(th) + super(th.inspect) + end + end + + class LockModeFailer < Err + Message = "Unknown lock mode(%s)" + def LockModeFailer.Fail(mode) + if mode.id2name + mode = id2name + end + super(mode) + end + end + end + + def Sync_m.extend_object(obj) + if Fixnum === obj or TRUE === obj or FALSE === obj or nil == obj + raise TypeError, "Sync_m can't extend to this class(#{obj.type})" + else + begin + eval "class << obj + @sync_locked + end" + obj.extend(For_primitive_object) + rescue TypeError + obj.extend(For_general_object) + end + end + end + + def sync_extended + unless (defined? locked? and + defined? shared? and + defined? exclusive? and + defined? lock and + defined? unlock and + defined? try_lock and + defined? synchronize) + eval "class << self + alias locked? sync_locked? + alias shared? sync_shared? + alias excluive? sync_exclusive? + alias lock sync_lock + alias unlock sync_unlock + alias try_lock sync_try_lock + alias synchronize sync_synchronize + end" + end + end + + def sync_locked? + sync_mode != UN + end + + def sync_shared? + sync_mode == SH + end + + def sync_exclusive? + sync_mode == EX + end + + def sync_try_lock(mode = EX) + return unlock if sync_mode == UN + + Thread.critical = TRUE + ret = sync_try_lock_sub(sync_mode) + Thread.critical = FALSE + ret + end + + def sync_lock(m = EX) + return unlock if m == UN + + until (Thread.critical = TRUE; sync_try_lock_sub(m)) + if sync_sh_locker[Thread.current] + sync_upgrade_waiting.push [Thread.current, sync_sh_locker[Thread.current]] + sync_sh_locker.delete(Thread.current) + else + sync_waiting.push Thread.current + end + Thread.stop + end + Thread.critical = FALSE + self + end + + def sync_unlock(m = EX) + Thread.critical = TRUE + if sync_mode == UN + Thread.critical = FALSE + Err::UnknownLocker.Fail(Thread.current) + end + + m = sync_mode if m == EX and sync_mode == SH + + runnable = FALSE + case m + when UN + Thread.critical = FALSE + Err::UnknownLocker.Fail(Thread.current) + + when EX + if sync_ex_locker == Thread.current + if (self.sync_ex_count = sync_ex_count - 1) == 0 + self.sync_ex_locker = nil + if sync_sh_locker.include?(Thread.current) + self.sync_mode = SH + else + self.sync_mode = UN + end + runnable = TRUE + end + else + Err::UnknownLocker.Fail(Thread.current) + end + + when SH + if (count = sync_sh_locker[Thread.current]).nil? + Err::UnknownLocker.Fail(Thread.current) + else + if (sync_sh_locker[Thread.current] = count - 1) == 0 + sync_sh_locker.delete(Thread.current) + if sync_sh_locker.empty? and sync_ex_count == 0 + self.sync_mode = UN + runnable = TRUE + end + end + end + end + + if runnable + if sync_upgrade_waiting.size > 0 + for k, v in sync_upgrade_waiting + sync_sh_locker[k] = v + end + wait = sync_upgrade_waiting + self.sync_upgrade_waiting = [] + Thread.critical = FALSE + + for w, v in wait + w.run + end + else + wait = sync_waiting + self.sync_waiting = [] + Thread.critical = FALSE + for w in wait + w.run + end + end + end + + Thread.critical = FALSE + self + end + + def sync_try_lock_sub(m) + case m + when SH + case sync_mode + when UN + self.sync_mode = m + sync_sh_locker[Thread.current] = 1 + ret = TRUE + when SH + count = 0 unless count = sync_sh_locker[Thread.current] + sync_sh_locker[Thread.current] = count + 1 + ret = TRUE + when EX + # ����, �⡼�ɤ�EX�Ǥ������, ɬ��EX���å��Ȥʤ�. + if sync_ex_locker == Thread.current + self.sync_ex_count = sync_ex_count + 1 + ret = TRUE + else + ret = FALSE + end + end + when EX + if sync_mode == UN or + sync_mode == SH && sync_sh_locker.size == 1 && sync_sh_locker.include?(Thread.current) + self.sync_mode = m + self.sync_ex_locker = Thread.current + self.sync_ex_count = 1 + ret = TRUE + + elsif sync_mode == EX && sync_ex_locker == Thread.current + self.sync_ex_count = sync_ex_count + 1 + ret = TRUE + else + ret = FALSE + end + else + Thread.critical = FALSE + Err::LockModeFailer.Fail mode + end + return ret + end + private :sync_try_lock_sub + + def sync_synchronize(mode = EX) + begin + sync_lock(mode) + yield + ensure + sync_unlock + end + end + + module For_primitive_object + include Sync_m + + LockState = Struct.new("LockState", + :mode, + :waiting, + :upgrade_waiting, + :sh_locker, + :ex_locker, + :ex_count) + + Sync_Locked = Hash.new + + def For_primitive_object.extend_object(obj) + super + obj.sync_extended + Finalizer.add(obj, For_primitive_object, :sync_finalize) + end + + def sync_extended + super + Sync_Locked[id] = LockState.new(UN, [], [], Hash.new, nil, 0 ) + end + + def sync_finalize + wait = Sync_Locked.delete(id) + # waiting == [] �Ȥ����� GC�����Τ�, �Ԥ�����β����ϰ�̣���ʤ�. + end + + def sync_mode + Sync_Locked[id].mode + end + def sync_mode=(value) + Sync_Locked[id].mode = value + end + + def sync_waiting + Sync_Locked[id].waiting + end + def sync_waiting=(v) + Sync_Locked[id].waiting = v + end + + def sync_upgrade_waiting + Sync_Locked[id].upgrade_waiting + end + def sync_upgrade_waiting=(v) + Sync_Locked[id].upgrade_waiting = v + end + + def sync_sh_locker + Sync_Locked[id].sh_locker + end + def sync_sh_locker=(v) + Sync_Locked[id].sh_locker = v + end + + def sync_ex_locker + Sync_Locked[id].ex_locker + end + def sync_ex_locker=(value) + Sync_Locked[id].ex_locker = value + end + + def sync_ex_count + Sync_Locked[id].ex_count + end + def sync_ex_count=(value) + Sync_Locked[id].ex_count = value + end + + end + + module For_general_object + include Sync_m + + def For_general_object.extend_object(obj) + super + obj.sync_extended + end + + def sync_extended + super + @sync_mode = UN + @sync_waiting = [] + @sync_upgrade_waiting = [] + @sync_sh_locker = Hash.new + @sync_ex_locker = nil + @sync_ex_count = 0 + end + + attr :sync_mode, TRUE + + attr :sync_waiting, TRUE + attr :sync_upgrade_waiting, TRUE + attr :sync_sh_locker, TRUE + attr :sync_ex_locker, TRUE + attr :sync_ex_count, TRUE + + end +end +Synchronizer_m = Sync_m + +class Sync + include Sync_m::For_general_object + + def initialize + sync_extended + end + +end +Synchronizer = Sync diff --git a/lib/thread.rb b/lib/thread.rb index c3347b60b4..30f77ddbeb 100644 --- a/lib/thread.rb +++ b/lib/thread.rb @@ -24,27 +24,37 @@ class Mutex end def try_lock - Thread.exclusive do - if not @locked - @locked=TRUE - return TRUE - end + result = FALSE + Thread.critical = TRUE + unless @locked + @locked = TRUE + result = TRUE end - FALSE + Thread.critical = FALSE + result end def lock - while not try_lock + while (Thread.critical = TRUE; @locked) @waiting.push Thread.current Thread.stop end + @locked = TRUE + Thread.critical = FALSE + self end def unlock + return unless @locked + Thread.critical = TRUE + wait = @waiting + @waiting = [] @locked = FALSE - if w = @waiting.shift + Thread.critical = FALSE + for w in wait w.run end + self end def synchronize @@ -57,37 +67,6 @@ class Mutex end end -class SharedMutex<Mutex - def initialize - @locking = nil - @num_locks = 0; - super - end - def try_lock - if @locking == Thread.current - @num_locks += 1 - return TRUE - end - if super - @num_locks = 1 - @locking = Thread.current - TRUE - else - FALSE - end - end - def unlock - unless @locking == Thread.current - raise ThreadError, "cannot release shared mutex" - end - @num_locks -= 1 - if @num_locks == 0 - @locking = nil - super - end - end -end - class Queue def initialize @que = [] @@ -95,19 +74,30 @@ class Queue end def push(obj) + Thread.critical = TRUE @que.push obj - if t = @waiting.shift - t.run - end + t = @waiting.shift + Thread.critical = FALSE + t.run if t end def pop non_block=FALSE - if @que.length == 0 - raise ThreadError, "queue empty" if non_block - @waiting.push Thread.current - Thread.stop + item = nil + until item + Thread.critical = TRUE + if @que.length == 0 + if non_block + Thread.critical = FALSE + raise ThreadError, "queue empty" + end + @waiting.push Thread.current + Thread.stop + else + item = @que.shift + end end - @que.shift + Thread.critical = FALSE + item end def empty? @@ -118,36 +108,3 @@ class Queue @que.length end end - -class Condition - def initialize - @waiting = [] - end - - def wait(mut) - Thread.exclusive do - mut.unlock - @waiting.push Thread.current - end - Thread.sleep - mut.lock - end - - def signal - th = nil - Thread.exclusive do - th = @waiting.pop - end - th.run - end - - def broadcast - w = @waiting - Thread.exclusive do - th = [] - end - for th in w - th.run - end - end -end diff --git a/lib/thwait.rb b/lib/thwait.rb new file mode 100644 index 0000000000..c638335f5d --- /dev/null +++ b/lib/thwait.rb @@ -0,0 +1,128 @@ +# +# thwait.rb - +# $Release Version: $ +# $Revision: 1.1 $ +# $Date: 1997/08/18 03:13:14 $ +# by Keiju ISHITSUKA(Nippon Rational Inc.) +# +# -- +# +# +# + +require "thread.rb" +require "e2mmap.rb" + +class ThreadsWait + RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/RCS/thwait.rb,v 1.1 1997/08/18 03:13:14 keiju Exp keiju $-' + + Exception2MessageMapper.extend_to(binding) + def_exception("ErrWaitThreadsNothing", "Wait threads nothing.") + def_exception("FinshedThreadsNothing", "finished thread nothing.") + + # class mthods + # all_waits + + # + # ���ꤷ������åɤ����ƽ�λ����ޤ��Ԥ�. ���ƥ졼���Ȥ��ƸƤФ��� + # ���ꤷ������åɤ���λ����ȥ��ƥ졼����ƤӽФ�. + # + def ThreadsWait.all_waits(*threads) + tw = ThreadsWait.new(th1, th2, th3, th4, th5) + if iterator? + tw.all_waits do + |th| + yield th + end + else + tw.all_waits + end + end + + # initialize and terminating: + # initialize + + # + # �����. �Ԥĥ���åɤλ��꤬�Ǥ���. + # + def initialize(*threads) + @threads = [] + @wait_queue = Queue.new + join_nowait(*threads) unless threads.empty? + end + + # accessing + # threads + + # �Ԥ�����åɤΰ������֤�. + attr :threads + + # testing + # empty? + # finished? + # + + # + # �Ԥ�����åɤ�¸�ߤ��뤫�ɤ������֤�. + def empty? + @threads.empty? + end + + # + # ���Ǥ˽�λ��������åɤ����뤫�ɤ����֤� + def finished? + !@wait_queue.empty? + end + + # main process: + # join + # join_nowait + # next_wait + # all_wait + + # + # �ԤäƤ��륹��åɤ��ɲä��Ԥ��ˤϤ���. + # + def join(*threads) + join_nowait(*threads) + next_wait + end + + # + # �ԤäƤ��륹��åɤ��ɲä���. �Ԥ��ˤ�����ʤ�. + # + def join_nowait(*threads) + @threads.concat threads + for th in threads + Thread.start do + th = Thread.join(th) + @wait_queue.push th + end + end + end + + # + # �����Ԥ��ˤϤ���. + # �ԤĤ٤�����åɤ��ʤ����, �㳰ErrWaitThreadsNothing ���֤�. + # nonnlock�����λ��ˤ�, nonblocking��Ĵ�٤�. ¸�ߤ��ʤ����, �㳰 + # FinishedThreadNothing���֤�. + # + def next_wait(nonblock = nil) + Threads.Wait.fail ErrWaitThreadsNothing if @threads.empty? + + th = @wait_queue.pop(nonblock) + @threads.delete th + th + end + + # + # ���ƤΥ���åɤ���λ����ޤ��Ԥ�. ���ƥ졼���Ȥ��ƸƤФ줿����, �� + # ��åɤ���λ�����٤�, ���ƥ졼����ƤӽФ�. + # + def all_waits + until @threads.empty? + th = next_wait + yield th if iterator? + end + end +end @@ -345,7 +345,7 @@ class TkObject<TkKernel def configure(slot, value) if value == FALSE value = "0" - elsif value.type == Proc + elsif value.kind_of? Proc value = install_cmd(value) end tk_call path, 'configure', "-#{slot}", value @@ -358,6 +358,61 @@ class TkObject<TkKernel def bind(context, cmd=Proc.new, args=nil) _bind path, context, cmd, args end + + def tk_trace_variable(v) + unless v.kind_of?(TkVariable) + fail ArgumentError, format("requires TkVariable given %s", v.type) + end + v + end + private :tk_trace_variable + + def destroy + tk_call 'trace', 'vdelete', @tk_vn, 'w', @var_id if @var_id + end +end + + +class TkVariable + include Tk + $tk_variable_id = "v00000" + def initialize(val="") + @id = $tk_variable_id + $tk_variable_id = $tk_variable_id.succ + tk_call(format('global %s; set %s', @id, @id), val) + end + + def id + @id + end + + def value + tk_call(format('global %s; set', @id), @id) + end + + def value=(val) + tk_call(format('global %s; set %s', @id, @id), val) + end + + def to_i + Integer(number(value)) + end + + def to_f + Float(number(value)) + end + + def to_s + String(string(value)) + end + + def inspect + format "<TkVariable: %s>", @id + end + + def to_a + list(value) + end end class TkWindow<TkObject @@ -391,6 +446,36 @@ class TkWindow<TkObject self end + def place(keys = nil) + tk_call 'place', epath, *hash_kv(keys) + self + end + + def unplace(keys = nil) + tk_call 'place', 'forget', epath, *hash_kv(keys) + self + end + alias place_forget unplace + + def place_config(keys) + tk_call "place", 'configure', epath, *hash_kv(keys) + end + + def place_info() + ilist = list(tk_call('place', 'info', epath)) + info = {} + while key = ilist.shift + info[key[1,-1]] = ilist.shift + end + return info + end + + def place_slaves() + list(tk_call('place', 'slaves', epath)).collect { |w| + window(w) + } + end + def focus tk_call 'focus', path self @@ -426,7 +511,7 @@ class TkWindow<TkObject self end - def command(cmd) + def command(cmd=Proc.new) configure_cmd 'command', cmd end @@ -443,6 +528,7 @@ class TkWindow<TkObject end end $tk_window_list[path] = nil + super end end @@ -486,14 +572,7 @@ class TkLabel<TkWindow tk_call 'label', @path end def textvariable(v) - v = v.id2name unless v.kind_of? String - vn = @path + v - vset = format("global {%s}; set {%s} %%s", vn, vn) - tk_write vset, eval(v).inspect - trace_var v, proc{|val| - tk_write vset, val.inspect - } - configure 'textvariable', vn + configure 'textvariable', tk_trace_variable(v) end end @@ -520,26 +599,7 @@ class TkRadioButton<TkButton tk_send 'select' end def variable(v) - v = v.id2name unless v.kind_of? String - if v =~ /^\$/ - v = $' - else - fail ArgumentError, "variable must be global(%s)", v - end - vn = 'btns_selected_' + v - trace_var v, proc{|val| - tk_write 'global %s; set %s %s', vn, val - } - @var_id = install_cmd(proc{|name1,| - val = tk_call(format('global %s; set', name1), name1) - eval(format("%s = '%s'", v.id2name, val)) - }) - tk_call 'trace', 'variable', vn, 'w', @var_id - configure 'variable', vn - end - def destroy - tk_call 'trace vdelete', vn, 'w', @var_id - super + configure 'variable', tk_trace_variable(v) end end @@ -678,7 +738,7 @@ class TkMenu<TkWindow tk_send 'activate', index end def add(type, keys=nil) - tk_send 'add', type, *kv_hash(keys) + tk_send 'add', type, *hash_kv(keys) end def index(index) tk_send 'index', index @@ -686,8 +746,8 @@ class TkMenu<TkWindow def invoke tk_send 'invoke' end - def insert(index, type, keys=nil) - tk_send 'add', index, type, *kv_hash(keys) + def insert(index, type, *keys) + tk_send 'add', index, type, *hash_kv(keys) end def post(x, y) tk_send 'post', x, y @@ -695,7 +755,7 @@ class TkMenu<TkWindow def postcascade(index) tk_send 'postcascade', index end - def postcommand(cmd) + def postcommand(cmd=Proc.new) configure_cmd 'postcommand', cmd end def menutype(index) diff --git a/lib/tkcanvas.rb b/lib/tkcanvas.rb index b0ae8b1daa..46acd8c9d7 100644 --- a/lib/tkcanvas.rb +++ b/lib/tkcanvas.rb @@ -110,11 +110,11 @@ class TkCanvas<TkWindow def select(*args) tk_send 'select', *args end - def xview(index) - tk_send 'xview', index + def xview(*index) + tk_send 'xview', *index end - def yview(index) - tk_send 'yview', index + def yview(*index) + tk_send 'yview', *index end end @@ -125,12 +125,12 @@ class TkcItem<TkObject end @c = parent @path = parent.path - if args[-1].type == Hash + if args[-1].kind_of? Hash keys = args.pop end @id = create_self(*args) if keys - tk_call @path, 'itemconfigure', *hash_kv(keys) + tk_call @path, 'itemconfigure', @id, *hash_kv(keys) end end def create_self(*args) end @@ -226,6 +226,11 @@ class TkcPolygon<TkcItem tk_call(@path, 'create', 'polygon', *args) end end +class TkcRectangle<TkcItem + def create_self(*args) + tk_call(@path, 'create', 'rectangle', *args) + end +end class TkcText<TkcItem def create_self(*args) tk_call(@path, 'create', 'text', *args) @@ -272,7 +277,7 @@ class TkImage<TkObject def initialize(keys=nil) @path = $tk_image_id $tk_image_id = $tk_image_id.succ - tk_call 'image', @type, @path, *hash_kv(keys) + tk_call 'image', 'create', @type, @path, *hash_kv(keys) end def height @@ -302,7 +307,7 @@ end class TkPhotoImage<TkImage def initialize(*args) - @type = 'bitmap' + @type = 'photo' super end diff --git a/lib/tkclass.rb b/lib/tkclass.rb index 10ecc80b20..17f57f581d 100644 --- a/lib/tkclass.rb +++ b/lib/tkclass.rb @@ -25,11 +25,13 @@ Bitmap = TkcBitmap Line = TkcLine Oval = TkcOval Polygon = TkcPolygon +Rectangle = TkcRectangle TextItem = TkcText WindowItem = TkcWindow Selection = TkSelection Winfo = TkWinfo Pack = TkPack +Variable = TkVariable def Mainloop Tk.mainloop diff --git a/lib/tkcore.rb b/lib/tkcore.rb index 018e140ef0..9fd2c88efc 100644 --- a/lib/tkcore.rb +++ b/lib/tkcore.rb @@ -22,7 +22,7 @@ module Tk break if wish_path end } - fail 'can\'t find wish' if not wish_path + fail 'can\'t find wish' if not wish_path #' def Tk.tk_exit if not PORT.closed? @@ -31,7 +31,8 @@ module Tk end end - PORT = open(format("|%s -n %s", wish_path, File.basename($0)), "w+"); +# PORT = open(format("|%s -n %s", wish_path, File.basename($0)), "w+"); + PORT = open(format("|%s", wish_path), "w+"); trap "EXIT", proc{Tk.tk_exit} trap "PIPE", "" @@ -46,8 +47,8 @@ proc rb_out args { puts [format %%s $args] flush stdout } -proc rb_ans args { - if [catch "$args" var] {puts "!$var"} {puts "=$var@@"} +proc rb_ans arg { + if [catch $arg var] {puts "!$var"} {puts "=$var@@"} flush stdout } proc tkerror args { exit } @@ -85,12 +86,11 @@ after 120000 keepalive' } def error_at - n = 1 - while c = caller(n) - break if c !~ /tk\.rb:/ - n+=1 + frames = caller(1) + frames.delete_if do |c| + c =~ %r!/tk(|core|thcore|canvas|text|entry|scrollbox)\.rb:\d+! end - c + frames end def tk_tcl2ruby(val) @@ -197,17 +197,21 @@ after 120000 keepalive' s = "1" elsif s.kind_of?(TkObject) s = s.path + elsif s.kind_of?(TkVariable) + s = s.id else s = s.to_s - s.gsub!(/[{}]/, '\\\\\0') + s.gsub!(/["\\\$\[\]]/, '\\\\\0') #" + s.gsub!(/\{/, '\\\\173') + s.gsub!(/\}/, '\\\\175') end - "{#{s}}" + "\"#{s}\"" end } str += " " str += args.join(" ") print str, "\n" if $DEBUG - tk_write 'rb_ans %s', str + tk_write 'rb_ans {%s}', str while PORT.gets print $_ if $DEBUG $_.chop! @@ -229,10 +233,12 @@ after 120000 keepalive' $@ = error_at msg = $' if msg =~ /unknown option "-(.*)"/ - fail NameError, format("undefined method `%s' for %s(%s)", $1, self, self.type) #`' + $! = NameError.new(format("undefined method `%s' for %s(%s)", + $1, self, self.type)) #`' else - fail format("%s - %s", self.type, msg) + $! = RuntimeError.new(format("%s - %s", self.type, msg)) end + fail end $tk_event_queue.push $_ end @@ -250,7 +256,7 @@ after 120000 keepalive' if keys for k, v in keys conf.push("-#{k}") - v = install_cmd(v) if v.type == Proc + v = install_cmd(v) if v.kind_of? Proc conf.push(v) end end @@ -415,10 +421,10 @@ after 120000 keepalive' module_function :after, :update, :dispatch, :mainloop, :root, :bell module Scrollable - def xscrollcommand(cmd) + def xscrollcommand(cmd=Proc.new) configure_cmd 'xscrollcommand', cmd end - def yscrollcommand(cmd) + def yscrollcommand(cmd=Proc.new) configure_cmd 'yscrollcommand', cmd end end diff --git a/lib/tkentry.rb b/lib/tkentry.rb index 9a03c34058..7c13e3bdb1 100644 --- a/lib/tkentry.rb +++ b/lib/tkentry.rb @@ -14,11 +14,7 @@ class TkEntry<TkLabel end def delete(s, e=None) - if e - tk_send 'delete', s - else - tk_send 'delete', s, e - end + tk_send 'delete', s, e end def cursor @@ -28,13 +24,10 @@ class TkEntry<TkLabel tk_send 'icursor', index end def index(index) - tk_send 'index', index + number(tk_send('index', index)) end - def insert(text, pos=None) - if pos - tk_send 'icursor', pos - end - tk_send 'insert', 'insert', text + def insert(pos,text) + tk_send 'insert', pos, text end def mark(pos) tk_send 'scan', 'mark', pos diff --git a/lib/tkscrollbox.rb b/lib/tkscrollbox.rb index b8dbe9b236..76844ed90a 100644 --- a/lib/tkscrollbox.rb +++ b/lib/tkscrollbox.rb @@ -18,8 +18,8 @@ class TkScrollbox<TkListbox scroll.configure 'command', list.path+" yview" scroll.pack 'side'=>'right','fill'=>'y' - delegate('DEFALUT', list) - delegate('foreground', list, scroll) + delegate('DEFAULT', list) + delegate('foreground', list) delegate('background', list, scroll) delegate('borderwidth', @frame) delegate('relief', @frame) diff --git a/lib/tktext.rb b/lib/tktext.rb index 55e396c497..91a60529d1 100644 --- a/lib/tktext.rb +++ b/lib/tktext.rb @@ -24,10 +24,9 @@ class TkText<TkTextWin def _addcmd(cmd) @cmdtbl.push id end - def _addtag(cmd) - @cmdtbl.push id + def _addtag(name, obj) + @tags[name] = obj end - private :_addcmd, :_addtag def tag_names tk_send('tag', 'names').collect{|elt| if not @tags[elt] @@ -75,18 +74,25 @@ class TkText<TkTextWin def yview_pickplace(*what) tk_send 'yview', '-pickplace', *what end + + def xview(*what) + tk_send 'xview', *what + end + def xview_pickplace(*what) + tk_send 'xview', '-pickplace', *what + end end class TkTextTag<TkObject $tk_text_tag = 'tag0000' - def initialize(parent) + def initialize(parent, keys=nil) if not parent.kind_of?(TkText) fail format("%s need to be TkText", parent.inspect) end @t = parent - @path = parent.path - @id = $tk_text_tag + @path = @id = $tk_text_tag $tk_text_tag = $tk_text_tag.succ + tk_call @t.path, "tag", "configure", @id, *hash_kv(keys) @t._addtag id, self end def id @@ -94,25 +100,25 @@ class TkTextTag<TkObject end def add(*index) - tk_call path, 'tag', 'add', @id, *index + tk_call @t.path, 'tag', 'add', @id, *index end - def configure(slot, value) - tk_call path, 'tag', 'configure', id, "-#{slot}", value + def configure(keys) + tk_call @t.path, 'tag', 'configure', @id, *hash_kv(keys) end def bind(seq, cmd=Proc.new) id = install_cmd(cmd) - tk_call path, 'tag', 'bind', tag, "<#{seq}>", id + tk_call @t, 'tag', 'bind', tag, "<#{seq}>", id @t._addcmd cmd end def lower(below=None) - tk_call path, 'tag', 'lower', below + tk_call @t.path, 'tag', 'lower', below end def destroy - tk_call path, 'tag', 'delete', @id + tk_call @t.path, 'tag', 'delete', @id end end @@ -123,10 +129,9 @@ class TkTextMark<TkObject fail format("%s need to be TkText", parent.inspect) end @t = parent - @path = parent.path - @id = $tk_text_mark + @path = @id = $tk_text_mark $tk_text_mark = $tk_text_mark.succ - tk_call @t, 'set', @id, index + tk_call @t.path, 'set', @id, index @t._addtag id, self end def id @@ -134,11 +139,11 @@ class TkTextMark<TkObject end def set(where) - tk_call path, 'mark', 'unset', @id, where + tk_call @t.path, 'mark', 'unset', @id, where end def unset - tk_call path, 'mark', 'unset', @id + tk_call @t.path, 'mark', 'unset', @id end alias destroy unset end @@ -149,12 +154,11 @@ class TkTextWindow<TkObject fail format("%s need to be TkText", parent.inspect) end @t = parent - @path = parent.path - @index = index - tk_call @path, 'window', 'create', index, *args + @path = @index = index + tk_call @t.path, 'window', 'create', index, *args end def configure(slot, value) - tk_call path, 'window', 'configure', @index, "-#{slot}", value + tk_call @t.path, 'window', 'configure', @index, "-#{slot}", value end end diff --git a/lib/tkthcore.rb b/lib/tkthcore.rb index 5e0abd72c5..b89850cb73 100644 --- a/lib/tkthcore.rb +++ b/lib/tkthcore.rb @@ -30,7 +30,7 @@ module Tk break if wish_path end } - fail 'can\'t find wish' if not wish_path + fail 'can\'t find wish' if not wish_path #' # mark for non-given arguments None = Object.new @@ -66,9 +66,10 @@ module Tk ary = [PORT] loop do str = Qin.pop - print str, "\n" if $DEBUG + print "Qin: ", str, "\n" if $DEBUG tk_write 'if [catch {%s} var] {puts "!$var"} {puts "=$var@@"};flush stdout', str - Qout.push(tk_recv) + line = tk_recv + Qout.push(line) end end end @@ -89,7 +90,7 @@ module Tk val += $' return val else - v>al += $_ + val += $_ end end elsif /^!/ @@ -101,7 +102,6 @@ module Tk fail format("%s - %s", self.type, msg) end end - Qcmd.push line end fail 'wish closed' if PORT.closed? @@ -122,11 +122,15 @@ module Tk s = "1" elsif s.kind_of?(TkObject) s = s.path + elsif s.kind_of?(TkVariable) + s = s.id else s = s.to_s - s.gsub!(/[{}]/, '\\\\\0') + s.gsub!(/["\\\$\[\]]/, '\\\\\0') #" + s.gsub!(/\{/, '\\\\173') + s.gsub!(/\}/, '\\\\175') end - "{#{s}}" + "\"#{s}\"" end } str += " " @@ -240,12 +244,11 @@ after 120000 keepalive' module_function :dispatch def error_at - n = 1 - while c = caller(n) - break if c !~ /tk\.rb:/ - n+=1 + frames = caller(1) + frames.delete_if do |c| + c =~ %r!/tk(|core|thcore|canvas|text|entry|scrollbox)\.rb:\d+! end - c + frames end def bool(val) @@ -295,7 +298,7 @@ after 120000 keepalive' if keys for k, v in keys conf.push("-#{k}") - v = install_cmd(v) if v.type == Proc + v = install_cmd(v) if v.kind_of? Proc conf.push(v) end end @@ -440,10 +443,10 @@ after 120000 keepalive' module_function :after, :update, :dispatch, :mainloop, :root, :bell module Scrollable - def xscrollcommand(cmd) + def xscrollcommand(cmd=Proc.new) configure_cmd 'xscrollcommand', cmd end - def yscrollcommand(cmd) + def yscrollcommand(cmd=Proc.new) configure_cmd 'yscrollcommand', cmd end end diff --git a/lib/tracer.rb b/lib/tracer.rb new file mode 100644 index 0000000000..d37339fd62 --- /dev/null +++ b/lib/tracer.rb @@ -0,0 +1,75 @@ +class Tracer + MY_FILE_NAME_PATTERN = /^tracer\.(rb)?/ + Threads = Hash.new + Sources = Hash.new + + EVENT_SYMBOL = { + "line" => "-", + "call" => ">", + "return" => "<", + "class" => "C", + "end" => "E"} + + def on + set_trace_func proc{|event, file, line, id, binding| + trace_func event, file, line, id, binding + } + print "Trace on\n" + end + + def off + set_trace_func nil + print "Trace off\n" + end + + def get_thread_no + unless no = Threads[Thread.current.id] + Threads[Thread.current.id] = no = Threads.size + end + no + end + + def get_line(file, line) + unless list = Sources[file] + f =open(file) + begin + Sources[file] = list = f.readlines + ensure + f.close + end + end + list[line - 1] + end + + def trace_func(event, file, line, id, binding) + return if File.basename(file) =~ MY_FILE_NAME_PATTERN + + Thread.critical = TRUE + printf("#%d:%s:%d:%s: %s", + get_thread_no, + file, + line, + EVENT_SYMBOL[event], + get_line(file, line)) + Thread.critical = FALSE + end + + Single = new + def Tracer.on + Single.on + end + + def Tracer.off + Single.off + end + +end + +if File.basename($0) =~ Tracer::MY_FILE_NAME_PATTERN + $0 = ARGV.shift + + Tracer.on + load $0 +else + Tracer.on +end |