summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorYukihiro Matsumoto <matz@ruby-lang.org>1997-10-02 17:59:18 +0900
committerTakashi Kokubun <takashikkbn@gmail.com>2019-08-17 22:09:32 +0900
commit10d21745c8c1c3c78678ea7e0b62c0a7433ccfce (patch)
tree4e40254178d66c343cae763029131d959518f795 /lib
parentce930d042913722f209bbd3209b6c90a3c71325f (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 <matz@netlab.co.jp> * version 1.0-971002 Wed Oct 1 14:01:49 1997 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> * ext/marshal/marshal.c (w_byte): argument must be char. Wed Oct 1 10:30:22 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * version 1.0-970930 Fri Sep 30 14:29:22 1997 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> * ext/marshal/marshal.c (w_object): marshal dumped core. Tue Sep 30 10:27:39 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * sample/test.rb: bignum test suits added. Mon Sep 29 13:37:58 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * ruby.c (forbid_setid): forbid some options in suid mode. Mon Sep 27 09:53:48 1997 EGUCHI Matsumoto <eguchi@shizuokanet.or.jp> * bignum.c: modified for speeding. Fri Sep 26 18:27:59 1997 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> * sample/from.rb: some extensions. Mon Sep 29 13:15:56 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * parse.y (lhs): no more syntax error on `obj.CONSTANT = value'. Fri Sep 26 14:41:46 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * eval.c (ruby_run): deferred calling Init_ext() just before eval_node. Fri Sep 26 13:27:24 1997 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> * io.c (io_isatty): forgot to return TRUE value. Fri Sep 25 11:10:58 1997 EGUCHI Osamu <eguchi@shizuokanet.or.jp> * eval.c: use _setjmp/_longjmp instead of setjmp/longjmp on some platforms. Wed Sep 24 17:43:13 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * string.c (Init_String): String#taint and String#taint? added. Wed Sep 24 00:57:00 1997 Katsuyuki Okabe <HGC02147@niftyserve.or.jp> * X68000 patch. Tue Sep 23 20:42:30 1997 EGUCHI Osamu <eguchi@shizuokanet.or.jp> * parse.y (node_newnode): SEGV on null node setup. Mon Sep 22 11:22:46 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * ruby.c (ruby_prog_init): wrong safe condition check. Sun Sep 21 14:46:02 1997 MAEDA shugo <shugo@po.aianet.ne.jp> * error.c (exc_inspect): garbage added to classpath. Fri Sep 19 11:49:23 1997 <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * 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 <watanabe@ase.ptg.sony.co.jp> * regex.c (re_compile_pattern): \w{3} and \W{3} did not work. Thu Sep 11 10:31:48 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * version 1.0-970910 * ext/marshal/marshal.c (r_bytes0): extra big length check. Tue Sep 9 16:27:14 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * version 1.0-970903 * eval.c (f_load): expand path if fname begins with `~'. Mon Sep 1 13:42:48 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * eval.c (rb_call): alias occured in the module body caused SEGV. Fri Aug 29 11:10:21 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * parse.y (yylex): revised `=begin' skip code. * eval.c (is_defined): separated from rb_eval(). Wed Aug 27 11:32:42 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * variable.c (fc_i): some classes/modules does not have iv_tbl. * variable.c (find_class_path): avoid inifinite loop. Tue Aug 26 13:43:47 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * eval.c (error_print): modified exception print format. Thu Aug 21 16:10:58 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * sample/ruby-mode.el (ruby-calculate-indent): wrong indent level calculated with keyword operators. Thu Aug 21 11:55:41 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * version 1.0-970821 Thu Aug 21 11:36:58 1997 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> * parse.y (arg): ary[0] += 1 cause SEGV Wed Aug 20 14:24:42 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * version 1.0-970820 * eval.c (rb_call): infinite loop bug Tue Aug 19 00:15:38 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * object.c (class_s_new): do not make subclass of singleton class. Fri Aug 15 15:49:46 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * eval.c (call_trace_func): block context switch in the trace function. * eval.c (rb_eval): clear method cache at class extention. Fri Aug 15 19:40:43 1997 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> * ext/socket/socket.c (Init_socket): small typo caused SEGV. Tue Aug 12 16:02:18 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * object.c (Init_Object): remove private_attr/public_attr. Wed Aug 6 14:21:36 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * object.c (mod_attr): forgot to check nil for false value. Mon Aug 4 11:50:28 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * eval.c (rb_eval): stop to cache const value in nodes. Sat Jul 26 03:17:22 1997 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> * numeric.c (flo_to_s): wrong .0 at end. Sat Jul 26 00:36:36 1997 Yukihiro Matsumoto <matz@netlab.co.jp> * 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 <matz@netlab.co.jp> * string.c (uscore_get): proper error message for unset $_. Wed Jul 23 09:56:55 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <kkimura@pure.cpdc.canon.co.jp> * Native mswin32 support. Tue Jul 1 09:59:00 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * version 1.0-970701 * parse.y (mrhs): allow rest-star(*) in right hand side. Tue Jun 24 19:04:31 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * version 1.0-970624 Sat Jun 20 22:22:51 1997 Michio "Karl" Jinbo <karl@marcer.nagaokaut.ac.jp> * eval.c: freebsd 3.0 <sys/select.h> support. Fri Jun 20 01:24:45 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * version 1.0-970619 * string.c (str_split_method): wrong limit. Sat Jun 14 01:54:16 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <shugo@po.aianet.ne.jp> * array.c (sort_2): wrong comparison. Sat Jun 14 00:53:44 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * hash.c (hash_foreach): safe iteration. Fri Jun 13 14:04:56 1997 Michio "Karl" Jinbo <karl@marcer.nagaokaut.ac.jp> * configure.in: -Bshareable option for netbsd. Fri Jun 13 01:16:22 1997 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> * io.c (pipe_open): call io_unbuffered() only for writable pipes. Thu Jun 12 01:14:15 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * gc.c (rb_newobj): remove needless memset(). Mon Jun 9 13:03:43 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * version 1.0-970528 * process.c (rb_waitpid): do not block other threads. Tue May 27 12:02:31 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * variable.c (rb_ivar_set): invalid instance variable access for built-in object raises TypeError. Fri May 16 17:32:21 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * file.c (file_s_dirname): need to return "." for path without slashes. Wed May 7 19:18:48 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * ext/curses/curses.c: modified for portability and add to the standard distribution. Wed Apr 30 00:34:00 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * file.c (file_s_size): returns 0 for empty files (not FALSE). Fri Apr 25 02:17:50 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * version 1.0-970422 Thu Apr 17 00:40:51 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * configure.in (rb_cv_bsdpgrp): proper check for BSD setpgrp/setpgrp. Wed Apr 16 16:14:02 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (proc_call): proc called in other thread must be orphan. Tue Apr 15 10:46:31 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * version 1.0-970414 Fri Apr 12 01:20:12 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * ruby.h: String pointer changed to unsigned char. Fri Apr 11 10:27:29 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * io.c (arg_read): bug with 0 length input. Mon Apr 7 11:36:16 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * version 1.0-970404 * gc.c (obj_free): finalizer added for experiment. Thu Apr 3 02:12:31 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * version 1.0-970331 Sun Mar 30 19:40:57 1997 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> * parse.y (terms): avoided win32 gcc's optimization bug. Sat Mar 29 11:21:58 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * struct.c (make_struct): St[val,..] creates new structure. Fri Mar 28 11:24:51 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <watanabe@ase.ptg.sony.co.jp> * pack.c (pack_unpack): extra null byte after unpacked string. Wed Mar 26 15:20:34 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * version 1.0-970324 Thu Mar 20 22:04:59 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (mod_modfunc): forget to clear method cache. Wed Mar 19 17:06:55 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * ext/socks/socks.c: socket module with socks library. Mon Mar 10 20:44:22 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * re.c (reg_regsub): \& for substitution. \`, \', and \+ are avaiable also. Thu Mar 6 01:47:03 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * version 1.0-970305 Tue Mar 4 12:28:32 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * ruby.c (proc_options): search through RUBYPATH and PATH for option -S. Mon Mar 3 22:44:55 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * eval.c (rb_eval): restore $! value after rescue clause, to re-raise exceptions correctly. Fri Feb 28 16:43:38 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * version 1.0-970228 Thu Feb 27 11:23:41 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * eval.c (eval): forgot to restore dynamic local variable bindings. Tue Feb 25 11:22:08 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * version 1.0-970220 Thu Feb 20 11:25:50 1997 Yasuo OHBA <jammy@shljapan.co.jp> * lib/date.rb: update Thu Feb 20 08:25:57 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * ruby.h (Data_Make_Struct): rename macros. Sun Feb 8 11:48:13 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * io.c (f_syscall): argument offset was wrong. Fri Feb 7 18:01:17 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * hash.c (hash_rehash): re-register all key-value. Thu Jan 30 02:14:49 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <watanabe@ase.ptg.sony.co.jp> * util.c (_fixpath): supports SJIS filenames on DJGPP. Thu Jan 23 16:52:06 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <watanabe@ase.ptg.sony.co.jp> * eval.c (Init_Thread): allocate main_thread first to avoid crash. Thu Jan 23 02:09:26 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * eval.c (thread_run): no context switch in the critical section. Mon Jan 20 09:40:59 1997 WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> * utils.c: supports 8+3 filenames Sat Jan 18 01:23:03 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * eval.c (thread_create): threadが生成されるまで割込みを設定しない * eval.c (Init_Thread): 割込みタイミングを100msecに Sat Jan 11 00:17:05 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * string.c (str_sub_s): 文字列長より長いoffsetの検出 * regex.c (re_search): 空にマッチするパターン後の$で失敗 Thu Jan 2 16:36:23 1997 Yukihiro Matsumoto <matz@caelum.co.jp> * 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 <matz@caelum.co.jp> * io.c (f_select): timeoutでnilを返す Fri Dec 27 13:06:44 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * file.c (file_s_open): サブクラスではそのクラスのインスタンスを返 すように. Fri Dec 27 08:58:27 1996 ono@isl.nara.sharp.co.jp * numeric.c (flo_to_s): index()を使わない.strstr()に. Thu Dec 26 01:34:17 1996 Yukihiro Matsumoto <matz@caelum.co.jp> * lib/tk.rb: placeが使えるように * pack.c (endian): マクロDYNAMIC_ENDIANを指定すると実行時にendian を判定するように. * eval.c (thread_alloc): 初期化忘れのメンバがあった. Co-authored-by: EGUCHI Matsumoto <eguchi@shizuokanet.or.jp> Co-authored-by: EGUCHI Osamu <eguchi@shizuokanet.or.jp> Co-authored-by: KIMURA Koichi <kkimura@pure.cpdc.canon.co.jp> Co-authored-by: Katsuyuki Okabe <HGC02147@niftyserve.or.jp> Co-authored-by: MAEDA shugo <shugo@po.aianet.ne.jp> Co-authored-by: Michio "Karl" Jinbo <karl@marcer.nagaokaut.ac.jp> Co-authored-by: WATANABE Hirofumi <watanabe@ase.ptg.sony.co.jp> Co-authored-by: Yasuo OHBA <jammy@shljapan.co.jp> Co-authored-by: maeda shugo <shugo@po.aianet.ne.jp> Co-authored-by: ono <ono@isl.nara.sharp.co.jp>
Diffstat (limited to 'lib')
-rw-r--r--lib/English.rb28
-rw-r--r--lib/base64.rb47
-rw-r--r--lib/date.rb221
-rw-r--r--lib/debug.rb262
-rw-r--r--lib/e2mmap.rb94
-rw-r--r--lib/e2mmap1_0.rb71
-rw-r--r--lib/finalize.rb205
-rw-r--r--lib/ftplib.rb617
-rw-r--r--lib/jcode.rb35
-rw-r--r--lib/mathn.rb3
-rw-r--r--lib/matrix.rb777
-rw-r--r--lib/mutex_m.rb183
-rw-r--r--lib/observer.rb2
-rw-r--r--lib/parsedate.rb12
-rw-r--r--lib/ping.rb55
-rw-r--r--lib/safe.rb78
-rw-r--r--lib/sync.rb376
-rw-r--r--lib/thread.rb117
-rw-r--r--lib/thwait.rb128
-rw-r--r--lib/tk.rb128
-rw-r--r--lib/tkcanvas.rb21
-rw-r--r--lib/tkclass.rb2
-rw-r--r--lib/tkcore.rb40
-rw-r--r--lib/tkentry.rb15
-rw-r--r--lib/tkscrollbox.rb4
-rw-r--r--lib/tktext.rb46
-rw-r--r--lib/tkthcore.rb33
-rw-r--r--lib/tracer.rb75
28 files changed, 3376 insertions, 299 deletions
diff --git a/lib/English.rb b/lib/English.rb
new file mode 100644
index 0000000..c7e13be
--- /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 9bb6487..96208a6 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 0000000..260f6e7
--- /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 0000000..432c7b4
--- /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 0000000..d10657b
--- /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 $@.nil?
+ $@.shift
+ 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 0000000..c5797fd
--- /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 0000000..e934753
--- /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) ǷФdependantfinalize.
+# finalize_by_dependant(dependant, method = :finalize)
+# ¸Ϣ R_method(*, dependtant) ǷФdependantfinalize.
+# fainalize_all_by_dependant(dependant)
+# ¸Ϣ R_*(*, dependtant) ǷФdependantfinalize.
+# finalize_all
+# FinalizerϿƤdependantfinalize
+#
+# safe{..}
+# gcFinalizerưΤߤ.
+#
+#
+
+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) ǷФdependantfinalize
+ # .
+ 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) ǷФdependantfinalize.
+ 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) ǷФdependantfinalize.
+ 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) ǷФdependantfinalize.
+ def fainalize_all_by_dependant(dependant)
+ for id in @dependency.keys
+ finalize_all_dependency(id, dependant)
+ end
+ end
+
+ # FinalizerϿƤƤdependantfinalize
+ 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 0000000..34ee2f8
--- /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 <shugo@po.aianet.ne.jp>
+
+### 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 5b22899..40ab48d 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 359cb45..fdf27f6 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 0000000..394c66f
--- /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"+@rows.inspect
+ 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"+@elements.inspect
+ end
+end
+
diff --git a/lib/mutex_m.rb b/lib/mutex_m.rb
new file mode 100644
index 0000000..823888e
--- /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 9a75393..b802dac 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 3f4612e..1c1dda7 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 0000000..d742a50
--- /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 7c95555..0000000
--- 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 0000000..fd18291
--- /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 c3347b6..30f77dd 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 0000000..c638335
--- /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
diff --git a/lib/tk.rb b/lib/tk.rb
index 237408a..48a3940 100644
--- a/lib/tk.rb
+++ b/lib/tk.rb
@@ -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 b0ae8b1..46acd8c 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 10ecc80..17f57f5 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 018e140..9fd2c88 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 9a03c34..7c13e3b 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 b8dbe9b..76844ed 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 55e396c..91a6052 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 5e0abd7..b89850c 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 0000000..d37339f
--- /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