From 7ea2ceddb832b9973694fecac9fe3c30400735ba Mon Sep 17 00:00:00 2001 From: matz Date: Fri, 16 Jan 1998 12:19:22 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r11, which included commits to RCS files with non-trunk default branches. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@12 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 4400 ++++++------------------------------------------- MANIFEST | 26 +- Makefile.in | 128 +- README | 69 +- README.jp | 73 +- array.c | 548 +++--- bignum.c | 358 ++-- class.c | 341 +++- defines.h | 2 +- dir.c | 40 +- dln.c | 71 +- enum.c | 68 +- env.h | 6 +- error.c | 25 +- eval.c | 1576 +++++++++++------- ext/Setup | 2 +- ext/curses/curses.c | 67 +- ext/dbm/dbm.c | 8 +- ext/dbm/depend | 2 +- ext/etc/depend | 2 +- ext/extmk.rb.in | 76 +- ext/extmk.rb.nt | 115 +- ext/fcntl/depend | 2 +- ext/kconv/depend | 2 +- ext/kconv/kconv.c | 122 +- ext/md5/depend | 2 +- ext/socket/depend | 2 +- ext/socket/extconf.rb | 17 +- ext/socket/socket.c | 404 +++-- ext/tkutil/depend | 2 +- file.c | 277 ++-- gc.c | 168 +- hash.c | 360 ++-- inits.c | 36 +- io.c | 303 +++- io.h | 7 +- lib/cgi-lib.rb | 77 +- lib/finalize.rb | 36 +- lib/mailread.rb | 43 +- lib/sync.rb | 90 +- lib/tk.rb | 573 ++++++- lib/tktext.rb | 4 +- math.c | 52 +- missing/dir.h | 63 - missing/nt.c | 15 +- missing/nt.h | 137 ++ missing/setenv.c | 74 +- node.h | 43 +- numeric.c | 176 +- object.c | 393 ++++- pack.c | 133 +- parse.y | 838 ++++++---- process.c | 132 +- random.c | 3 +- range.c | 3 +- re.c | 409 +++-- re.h | 7 +- regex.c | 1461 +++++++++++----- regex.h | 9 +- ruby.c | 137 +- ruby.h | 150 +- sample/exyacc.rb | 2 +- sample/fact.rb | 10 +- sample/mkproto.rb | 2 +- sample/ruby-mode.el | 11 +- sample/test.rb | 244 +-- sample/tkhello.rb | 17 +- sample/uumerge.rb | 36 +- sprintf.c | 12 +- string.c | 790 +++++---- struct.c | 127 +- time.c | 65 +- top.sed | 6 +- util.c | 54 +- variable.c | 395 +++-- version.c | 2 +- version.h | 4 +- win32/Makefile | 42 +- win32/ruby.def | 439 ++++- 79 files changed, 8846 insertions(+), 8177 deletions(-) diff --git a/ChangeLog b/ChangeLog index 8c4a1eaa39..029e20077c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4305 +1,831 @@ -Thu Dec 25 17:06:30 1997 Yukihiro Matsumoto +Fri Jan 16 00:43:43 1998 Yukihiro Matsumoto - * version 1.0-971225 + * ruby.h (CLONESETUP): copies its singleton classes too. - * some minor bug fixes. + * class.c (singleton_class_attached): saves binded object in the + singleton classes. -Tue Dec 9 17:54:56 1997 Yukihiro Matsumoto + * eval.c (rb_eval): calls singleton_method_added even in the + singleton class clauses. - * version 1.0-971209 +Fri Jan 15 23:22:43 1998 WATANABE Hirofumi - * sample/ruby-mode.el (ruby-expr-beg): forgot to handle modifiers. - - * parse.y (tokadd): token buffer overrun. - -Thu Dec 4 14:29:59 1997 Yukihiro Matsumoto - - * version 1.0-971204 - -Mon Dec 1 15:24:41 1997 Yukihiro Matsumoto - - * compar.c (cmp_between): wrong comparison made. - -Wed Nov 26 18:18:05 1997 Yukihiro Matsumoto - - * numeric.c (fix2str): enlarge buffer to prevent overflow on some - machines. - -Tue Nov 25 15:03:28 1997 Yukihiro Matsumoto - - * version 1.0-971125 - -Fri Nov 21 13:17:12 1997 Yukihiro Matsumoto - - * parse.y (yylex): skip multibyte characters in comments. - -Wed Nov 19 17:19:20 1997 Yukihiro Matsumoto - - * parse.y (call_args): wrong node generation. - -Tue Nov 18 13:59:59 1997 Yukihiro Matsumoto - - * version 1.0-971118 - -Tue Nov 18 10:13:08 1997 Yukihiro Matsumoto - - * regex.c (re_compile_pattern): insert initialize code for jump_n, - before entering loops. - -Sat Nov 15 00:11:36 1997 WATANABE Hirofumi - - * io.c (io_s_popen): "rb" detection - -Wed Nov 12 13:44:47 1997 Yukihiro Matsumoto - - * time.c: remove coerce from Time class. - -Wed Nov 2 16:00:00 1997 WATANABE Hirofumi - - * string.c (str_sub_s): "".sub! "", "" => "\000" - -Thu Oct 30 16:54:01 1997 WATANABE Hirofumi - - * string.c (str_chop_bang): "".chop caused SEGV. - -Mon Oct 27 13:49:13 1997 Yukihiro Matsumoto - - * ext/extmk.rb.in: library may have pathname contains `.' - - * eval.c (rb_rescue): should not protect SystemError. - -Thu Oct 23 11:17:44 1997 Yukihiro Matsumoto - - * range.c (range_eqq): fixnum check for last needed too. - -Wed Oct 22 12:52:30 1997 Yukihiro Matsumoto - - * array.c (ary_join): call ary_join() recursively for the 1st - array element. - -Tue Oct 21 13:31:29 1997 Yukihiro Matsumoto - - * version 1.0-971021 - -Mon Oct 20 12:18:29 1997 WATANABE Hirofumi - - * ruby.c (load_file): wrong condition for #! check with -x. - - * file.c (file_s_dirname): did return "" for "/a". - -Fri Oct 17 14:29:09 1997 Yukihiro Matsumoto - - * bignum.c (bigadd): some undefined side effect order assumed. - -Wed Oct 15 18:08:37 1997 Yukihiro Matsumoto - - * version 1.0-971015 - -Fri Oct 3 10:51:10 1997 Yukihiro Matsumoto - - * version 1.0-971003 - - * eval.c (ruby_options): f_require() called too early. - - * eval.c (rb_provide): module extentions should always be `.o'. - -Thu Oct 2 17:59:18 1997 Yukihiro Matsumoto - - * ext/marshal/marshal.c (r_object): remove temporal regist for - structs. (caused problem if structs form cycles.) - - * version 1.0-971002 - -Wed Oct 1 14:01:49 1997 WATANABE Hirofumi - - * ext/marshal/marshal.c (w_byte): argument must be char. - -Wed Oct 1 10:30:22 1997 Yukihiro Matsumoto - - * 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 - - * version 1.0-970930 - -Fri Sep 30 14:29:22 1997 WATANABE Hirofumi - - * ext/marshal/marshal.c (w_object): marshal dumped core. - -Tue Sep 30 10:27:39 1997 Yukihiro Matsumoto - - * sample/test.rb: bignum test suits added. - -Mon Sep 29 13:37:58 1997 Yukihiro Matsumoto - - * ruby.c (forbid_setid): forbid some options in suid mode. - -Mon Sep 27 09:53:48 1997 EGUCHI Matsumoto - - * bignum.c: modified for speeding. - -Fri Sep 26 18:27:59 1997 WATANABE Hirofumi - - * sample/from.rb: some extensions. - -Mon Sep 29 13:15:56 1997 Yukihiro Matsumoto - - * parse.y (lhs): no more syntax error on `obj.CONSTANT = value'. - -Fri Sep 26 14:41:46 1997 Yukihiro Matsumoto - - * eval.c (ruby_run): deferred calling Init_ext() just before eval_node. - -Fri Sep 26 13:27:24 1997 WATANABE Hirofumi - - * io.c (io_isatty): forgot to return TRUE value. - -Fri Sep 25 11:10:58 1997 EGUCHI Osamu - - * eval.c: use _setjmp/_longjmp instead of setjmp/longjmp on some - platforms. - -Wed Sep 24 17:43:13 1997 Yukihiro Matsumoto - - * string.c (Init_String): String#taint and String#taint? added. - -Wed Sep 24 00:57:00 1997 Katsuyuki Okabe - - * X68000 patch. - -Tue Sep 23 20:42:30 1997 EGUCHI Osamu - - * parse.y (node_newnode): SEGV on null node setup. - -Mon Sep 22 11:22:46 1997 Yukihiro Matsumoto - - * ruby.c (ruby_prog_init): wrong safe condition check. - -Sun Sep 21 14:46:02 1997 MAEDA shugo - - * error.c (exc_inspect): garbage added to classpath. - -Fri Sep 19 11:49:23 1997 - - * 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 - - * 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 - - * regex.c (re_compile_pattern): \w{3} and \W{3} did not work. - -Thu Sep 11 10:31:48 1997 Yukihiro Matsumoto - - * 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 - - * version 1.0-970910 - - * ext/marshal/marshal.c (r_bytes0): extra big length check. - -Tue Sep 9 16:27:14 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * version 1.0-970903 - - * eval.c (f_load): expand path if fname begins with `~'. - -Mon Sep 1 13:42:48 1997 Yukihiro Matsumoto - - * eval.c (rb_call): alias occured in the module body caused SEGV. - -Fri Aug 29 11:10:21 1997 Yukihiro Matsumoto - - * 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 - - * parse.y (yylex): revised `=begin' skip code. - - * eval.c (is_defined): separated from rb_eval(). - -Wed Aug 27 11:32:42 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * 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 - - * eval.c (error_print): modified exception print format. - -Thu Aug 21 16:10:58 1997 Yukihiro Matsumoto - - * sample/ruby-mode.el (ruby-calculate-indent): wrong indent level - calculated with keyword operators. - -Thu Aug 21 11:55:41 1997 Yukihiro Matsumoto - - * version 1.0-970821 - -Thu Aug 21 11:36:58 1997 WATANABE Hirofumi - - * parse.y (arg): ary[0] += 1 cause SEGV - -Wed Aug 20 14:24:42 1997 Yukihiro Matsumoto - - * version 1.0-970820 - - * eval.c (rb_call): infinite loop bug - -Tue Aug 19 00:15:38 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * object.c (class_s_new): do not make subclass of singleton class. - -Fri Aug 15 15:49:46 1997 Yukihiro Matsumoto - - * 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 - - * ext/socket/socket.c (Init_socket): small typo caused SEGV. - -Tue Aug 12 16:02:18 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * 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 - - * object.c (Init_Object): remove private_attr/public_attr. - -Wed Aug 6 14:21:36 1997 Yukihiro Matsumoto - - * object.c (mod_attr): forgot to check nil for false value. - -Mon Aug 4 11:50:28 1997 Yukihiro Matsumoto - - * 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 - - * eval.c (rb_eval): stop to cache const value in nodes. - -Sat Jul 26 03:17:22 1997 WATANABE Hirofumi - - * numeric.c (flo_to_s): wrong .0 at end. - -Sat Jul 26 00:36:36 1997 Yukihiro Matsumoto - - * 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 - - * string.c (uscore_get): proper error message for unset $_. - -Wed Jul 23 09:56:55 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * 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 - - * Native mswin32 support. - -Tue Jul 1 09:59:00 1997 Yukihiro Matsumoto - - * version 1.0-970701 - - * parse.y (mrhs): allow rest-star(*) in right hand side. - -Tue Jun 24 19:04:31 1997 Yukihiro Matsumoto - - * version 1.0-970624 - -Sat Jun 20 22:22:51 1997 Michio "Karl" Jinbo - - * eval.c: freebsd 3.0 support. - -Fri Jun 20 01:24:45 1997 Yukihiro Matsumoto - - * 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 - - * version 1.0-970619 - - * string.c (str_split_method): wrong limit. - -Sat Jun 14 01:54:16 1997 Yukihiro Matsumoto - - * 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 - - * array.c (sort_2): wrong comparison. - -Sat Jun 14 00:53:44 1997 Yukihiro Matsumoto - - * hash.c (hash_foreach): safe iteration. - -Fri Jun 13 14:04:56 1997 Michio "Karl" Jinbo - - * configure.in: -Bshareable option for netbsd. - -Fri Jun 13 01:16:22 1997 WATANABE Hirofumi - - * io.c (pipe_open): call io_unbuffered() only for writable pipes. - -Thu Jun 12 01:14:15 1997 Yukihiro Matsumoto - - * 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 - - * gc.c (rb_newobj): remove needless memset(). - -Mon Jun 9 13:03:43 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * 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 - - * 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 - - * version 1.0-970528 - - * process.c (rb_waitpid): do not block other threads. - -Tue May 27 12:02:31 1997 Yukihiro Matsumoto - - * 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 - - * variable.c (rb_ivar_set): invalid instance variable access for - built-in object raises TypeError. - -Fri May 16 17:32:21 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * file.c (file_s_dirname): need to return "." for path without - slashes. - -Wed May 7 19:18:48 1997 Yukihiro Matsumoto - - * 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 - - * ext/curses/curses.c: modified for portability and add to the - standard distribution. - -Wed Apr 30 00:34:00 1997 Yukihiro Matsumoto - - * file.c (file_s_size): returns 0 for empty files (not FALSE). - -Fri Apr 25 02:17:50 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * version 1.0-970422 - -Thu Apr 17 00:40:51 1997 Yukihiro Matsumoto - - * configure.in (rb_cv_bsdpgrp): proper check for BSD - setpgrp/setpgrp. - -Wed Apr 16 16:14:02 1997 Yukihiro Matsumoto - - * eval.c (proc_call): proc called in other thread must be orphan. - -Tue Apr 15 10:46:31 1997 Yukihiro Matsumoto - - * 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 - - * version 1.0-970414 - -Fri Apr 12 01:20:12 1997 Yukihiro Matsumoto - - * ruby.h: String pointer changed to unsigned char. - -Fri Apr 11 10:27:29 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * ruby.c: forgot to include 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 - - * io.c (arg_read): bug with 0 length input. - -Mon Apr 7 11:36:16 1997 Yukihiro Matsumoto - - * 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 - - * version 1.0-970404 - - * gc.c (obj_free): finalizer added for experiment. - -Thu Apr 3 02:12:31 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * 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 - - * version 1.0-970331 - -Sun Mar 30 19:40:57 1997 WATANABE Hirofumi - - * parse.y (terms): avoided win32 gcc's optimization bug. - -Sat Mar 29 11:21:58 1997 Yukihiro Matsumoto - - * struct.c (make_struct): St[val,..] creates new structure. - -Fri Mar 28 11:24:51 1997 Yukihiro Matsumoto - - * 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 - - * pack.c (pack_unpack): extra null byte after unpacked string. - -Wed Mar 26 15:20:34 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * version 1.0-970324 - -Thu Mar 20 22:04:59 1997 Yukihiro Matsumoto - - * eval.c (mod_modfunc): forget to clear method cache. - -Wed Mar 19 17:06:55 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * 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 - - * 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 - - * ext/socks/socks.c: socket module with socks library. - -Mon Mar 10 20:44:22 1997 Yukihiro Matsumoto - - * re.c (reg_regsub): \& for substitution. \`, \', and \+ are - avaiable also. - -Thu Mar 6 01:47:03 1997 Yukihiro Matsumoto - - * 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 - - * version 1.0-970305 - -Tue Mar 4 12:28:32 1997 Yukihiro Matsumoto - - * ruby.c (proc_options): search through RUBYPATH and PATH for - option -S. - -Mon Mar 3 22:44:55 1997 Yukihiro Matsumoto - - * 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 - - * eval.c (rb_eval): restore $! value after rescue clause, to - re-raise exceptions correctly. - -Fri Feb 28 16:43:38 1997 Yukihiro Matsumoto - - * version 1.0-970228 - -Thu Feb 27 11:23:41 1997 Yukihiro Matsumoto - - * 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 - - * eval.c (eval): forgot to restore dynamic local variable - bindings. - -Tue Feb 25 11:22:08 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * version 1.0-970220 - -Thu Feb 20 11:25:50 1997 Yasuo OHBA - - * lib/date.rb: update - -Thu Feb 20 08:25:57 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * ruby.h (Data_Make_Struct): rename macros. - -Sun Feb 8 11:48:13 1997 Yukihiro Matsumoto - - * io.c (f_syscall): argument offset was wrong. - -Fri Feb 7 18:01:17 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * 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 - - * hash.c (hash_rehash): re-register all key-value. - -Thu Jan 30 02:14:49 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * 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 - - * 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 - - * 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 - - * util.c (_fixpath): supports SJIS filenames on DJGPP. - -Thu Jan 23 16:52:06 1997 Yukihiro Matsumoto - - * 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 - - * eval.c (Init_Thread): allocate main_thread first to avoid crash. - -Thu Jan 23 02:09:26 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * eval.c (thread_run): no context switch in the critical section. - -Mon Jan 20 09:40:59 1997 WATANABE Hirofumi - - * utils.c: supports 8+3 filenames - -Sat Jan 18 01:23:03 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * 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 - - * 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 - - * eval.c (thread_create): threadが生成されるまで割込みを設定しない - - * eval.c (Init_Thread): 割込みタイミングを100msecに - -Sat Jan 11 00:17:05 1997 Yukihiro Matsumoto - - * 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 - - * 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 - - * string.c (str_sub_s): 文字列長より長いoffsetの検出 - - * regex.c (re_search): 空にマッチするパターン後の$で失敗 - -Thu Jan 2 16:36:23 1997 Yukihiro Matsumoto - - * 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 - - * io.c (f_select): timeoutでnilを返す - -Fri Dec 27 13:06:44 1996 Yukihiro Matsumoto - - * 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 - - * lib/tk.rb: placeが使えるように - - * pack.c (endian): マクロDYNAMIC_ENDIANを指定すると実行時にendian - を判定するように. - - * eval.c (thread_alloc): 初期化忘れのメンバがあった. - -Wed Dec 25 00:33:19 1996 Yukihiro Matsumoto - - * version 1.0-961225 - - * io.c (Init_IO): newを無効化 - - * lib/tkthcore.rb: tk_call "global $foo; set foo 5"などもできるように - - * eval.c (thread_restore_context): $~, $_でスタックを壊していた - - * process.c (rb_waitpid): threadに一応対応 - -Tue Dec 24 15:20:58 1996 Yukihiro Matsumoto - - * version 0.99.4-961224 - - * configure.in: charがunsignedかどうかもチェック - - * regex.c (SIGN_EXTEND_CHAR): __CHAR_UNSIGNED__にも対応 - - * pack.c (pack_unpack): 明示的にsigned charを指定. - -Mon Dec 23 14:41:23 1996 Yukihiro Matsumoto - - * ruby.c (load_file): 標準入力からのスクリプトで一時ファイルを使わ - ないように - - * object.c (f_integer): `0x', `0'などでbaseを解釈するように. - -Fri Dec 20 01:44:39 1996 Yukihiro Matsumoto - - * Makefile.in (flock.o): flockに対応 - -Thu Dec 19 20:13:32 1996 Yukihiro Matsumoto - - * version 0.99.4-961219 - -Wed Dec 18 00:06:48 1996 Yukihiro Matsumoto - - * glob.c (glob_filename): strrchrがマクロの場合に対応 - - * configure.in: をチェック - - * ext/kconv/kconv.c: 1.62ベースに - - * ext/kconv/kconv.c: Kconvモジュール - - * string.c (str_substr): lenが元の文字列より長い時に対応 - - * parse.y (iterator): 「$bar do .. end」などは許さないように - - * parse.y (iterator): FID(foo!,foo?)をdo形式のイテレータにできる. - - * missing/flock.c (flock): lockf()を使って代替 - - * file.c (file_flock): flockを実装 - -Tue Dec 17 12:13:38 1996 Yukihiro Matsumoto - - * version 0.99.4-961217 - -Fri Dec 13 02:05:03 1996 Yukihiro Matsumoto - - * configure.in: RUBYLIBのカレントを後回し(@mix/awk offline) - - * dln.c: AIXに対応した?(@mix/awk offline) - - * eval.c (thread_schedule): critical sectionでも明示的なコンテキス - トスイッチは起きないとまずい - - * re.c (reg_search): matchに失敗した時に$~をnilに. - - * re.c (reg_search): 毎回matchを生成するように - -Thu Dec 12 17:03:30 1996 Yukihiro Matsumoto - - * numeric.c (flo_to_s): 2.0.to_s -> 2.0に - - * eval.c (thread_save_context): $_, $~をthread毎に保存 - - * eval.c (thread_kill): main threadではexit(0) - - * string.c (str_split_method): 間違った結果を返していた - -Thu Dec 12 15:32:48 1996 WATANABE Hirofumi - - * dir.c: CYGWIN32対応 - - * ext/socket/socket.c: CYGWIN32対応 - - * io.c: CYGWIN32対応 - -Thu Dec 12 14:43:51 1996 Jun Kuroda - - * lib/tk.rb: wish4.2も探索候補に含める - - * config.guess: JCC対応 - -Thu Dec 12 00:41:17 1996 Yukihiro Matsumoto - - * version 0.99.4-961212 - - * parse.y (parse_string): """..."""はやはり無くすことにした - - * parse.y (parse_regx): %r|...|でterminatorを \ でエスケープできる - ように - - * signal.c (posix_signal): sigactionを使うsignal - - * configure.in: posix signal/bsd signalの検出 - -Wed Dec 11 17:47:35 1996 Yukihiro Matsumoto - - * eval.c (thread_schedule): critical sectionではコンテキストスイッ - チが起きないように - - * lib/thread.rb: SharedMutexクラス - - * lib/jcode.rb: String#scanを使うように - -Tue Dec 10 12:21:28 1996 Yukihiro Matsumoto - - * version 0.99.3-961210 - - * string.c (str_split_method): 正規表現に()を含む時にバグ - - * lib/jcode.rb: ちょっとましになった - - * string.c (tr_setup_table): 置換文字が短すぎる(2文字)のときのバグ - -Mon Dec 9 11:38:04 1996 Yukihiro Matsumoto - - * string.c (str_scan): 文字列のマッチを行う.イテレータとしても動 - 作する - - * regex.c (re_copy_registers): allocatedが初期化されていなかった - - * re.c (match_to_s): $~の文字列化 - - * re.c (match_to_a): $~を配列化できるように - - * re.c (match_getter): レジスタが初期化されていなかった - -Thu Dec 5 11:06:10 1996 Yukihiro Matsumoto - - * string.c (str_split_method): マッチしなかった括弧は空文字列を - pushするべきではない - - * string.c (str_succ): アルファベットを含まない文字に対応 - -Wed Dec 4 10:48:09 1996 Yukihiro Matsumoto - - * version 0.99.3-961204 - - * io.c (io_binmode): DJGPPでのbinmode対応 - - * sprintf.c (f_sprintf): intの範囲の数値は直接sprintfで変換する - - * sprintf.c (f_sprintf): "%02s"に頼らない - - * re.c (reg_search): indexでSEGV - -Tue Dec 3 10:09:36 1996 Yukihiro Matsumoto - - * version 0.99.3-961203 - - * ext/extmk.rb.in (install): INSTALL_DATAからINSTALLに変更 - - * dln.c: hpux対応 - - * string.c (str_aset_method): 負の値を含む範囲でも例外を起こさない - - * array.c (ary_replace): 負の値を含む範囲でも例外を起こさない - - * array.c (beg_len): beg==endの時,長さ0に - -Mon Dec 2 14:07:12 1996 Yukihiro Matsumoto - - * configure.in: HP shl対応 - - * string.c (str_upto): beg > endの時無限ループに落ちるのを止めた - - * range.c (range_each): String#uptoが再定義された場合に対応 - - * string.c (str_split_method): "ABC".split(/(B)/)が誤動作 - -Sat Nov 30 01:43:52 1996 Yukihiro Matsumoto - - * eval.c (rb_eval): undefでSEGV - -Fri Nov 29 12:17:59 1996 Yukihiro Matsumoto - - * sample/ruby-mode.el (ruby-parse-region): %Q#..#などに対応.しか - し,区切り文字が演算子で行末にある場合には対応できなかった. - - * re.c (reg_raise): 例外でもスラッシュをエスケープ - - * re.c (reg_inspect): スラッシュをエスケープ - - * parse.y (parse_string): `%[QqXxRr](.)..\1'なる文字列形式(テスト - 採用) - - * parse.y (parse_qstring): '''...'''の形式 - - * ext/dbm/dbm.c (Init_dbm): 述語key?,value?の追加 - - * ext/dbm/dbm.c (Init_dbm): includes->include? - - * hash.c (Init_Hash): 述語key?,value?,include?の追加 - - * eval.c (rb_eval): unlessでelse節が実行されない(うーん) - - * string.c (str_sub_iter_s): イテレータブロック内でマッチが行われ - ると位置がずれる(時に無限ループに落ちる) - - * string.c (str_resize): lenが0の時sizeの調整が行われなかった - -Thu Nov 28 00:59:54 1996 Yukihiro Matsumoto - - * version 0.99.3-961128 - - * parse.y (parse_string): 3-quote styleの文字列(例:"""abc"d"e""") - - * configure.in (EXTSTATIC): extを静的にリンクする時にはrubyはdllを - 使うように - - * io.c (Init_IO): getsの引数が間違っていた - - * string.c (str_each_line): RSを明示的に指定できるように - -Wed Nov 27 12:37:46 1996 Yukihiro Matsumoto - - * version 0.99.3-961127 - - * eval.c (rb_eval): iver defined? でselfを指定するのを忘れた - - * io.c: gets等でRSを明示的に指定できるように - - * ext/extmk.rb.in (install): static linkに失敗 - -Tue Nov 26 10:33:04 1996 Yukihiro Matsumoto - - * version 0.99.3-961126 - - * string.c (str_sub_s): 置換後の文字列長さが間違っていた - -Mon Nov 25 09:11:22 1996 Yukihiro Matsumoto - - * numeric.c (fix_rshift): 32以上の右シフトで0を返すように(Cの - rshiftは(x>>(y%32))を返していた). - - * string.c (str_gsub): 置換が行われない場合があった - - * string.c (str_resize): 本当に必要な時だけrealloc - -Thu Nov 21 04:13:21 1996 Yukihiro Matsumoto - - * configure.in (EXTSTATIC): --with-static-linked-extで全てのモジュー - ルを静的リンクするように - - * pack.c (pack_unpack): 行末の改行がない時にもチェックサムをスキッ - プするように - -Wed Nov 20 96 21:42:51 1996 Yasuo OHBA xc - - * configure.in: freebsd対応 - -Wed Nov 20 10:24:24 1996 Yukihiro Matsumoto - - * ext/extmk.rb.in (install): 通常リンク用のLDFLAGSとダイナミックリ - ンク用のDLDFALGSを分離 - - * ext/extmk.rb.in (install): コンパイルの成功したものを静的リンク - のリストに追加する - - * eval.c (f_missing): オブジェクトの文字列表現が長すぎる時バッファ - を書き潰していた - - * process.c (proc_exec_v): forkした後例外を発生させてはいけない - -Tue Nov 19 13:28:15 1996 Yukihiro Matsumoto - - * version 0.99.3-961119 - - * eval.c (mod_method_defined): Module#method_defined? の追加 - - * parse.y (call_args): 引数が唯一のコマンドコールである時のバグ(戻 - り値が展開されてしまう) - -Mon Nov 18 13:28:18 1996 Yukihiro Matsumoto - - * string.c (str_sub): 失敗した時にnilを返していた - - * string.c (str_split_method): 検索開始位置が移動してなかった - - * ext/socket/socket.c (sock_s_getservbyaname): まだ間違っていた - - * version 0.99.3-961118 - - * string.c (str_sub_s): 元の文字列を置換するのを止めた - - * pack.c (encodes): 領域外をアクセスしていた - -Fri Nov 15 17:10:35 1996 Yukihiro Matsumoto - - * bignum.c (big_divmod): Bignumが引数の場合の対応忘れ - - * sample/ruby-mode.el (ruby-expr-beg): word?形式への対応が不完全 - -Wed Nov 13 15:42:40 1996 Yukihiro Matsumoto - - * string.c (str_tr_s_bang): tr_sでtrが行われていなかった - - * eval.c (rb_eval): autoloadクラスのチェック - - * string.c (f_sub): subがsub!と同じ動作になっていた - - * eval.c (thread_sleep): stopとsleepの分離 - -Mon Nov 11 13:53:19 1996 Yukihiro Matsumoto - - * version 0.99.3-961111 - - * numeric.c (fix_step): to, stepが整数以外の場合に対応 - - * eval.c (rb_call): dynamic varがdynamic scopingになっていた(これ - はまずい) - - * string.c (str_chop_bang): 長さ0の文字列のchopで,領域外のアクセ - スが発生していた. - - * parse.y (yyerror): 割り当てた領域外をアクセスしていた - -Fri Nov 8 11:54:46 1996 Yukihiro Matsumoto - - * eval.c (thread_yield): scopeをheapにコピー - -Thu Nov 7 09:56:53 1996 Yukihiro Matsumoto - - * numeric.c (num_coerce): とりあえず両辺をFloatに変換することに - -Wed Nov 6 10:45:13 1996 Yasuo OHBA - - * lib/parsearg.rb: 第2引数を変更. - -Tue Nov 5 14:21:09 1996 Yukihiro Matsumoto - - * version 0.99.3-961105 - -Sat Nov 2 01:11:40 1996 Yukihiro Matsumoto - - * bignum.c (big_pow): typo (dy -> dx) - - * bignum.c (big_divmod): 知らない型はfloatに変換してみる - - * numeric.c (fix_lshift): 境界条件のバグ(負になっていた) - - * bignum.c (big_pow): 無駄なfloatへの変換をなくした - - * math.c (math_atan2): typo(x -> y) - -Fri Nov 1 15:30:59 1996 Yukihiro Matsumoto - - * ext/socket/socket.c (sock_gethostname): gethostnameがない時には - unameを使ってホスト名を得る - - * ext/etc/etc.c (etc_getlogin): getloginがNULLを返しても環境変数を - 調べるように - - * object.c (krn_clone): オブジェクトのフラグもコピー - - * hash.c (rb_cmp): ハッシュの比較を`=='でなく`eql?'に変更 - - * math.c (Need_Float): Float()を使って変換する - - * compar.c (cmp_gt): 以前の右辺を返す仕様の名残が残っていた - -Thu Oct 31 12:55:51 1996 Yukihiro Matsumoto - - * version 0.99.3-961031 - - * numeric.c (Init_Numeric): typo - - * eval.c (error_print): 長すぎるtrace backを途中省略する - - * regex.c (re_compile_pattern): 全角のrangeに対応 - -Wed Oct 30 03:03:18 1996 Yukihiro Matsumoto - - * version 0.99.3-961030 - - * io.c (f_ungetc): 関数を追加 - - * eval.c (dyna_var_asgn): return値忘れ - -Tue Oct 29 10:05:28 1996 Yukihiro Matsumoto - - * string.c (f_split): 関数splitを追加 - - * eval.c (rb_call): ネストした外側のクラス/モジュールの定数を参照 - できるように - -Mon Oct 28 09:51:03 1996 Yukihiro Matsumoto - - * string.c (str_sub): offsetが文字の末尾にある時のチェック - - * regex.c (re_match): 割り当てるレジスタの数が1多かった - - * io.c (io_gets): $/ = ""の動作をperlに合わせる(awkとはちょっと違 - うらしい) - - * io.c (io_gets): $/ = nilの時少し高速化 - - * string.c (str_split_method): 括弧がnullにマッチした時にも無視し - ないように - - * string.c (str_split_method): 括弧にマッチした分はlimitの数に含め - ないように. - - * numeric.c (num_coerce_bin): coerceの定義を変更,2要素の配列 - [x,y]を返すように - - * sample/ruby-mode.el (ruby-calculate-indent): "do |aa|"の対応を改 - 善した. - -Sat Oct 26 01:43:51 1996 Yukihiro Matsumoto - - * ext/marshal/marshal.c (w_object): ビルトインクラスのサブクラスを - 正しく復旧できるように - - * ext/marshal/marshal.c (w_object): ユーザ定義dumpの優先 - - * numeric.c (flo_coerce): Float()を使って定義 - - * numeric.c (Init_Numeric): Numericのnewのundefはまずい - - * ext/marshal/marshal.c (w_symbol): シンボルの内容(文字列)は一度し - かファイルに書き出さない. - - * sample/ruby-mode.el (ruby-parse-region): if/while修飾子に対応し - なくなっていた - - * bignum.c (Init_Bignum): Bignum.newを除く - - * eval.c (rb_eval): 引数評価後にファイル名と行番号を再設定 - - * numeric.c (flo_div): typo - - * sample/ruby-mode.el (ruby-parse-region): def /, def `に対応 - -Fri Oct 25 09:26:29 1996 Yukihiro Matsumoto - - * sample/ruby-mode.el (ruby-calculate-indent): "do |aa|"に対応 - - * array.c (ary_aset): indexがfixnumの場合ちょっと高速化 - - * eval.c (thread_fd_writable): 書き込み前のselectチェック - - * array.c (ary_assoc): 無限ループに落ちた - - * eval.c (thread_wait_for): selectがエラー終了した時,linux以外で - の動作が正しくなかった. - -Thu Oct 24 08:26:48 1996 Yukihiro Matsumoto - - * eval.c (backtrace): `$@'を文字列から配列に変更した. - - * eval.c (eval): eval中の例外発生位置を保存する - - * bignum.c (bigsub): オペランドの大小比較の失敗 - - * re.c (reg_search): 直接参照がない時にも`$~'がセットされるように - -Wed Oct 23 10:40:10 1996 Yukihiro Matsumoto - - * version 0.99.2-961023 - - * ext/marshal/marshal.c (r_bytes): mallocをやめ,allocaを使う - - * sample/ruby-mode.el (ruby-calculate-indent): 括弧の対応を変更. - ()内ではインデントをレベルを合わせるように - -Tue Oct 22 12:59:11 1996 Yukihiro Matsumoto - - * hash.c (hash_s_new): sizeを指定できるように - - * ext/marshal/marshal.c (w_object): dumpする深さ制限を指定できるよ - うに - - * array.c (ary_s_new): sizeを指定した時の初期化忘れ - - * object.c (f_float): big2dblの宣言忘れ. - - * bignum.c (bigsub): 大きさの近いBignum同士の演算で結果が負になる - 場合に間違いがあった. - - * array.c (ary_aset): 置換先と置換元が同じ長さの時内容を - shift(memmove)しないように. - - * ext/marshal/marshal.c (marshal_dump): ファイルフォーマットにバー - ジョンを埋め込むように - - * ext/marshal/marshal.c (tmpnam): linux-aout-dln用に定義 - -Mon Oct 21 08:40:20 1996 Yukihiro Matsumoto - - * ext/socket/socket.c (sock_s_gethostbyname): hostent構造体の情報 - を返す - (sock_s_gethostbyaddr): IPアドレスからhostent構造体を得る - (sock_s_getservbyaname): getservbyname(3) - -Fri Oct 18 10:37:36 1996 Yukihiro Matsumoto - - * sample/ruby-mode.el (ruby-indent-to): 移動先カラムが負になるバグ - - * eval.c (compile): evalで元ソースの行番号でエラーを表示する - -Thu Oct 17 09:52:28 1996 Yukihiro Matsumoto - - * eval.c (eval): evalで文法エラーがあった時にSEGV - - * lib/safe.rb: Restricted.evalの中だけ制限を加える. - - * eval.c (error_print): バックトレースの出力.callerで例外発生位置 - を調整した時に問題が出る(そんなことをしなければ良いのだが…) - - * eval.c (make_backtrace): バックトレースの生成 - -Wed Oct 16 12:56:22 1996 Yukihiro Matsumoto - - * ruby-man-0.99.2-jp/index.html: 日本語版ドキュメントの完成(長かった…) - - * re.c (reg_regcomp): $=がnilの時の処理 - - * string.c (f_chop): $_に対するchop - -Tue Oct 15 11:04:23 1996 Yukihiro Matsumoto - - * version 0.99.2-961015 - -Mon Oct 14 18:22:38 1996 Yukihiro Matsumoto - - * eval.c (thread_schedule): BOW対応.selectが-1を返した時にバグ(実 - はdo .. whileがcontinueで先頭にジャンプすると思い込んでいた.条 - 件の直前だったのね ^^);;;;; - - * sample/ruby-mode.el (ruby-mode-syntax-table): ?のsyntaxが"/"では - まずいらしい - - * hash.c (rb_hash): name conflict - -Fri Oct 11 00:23:05 1996 Yukihiro Matsumoto - - * version 0.99.2-961011 - - * ext/marshal/marshal.c (w_object): 結局動いていなかった循環オブジェ - クト対応を外した. - - * hash.c (rb_hash): Fixnumと文字列の高速化 - - * ext/marshal/marshal.c (w_object): 無駄なデータの削除(フォーマッ - トの非互換性) - - * io.c (io_readline): 戻り値の不備 - - * ext/marshal/marshal.c (marshal_dumps): MSDOS対応 - - * ruby.c (load_file): MSDOS対応 - -Wed Oct 9 17:46:27 1996 Yukihiro Matsumoto - - * ext/extmk.rb.in (install): 無駄なコピーを避ける - - * string.c (str_sub_method): マッチがなかった時のString#subの値が - 違っていた. - - * eval.c (obj_extend): extendした時にobject_extendedを呼ぶように - -Tue Oct 8 00:55:38 1996 Yukihiro Matsumoto - - * eval.c (thread_alloc): 割当の平均化 - - * eval.c (thread_schedule): joinのバグを修正 - - * eval.c (thread_wait_for): selectへの割込みなどに対応 - - * eval.c (thread_select): linuxのselectの挙動に対応(timeoutが変化 - する) - -Mon Oct 7 09:47:19 1996 Yukihiro Matsumoto - - * version 0.99.2-961007 - - * eval.c (PUSH_BLOCK): the_classの保存を忘れていた. - - * ext/dbm/dbm.c (fdbm_store): sizeの保存する場所が間違っていた - - * ext/socket/socket.c (s_accept): thread対応していなかった - -Sat Oct 5 01:32:27 1996 Yukihiro Matsumoto - - * io.c (io_readchar): EOFで例外を発生させる - -Fri Oct 4 11:59:54 1996 Yukihiro Matsumoto - - * ext/marshal/marshal.c (w_object): HashとObjectの復旧に必要なハッ - シュテーブルが渡されていなかった. - - * variable.c (rb_path2class): ユーザ定義クラスの復旧に失敗していた - - * variable.c (rb_path2class): クラスが存在しない時のエラーをFatal - からNameErrorへ. - - * range.c (range_s_new): first,lastが両方Numericの時エラーになって - いた. - - * range.c: start->first, end->last - -Wed Oct 2 02:02:46 1996 Yukihiro Matsumoto - - * file.c: DJGPPでchmod,chownを使えるように(ってDOSにchownがあるのか?) - - * class.c (rb_singleton_class): ビルトインクラスもextendしたり特異 - メソッドを追加したりできるように - - * variable.c (rb_set_class_path): ユーザ定義のトップレベルクラスに - pathを設定しない - - * eval.c (eval): 例外がRuntimeErrorに化けていた - - * eval.c (eval): eval中の例外の表現の改善 - - * eval.c (eval): eval_with_bindingとの一本化 - - * eval.c (rb_eval): クラス/モジュール定義の中から定義中のクラス/モ - ジュールが参照できるように - -Tue Oct 1 01:40:09 1996 Yukihiro Matsumoto - - * version 0.99.2-961001 - - * parse.y: cur_crefが2度宣言されていた - - * signal.c (trap): SIGSEGV,SIGBUSのない機種に対応 - - * io.c (Init_IO): 引数タイプの指定間違い - -Mon Sep 30 15:28:00 1996 Yukihiro Matsumoto - - * version 0.99.2-960930 - - * config.guess,config.sub: $host_osが正しく設定されない - - * eval.c (rb_eval): yieldで正しくないselfが設定されていた - - * eval.c (ruby_run): toplevelの例外処理のバグ - -Mon Sep 30 09:13:26 1996 WATANABE Hirofumi - - * djgpp対応 - -Sat Sep 28 02:45:10 1996 Yukihiro Matsumoto - - * version 0.99.2-960928 - - * sample/ruby-mode.el (ruby-beginning-of-block): ブロックの先頭に - 移動(正しくインデントしていないと動作しない) - (ruby-end-of-block): 同上 - - * eval.c (class_s_new): Class#newがイテレータとして呼ばれた時は - initializeもイテレータとして呼ばれるように - - * signal.c (sigsegv): SEGVでbacktraceを表示するように - -Fri Sep 27 09:51:07 1996 Yukihiro Matsumoto - - * version 0.99.2-960927 - - * eval.c (error_print): 引数のないraiseでメッセージが正しく表示さ - れるように. - - * eval.c (rb_longjmp): mesgがnilの時RuntimeErrorを生成する. - - * eval.c (f_raise): 引数がない時に対応 - - * eval.c (thread_mark): stack上にないデータのアドレス変換を行って - いた. - - * eval.c (Init_Thread): 割込みの間隔が1秒と長すぎた. - -Thu Sep 26 16:02:45 1996 Yukihiro Matsumoto - - * eval.c (thread_schedule): 一度ペンディングになるとフラグがクリア - されていなかった. - - * process.c (rb_proc_exec): system/execの引数が空文字列であった場 - 合,例外を発生すべきだった. - - * config.sub/config.guess: 新しいものに置き換え - -Thu Sep 26 15:41:35 1996 WATANABE Hirofumi - - * io.c (next_argv): -i.bakをBOWとDOSに対応. - -Thu Sep 26 01:31:43 1996 Yukihiro Matsumoto - - * io.c (io_sysread): EOFで例外 - - * io.c (f_readline): EOFで例外を発生するように.getsは互換性のため - nilを返すままにする - - * eval.c (proc_call): lambdaからのreturnでIN_BLOCKフラグが立ったま - まだった - - * eval.c (PUSH_BLOCK2): threadに対応するためBlockを一度stackにコピー - -Wed Sep 25 11:54:11 1996 Yukihiro Matsumoto - - * parse.y (method_call): Const::method()形式を使えるようにしてみた. - 引数括弧は省略できない. - - * sample/test.rb: Process.killの存在を確かめてからテストを行う - - * eval.c (eval_with_binding): 第2引数としてbinding(またはlambda)を - 与えるとその環境でevalを実行するようにした - - * eval.c (f_binding): 現在のbindingを返す関数 - - * eval.c: block構造体にthe_classを保存するメンバを追加 - - * process.c (Init_process): kill,wait,waitpidをProcessに移動 - -Tue Sep 24 02:44:43 1996 Yukihiro Matsumoto - - * sample/ruby-mode.el: いろいろ問題が多いので以前の高速化は破棄. - 別のアプローチを使った. - - * lib/tk.rb (Tk.pack): 複数のウィンドウを受け付けるpack - -Sat Sep 21 11:08:09 1996 Yukihiro Matsumoto - - * parse.y (exprs): 空文も受け付けるように文法を変更.今までは改行 - の連続だけが許されていた. - -Fri Sep 20 11:39:18 1996 Yukihiro Matsumoto - - * Failの大半を名前つき例外に変更. - - * re.c (Init_Regexp): 名前つき例外を導入. - - * eval.c (f_missing): Objectはinspectしない. - - * object.c (inspect_i): Object#inspectでloopに対応. - - * regex.c (re_search): /^$/が""にマッチしなかった. - -Thu Sep 19 19:25:12 1996 Yukihiro Matsumoto - - * regex.c (re_search): /^$/が非空行にマッチしていた. - -Tue Sep 17 10:28:11 1996 Yukihiro Matsumoto - - * version 0.99.2-960917 - -Mon Sep 16 10:47:56 1996 Yukihiro Matsumoto - - * sample/ruby-mode.el (ruby-calculate-indent): 演算子継続の場合の - 文字列の判定のバグ - - * sample/ruby-mode.el (ruby-calculate-indent): elseなどの次の行の - インデント計算を正しく. - -Sat Sep 14 08:37:19 1996 Yukihiro Matsumoto - - * version 0.99.2-960914 - -Fri Sep 13 08:06:03 1996 Yukihiro Matsumoto - - * ext/socket/socket.c (tcpaddr): port番号にntohsをつけ忘れ - - * dln.c (link_undef): テーブルの種類が間違っていた. - - * bignum.c (bigadd): 引き算が発生する時に計算違いが起きていた. - - * parse.y (iter_do_block): do..endでもdynamic variableを. - - * bignum.c (big_pow): より正確な計算を(整数同士ではfloatに変換しな - い). - -Thu Sep 12 13:11:55 1996 Yukihiro Matsumoto - - * variable.c (rb_set_class_path): Stringクラスが初期化される前に - Stringを作っていた.組込みクラスにはpathはいらない - - * parse.y (yylex): 0.1が0になっていた - - * parse.y (yylex): 行番号の不整合 - - * gc.c (oblist_live_obj): 今「生きている」全部のオブジェクトを返す - イテレータ.そのクラス(またはサブクラス)の全部のインスタンスを返 - すeach_object_ofも定義した. - - * class.c (rb_define_class_id): 無駄なクラスを割り当てていた.結果 - として未初期化のクラスオブジェクトが存在していた. - -Wed Sep 11 00:56:23 1996 Yukihiro Matsumoto - - * parse.y (yylex): octalの定数の検出をより正確に(090はエラーとか). - - * bignum.c (big_minus): yがxより大きい場合にエラー. - - * parse.y (yylex): エラー行番号の表示をより正確に - - * sample/ruby-mode.el (ruby-expr-beg): 変数名が1文字の時誤動作して - いた. - - * sample/ruby-mode.el (ruby-calculate-indent): ?/でループに落ちい - たバグを修正. - - * enum.c (enum_min,enum_max): sortのようにイテレータとしても動作す - るように. - - * enum.c (enum_find_all): typo - -Tue Sep 10 12:07:12 1996 Yukihiro Matsumoto - - * node.h (nd_line): NODEのlineをflagsに押し込めてオブジェクトサイ - ズを小さくした.制限:32bit intのマシンの場合,ファイルの行数が - 32767を越えると正常に表示されない. - - * st.c: hashとcompareの関数メンバを構造体にパック,クラス的な使い - 方を行う.1 tableあたり4 byteの節約. - -Mon Sep 9 16:35:54 1996 Yukihiro Matsumoto - - * file.c (file_truncate): 提供されない時には特別な例外を発生するよ - うに. - - * eval.c (Init_Proc): 不適切な位置のlocal-jumpを例外に. - -Sat Sep 7 17:06:15 1996 Yukihiro Matsumoto - - * eval.c (proc_call): まだスコープがスタック上にある時には局所脱出 - を有効にする.これで,procを生成してcallすることは,スコープを脱 - 出しない限り,yieldと同じ意味を持つことになる. - -Fri Sep 6 13:30:59 1996 Yukihiro Matsumoto - - * sample/ruby-mode.el (ruby-indent-to): インデントが変わらない時に - はバッファを変更しない. - (ruby-calculate-indent): まず文字列の内部か判断してから,前の行 - からパーズを行う.defunが大きくなった時の高速化. - (ruby-in-string-p): 文字列の内部かどうかを判断する関数(以前の - parseから分離) - (ruby-parse-region): 文字列に対する処理をはずす. - (ruby-beginning-of-block): ブロックの先頭に - (ruby-end-of-block): ブロックの末尾に(遅い…) - -Thu Sep 5 14:23:07 1996 Yukihiro Matsumoto - - * file.c (file_s_split): [dirname,basename]にsplitする. - - * eval.c (rb_eval): evalの中でも定数の値が正しくなるように.これで - 定数に関しては静的なスコープが保証されるようになった. - - * st.c (rehash): ハッシュ拡大の系数を2から1.79に.割算がより良い値 - を返すように. - -Thu Sep 5 00:32:07 1996 Yukihiro Matsumoto - - * eval.c (class_superclass) クラスのスーパークラスを返すメソッド. - -Wed Sep 4 16:54:56 1996 Yukihiro Matsumoto - - * random.c (f_rand): Bignumやlongの範囲を越えるFloatに対する乱数も - 発生できるように. - - * struct.c (struct_alloc): Fatalではなく例外を発生させるように(通 - 常の使用で発生しうる). - - * struct.c (struct_s_members): Structの特異メソッドではなく,生成 - されたStructクラスの特異メソッドにした. - - * st.c (st_init_table): ruby専用にパラメタを固定にした(サイ - ズが減った) - -Mon Sep 2 11:37:59 1996 Yukihiro Matsumoto - - * array.c (ary_shift): capaがあまりにも大きい時には領域をREALLOC - (ary_pop): 同上 - - * string.c (str_inspect): multibyte character 対応にミス. - (str_inspect): unsigned charにしないと符号展開されてしまう - - * parse.y (primary): `::'をprimaryに移動 Foo::Bar.Bazがエラーにな - らないように. - - * parse.y (primary): オペレータ形式の特異メソッドが定義できない - - * random.c (f_rand): maxが0の時に対応 - - * io.c (io_printf): 関数を定義していたがインタプリタに登録していな - かった. - - * file.c (file_s_basename): 第2引数が無い時にエラー. - -Thu Aug 29 10:49:40 1996 Yukihiro Matsumoto - - * parse.y (expr): イテレータの新形式に「method do .. end」形式を採 - 用した.もちろん昔の形式も有効. - - * sample/ruby-mode.el (ruby-calculate-indent): endの数の方が多い場 - 合にもエラーを起こさないように. - -Wed Aug 28 09:41:36 1996 Yukihiro Matsumoto - - * numeric.c (upto,downto,step,times): 対象がfixnumの範囲を越えても - 動作するように. - -Mon Aug 26 10:04:37 1996 Yukihiro Matsumoto - - * missing/setenv.c (envix): typo(missing `== 0' for memcmp) - - * dir.c (dir_foreach): foreach(dir open -> read loop -> closeまで) - - * io.c (io_foreach): foreach(file open -> read loop -> closeまで) - - * Fatalのうち捕捉可能ないくつかを例外に. - -Sat Aug 24 23:56:37 1996 Yukihiro Matsumoto - - * bignum.c (bigdivmod): FIX2INT -> INT2FIX 大間違い - -Fri Aug 23 18:13:03 1996 Yukihiro Matsumoto - - * regex.c (re_free_registers): allocateしていない時には当然 free - してはいけない. - -Thu Aug 22 01:20:35 1996 Yukihiro Matsumoto - - * eval.c (thread_create): 外側から強制終了させられたthreadは - cleanupする必要が無い. - -Wed Aug 21 09:57:28 1996 Yukihiro Matsumoto - - * eval.c (thread_create): threadを終了させた大域脱出の情報を - main_threadに渡すように. - - * parse.y (call_args): 最終引数に括弧を省略したメソッド呼出しを置 - けるように(例: print foo bar, baz == print(foo(bar,baz))) - -Tue Aug 20 13:37:16 1996 Yukihiro Matsumoto - - * eval.c (masign): 多重代入とrest引数の動作を合わせて空の配列を代 - 入するように. - - * parse.y (arg): defined?の強度をもうちょっと強く - - * eval.c (error_print): -wで例外名も表示するように - - * eval.c (rb_eval): 新構文に対応 - (handle_rescue): 捕捉する例外を kind_of? で同定 - - * parse.y (primary): rescueの構文を変更(同定引数の追加,複数rescue) - - * Fail()のかなりを適当な例外を使うように - - * eval.c (thread_interrupt): Interrupt(今はnon-local jump)は - main-threadに送られるように. - - * eval.c (rb_longjmp): $! の内容を文字列から例外クラスに変更 - (rb_raise): rb_fail から名称変更 - (rb_interrupt): 例外化 - (rb_exit): 例外化 - - * error.c (Init_Exception): 例外クラスの新設(文字列のサブクラス) - -Mon Aug 19 19:40:52 1996 Yukihiro Matsumoto - - * signal.c (trap): 古いハンドラを返すように. - -Wed Aug 14 00:07:18 1996 Yukihiro Matsumoto - - * eval.c (rb_trap_eval): ハンドラのためにthreadをforkすることを止 - めた. - - * eval.c (thread_mark): thread毎の $!, $@ をマークし忘れ - - * ext/dbm/dbm.c (fdbm_delete): イテレータとして呼ばれた場合,要素 - が無ければブロックを評価する. - - * hash.c (hash_delete): イテレータとして呼ばれた場合,要素が無けれ - ばブロックを評価する. - - * array.c (ary_delete): イテレータとして呼ばれた場合,要素が無けれ - ばブロックを評価する. - - * eval.c (rb_interrupt): SIGINTのデフォルトをexitから特別な大域脱 - 出に.やはり割り込まれた位置の表示が無いのは寂しいので. - -Tue Aug 13 01:34:00 1996 Yukihiro Matsumoto - - * eval.c (rb_exit): sub-thread内でのexitもstatusを保存するように - (thread_create): 自thread内のexitに対応 - - * signal.c (sighandle): SIGINTのデフォルトハンドラはexitするように - (以前は例外を発生していた). - - * 例外の一部をFatalに. - - * string.c (str_aset): 文字列の置換の対象が部分文字列でなかった時, - 例外を発生させないように - - * eval.c (proc_call): Procの中からbreak/nextは通し,他のものは通さ - ないように - -Mon Aug 12 14:15:09 1996 Yukihiro Matsumoto - - * object.c (krn_type): 文字列を返す - - * eval.c (thread_create): sub-thread内でのexitに対応 - - * numeric.c (fix_type): 文字列を返す - - * io.c (f_p): デバッグ用データ表示メソッド - - * eval.c (f_missing): nil/TRUE/FALSEを特別扱い - - * string.c (str_inspect): 長い文字列を短縮表示.inspectの働きを - human readable stringの生成に統一(re-generatable string は正式に - 無くなった). - -Sat Aug 10 16:54:21 1996 Yukihiro Matsumoto - - * object.c (Init_Object): kernel/nil/false/trueのクラス名を変更(小 - 文字に),rubyスクリプトからアクセスできないように. - - * eval.c (rb_eval): CONSTANTのアクセス先を単純化.crefを使わない. - - * eval.c (f_eval): 特異メソッド内でも定数の値が正しくなるように - -Fri Aug 9 12:23:17 1996 Yukihiro Matsumoto - - * array.c (ary_concat): append -> concat Stringに合わせた - - * parse.y (yylex): `$;'が使えなかった. - - * array.c (ary_push_method): 複数引数を受け付けるように. - (ary_unshift): 複数引数を受け付けるように. - - * io.c (io_popen): IO.popenでcommand pipeが開けるように. - - * object.c (Init_Object): KernelとNilをruby scriptからアクセスでき - ないように. - -Thu Aug 8 01:21:47 1996 Yukihiro Matsumoto - - * object.c (f_integer): 整数への変換関数 - (f_float): 実数への変換関数 - (f_string): 文字列への変換関数 - (f_array): 配列への変換関数 - - * bignum.c (big_to_i): FIXNUMの範囲でない時はBignumのまま返すよう - に変更. - -Wed Aug 7 09:28:38 1996 Yukihiro Matsumoto - - * version 0.99.1-960807 - - * parse.y (mlhs): 「*foo = 1,2,3」タイプの多重代入も可能に. - - * object.c (Init_Object): クラスTrue/Falseをruby scriptからアクセ - スできないように. - - * object.c (nil_inspect): inspect表現は"nil"に - - * io.c (io_print): nilのprintをnilに. - - * object.c (nil_to_s): nilの文字列表現を""に. - -Tue Aug 6 01:12:32 1996 Yukihiro Matsumoto - - * dir.c (dir_s_open): file descripterが足りない時にはgcしてからも - う一度openしてみる. - - * io.c (rb_fopen): すべてのfopen()についてfile descripterが足りな - い時にはgcしてからもう一度openしてみる. - - * ext/socket/socket.c (Init_socket): 定数の追加. - - * sample/ruby-mode.el (ruby-indent-to): インデント後のカーソル位置 - の調整を正しく. - - * gc.c (gc): 割込みチェックを行わない(Cコードの中で安心して - malloc()が使えなくなるので). - - * st.c (call_hash_func): signalとthreadによる割込みに対応. - - * sig.h (DEFER_INTS): 割込み禁止区間の指定 - - * eval.c (f_require): threadによるrequireの競合に対応(最初の - requireが終了するまで他のthreadは待つ). - - * bignum.c (str2inum): 0x80000000の値が負になっていた - - * sprintf.c (f_sprintf): 文字列末尾,行末の単独の`%'に対応 - - * bignum.c (big_cmp): 比較の結果が逆になる時があった. - -Mon Aug 5 10:58:13 1996 Yukihiro Matsumoto - - * process.c (proc_exec_v): 例外のメッセージを分かりやすく. - - * ext/dbm/dbm.c (fdbm_store): nilを格納すると要素の削除になる - - * ext/dbm/dbm.c: サイズをキャッシュ. - -Sat Aug 3 01:52:52 1996 Yukihiro Matsumoto - - * eval.c (rb_fail): `fail'が引数無しで呼ばれた時だけ以前の`$@'を保 - 存するように. - - * eval.c (f_fail): frameの調整 - -Fri Aug 2 11:26:21 1996 Yukihiro Matsumoto - - * ext/socket/socket.c (bsock_setopt): valとしてTRUE/FALSE/Fixnumも - 受け付けるように. - - * ext/socket/socket.c (Init_socket): SO_REUSEADDR等の定数の追加 - - * ext/md5/md5init.c: md5モジュール(初の複数ファイルからなるモジュー - ルでもある) - - * ruby.h (Make_Data_Struct): Data: objectのinstance変数に格納 -> - Data型のObjectに(Dir,Time,Proc,Thread,DBM) - -Thu Aug 1 11:38:44 1996 Yukihiro Matsumoto - - * ext/dbm/dbm.c (fdbm_store): valueが文字で無い時に対応 - -Wed Jul 31 10:53:42 1996 Yukihiro Matsumoto - - * ext/socket/socket.c (open_inet): htonsが必要であった - (tcpaddr): ntohlで変換した - - * process.c (rb_proc_exec): execvp -> execv - -Tue Jul 30 17:48:33 1996 Yukihiro Matsumoto - - * eval.c: `$?'をthread localに - - * Makefile.in (install): install時にstripを行う - - * configure.in: install時のstripの検出 - - * configure.in: NEXTSTEP対応 - - * version 0.99.1-960730 - -Tue Jul 30 16:40:35 1996 SHIROYAMA Takayuki - - * dln.c (dln_load): NeXT dln(mach-o)対応.configureは未対応 - -Tue Jul 30 09:46:51 1996 Yukihiro Matsumoto - - * process.c (f_system): 複数引数もとれるように - - * process.c (f_exec): 複数引数もとれるように - - * array.c (ary_append): 配列(またはEnum)の要素を破壊的に追加 - - * array.c (ary_plus): Enumはその要素を追加 - - * file.c (file_s_open): File.openを追加 - - * struct.c (struct_new): FIX2INTを忘れていた - - * file.c (Init_File): exists? -> exist? - - * object.c (obj_is_kind_of): is_kind_of? -> kind_of?, is_a? - - * object.c (obj_is_instance_of): is_instance_of? -> instance_of? - -Mon Jul 29 16:40:02 1996 Yukihiro Matsumoto - - * parse.y (parse_regx): 式展開を行った場合,casefoldの設定ができて - いなかった. - - * object.c (true_type): TRUE/FALSEにtypeを実装. - - * parse.y (read_escape): 3文字以内のoctalに対応(\0とか) - -Fri Jul 26 00:31:45 1996 Yukihiro Matsumoto - - * array.c (ary_reverse_bang): in-placeで配列を反転させる - (ary_sort_bang): in-placeでsortする - (ary_sort): sortした配列を返すように - (ary_delete_at): 指定した位置の要素を削除する - - * eval.c (rb_call): stack深さチェックを毎回は行わないように - - * error.c (Warning): 実行中のwarningが表示されていなかった - - * eval.c (compile): 例外発生を分離. - - * eval.c (f_eval): 変数rb_in_evalを正しく管理するように - - * ext/dbm/dbm.c (fdbm_store): 格納するkeyを文字列に変換 - - * eval.c (rb_call): 無限再帰のチェックを大域脱出を行うC methodにも - 対応させた.threadのstack深さチェックルーチンを流用. - - * parse.y (yylex): 第1引数のunary -/+の判定が間違っていた. - - * parse.y (yylex): unary +で数字を余計に読んでいた(ex. +5 -> 55) - -Thu Jul 25 12:15:04 1996 Yukihiro Matsumoto - - * parse.y (yylex): 曖昧でない引数に対して警告を出していた. - - * eval.c (iterator_p): 引数で呼んでも正しい結果を返すように. - - * parse.y: break/next/redo/retryのメソッド化. - - * sample/ruby-mode.el (ruby-calculate-indent): nestのチェックミス - - * sample/ruby-mode.el (ruby-parse-region): 予約語のチェックを強化 - - * parse.y (primary): unless/untilの復活 - -Tue Jul 23 18:50:10 1996 Yukihiro Matsumoto - - * array.c (Array#empty?), Hash.c (Hash#empty?), ext/dbm/dbm.c (DBM#empty?): - 空の判定述語 - - * eval.c (f_unless): ifの逆をするイテレータ - - * eval.c (f_until): whileの逆をするイテレータ - - * parse.y: notの優先順位をand/orより高く - - * parse.y (expr): `!'を引数括弧を省略したcallでも有効に - -Mon Jul 22 10:15:38 1996 Yukihiro Matsumoto - - * version 0.99-960722 - - * array.c (ary_print_on): OFSのNILチェックが不完全 - - * ruby.c (load_file): 標準入力からのスクリプトが空の時に対応. - - * ruby.c (proc_options): -wでは引数無しの時には標準入力からスクリ - プトをとる(-vではたんに終了する). - - * array.c (ary_compact): nilの要素を取り除くメソッド - - * array.c (ary_nitems): nilでない要素を数えるメソッド - -Sun Jul 20 00:51:53 1996 Yukihiro Matsumoto - - * ruby.c (proc_options): -w optionを追加 - - * parse.y: {}が閉じていない時には展開しない文字列を - -Fri Jul 19 16:16:05 1996 Yukihiro Matsumoto - - * version 0.99-960719 - - * lib/find.rb: 石塚版(pruneの拡張付き) - - * file.c (test_l): lstatで調べないとね. - - * eval.c (f_throw): 第2引数を省略可能に. - - * parse.y (str_extend): {}のネストに対応 - -Thu Jul 18 18:25:46 1996 Yukihiro Matsumoto - - * version 0.99-960718 - - * parse.y (str_extend): 文字列中の式展開に \" ' ` / を含む事ができ - るように. - -Tue Jul 16 15:55:31 1996 Yukihiro Matsumoto - - * sample/ruby-mode.el (ruby-parse-region): 正規表現内のエスケープ - に対応 - - * version 0.99-960716 - -Fri Jul 12 10:06:19 1996 Yukihiro Matsumoto - - * io.c (f_select): 引数のclose check. - - * ruby.c (load_file): #!行の引数チェックを第1引数に限定(実をいうと - DOS改行対策) - -Wed Jul 10 17:18:35 1996 Yukihiro Matsumoto - - * version 0.99-960710 - - * time.c (time_s_timegm/time_s_timelocal): 時間を生成するメソッド - -Mon Jun 17 15:59:20 1996 Yukihiro Matsumoto - - * version 0.99-960617 - - * parse.y (yyerror): エラー表示の簡略化. - -Wed Jun 12 14:11:01 1996 Yukihiro Matsumoto - - * signal.c (rb_trap_exit): trap 0はthreadを生成せずに処理する. - -Fri Jun 7 10:17:01 1996 Yukihiro Matsumoto - - * array.c/hash.c (indexes): 配列1引数のパターンを無くした.配列の - 場合は`*ary'を使ってもらおう. - - * eval.c (thread_wait_threads): main_threadが終了する前に他の - threadを待つ(強制的には終了させない). - (ruby_run): 他のthreadを待っている間にシグナルが来たら,全thread - を強制終了させる. - - * eval.c (rb_fail): メソッド名を`$!'に埋め込む. - - * eval.c (thread_create): main_threadのコンテクストがセーブされな - い場合があった. - - * process.c (f_sleep): 時間を指定せず,threadがひとつしかない状況 - にも対応. - - * eval.c (thread_create): create後,fnを呼び出す前にcontext switch - が起きると違うcontextでfnが実行されてしまうバグ. - -Mon Jun 3 08:03:17 1996 Yukihiro Matsumoto - - * struct.c (struct_s_def): メンバの指定を文字列,シンボル(FIXNUM) - 双方で可能にした. - - * ext/etc/etc.c (Init_etc): 構造体オブジェクトをGCから保護した. - - * error.c (rb_sys_fail): nil/FALSEを引数として受け付けるように. - -Thu May 30 16:19:08 1996 Yukihiro Matsumoto - - * eval.c (thread_select): EINTRに対応. - -Wed May 29 11:04:51 1996 Yukihiro Matsumoto - - * eval.c (f_catch): catch/throwを実装した. - -Tue May 28 13:30:52 1996 Yukihiro Matsumoto - - * version 0.99-960528 - - * eval.c (thread_cleanup): main threadが終了すると他のthreadも終了 - することの明確化. - - * signal.c (trap): SIGINTのデフォルトの設定ミス(本当にSIG_DFLでは - まずかった).rubyではちゃんとハンドルしないと. - - * eval.c (thread_interrupt): SIGINTはmain_threadに例外を発生させる - ように. - -Mon May 27 15:13:31 1996 Yukihiro Matsumoto - - * eval.c (thread_status): threadの状態を返すメソッド.threadの終了 - を待たない. - - * eval.c (thread_value): 一種のpromiseを実装するためのメソッド. - - * eval.c (thread_join): 待っているthreadが例外を起こした時には, - joinがその例外を発生するように. - - * eval.c (thread_create): threadでの例外をpropagateしないように. - -Fri May 24 10:47:53 1996 Yukihiro Matsumoto - - * enum.c (Init_Enumerable): `size' as alias to the `length' - - * eval.c (thread_save_context): `$@', `$!'をスレッド毎にセーブ. - - * eval.c (superclass): エラー表示をより親切に. - -Thu May 23 10:38:41 1996 Yukihiro Matsumoto - - * version 0.99-960523 - - * eval.c (superclass): エラー時にスーパークラス名を(分かれば)表示 - するように. - -Wed May 22 19:48:42 1996 Yukihiro Matsumoto - - * parse.y (superclass): スーパークラスの指定子を`:'から`<'に変更. - -Tue May 21 09:27:59 1996 Yukihiro Matsumoto - - * lib/thread.rb: threadをサポートするクラス(Mutex, Queue). - -Mon May 20 09:39:49 1996 Yukihiro Matsumoto - - * time.c (time_cmp): 浮動小数点数も扱えるように. - (time_minus): Time - Timeが浮動小数点数を返すように. - -Fri May 17 15:40:10 1996 Yukihiro Matsumoto - - * process.c (rb_proc_exec): Thread対応時にexecの直前に - ITIMER_VIRTUALをリセットする. - -Tue May 14 02:12:44 1996 Yukihiro Matsumoto - - * signal.c (sighandle): SIGINTに対してデフォルトで例外を発生させる - のをやめ,status 130でexitするようにした. - - * eval.c (thread_schedule): Threadのバグはほとんどとれたようだ. - -Fri May 10 11:21:08 1996 Yukihiro Matsumoto - - * eval.c (thread_schedule): ユーザレベルThread機能.効率はともかく - 移植性はある.今後,thread間の通信機能を実装する予定. - -Thu May 2 21:22:31 1996 Yukihiro Matsumoto - - * time.c (time_timeval): struct timevalを直接返すように(static変数 - を使わない). - -Wed May 1 17:27:32 1996 Yukihiro Matsumoto - - * process.c (f_sleep): 整数以外のtimeを指定できるように. - -Thu Apr 25 08:19:15 1996 Yukihiro Matsumoto - - * file.c (file_s_dirname): ファイル名が"/"を含まない時,"."を返す - ように(GNU dirnameの仕様). - - * file.c (file_s_basename): まだnilと0を混同しているソースが残って - いた. - - * parse.y (exprs): エラーリカバリを追加. - -Wed Apr 24 15:51:05 1996 Yukihiro Matsumoto - - * string.c (str_chop_bang): CRLFの場合2 bytesをchop!するように. - - * ext/socket/socket.c (tcp_svr_s_open): まだnilと0を混同しているソー - スが残っていた. - -Tue Apr 23 18:14:25 1996 Yukihiro Matsumoto - - * pack.c (pack_pack): "A/a"のバグ.余計なpaddingが入っていた. - -Thu Apr 18 13:02:11 1996 Yukihiro Matsumoto - - * configure.in: アーキテクチャ依存部を別ディレクトリにインストール - するように. - - * parse.y (yyerror): エラー発生時にエラー行とその位置を表示するよ - うに. - -Wed Apr 17 14:22:42 1996 Yukihiro Matsumoto - - * defines.h: SAFE_SIGHANDLEを無くし,危険な選択はできないように. - - * io.c (io_ungetc): 新機能. - - * ruby.c (load_file): ファイルからの読み込み方式が変わったのに対応. - - * parse.y (compile_file): ファイルからの入力を一度全部読み込むのを - 止めて,getsを使うことにした. - -Wed Apr 10 17:40:11 1996 Yukihiro Matsumoto - - * version 0.98 - -Tue Apr 9 09:54:30 1996 Yukihiro Matsumoto - - * parse.y (iter_block): イテレータブロックの指定をメソッド呼び出し - に限定.文法の明確化. - - * eval.c (rb_eval): 条件式の正規表現の比較をinline化. - - * eval.c (rb_eval): defined? の 定義情報(種別)を文字列で返す. - - * node.h: NODE_BEGIN -> NODE_RESCUE, NODE_ENSUREに分離. - - * eval.c (rb_eval): option -n/-pのトップレベルループのinline展開. - - * parse.y (cond0): 条件式中の文字列は比較の対象としない - -Wed Mar 27 12:33:54 1996 Tairo Nomura - - * defines.h: NeXT対応 - -Wed Mar 27 10:02:44 1996 Yukihiro Matsumoto - - * parse.y: 予約語の変更 continue -> next - -Mon Mar 25 07:34:37 1996 Yukihiro Matsumoto - - * parse.y (parse_regx): o(once)オプションを追加. - -Fri Mar 22 14:25:35 1996 Yukihiro Matsumoto - - * version 0.97d - - * eval.c (dyna_var_defined): 動的ローカル変数の定義チェック用ルー - チン. - - * parse.y (gettable): eval()の中での動的ローカル変数(既に値を持っ - ているもの)の検出に失敗していた. - -Tue Mar 19 10:46:47 1996 Yukihiro Matsumoto - - * version 0.97c - - * re.c (reg_s_new): compile時にsegmentation fault. - - * parse.y (str_extend): いつもevalするように. - -Wed Mar 13 11:00:42 1996 Yukihiro Matsumoto - - * parse.y (str_extend): 文字列中の式展開の不備を無くした. - - * parse.y: 下手なエラーリカバリを外した. - -Tue Mar 12 12:30:20 1996 Yukihiro Matsumoto - - * eval.c (rescue): 間違ってensureでも例外を捕捉していた. - -Wed Mar 6 12:11:03 1996 Yukihiro Matsumoto - - * parse.y (var_extend): 変数展開"#{}"で,任意の式を書けるようにし - た,これで「変数」展開では無くなっちゃったなあ. - - * regex.c (init_syntax_once): `_'をwordに追加. - - * regex.c (re_compile_pattern): `\w',`\W'の判定をsyntax tableを使 - うように. - -Tue Feb 27 10:15:32 1996 Yukihiro Matsumoto - - * object.c (obj_inspect): 表示するインスタンス変数が無い時には, - to_sを使う. - - * configure.in: dlnの検出を自動的に. - -Mon Feb 26 19:55:33 1996 Yukihiro Matsumoto - - * ruby.c (readin): read(2)で一度にファイルが読み込めない場合に対応. - -Sat Feb 24 14:47:18 1996 Yukihiro Matsumoto - - * version 0.97b - -Fri Feb 23 11:26:02 1996 Yukihiro Matsumoto - - * class.c (rb_define_module): C言語で定義されたモジュールのPATHの - 設定忘れ.文字列化でcore dump. - - * eval.c (mod_include): 戻り値をnilに. - - * version 0.97a - -Thu Feb 22 21:03:42 1996 Yukihiro Matsumoto - - * array.c (ary_times): 「配列*文字列」がjoinと同じ働きをするように. - -Wed Feb 21 11:18:09 1996 Yukihiro Matsumoto - - * configure.in : fileCountをcache. - - * configure.in : LinuxでELF環境を自動的に検出できるよう. - -Tue Feb 20 11:18:09 1996 Mitsuhide Satou - - * FreeBSD dynamic link対応. - -Fri Feb 16 08:50:01 1996 Yukihiro Matsumoto - - * object.c (obj_inspect): インスタンス変数を持たないオブジェクトも - 正しく表示されるように. - -Wed Feb 14 16:56:44 1996 Yukihiro Matsumoto - - * eval.c (rb_eval): 条件式の`2..2'など左辺成立直後に右辺が成立する - パターンにバグ. - -Tue Feb 13 18:22:22 1996 Yukihiro Matsumoto - - * version 0.97 - -Fri Feb 9 21:32:55 1996 Yukihiro Matsumoto - - * lib/tkscrollbox.rb: スクロールでtclの設定を行い,ruby<->wishの不 - 要な通信を無くした. - -Wed Feb 7 10:26:52 1996 Yukihiro Matsumoto - - * string.c (str_aref): indexをunsigned intでとっていた. - - * string.c (str_aref): 範囲外のindexに対してnilを返す. - - * parse.y (special_local_set): `$_'が宣言無しに使われた場合に対応. - 関数をvariable.cから移動. - - * string.c (str_sub): 置換開始位置が間違っていた. - -Tue Feb 6 16:17:31 1996 Yukihiro Matsumoto - - * sample/ruby-mode.el (ruby-parse-region): コメントの読み飛ばしの - バグ. - -Fri Feb 2 18:35:28 1996 Yukihiro Matsumoto - - * variable.c (lastline_get): `$_'を`$~'と同じようにSCOPEローカルな - 変数にした. - -Thu Feb 1 14:14:07 1996 Yukihiro Matsumoto - - * file.c: statのcacheをやめた. - -Wed Jan 31 07:13:08 1996 Yukihiro Matsumoto - - * eval.c (proc_s_new): procの中でyieldを呼ばれた時にcore dumpして - いた.とりあえず例外を発生させる. - - * variable.c (rb_class2path): singleton classに対応. - - * ext/etc/etc.c (Init_etc): struct_defineのターミネータがnilだった - (0でなければならない). - - * ext/marshal/marshal.c: TRUE/FALSEを吐き出せるように. - - * eval.c (rb_get_method_body): キャッシュのalias対応,いままでは - aliasはキャッシュに入っていなかった. - -Tue Jan 30 09:55:13 1996 Yukihiro Matsumoto - - * eval.c (rb_eval): NODE_BLOCK - tail recursive(というほどでもない - が). - - * io.c (io_pipe): pipe(2)を実装した. - - * eval.c (rb_eval): Qselfをなくした.thread対応への第一歩.先は遠 - いが…. - - * eval.c (proc_call): procの中でのreturnはprocの終了を意味するよう - に.ただし,procからのyieldの中でのreturnは例外を発生する. - -Wed Jan 24 11:33:48 1996 Yukihiro Matsumoto - - * version 0.96a - - * dir.c (dir_each): `$_'の値を変更するのをやめた. - - * io.c (f_readlines): nilとFALSEの分離のあおりで無限ループに落ちて - いた. - - * ruby.c (ruby_options): $0の設定ミス. - -Tue Jan 23 15:28:21 1996 Yukihiro Matsumoto - - * eval.c (rb_eval): ``は文字列を引数とするメソッド(`)呼び出しのシ - ンタックスシュガーであるとした. - - * ruby.c (addpath): `-I'オプションでディレクトリが「前に」追加され - るように変更. - -Fri Jan 19 11:23:12 1996 Yukihiro Matsumoto - - * dln.c (load_1): N_INDR対応(出来たような気がする). - -Thu Jan 18 18:14:20 1996 Yukihiro Matsumoto - - * ruby.texi: FALSEとnilの分離を反映した. - -Tue Jan 16 17:39:23 1996 Yukihiro Matsumoto - - * version 0.96 - とりあえずnilとFALSEを区別する版 - -Wed Jan 10 15:31:48 1996 Yukihiro Matsumoto - - * re.c (reg_match): マッチしなかった時の戻り値はFALSE. - - * object.c (rb_equal): `0 == nil'がTRUEになるバグ. - -Tue Jan 9 00:44:58 1996 Yukihiro Matsumoto - - * nilとFALSEが分離可能に変更. - - * nilとFALSEと0の区別を厳密に. - - * struct.c (struct_new): 引数を0で終る必要が無くなった. - - * object.c (inspect_i): オブジェクトのチェックのバグ(Fixnumでcore - dumpしていた). - - * range.c (range_to_s): Rangeの表示を改善. - - * object.c (true_inspect): TRUEの表示を`TRUE'に. - -Mon Jan 8 15:02:33 1996 Yukihiro Matsumoto - - * numeric.c (fix_mul): divide by zero errorが発生した(オーバーフロー - 検出のバグ) - - * texinfo.texをパッケージに含めた. - -Sun Dec 31 00:08:49 1995 Yukihiro Matsumoto - - * eval.c (rb_eval): `::'では,そのクラスで定義された定数を参照する - ように変更. - - * string.c (Init_String): eachをeach_lineに戻した. - -Thu Dec 28 12:31:55 1995 Yukihiro Matsumoto - - * eval.c (rb_eval): caseの演算子を`=~'から`==='に. - - * variable.c (rb_const_set): クラス定数の再定義を許す(同じクラスで - は不可).警告は出す. - -Wed Dec 27 13:27:52 1995 Yukihiro Matsumoto - - * version 0.95c - - * ext/tkutil/tkutil.c: wishがあってもなくても一応コンパイルだけは - するように. - - * lib/tk.rb: 環境変数PATHから{wish|wish4.0}を探すように. - -Tue Dec 26 01:03:42 1995 Yukihiro Matsumoto - - * sample/ruby-mode.el (ruby-parse-region): 正規表現の検出強化. - - * numeric.c (fix_mul): 乗算のオーバーフロー検出アルゴリズムのバグ. - - * ext/extmk.rb.in: ./install-shを使う場合のPATHを調整. - - * Makefile.in (install): lib/*.rbを一つずつインストール. - - * io.c (io_each_line): イテレータの戻り値をnilで統一. - -Fri Dec 22 10:34:32 1995 Yukihiro Matsumoto - - * version 0.95b - - * variable.c (f_untrace_var): 第2引数を指定すると特定のtraceを削除 - できるように. - - * variable.c (f_trace_var): 第2引数がnilの時,traceを削除する. - - * lib/tk.rb (file_readable/file_writable): 第2引数をnilにすること - によるevent handlerの削除. - - * parse.y (variable): ドキュメントに`__FILE__'と`__LINE__'が残って - いた.`caller(0)'で代用したはずだったのに. - - * eval.c (f_eval): $!のリセット. - - * error.c (err_sprintf): 勝手に"\n"を付加するのを止めた. - - * parse.y (f_arglist): 引数リスト直後のif/whileの読み間違い. - lex_stateの値が設定されていなかった. - -Thu Dec 21 00:56:57 1995 Yukihiro Matsumoto - - * version 0.95a - ^^;;; - - * lib/tkscrollbox.rb: パッケージに入ってなかった. - - * configure.in: FILE structureのチェックにバグ. - - * Makefile.in (clean): ext以下をinstallしていた. - - * ext/socket/extconf.rb: Solarisにおける-lnlsのチェック. - - * array.c (beg_len): バグがあった….悲しい. - - * version 0.95 - fj.sourcesに - - * eval.c (rb_eval): rescueのロジックをrb_rescue()に一元化. - -Wed Dec 20 19:30:58 1995 Yukihiro Matsumoto - - * Makefile.in: 不要なコンパイルの回避(より完全に). - - * class.c (singleton_class_new): `single'->`singleton' - -Tue Dec 19 07:14:33 1995 Yukihiro Matsumoto - - * io.c (closed?): IOがcloseされているかどうかを知る述語. - - * parse.y (primary): 特異メソッドの引数のlex_stateが不適切. - - * lib/tk.rb: tcl->rubyの変換関数の用意. - - * ext/extmk.rb.in (install): installの2重コンパイルの回避. - - * array.c (range_beg_len): range指定の不適切なエラーを訂正. - - * string.c (str_aref): range指定のバグを削除. - - * lib/tk.rb (tk_split_list): Tclのリストに対応. - -Mon Dec 18 09:58:12 1995 Yukihiro Matsumoto - - * version 0.94 - - * dln.c (dln_load): HP対応(未確認) - - * eval.c (Init_Proc): BlockをProcに改名. - -Sat Dec 16 13:46:14 1995 Yukihiro Matsumoto - - * eval.c (rb_eval): retryでイテレータの再実行ができるように. - -Fri Dec 15 17:14:30 1995 Yukihiro Matsumoto - - * eval.c: proc:lambdaの親しみやすい別名 - -Thu Dec 14 17:21:55 1995 Yukihiro Matsumoto - - * eval.c (dyna_var_asgn): イテレータブロック内で最初に初期化された - ローカル変数の有効範囲をそのブロック内に限定.これでlambdaと呼べ - ないことはない. - -Wed Dec 13 02:30:58 1995 Yukihiro Matsumoto - - * gc.c: autoloadのマークミス. - - * lib/tk.rb: wishからの複数行の戻り値に対応 - - * lib/tkcomposite.rb: 複合widget - - * variable.c (rb_class2path): ICLASSに対応してなかった. - - * eval.c (ruby_run): exit(0)のバグ - -Sat Dec 9 01:21:24 1995 Yukihiro Matsumoto - - * ext/marshal/marshal.c (dumps|load): 文字列に対する入出力を可能に - した(ただし実はファイル経由なのだ). - -Fri Dec 8 18:29:11 1995 Yukihiro Matsumoto - - * ext/marshal/marshal.c: シンボルを一度だけ初期化する. - -Thu Dec 7 07:58:50 1995 Yukihiro Matsumoto - - * parse.y (yylex): 第1引数の正規表現の認識にエラーがあった.同時に - 状態数を減らした. - - * string.c (str_sub): 置換でスキップ幅が大きすぎた. - -Wed Dec 6 15:14:23 1995 Yukihiro Matsumoto - - * string.c (str_sub_method): sub/gsub(!なし)は置換が行なわれなかっ - た時,置換前の文字列を返す. - -Tue Dec 5 00:55:15 1995 Yukihiro Matsumoto - - * parse.y (yylex): 括弧を省略した時の引数展開の`*'に対応. - - * eval.c (ruby_run): EXITハンドラ内での例外に対応. - - * bignum.c (big_cmp): BignumとFixnumの比較で落ちる. - -Mon Dec 4 14:21:18 1995 Yukihiro Matsumoto - - * parse.y (call_op): コンパイル時の定数式の展開をやめた.労多くし - て益少ないと判断したので. - -Thu Nov 30 01:35:15 1995 Yukihiro Matsumoto - - * lib/tk.rb: {Radio,Check}Buttonのvariableの実装. - - * eval.c (rb_yield_0): Block.callがネストした時のバグ. - - * io.c (f_select): 常に配列3つをふくむ配列を返すように - - * lib/tk.rb: fileeventをruby側で実装. - -Wed Nov 29 17:53:23 1995 Yukihiro Matsumoto - - * variable.c (rb_ivar_get): selfを常に指定するように. - -Tue Nov 14 00:07:29 1995 Yukihiro Matsumoto - - * lib/tk.rb: Tk4.0対応 - -Mon Nov 13 16:23:32 1995 Yukihiro Matsumoto - - * version 0.93 - -Thu Nov 9 23:26:01 1995 Yukihiro Matsumoto - - * gc.c (gc_mark): モジュールのMixinのマーク忘れ. - - * parse.y (f_arglist): メソッド定義の引数を括弧で括らなくても良い - ようにした. - -Wed Nov 8 00:17:51 1995 Yukihiro Matsumoto - - * eval.c (rb_yield_0): 未初期化のローカル変数があった. - - * eval.c (rb_eval): pendig signalのチェックをeval実行後に行うよう - にした.でないとシグナルの発生と検出が遠く離れてしまう事がある. - - * parse.y: class文のsuperclass部を定数から式に拡張した. - - * lib/tk.rb: Tkのほぼ全ウィンドウクラスに対応.キャンバスとテキス - ト上のオブジェクトが残っている. - -Tue Nov 7 08:18:37 1995 Yukihiro Matsumoto - - * signal.c (trap): ブロックを指定できるように. - -Mon Nov 6 16:44:00 1995 Yukihiro Matsumoto - - * eval.c (f_caller): 呼出元の情報を得る. + * ruby.c (proc_options): -S does not recognize PATH. - * ext/tkutil/tkutil.c: wishのstderr出力を監視することで,エラー処 - 理を行う. +Thu Jan 15 02:03:12 1998 Yukihiro Matsumoto - * ext/tkutil/tkutil.c: wishとの通信部をCで記述. + * eval.c (rb_clear_cache_by_id): clear only affected cache + entries. -Sat Nov 4 01:12:59 1995 Yukihiro Matsumoto +Wed Jan 14 02:14:48 1998 Yukihiro Matsumoto - * sample/ruby-mode.el (ruby-calculate-indent): インデントの計算を - もう少しスマートにした(正規表現のチェック,継続行のチェック). + * ext/socket/socket.c: new UDP/IP socket classes. - * eval.c (rb_call): 無限再帰を避けるため,関数のネストレベルの制限 - を行なう. +Tue Jan 13 10:00:18 1998 Yukihiro Matsumoto - * lib/tk.rb: Tkインターフェース.まだ不完全だが. + * string.c (str_cmp): ignorecase($=) works wrong. - * eval.c (rb_yield_0): 空のBlockのバグ. +Fri Jan 9 13:19:55 1998 Yukihiro Matsumoto - * sample/ruby-mode.el (ruby-calculate-indent): 行末の演算子による - 行継続に対応. + * eval.c (f_missing): class name omitted from the error message. -Fri Nov 3 12:56:21 1995 Yukihiro Matsumoto + * error.c (exc_inspect): description changed. - * eval.c (rb_call): 本体が空の関数の実行にバグ. + * string.c (Init_String): GlobalExit's superclass did not filled, + since GlobalExit created earlier than String. - * parse.y (var_extend): 文字列の末尾の変数展開のバグ. +Thu Jan 8 12:10:09 1998 Yukihiro Matsumoto - * variable.c (rb_gvar_set): traceの評価時にに変数値を与えるように. + * parse.y (aryset): expr in the brackets can be null. - * eval.c (f_require): ruby scriptのrequireにbug. +Wed Jan 7 21:13:56 1998 Yukihiro Matsumoto - * variable.c (rb_const_get): モジュールのinclude対策. + * io.c (io_reopen): keep stderr unclosed. -Thu Oct 19 13:56:06 1995 Yukihiro Matsumoto + * io.c (io_errset): keep stderr unclosed. - * dln.c (dln_load): HP対応でのtypo. +Tue Jan 6 00:27:43 1998 Yukihiro Matsumoto -Wed Oct 18 17:39:39 1995 Yukihiro Matsumoto + * parse.y: syntax modified for `while expr do .. end' etc. - * version 0.92 + * process.c (f_exec,f_system): can supply arbitrary name for the + new process. - * object.c (krn_type): オブジェクトの動的な型を返すメソッド. +Mon Jan 5 16:59:13 1998 WATANABE Hirofumi -Tue Oct 17 00:48:18 1995 Yukihiro Matsumoto + * file.c (file_s_basename): removes any extention by ".*". - * ruby.c (proc_options): -X オプション.chdirだけを行う. +Sun Jan 4 19:36:22 1998 WATANABE Hirofumi - * re.c (reg_search): 漢字コードを途中で変更できるように.コンパイ - ル時のコードが変更された時にはマッチの直前に正規表現の再コンパイ - ルを行う.定数KCODEから変数$KCODEへ. + * parse.y (yylex): needed to update lex_p (reading point). - * parse.y: ()のなかにcompexprを許す. +Sat Jan 3 19:14:14 1998 WATANABE Hirofumi - * re.c (reg_search): メモリリークを直した. + * class.c,object.c: duplicate defines mKernel and cFinxnum. -Fri Oct 13 13:19:19 1995 Yukihiro Matsumoto +Fri Jan 2 20:38:59 1998 Yukihiro Matsumoto - * string.c (str_sub): 文字列置換にバグ. + * ext/curses/curses.c (NUM2CHAR): uses the first character for + string arguments. - * string.c (str_strip_bang): 文字列の後ろの長さの調整が行われてい - なかった. + * array.c (ary_fill): did not extend array for ranges. - * re.c (reg_search): $&, $1...はローカルに束縛するようになった.呼 - び出したメソッドでのマッチは現スコープの$&などの値に影響しない. - マッチの情報をスコープ外で得たいときには$~を使って束縛情報を持ち - 出す必要がある. + * array.c (beg_len): did not return end pos bigger than size. -Thu Oct 12 00:33:33 1995 Yukihiro Matsumoto +Fri Jan 2 02:09:16 1998 WATANABE Hirofumi - * re.c (reg_search): String:split, String:indexでは$&, $1...が変化 - しないようにした. + * dir.c (dir_s_chdir): bug in nil check. - * io.c (rb_str_setter): setterの仕様が変更になっていた. + * array.c (ary_fill): bug in nil check. - * variable.c (f_trace_var): 第2引数を省略してイテレータとして呼べ - るように. +Tue Dec 30 11:46:23 1997 Yukihiro Matsumoto -Wed Oct 11 11:50:59 1995 Yukihiro Matsumoto + * hash.c (env_path_tainted): checks directories in PATH + environment variable are not world writable. - * version 0.91 + * ruby.c (load_file): invoke specified interpreter if the #! line + does not contain the word `ruby'. - * variable.c (var_setter): 引数が間違っていた.致命的バグ. +Fri Dec 26 03:26:41 1997 Yukihiro Matsumoto - * io.c (pipe_open): $stderrの値が変更されている時にはそちらを - 子プロセスのstderrに設定する. + * string.c (uscore_get): type information included in the error + message. -Mon Oct 9 13:06:33 1995 Yukihiro Matsumoto + * variable.c (f_untrace_var): does not free trace-data within + trace procedure. - * object.c (mod_to_s): モジュール内のモジュールは`::'を使った表現 - で表示されるように. +Thu Dec 25 02:50:29 1997 Yukihiro Matsumoto - * variable.c (rb_gvar_set): 代入によるループが発生しないように, - trace内での代入ではtraceを評価しない. + * version 1.1b3 released. - * struct.c (struct_equal): structのequal判定にクラスの一致を含めた. + * ruby.h: inlining some functions on gcc 2.x -Sat Oct 7 00:18:32 1995 Yukihiro Matsumoto +Tue Dec 23 02:47:33 1997 Yukihiro Matsumoto - * eval.c (rb_eval): defined?の機能を拡張(yieldのチェック,superの - 存在など). + * eval.c (rb_eval): public/private information kept in the current + scope, to remove undesired state from the class/module. -Fri Oct 6 12:06:47 1995 Yukihiro Matsumoto + * time.c (time_strftime): remove hidden limit of 100 bytes of + result string, using malloc'ed buffer. - * version 0.90 + * hash.c (hash_update): merges the contents of another hash, + overriding existing keys. - * st.c (st_foreach): 要素を削除した時に要素数が変化していなかった. + * regex.c (must_instr): totally re-written. - * hash.c (hash_values): バグ修正.keysを返していた…. + * io.c (read_all): try to allocate proper sized buffer using + fstat(2) for speedup. - * parse.y (call_op): defined? の引数では定数の畳み込みを行わない - (チェックする前にコンパイルエラーになっては困る). +Sat Dec 20 00:27:28 1997 Yukihiro Matsumoto - * スコープ生成の一部見直し. + * regex.c (must_instr): need to skip 2 bytes for mbchars. -Thu Oct 5 00:29:43 1995 Yukihiro Matsumoto +Fri Dec 19 01:18:29 1997 Yukihiro Matsumoto - * 関数とクラスの命名規則を変更した.関数名,変数名の全面書き換え. + * version 1.1b2 released. - * gc.c (looks_pointerp): ヒープチェックの高速化. + * eval.c (check_errat): check and convert (if necessary) traceback + information before assigning to the variable $@. - * struct.c (Fstruct_aset): 構造体に対する`[]='. - (struct_set): 構造体メンバに対する代入. + * eval.c (f_raise): optional third argument to specify traceback + information. -Wed Oct 4 09:54:07 1995 Yukihiro Matsumoto + * io.c (f_open): prevent infinite recursive call. - * version 0.89 +Thu Dec 18 19:33:47 1997 Yukihiro Matsumoto - * eval.c (Frequire): ダイナミックロードのエラーチェックを厳しく. + * string.c (str_rindex): now accepts regexp as index. - * struct.c: structの構造を完全に書き換えた.以前は順序付きの - id->valueの連想配列であったが,今度は構造体毎に新しいクラスを生 - 成するようにした. +Thu Dec 18 18:42:50 1997 WATANABE Hirofumi - * parse.y: `::'の意味をAssocの生成からクラス(モジュール)内の定数ア - クセスへ変更. + * ext/socket/extconf.rb: modified to detect win32 socket lib. - * assoc.c: なくす. +Thu Dec 18 00:25:03 1997 Yukihiro Matsumoto -Tue Oct 3 13:31:08 1995 Yukihiro Matsumoto + * re.c (reg_equal): checks for source and casefold and kcode matching. - * variable.c (Ftrace_var): trace_var, 大域変数への書き込みhookを設 - 定する. + * marshal.c: became built-in module. - * variable.c: global_entryの構成を書き換えた.これでtrace_varを実 - 装できる. + * ext/marshal/marshal.c (r_object): displays struct name for + non-compatible struct. - * file.c (Ffile_stat): "&"で直前のfstatの結果も参照できるように. + * string.c (str_index_method): now searches character (fixnum) in + the string. -Fri Sep 29 14:15:13 1995 Yukihiro Matsumoto + * string.c (str_include): redefine `include?'. - * version 0.88 + * regex.c (re_match): start_nowidth saves current stack position + to stop_nowidth. - * dln.c (dln_load): AIXとHPに対応したコードを入れた(動作は未確認). + * regex.c (re_compile_pattern): add space to stop_nowidth to save + runtime stack position. - * ext/extmk.rb.in: 必要に応じて,定数EXTLIBを定義するように. +Tue Dec 16 14:57:43 1997 Yukihiro Matsumoto - * dln.c (dln_load): dln独立に書き換える.将来の拡張用. - (load_1): dln_a_outにおいてソースコードでライブラリを明示的にロー - ドする必要がないように変更した. + * string.c (scan_once): wrong exception for regexp that match with + null string (use substr instead of subseq). -Thu Sep 28 13:31:37 1995 Yukihiro Matsumoto +Sat Dec 13 00:13:32 1997 Yukihiro Matsumoto - * sample/ruby-mode.el: もっとましなhilit19対応(正規表現). + * parse.y (expr): remove bare assocs from expr rule. -Wed Sep 27 04:12:44 1995 Takahasi Mamoru + * rbconfig.rb: renamed from config.rb (it was too generic name). - * sample/test.rb: echoで-nを使わないように(SysV対策). +Fri Dec 12 00:50:25 1997 Yukihiro Matsumoto - * ext/extmk.rb.in: sub -> sub! + * parse.y (expr): warns if BEGIN or END appear in the method + bodies. -Tue Sep 26 19:12:42 1995 Yasuo OHBA + * string.c (str_match): calls y =~ x if y is neither String nor + Regexp so that eregex.rb works. - * dln.c (dln_find_1): `.', `..'から始まるパスに対応した. + * eval.c (f_at_exit): to register end proc. -Mon Sep 25 12:33:03 1995 Yukihiro Matsumoto + * class.c (rb_define_module_function): define 'function' method + for the Module, not private method. - * version 0.87 + * class.c (rb_define_function): function to define `function' method. -Sat Sep 23 10:00:18 1995 Yukihiro Matsumoto + * eval.c (rb_eval): inherit visibility from superclass's method + except when it is set to `function' - * eval.c (Fmod_modfunc): メソッドをprivateにし,同時に特異メソッド - も定義するメソッド.パッケージ的使い方のモジュール用. + * eval.c (rb_eval): new visibility status `function'. -Fri Sep 22 11:02:44 1995 Yukihiro Matsumoto + * parse.y (yycompile): do not clear eval_tree. thus enable multipe + command line script by optn `-e'. - * lib/find.rb: findを提供するライブラリ + * eval.c (rb_eval): END execute just once. - * variable.c (rb_define_variable): hookの設定を分離. - (add_hook): 1変数に対して複数のhookを設定できるように. + * parse.y (expr): BEGIN/END built in the syntax. -Thu Sep 21 00:22:11 1995 Yukihiro Matsumoto +Thu Dec 11 13:14:35 1997 Yukihiro Matsumoto - * string.c (Fstr_frozen): 文字列が更新不可かどうかをチェックする述 - 語メソッド. + * object.c (mod_le): Module (or Class) comparison. - * hash.c (Fhash_aset): keyが文字列の時,キーの内容が変化しないよう - に,dupしてfreezeする. + * eval.c (rb_remove_method): raises NameError if named method does + not exist. -Wed Sep 20 16:12:44 1995 Yukihiro Matsumoto - - * version 0.86 - - * ext/extmk.rb.in (have_header): キャッシュにバグ. - - * ext/extmk.rb.in (have_library): 引数の順序が変わった. - -Thu Sep 14 18:00:59 1995 Yukihiro Matsumoto - - * object.c (obj_is_instance_of): is_member_ofから名称変更. - - Wed Sep 13 15:44:35 1995 Yukihiro Matsumoto - - * string.c (Fstr_tr_bang): 範囲外の文字に対する変換バグ. - -Tue Sep 12 14:27:58 1995 Yukihiro Matsumoto - - * file.c (Sfile_expand_path): expand_file_name -> expand_pathに名 - 称変更. - - * enum.c (Fenum_member): includes? -> member? に名称変更. - - * string.c (Fstr_each_byte): StringはByteArrayであるという基本に戻っ - て,eachの定義をeach_byteに変更した.今までのeachはeach_lineでア - クセスできる. - -Mon Sep 11 18:31:17 1995 Yukihiro Matsumoto - - * file.c (cache_stat): ファイル名として"&"を指定すると直前の - stat(2)の結果を再利用するように. - -Fri Sep 8 14:18:51 1995 Yukihiro Matsumoto - - * ruby.texi: `!', `?'に対応してアップデート. - - * parse.y: defined -> defined? - - * file.c: FileOpの一文字メソッドをなくす.一文字テストはtestメソッ - ドにまかせる. - - * parse.y (yylex): 変数名の後ろに`?'も許す.述語メソッドの後ろに - `?'を追加する. - -Thu Sep 7 20:01:33 1995 Yukihiro Matsumoto - - * string.c: 文字列の中身を更新するメソッドの名前の終りに`!'を付加. - `!'の無いバージョンも用意した. - - * parse.y: 変数名の後ろに`!'を許す. - -Wed Sep 6 14:12:19 1995 Yukihiro Matsumoto - - * version 0.85 - - * string.c (Fstr_dup): 文字列の複製を作る - (Fstr_freeze): 文字列の更新不可属性を設定できるように. - (Fsub/Fgsub): $_の内容をdupしてから置換を行うように. - - * ruby.h (CLONESETUP): flagsの状態もコピー - -Tue Sep 5 01:27:50 1995 Yukihiro Matsumoto - - * sample/test.rb: 失敗の検出を厳しく. - -Fri Aug 25 14:31:02 1995 Yukihiro Matsumoto - - * process.c (Ffork): イテレータとしても動作するように. - - * version 0.84 - - * signal.c (sig_beg): ハンドラが設定されている時には再設定しない. - - * ext/extmk.rb.in (create_makefile): shared objectのリンクの際に - `-l'オプションを指定するように. - - * signal.c (trap): `EXIT'で終了処理を行う設定が出来る. - -Wed Aug 16 00:13:22 1995 Yukihiro Matsumoto - - * signal.c (sig_beg): デフォルトではbegin節の中でだけSIGINTを捕捉 - するように変更. - - * io.c (io_ctl): fcntlを持たないシステムにも対応. - - * 各ディレクトリに分散していたMANIFESTをまとめた.拡張モジュール毎 - には必要. - - * string.c (Sstr_new,str_sub,Fstr_crypt): 引数を自動的に文字列に変 - 換するように. - -Sat Aug 12 00:44:02 1995 Yukihiro Matsumoto - - * string.c (Fstr_crypt): PD cryptを用意した. - -Fri Aug 11 14:37:03 1995 Yukihiro Matsumoto - - * assoc.c (Fassoc_clone): assocもcloneできるように. - - * io.c: マクロREAD_DATA_PENDINGの定義を変更(Linux対応) - - * io.c (io_fptr_finalize): fptrの開放時の処理を指定できるように. - -Wed Aug 9 16:52:41 1995 Yukihiro Matsumoto - - * eval.c (rb_provided): 複数のfeatureをロードすると無限ループに落 - ちるという単純な(しかし凶悪な)ミス. - - * ext/extmk.rb.in (install): dlopen対応を行った.今までdlnにしか十 - 分に対応していなかった. - -Tue Aug 8 14:17:06 1995 Yukihiro Matsumoto - - * version 0.83 - -Mon Aug 7 12:47:41 1995 Yukihiro Matsumoto - - * parse.y: resque -> rescue.恥ずかしいがtypoを残しておくわけには - いかないよなあ.なんで今まで気がつかなかったのか…. - -Thu Aug 3 18:18:05 1995 Yukihiro Matsumoto - - * missing/nt.c: NT移植用の関数群をまとめた. - - * variable.c (rb_const_get): また例外を発生するようにした.defined - がある以上例外を発生させない理由がないので(例外が発生した方がタ - イプミスの検出などの点で有利). - - * variable.c (Fautoload): autoloadを実装.今度は使えるか. - -Mon Jul 31 15:44:21 1995 Yukihiro Matsumoto - - * parse.y (arg_ambiguous): 第1引数のあいまいさを警告(-vオプション - で有効). - - * eval.c (rb_eval): `-v'オプションをつけて`def'が呼ばれると不必要 - なエラーメッセージが出た. - - * parse.y (yylex): メソッドの第1引数の判定をもうちょっと賢くした. - -Fri Jul 28 19:04:43 1995 Yukihiro Matsumoto - - * parse.y (yylex): `+/-/['の直前に空白が来るかどうかで動作を変更し - た(混乱のもとか?) - -Wed Jul 26 09:21:23 1995 Yukihiro Matsumoto - - * version 0.82a - - * sprintf.c (Fsprintf): `%s'で'\0'を含む文字列に対応. - - * pack.c (Fpck_pack): packの要素確保のバグ. - - * eval.c (Floop): 無限ループのイテレータ. - - * io.c (next_argv): 存在しないファイル名が指定された時のエラー処理 - が行われていなかった. - -Mon Jul 24 17:37:34 1995 Yukihiro Matsumoto - - * version 0.82 - - * ext/extmk.rb.in (install): 拡張モジュールをstatic linkする場合は - そのモジュールが既にrequireされたのと同じようにfeatureを設定する. - これで拡張モジュールの機能が必要な時には(static linkされているか - どうかにかかわらず)requireすればよくなる. - - * eval.c (Frequire): `$"'に格納する文字列をフルパスでなくフィーチャ - 名とする.rubyスクリプトをロードした時には`.rb',オブジェクトを - ロードした時には`.o'をフィーチャ名に付加する.lispのrequireと - provideの働きに(少し)近い. - -Thu Jul 20 12:50:05 1995 Yukihiro Matsumoto - - * Makefile.in (test): make testができるように. - - * struct.c (struct_new): typo. - - * eval.c (rb_eval): `defined'を追加.メソッド/変数/定数の定義状態 - を知る事が出来る. - -Wed Jul 19 18:04:01 1995 Yukihiro Matsumoto - - * version 0.81 - -Mon Jul 17 14:53:51 1995 Yukihiro Matsumoto - - * variable.c (rb_const_get): 未初期化のCONSTANTの値をnilにした.し - かし,今後また例外に戻す可能性はある.要はoptionalなクラス/モジュー - ルが存在するかチェックしたいだけなんだな. - - * st.c (int): grow_factorを固定にした(大嶋さんのマシンに対応). - -Fri Jul 14 00:48:40 1995 Yukihiro Matsumoto - - * ext/extmk.rb.in: キャッシュのバグを修正. - - * parse.y (var_extend): #{$数字}に対応した. - - * dln.c (dln_load_1): `Init_FILENAME'だけを有効に.`init_*'は今後 - 実行しない. - - * ext/etc/etc.c : Etcモジュールを拡張モジュールとして分離.実はNT - 対応への布石だったりするかもしれない. - -Tue Jul 11 17:12:48 1995 Yukihiro Matsumoto - - * gcc -Wallで出たwarningを元にソースを変更. - - * signal.c (trap): typo. - -Fri Jul 7 10:08:51 1995 Yukihiro Matsumoto - - * version 0.80 - - * ruby.texi: texinfo documentを提供.specとruby.1は無くなった. - - * signal.c (Ftrap): 割込み禁止中の例外発生に対応. - - * eval.c (Flambda): Blockオブジェクトを返す.Block.newと同義. - -Thu Jul 6 00:35:03 1995 Yukihiro Matsumoto - - * signal.c (Ftrap): SIG_DFLの処理を変更.SIGINTへのデフォルトハン - ドラを用意(例外を発生する). - - * file.c (Sfile_expand_fname): パス名を絶対パスに展開するメソッド. - (Sfile_basename): basenameを得るメソッド.拡張子も外せる. - (Sfile_dirname): basenameの反対. - - * eval.c (rb_call): argument評価中の例外発生に対応. - - * file.c (Ftest): `M', `A', `C'を追加. + * ext/curses/curses.c: remove CHECK macro for BSD curses. + +Thu Dec 11 12:44:01 1997 WATANABE Hirofumi -Tue Jul 4 12:36:33 1995 Yukihiro Matsumoto + * pack.c: sun4 cc patch - * file.c (Ftest): ファイルテスト用メソッド. +Wed Dec 10 15:21:36 1997 Yukihiro Matsumoto - * ruby.c (proc_options): `-r'オプションを追加. + * ext/marshal/marshal.c (marshal_load): can supply evolution proc + object as optional second argument. - * parse.y (f_args): デフォルト引数を追加. + * re.c (reg_source): get source string of the regular expression. - * eval.c (rb_call): 該当する引数が無い時,rest引数の値をnilに. +Tue Dec 9 10:05:17 1997 Yukihiro Matsumoto - * numeric.c (num_equal): 数値以外との比較で例外が発生していた. - FALSEを返すように. + * version 1.1b1 released. - * eval.c (masign): 多重代入のrest部の動作がおかしかった. + * parse.y (tokadd): token buffer overrun. -Sat Jun 17 01:03:16 1995 Yukihiro Matsumoto + * ruby.c (ruby_prog_init): forgot to protect rb_argv0 from gc. - * parse.y (gettable): 未初期化のローカル変数の参照(独立した識別子) - は正式にメソッド呼び出しとした. + * eval.c (ruby_run): call finalizers at process termination. - * parse.y (read_escape): tokenbufを使わないように修正.それにとも - ない,`\C-x',`\M-x'などのエスケープ表現を復活.これでドキュメン - トと実際の処理系が一致した. + * gc.c (gc_call_finalizer_at_exit): call free proc for every Data + Wrapper, and finalizer for specified objects at termination. -Thu Jun 15 15:42:00 1995 Yukihiro Matsumoto + * version.c (show_version): version format changed. - * re.c (re_regcomp): cacheのチェックを改善. + * regex.c (re_match): wrong match with non-greedy if they appear + more than once in regular expressions. -Mon Jun 12 18:50:51 1995 Yukihiro Matsumoto + * sample/ruby-mode.el (ruby-expr-beg): forgot to handle modifiers. - * version 0.79 +Mon Dec 8 19:00:15 1997 Yukihiro Matsumoto -Sat Jun 10 00:25:01 1995 Yukihiro Matsumoto + * io.c (io_puts): just put a newline if no argument given. - * re.c (re_regcomp): cache判定に`$='の値も反映させた. + * ext/tcltklib/tcltklib.c (lib_mainloop): thread-aware tk handle + when $tk_thread_safe is set. - * sample/test.rb: test suite作成. + * ext/tcltklib/tcltklib.c (lib_mainloop): use Tcl_DoOneEvent() + instead of Tk_MainLoop(). -Fri Jun 9 15:58:34 1995 Yukihiro Matsumoto +Mon Dec 6 07:11:16 1997 MAEDA shugo - * re.c (re_regcomp): cacheの判定が間違っていた. + * io.c (io_puts): core dumped without any argument. -Fri Jun 9 00:01:35 1995 Yukihiro Matsumoto (matz@dyna) +Fri Dec 5 18:17:17 1997 Yukihiro Matsumoto - * eval.c (rb_yield): block構造体に初期化していないメンバ(iter)があっ - たのでイテレータのネストが正しく動作しなかった. + * eval.c (mod_remove_method): remove (not undef) a method from the + class/module. -Thu Jun 8 00:59:03 1995 Yukihiro Matsumoto (matz@dyna) + * variable.c (obj_remove_instance_variable): method to remove + instance variables. - * re.c (=~): String以外との比較がFALSEを返すように(例外を発生して - いた). +Thu Dec 4 13:50:29 1997 Yukihiro Matsumoto - * extmk.rb.in: 判定した値をファイルにキャッシュするようにした. + * version 1.1b0 released. - * assoc.c (to_a): to_aメソッドが再定義されていなかった. - - * eval.c (rb_eval): 初期化されていないローカル変数へのアクセスを引 - 数の無いメソッド呼び出しと解釈する.ただし,(現状では)メソッドが - 定義されていない場合,エラーにせず変数未初期化のwaringを出して - nilを返している.「ruby -pe print」などが実行できるという意味で - はありがたいこの仕様は,しかし今後の検討が必要である.-- メソッ - ド呼び出しとするのを止めるか(以前の仕様),いつもメソッド呼び出し - とする(未定義ならばエラー)か,今の仕様で行くか. + * string.c (str_aref): called str_index for regexp. - * eval.c (rb_eval): 初期化されていないローカル変数へのアクセスで - (evalなどで)初期化された事が分かった時には以後初期化されたローカ - ル変数とみなす. +Mon Dec 1 15:24:41 1997 Yukihiro Matsumoto -Wed Jun 7 11:58:12 1995 Yukihiro Matsumoto + * compar.c (cmp_between): wrong comparison made. - * eval.c (rb_fail): 例外処理後も`$!'をクリアしないように. - (rb_fail): `$!'変数に最後に改行を追加しない. +Wed Nov 26 18:18:05 1997 Yukihiro Matsumoto - * io.c (Fprint): privateメソッドに変更.引数を取らない時の動作を変 - 更(`$_'を出力する). - (Fio_print): 出力先指定のprintメソッド. - (Fio_printf): 出力先指定のprintfメソッド. + * lib/mkmf.rb: generate Makefile for extention modules out of ruby + source tree. use like `ruby -r mkmf extconf.rb'. - * parse.y: not演算子の追加.優先順位の低い`!'演算子. + * numeric.c (fix2str): enlarge buffer to prevent overflow on some + machines. -Mon Jun 5 19:00:55 1995 Yukihiro Matsumoto + * parse.y (here_document): wrong line number generated after here-doc. - * version 0.78 +Fri Nov 21 13:17:12 1997 Yukihiro Matsumoto -Fri Jun 2 17:52:03 1995 Yukihiro Matsumoto + * parse.y (yylex): skip multibyte characters in comments. - * ruby.c (proc_options): -Iオプションで`$:'への追加される順番を修 - 正した. +Wed Nov 19 17:19:20 1997 Yukihiro Matsumoto -Fri Jun 2 00:36:34 1995 Yukihiro Matsumoto (matz@dyna) + * object.c (nil_to_a): nil.to_a => []. - * parse.y: while修飾子の動作を通常のwhileと同じにした.ただし, - begin式へのwhile修飾子だけはdo..while型のループとなる. + * parse.y (call_args): wrong node generation. -Wed May 31 18:36:30 1995 Yukihiro Matsumoto +Tue Nov 18 10:13:08 1997 Yukihiro Matsumoto - * version 0.77 + * array.c (Init_Array): Array#=== works as Array#include? -Mon May 29 18:39:37 1995 Yukihiro Matsumoto + * regex.c (re_compile_pattern): insert initialize code for jump_n, + before entering loops. - * ext/extmk.rb.in (install): 拡張モジュールもインストールできるよ - うに. + * re.c (reg_search): does not save registers unless $& etc appear + in the script. -Fri May 26 14:43:01 1995 Yukihiro Matsumoto +Mon Nov 17 13:01:43 1997 Yukihiro Matsumoto - * process.c (Fsystem): 戻り値をサブプロセスの失敗/成功を表す真偽値 - にした.終了ステータスは`$?'で得る. + * eval.c (is_defined): add defined? check for receivers and + arguments for calls. -Tue May 23 10:58:11 1995 Yukihiro Matsumoto + * re.c (reg_search): cache last match object. - * string.c (Fstr_upto): 無限ループに陥らないように. + * re.c (match_aref): $[0] etc. are available. - * parse.y (cond): `||'などの右辺に制御式が書けるように,条件式がか - ならずしも値を持たなくても良いようにした. +Sat Nov 15 00:11:36 1997 WATANABE Hirofumi - * ext/marshal/marshal.c: オブジェクトの読み書きをメソッドの再定義 - でコントロールできるように.インスタンスが`_dump_to'というメソッ - ドを定義している時はそちらを使うように. + * io.c (io_s_popen): "rb" detection - * ext/extmk.rb.in: static linkも設定できるような仕様にした. - ext/Setupというファイルにディレクトリ名を記述するとそのディレク - トリに存在するモジュールはstatic linkされる(はず). +Fri Nov 14 18:28:40 1997 Yukihiro Matsumoto - * eval.c (rb_eval): `..'を文法に組み込み,`..'と`...'の動作をperl - に合わせた. + * string.c (scan_once): returns whole match if the pattern does + not contain any parentheses. -Sat May 20 01:22:48 1995 Yukihiro Matsumoto (matz@dyna) +Thu Nov 13 14:39:06 1997 Yukihiro Matsumoto - * io.c (select): timeout時と割込み時の動作の明確化. + * string.c (str_sub): returns copy of the receiver string, even if + any substitution occurred. -Fri May 19 15:33:23 1995 Yukihiro Matsumoto + * regex.c (re_compile_pattern): no-width match by (?=..), (?!..). - * version 0.76 +Wed Nov 12 13:44:47 1997 Yukihiro Matsumoto -Fri May 19 00:48:08 1995 Yukihiro Matsumoto (matz@dyna) + * time.c: remove coerce from Time class. - * string.c (Fstr_each): イテレータブロック中で文字列の変更が行われ - たかどうかをチェック.ポインタの値が変わっていれば例外を発生する. + * regex.c (re_match): non-greedy match by ??, *? +?, {n,m}?. - * ruby-mode.el: ruby-electric-braceの新設. +Mon Nov 10 11:24:51 1997 Yukihiro Matsumoto -Thu May 18 12:27:23 1995 Yukihiro Matsumoto + * regex.c (re_compile_pattern): non-resitering parens (?:..). - * string.c (Fstr_tr): trの置換対象に`\0'を含む時に正しく置換を行わ - ないバグがあった.更に置換文字列をASCII順に指定しないと動作しな - い問題もあった.結果としてtrを書き換えたので,copyrightの問題は - 無くなった(と思う). + * regex.c (re_compile_pattern): new meta character \< (wordbeg) + and \> (wordend). - * gc.c (gc): the_scopeをマークしていなかったので,ローカル変数の指 - しているオブジェクトが間違って開放される場合があった. + * regex.c (re_compile_pattern): embedded comment for regular + expression by (?#...). - * gc.c (mark_locations_array): 若干の高速化. +Fri Nov 7 16:58:24 1997 Yukihiro Matsumoto -Mon May 15 11:43:49 1995 Yukihiro Matsumoto + * regex.c (re_compile_pattern): perl5 regxp \A and \Z available. - * ext/extmk.rb.in: Dynamic Loadモジュールのコンパイル用チェックを - 行うruby script.autoconfに近い感覚で使える.新しいモジュールを - 提供したい人はextの下にディレクトリを作るだけで良い.必須のファ - イルはファイル名の一覧を記録した`MANIFEST'というファイルのみ.必 - 要に応じて`depend'(ファイルの依存関係を記述するファイル gcc -MM - の出力),`extconf.rb'(コンパイル用にライブラリと関数の存在チェッ - クするファイル)を用意できる. + * regex.c (re_compile_pattern): can expand compile stack dynamically. - * eval.c (rb_call): rubyメソッドの引数チェック時に未初期化の - jmp_bufを使用していた. + * regex.c (PUSH_FAILURE_POINT): wrong compare condition. - * parse.y: `or'と`and'の優先順位を同じにした. +Wed Nov 2 16:00:00 1997 WATANABE Hirofumi -Wed May 3 18:21:36 1995 Yukihiro Matsumoto (matz@dyna) + * string.c (str_sub_s): "".sub! "", "" => "\000" - * dln.c: Linuxでは`__.SYMDEF/'であった. +Fri Oct 31 15:52:10 1997 Yukihiro Matsumoto - * dln.c: system callのエラーチェックを忘れていた. + * parse.y (assoc): keyword assoc like {fg->"black"}. -Wed Apr 26 09:50:56 1995 Yukihiro Matsumoto (matz@ix-02) +Thu Oct 30 17:33:38 1997 Yukihiro Matsumoto - * parse.y: イテレータブロックの変数宣言を`|'で括るようにした.これ - でイテレータ変数がない時は宣言そのものを省略できる.文法の変更は - 久しぶりだ. + * io.c (io_println): print with newline, which is not affected by + the values of $/ and $\. -Tue Apr 25 12:04:17 1995 Yukihiro Matsumoto (matz@ix-02) +Thu Oct 30 16:54:01 1997 WATANABE Hirofumi - * eval.c(require): loadからダイナミックロードの機能を移してきた. - さらに拡張子の補完機能を追加してユーザがdln/dlopenの差を意識する - 必要のないようにした. + * string.c (str_chop_bang): "".chop caused SEGV. - * string.c(sub,sub): イテレータとしても動作するように. + * string.c (str_chomp_bang): method to chop out last newline. - * object.c: init_object -> initialize. +Mon Oct 27 13:49:13 1997 Yukihiro Matsumoto -Mon Apr 24 14:22:39 1995 Yukihiro Matsumoto (matz@ix-02) + * ext/extmk.rb.in: library may have pathname contains `.' - * NEWS-OS 3.4対応 + * eval.c (rb_rescue): should not protect SystemError. - * io.c: Solarisのstdioの動作が違うようだ.signalでEOFを返してしま - う….perlでも同様の問題がある. +Fri Oct 24 10:58:53 1997 Yukihiro Matsumoto -Fri Apr 21 20:04:39 1995 Yukihiro Matsumoto (matz@ix-02) + * io.c (io_s_with_open_stream): ensures to close stream. - * version 0.75 +Thu Oct 23 11:17:44 1997 Yukihiro Matsumoto - * signal.c: trapがなくなっていた.うーむ. + * io.c (io_errset): value of $stderr can be changed (to any IO + object). - * configure: Solaris 2.3対応. + * io.c (next_argv): $< can be anything that responds to `write'. - * io.c: #elifのないcppもある. + * file.c (file_s_with_open_file): ensures to close file. - * dir.c: autoconf 2.xへの対応が不十分 + * error.c (exception): create error under the current class/module. -Thu Apr 20 12:31:24 1995 Yukihiro Matsumoto (matz@ix-02) + * range.c (range_eqq): fixnum check for last needed too. - * version 0.74 +Wed Oct 22 12:52:30 1997 Yukihiro Matsumoto - * env.h, gc.c, regex.c: IRIXへの移植対応 + * ext/socket/socket.c: Socket::Constants added. - * configure: dlopen用にpicを生成するoptionの検出のため,システムタ - イプをチェックするように. + * file.c: File::Constants added for inclusion. -Tue Apr 18 19:08:17 1995 Yukihiro Matsumoto (matz@ix-02) + * array.c (ary_join): call ary_join() recursively for the 1st + array element. - * gc.c(xrealloc): ptr=nilの時,malloc()と同じ働きを +Mon Oct 20 12:18:29 1997 WATANABE Hirofumi - * array.c(astore): 空の配列の0番目の要素に代入するとsize=0で - realloc()を呼んでいた. + * ruby.c (load_file): wrong condition for #! check with -x. - * configure, glob.c: Solaris 2.xでコンパイルできるように + * file.c (file_s_dirname): did return "" for "/a". -Mon Apr 10 18:36:06 1995 Yukihiro Matsumoto (matz@ix-02) +Fri Oct 17 14:29:09 1997 Yukihiro Matsumoto - * version 0.73 + * ruby.c: now works on alpha-linux. -Fri Apr 7 13:51:08 1995 Yukihiro Matsumoto (matz@ix-02) + * bignum.c (bigadd): some undefined side effect order assumed. - * cons.c->assoc.c: consの余計な機能は外してpairとしての機能だけを - 残した.Enumerableをincludeするのもやめた. +Wed Oct 15 17:49:24 1997 Yukihiro Matsumoto - * string.c(esub): 文字列置換イテレータ.perlのs///eの相当する. + * intern.h: function prototypes added. -Wed Apr 5 11:35:21 1995 Yukihiro Matsumoto (matz@ix-02) +Mon Oct 13 16:54:18 1997 Yukihiro Matsumoto - * version 0.72 + * class.c (rb_define_class_id): call superclass's `inherited' + method when making subclasses. - * EWS4800対応 + * parse.y (nextc): clear lex_lastline at the end of file. - * file.c: utimesがない時はutimeを使うように. + * object.c (Init_Object): need to undef Class#append_features. -Mon Apr 3 15:19:41 1995 Yukihiro Matsumoto (matz@ix-02) + * eval.c (rb_eval): no warning on extending classes or modules. - * version 0.71 +Thu Oct 9 11:17:50 1997 Yukihiro Matsumoto - * regexp.c(re_match): バグがあった.match_2を削除した時にenbugして - いたのだった. + * eval.c (error_print): the exception name follows after the error + message. -Mon Mar 27 15:41:43 1995 Yukihiro Matsumoto (matz@ix-02) + * eval.c (compile_error): error message slightly changed. - * dict.c: Dict->Hashに全面的に移行. + * parse.y (nextc): script parsing will be terminated by __END__ at + beginning of line. -Thu Mar 23 20:30:00 1995 Yukihiro Matsumoto (matz@ix-02) + * eval.c (compile_error): `__END__' is no longer a keyword. - * dbm.c,socket.c: extディレクトリに分離. + * parse.y (nextc): protect lastline read from script stream. - * configure: dln周りのチェックの強化 +Tue Oct 7 14:06:06 1997 Yukihiro Matsumoto - * dln.c: initの呼び出しをdlopen()版に合わせた. + * version 1.1 alpha9 released. -Mon Mar 20 17:45:08 1995 Yukihiro Matsumoto (matz@ix-02) + * eval.c (mod_append_features): renamed from extend_class. - * configure: autoconf 2.2に対応(一部). + * eval.c (rb_eval): defining method calls `method_added'. -Fri Mar 17 15:56:44 1995 Yukihiro Matsumoto (matz@ix-02) + * eval.c (ruby_options): exception while processing options must + terminate the interpreter. - * dln.c: dlopenのあるマシンではそちらを使うように.ただし,ちゃん - と動いているかどうかは自信がない. + * error.c (Init_Exception): wrong method configuration. `new' + should have been a singleton method. - * regex.c: virtual concatinationをやめた. +Mon Oct 6 18:55:38 1997 Yukihiro Matsumoto -Thu Mar 16 11:32:57 1995 Yukihiro Matsumoto (matz@ix-02) + * ext/kconv/kconv.c (kconv_guess): code to guess character code + from string. - * version 0.70 +Mon Oct 6 18:38:17 1997 WATANABE Hirofumi - * eval.c,regex.c: gccでのコンパイルエラー. + * pack.c: now encode/decode base64 by `m' template. - * io.c: inplace-editで拡張子が指定されない場合,もとのファイルを削 - 除する. +Fri Oct 3 10:51:10 1997 Yukihiro Matsumoto -Wed Mar 15 14:59:18 1995 Yukihiro Matsumoto (matz@ix-02) + * MANIFEST: needed to include lex.c in the distribution. - * version 0.69 + * eval.c (ruby_options): f_require() called too early. - * eval.c(method_missing): unknownから名称変更. + * eval.c (rb_provide): module extentions should always be `.o'. - * eval.c(single_method_added): 特異メソッドが定義された時に呼ばれ - るメソッド.hookとして使える.実際に定義される直前に呼ばれる. +Thu Oct 2 11:38:31 1997 Yukihiro Matsumoto -Tue Mar 14 14:46:44 1995 Yukihiro Matsumoto (matz@ix-02) + * version 1.1 alpha8 released. - * ruby.c(proc_options): 引数の解析を自分でやることにより引数指定の - 方法がperlに近付いた.getopt_longはもう使わない. + * ext/marshal/marshal.c (r_object): remove temporal regist for + structs. (caused problem if structs form cycles.) - * dir.c(glob): `{}'のネストを許すようにした. + * parse.y (match_gen): static binding for match(=~) calls + with regexp literals. -Mon Mar 13 17:56:25 1995 Yukihiro Matsumoto (matz@ix-02) +Wed Oct 1 15:26:55 1997 Yukihiro Matsumoto - * glob.c: Glob(ワイルドカードオブジェクト)はなくなった.ワイルドカー - ドの展開はDir.glob(文字列)を使う.ワイルドカードのマッチは正規表 - 現で代用. + * eval.c: protect retval in struct tag from GC for C_ALLOCA. -Fri Mar 10 18:35:46 1995 Yukihiro Matsumoto (matz@ix-02) + * eval.c: no more pointer value from setjmp/longjmp. - * eval.c: Mathのようなモジュールは自分自身でextendする. +Wed Oct 1 14:01:49 1997 WATANABE Hirofumi - * eval.c: クラスやモジュールを定義する時,既に同名のものがあれば追 - 加定義となるように.ただし.superクラスの違いなどはチェックする. + * ext/marshal/marshal.c (w_byte): argument must be char. - * regex.c: debug. +Wed Oct 1 10:30:22 1997 Yukihiro Matsumoto - * math.c: 定数PIとEを定義. + * variable.c (mod_const_at): global constants now belongs to the + class Object. -Thu Mar 9 21:35:12 1995 Yukihiro Matsumoto (matz@ix-02) + * object.c (Init_Object): new global constant NIL. - * regex.c: EUC,SJISモードでは0x80以上の8進,16進リテラルを禁止. + * ext/marshal/marshal.c (marshal_dump): try to set binmode. - * regex.c: クラス内でも数値リテラル・文字クラスが使えるようした. + * ext/marshal/marshal.c (r_object): forgot to re-regist structs in + the object table. -Wed Mar 8 17:39:05 1995 Yukihiro Matsumoto (matz@ix-02) + * eval.c (ruby_options): call Init_ext() before any require() + calls by `-r'. - * regex.c: \200など括弧の数以上の表現は8進リテラルと解釈する.ただ - し,\1から\9までは例外. +Fri Sep 30 14:29:22 1997 WATANABE Hirofumi - * regex.c: \9以上のリファレンスも有効にした. + * ext/marshal/marshal.c (w_object): marshal dumped core. -Tue Mar 7 14:26:01 1995 Yukihiro Matsumoto (matz@ix-02) +Tue Sep 30 10:27:39 1997 Yukihiro Matsumoto - * eval.c(public/private): スコープ制御メソッドの名称変更.静的なア - クセスも出来るようにしてみたが,不採用. + * sample/test.rb: bignum test suits added. -Mon Mar 6 19:34:32 1995 Yukihiro Matsumoto (matz@ix-02) + * eval.c (rb_eval): new pseudo variable `true' and `false'. - * eval.c(inlcude): メソッド化.動的にモジュールをインクルードでき - るように.さらに任意のオブジェクトにもモジュールをインクルードで - きるメソッド `extend'も用意した. + * parse.y: new keywords `true' and `false' added. - * parse.y: 文法からincludeを削除.メソッド化. +Mon Sep 29 13:37:58 1997 Yukihiro Matsumoto -Tue Feb 28 15:35:10 1995 Yukihiro Matsumoto (matz@ix-02) + * ruby.c (forbid_setid): forbid some options in suid mode. - * parse.y: 配列,連想配列の最後に`,'をおけるように. + * ruby.h (NUM2DBL): new macro to convert into doubles. -Fri Feb 24 13:15:43 1995 Yukihiro Matsumoto (matz@ix-02) +Mon Sep 27 09:53:48 1997 EGUCHI Osamu - * version 0.68 + * bignum.c: modified for speeding. -Thu Feb 23 11:19:19 1995 Yukihiro Matsumoto (matz@ix-02) +Fri Sep 26 18:27:59 1997 WATANABE Hirofumi - * eval.c: resque節のselfの値が間違っていた. + * sample/from.rb: some extensions. - * eval.c(rb_clear_cache): キャッシュのクリアし忘れがあった. +Mon Sep 29 13:15:56 1997 Yukihiro Matsumoto - * eval.c: 定数のスコープをクラス内の静的スコープに変更した.これに - よって,特異メソッドから参照される定数は,レシーバのクラスではな - く,定義されたスコープのクラスの定数となる. + * parse.y (lhs): no more syntax error on `obj.CONSTANT = value'. -Wed Feb 22 00:51:38 1995 Yukihiro Matsumoto (matz@dyna) +Fri Sep 26 14:41:46 1997 Yukihiro Matsumoto - * regex.c: ignorecaseを正規表現のコンパイル前に指定しないと正しく - 動作しない.修正. + * eval.c (ruby_run): deferred calling Init_ext() just before eval_node. - * string.c(toupper,tolower): bug fix. +Fri Sep 26 13:27:24 1997 WATANABE Hirofumi - * ENV,VERSION: readonly変数から定数へ. + * io.c (io_isatty): forgot to return TRUE value. -Tue Feb 21 18:56:56 1995 Yukihiro Matsumoto (matz@ix-02) +Fri Sep 25 11:10:58 1997 EGUCHI Osamu - * io.c(STDIN, STDOUT, STDERR): 定数として定義. + * eval.c: use _setjmp/_longjmp instead of setjmp/longjmp on some + platforms. - * io.c(select): bug fix. +Wed Sep 24 17:43:13 1997 Yukihiro Matsumoto - * version 0.67 + * string.c (Init_String): String#taint and String#taint? added. -Mon Feb 20 16:10:14 1995 Yukihiro Matsumoto (matz@ix-02) + * class.c (mod_ancestors): ancestors include the class itself. - * parse.y(yylex): 定数を`%識別子'から,第1文字が大文字の識別子に変 - 更.それにともないクラスは定数となった. +Wed Sep 24 00:57:00 1997 Katsuyuki Okabe - * eval.c: クラス定義内のselfがクラス定義外部のthe_classだった. + * X68000 patch. - * variable.c(rb_name_class): クラス名をインスタンス変数に格納する. +Tue Sep 23 20:42:30 1997 EGUCHI Osamu -Thu Feb 16 15:36:17 1995 Yukihiro Matsumoto (matz@ix-02) + * parse.y (node_newnode): SEGV on null node setup. - * parse.y: BLOCKをbraceで表現する文法に変更したものを作ってみる. - MLに提示してみるが反応がない. +Mon Sep 22 11:22:46 1997 Yukihiro Matsumoto - * object.c(do,forever): なくした. + * ruby.c (ruby_prog_init): wrong safe condition check. -Wed Feb 15 13:20:49 1995 Yukihiro Matsumoto (matz@ix-02) +Sun Sep 21 14:46:02 1997 MAEDA shugo - * re.c(new): 第2引数が与えられて,かつnilでないときだけ設定するよ - うに(以前はnilの時にも設定を行なっていた). + * error.c (exc_inspect): garbage added to classpath. - * parse.y(parse_regexp): 正規表現リテラルで大文字小文字を無視する - かどうか指定できるように. +Fri Sep 19 11:49:23 1997 Yukihiro Matsumoto -Tue Feb 14 00:55:33 1995 Yukihiro Matsumoto (matz@dyna) + * parse.y (newtok): forgot to adjust buffer size when shrinking + the token buffer. - * parse.y: (compexpr) -> (expr). + * enum.c (enum_find): rb_eval_cmd() does not return value. -Fri Feb 10 16:30:00 1995 Yukihiro Matsumoto (matz@ix-02) + * io.c (pipe_open): close fds on pipe exec. fcntl(fd, F_SETFD, 1) + no longer used. - * ruby.c(load_file): scriptを読み込む時だけ"#!"の解析を行うように. +Tue Sep 16 17:54:25 1997 Yukihiro Matsumoto - * ruby.c(readin): ファイル読み込み時に先頭に"#!"があり,その行が - "ruby"という文字列を含む時,rubyに引数が与えられていれば,その引 - 数も有効になる. + * file.c (f_test): problem if wrong command specified. - * parse.y(yylex): コメント行の終りが`\'であった時,次の行に継続し - ているとみなすようにした. + * ruby.c (ruby_prog_init): close stdaux and stdprn for MSDOS. -Thu Feb 9 16:18:37 1995 Yukihiro Matsumoto (matz@ix-02) + * ruby.c (ruby_prog_init): should not add path from environment + variable, if ruby is running under seuid. - * version 0.66 + * process.c (init_ids): check suid check for setuid/seteuid etc. - * parse.y: protectをbeginに変更.begin..endは例外処理だけでなく, - 文括弧としても働くことになった. +Mon Sep 15 00:42:04 1997 WATANABE Hirofumi -Wed Feb 1 19:48:24 1995 Yukihiro Matsumoto (matz@ix-02) + * regex.c (re_compile_pattern): \w{3} and \W{3} did not work. - * version 0.65 +Thu Sep 11 10:31:48 1997 Yukihiro Matsumoto - * string.c(str_replace): 置き換える文字列の長さが等しい時メモリコ - ピーをしない. + * version 1.1 alpha7 released. - * string.c(rindex): バグ修正. + * ext/socket/socket.c (sock_new): no setbuf() for NT. -Mon Jan 30 11:23:05 1995 Yukihiro Matsumoto (matz@ix-02) + * io.c (rb_fopen,rb_fdopen): set close-on-exec for every fd. - * parse.y(value_expr): ifのチェックを追加. +Wed Sep 10 15:55:31 1997 Yukihiro Matsumoto - * gc.c(gc_mark): free cellの扱いにバグ. + * ext/marshal/marshal.c (r_bytes0): extra big length check. - * parse.y: 文法の変更(よりシンプルに).例外を減らした. +Tue Sep 9 16:27:14 1997 Yukihiro Matsumoto -Thu Jan 26 00:52:55 1995 Yukihiro Matsumoto (matz@dyna) + * io.c (pipe_fptr_atexit): clean up popen()'ed fptr. - * parse.y: 引数として連想配列を置くことができるように.この場合, - 連想配列リテラルが最終引数となる. + * error.c (set_syserr): some system has error code that is bigger + than sys_nerr. grrr. - * parse.y: 配列参照の`[]'内が空でもよいことにした. +Mon Sep 8 18:33:33 1997 Yukihiro Matsumoto -Tue Jan 24 14:45:15 1995 Yukihiro Matsumoto (matz@ix-02) + * io.c (io_s_new): dereferenced nil for optional mode. - * class.c(rb_include_module): `-v'を指定した時にはincludeしたモジュー - ルとクラス定数が衝突していないかチェックする. +Fri Sep 5 10:26:03 1997 Yukihiro Matsumoto -Mon Jan 23 10:42:09 1995 Yukihiro Matsumoto (matz@ix-02) + * class.c (class_instance_methods): do not include methods which + are changed to private in subclasses. - * parse.y(rb_class2name): メタクラスに関するbug fix. +Thu Sep 4 12:38:53 1997 Yukihiro Matsumoto - * dict.c: Dict[..]で辞書の生成が出来るように. + * variable.c (f_global_variables): list name of the global + variables. - * array.c: Array[..]で配列の生成が出来るように. + * object.c (obj_id): returns unique integer. - * parse.y: 辞書の表現として{a,b,..}という形式も許すように. +Wed Sep 3 14:05:16 1997 Yukihiro Matsumoto -Fri Jan 20 10:28:38 1995 Yukihiro Matsumoto (matz@ix-02) + * version 1.1 alpha6 released. - * re.c(Regexp.quote): 正規表現をエスケープするメソッド. + * eval.c (mod_s_constants): context sensitive constant list. - * 無駄なrb_intern()を減らした. + * variable.c (mod_constants): no more `all' option. - * parse.y: `!', `!=', `!~'を特殊演算子にする.よってこれらは再定義 - できなくなった. + * variable.c (mod_const_of): the values for autoload classes are + their name strings. -Wed Jan 18 13:20:41 1995 Yukihiro Matsumoto (matz@ix-02) + * class.c (class_instance_methods): no special treatment for + singleton classes. - * parse.y: 文法の整理(unless,untilをなくした). + * object.c (obj_singleton_methods): returns list of singleton + method names. -Tue Jan 17 11:11:27 1995 Yukihiro Matsumoto (matz@ix-02) + * parse.y (yylex): no here document after `class' keyword. - * eval.c: defでメソッド再定義時にはスーパークラスのメソッドの可視 - 性を継承する.最初の定義の時は今までと同じデフォルト(トップレベ - ルで関数的,クラス定義内で通常メソッド). + * eval.c (f_load): expand path if fname begins with `~'. - * object.c(Class#new): オブジェクトの生成時に関数的メソッド - init_objectが必ず呼ばれるように変更. +Tue Sep 2 13:19:48 1997 Yukihiro Matsumoto - * eval.c: 未定義のメソッドに対してunknownメソッドが呼ばれるように - なった.エラー表示が今までと同じになるようにenvを調節している. + * class.c (ins_methods_i): do not list undef'ed methods. -Fri Jan 13 14:40:30 1995 Yukihiro Matsumoto (matz@ix-02) +Mon Sep 1 13:42:48 1997 Yukihiro Matsumoto - * gc.c: gcを若干書き換えて整理した.が,あまり変化はなかったようだ. + * version 1.1 alpha5 released. - * parse.y(yylex): symbolを\symから:symに変更した. + * object.c (mod_attr_reader): create methods to define attribute + reader/write/accessor. -Thu Jan 12 01:39:28 1995 Yukihiro Matsumoto (matz@dyna) + * class.c (rb_define_attr): always defines accessors. - * eval.c: 新規関数 rb_eval_string(). + * eval.c (rb_call): alias occured in the module body caused SEGV. - * gc.c: gc_mark()を一部非再帰化. + * parse.y: did not generate here document strings properly. - * variable.c(rb_ivar_{get,set}): インスタンス変数のアクセス周りで - チェックが足りなかった. +Mon Sep 1 11:43:57 1997 WATANABE Hirofumi + + * parse.y (yylex): heredoc dropped an extra character. - * variable.c: クラス定数とインスタンス変数でハッシュテーブルを共有 - するようにした. +Fri Aug 29 11:10:21 1997 Yukihiro Matsumoto - * ruby.h: iv_tblをRBasicからRObjectとRClassへ移動した.これにより, - ObjectとClass,Moduleしかインスタンス変数を持てなくなる.が,メモ - リ効率は若干向上する. + * class.c (class_instance_methods): same method names should not + appear more than twice. -Tue Jan 10 00:58:20 1995 Yukihiro Matsumoto (matz@dyna) + * parse.y (yylex): spaces can follow =begin/=end. - * 0.64 released + * variable.c (find_class_path): look for class_tbl also for + unnamed fundamental classes, such as Object, String, etc. - * eval.c: レシーバと引数は常にiterではない. + * variable.c (rb_name_class): can't name class before String class + is initilialized. - * cons.c(aref,aset): negative offset対応. + * inits.c (rb_call_inits): unrecognized dependency from GC to + Array. -Mon Jan 9 14:40:39 1995 Yukihiro Matsumoto (matz@ix-02) + * variable.c (find_class_path): could not find class if Object's + iv_tbl is NULL. - * parse.y: foo{..}の形式において,fooをローカル変数やクラス名では - なく,引数なしの関数型メソッド呼び出しとみなすようにした. +Thu Aug 28 13:12:05 1997 Yukihiro Matsumoto - * list.c -> cons.c: 名称変更(クラス名も). + * version 1.1 alpha4 released. - * list.c: a::b::c::nilをリスト(a b c)とみなすlisp形式から,a::b::c - をリスト(a b c)とみなすruby形式に変更.[], []=, eachもそれに会わ - せた仕様とする. + * variable.c (mod_constants): wrong condition for singleton + class. - * list.c: consペアとしての機能を強調.仕様変更. + * parse.y (yylex): revised `=begin' skip code. -Sat Jan 7 01:26:26 1995 Yukihiro Matsumoto (matz@dyna) + * parse.y (here_document): forgot to free(eos). - * eval.c: 自己代入の不具合修正. + * parse.y (yylex): spaces after `<<' prohibited for here + documents to avoid confusing with operator `<<'. - * eval.c(masign): 多重代入が配列もリストもとれるようにした. + * eval.c (is_defined): separated from rb_eval(). - * list.c: assocを2要素の配列からList(CONSペア)に変更した. +Wed Aug 27 11:32:42 1997 Yukihiro Matsumoto -Fri Jan 6 13:42:12 1995 Yukihiro Matsumoto (matz@ix-02) + * version 1.1 alpha3 released. - * parse.y: a[b]+=cやa.b+=cなどの自己代入形式で,aやbを2度評価しな - くなった. + * variable.c (mod_name): returns name of the class/module. - * eval.c: iterator設定のバグフィックス. + * parse.y (here_document): finally here document available now. - * list.c: Listクラスを新設. + * variable.c (fc_i): some classes/modules does not have iv_tbl. -Thu Jan 5 13:55:00 1995 Yukihiro Matsumoto (matz@ix-02) + * variable.c (find_class_path): avoid inifinite loop. - * parse.y: SCOPEのメモリリークをなくした. +Tue Aug 26 13:43:47 1997 Yukihiro Matsumoto - * eval.c: built-inメソッドへの引数の引き渡し方を変更して,配列の生 - 成数を減らした. + * eval.c (rb_eval): undef'ing non-existing method will raise + NameError exception. - * re.c: match-dataを毎回生成することをやめた.`$~'をアクセスした時 - にon-demandで生成する. + * object.c (class_s_new): needed to create metaclass too. - * string.c etc: 不必要なmemmoveをmemcpyに置換. + * eval.c (error_print): no class name print for anonymous class. - * parse.y: =~, !~は副作用があるのでコンパイル時に展開できない. + * eval.c (rb_longjmp): proper exception raised if raise() called + without arguments, with $! or $@ set. -Tue Jan 3 02:04:36 1995 Yukihiro Matsumoto (matz@dyna) + * object.c (Init_Object): superclass()'s method argument setting + was wrong again. - * eval.c: rest引数のbug fix. + * class.c (mod_anscestors): list superclasses and included modules + in priority order. - * eval.c,gc.c: scopeをオブジェクトにした. +Mon Aug 25 11:53:11 1997 Yukihiro Matsumoto - * eval.c: envとscopeの扱いを変更した. + * version 1.1 alpha2 released. -Wed Dec 28 09:46:57 1994 Yukihiro Matsumoto (matz@ix-02) + * sample/ruby-mode.el (ruby-parse-region): auto-indent now + supports "\\" in the strings. - * parse.y: evalでローカル変数が追加された場合に対応した. + * struct.c (struct_getmember): new API to get member value from C + language side. - * parse.y: 演算子を含むaliasのbug fix. +Sat Aug 23 21:39:05 1997 Yukihiro Matsumoto -Tue Dec 27 16:45:20 1994 Yukihiro Matsumoto (matz@ix-02) + * parse.y (asignable): remove unnecessary local variable + initialize by nil. - * parse.y: def A Bをalias A Bに変更. +Fri Aug 22 14:26:40 1997 Yukihiro Matsumoto - * eval.c: alias関係のbug修正.nodeをオブジェクト化した時にenbugし - たようだ. + * eval.c (error_print): modified exception print format. - * signal.c: システムコールの再定義を止めた. +Thu Aug 21 16:10:58 1997 Yukihiro Matsumoto - * io.c(select): write/exceptのフラグ設定にバグ. + * sample/ruby-mode.el (ruby-calculate-indent): wrong indent level + calculated with keyword operators. - * Makefile.in: static link用オプションをMake変数として独立させた. +Thu Aug 21 11:36:58 1997 WATANABE Hirofumi -Tue Dec 20 00:46:19 1994 Yukihiro Matsumoto (matz@dyna) + * parse.y (arg): ary[0] += 1 cause SEGV - * 0.63 released +Wed Aug 20 17:28:50 1997 Yukihiro Matsumoto - * eval.c(rb_call): superの呼び出しで落ちる.argc, argvの設定を忘れ - ていた. + * ruby.c (ruby_process_options): require() all modules after + processing all options - * parse.y(read_escape): 展開エラー. + * process.c (rb_proc_exec): more security checks added. - * variable.c: 定義済みの変数のhookを変更しないように. + * process.c (rb_proc_exec): insecure path on exec. -Mon Dec 19 12:01:10 1994 Yukihiro Matsumoto (matz@ix-02) + * hash.c (f_getenv): PATH modification security check. - * parse.y(cond): 条件式に代入式が置かれた場合,`-v'オプションで警 - 告が出るように. +Tue Aug 19 00:15:38 1997 Yukihiro Matsumoto - * parse.y(**): 冪乗演算子`**'の優先順位を単項演算子より高くした. + * version 1.1 alpha1 released. - * parse.y(and,or): 優先順位の低い演算子`and', `or'. + * eval.c (mod_eval): work as normal eval() if second binding + argument given. - * 0.62 released. + * eval.c (rb_call): did not raise ArgumentError if too many + arguments more than optional arguments (without rest arg). - * eval.c: 不必要になったPUSH_ENV, POP_ENVを減らした. + * eval.c (rb_eval): did not work well for op_asgn2 (attribute + self assignment). - * env.h: ENVIONからselfをはずした.PUSH_ENVはsuperの準備のためだけ - に用いることにした. + * eval.c (Init_Thread): returns main thread. - * eval.c: 下記のオブジェクト化で遅くなった実行速度をもとに戻した. +Mon Aug 18 09:25:56 1997 Yukihiro Matsumoto -Mon Dec 17 23:01:10 1994 Yukihiro Matsumoto (matz@ix-02) + * object.c (inspect_i): did not display T_DATA instance variables. - * eval.c: env.{argv,argc}とscope.local_varsのオブジェクト化. + * parse.y: provides more accurate line number information. - * eval.c: 1スコープ内で複数Blockを生成したときのバグを修正. + * eval.c (thread_value): include value's backtrace information in + the variable `$@'. -Fri Dec 16 15:52:06 1994 Yukihiro Matsumoto (matz@ix-02) + * eval.c (f_abort): print backtrace and exit. - * parse.y: `&&'と`||'の両辺はいつでも条件式とした. +Sat Aug 16 00:17:44 1997 Yukihiro Matsumoto -Thu Dec 15 00:16:04 1994 Yukihiro Matsumoto (matz@dyna) + * eval.c (class_new_instance): do not make instance from virtual + classes. - * eval.c(Block): Blockオブジェクトを実現. + * object.c (class_s_new): do not make subclass of singleton class. - * node.h: NODE_QLISTはなくなった. +Fri Aug 15 15:49:46 1997 Yukihiro Matsumoto - * eval.c(rb_call): 引数への代入を名前で一つずつ代入するのをやめて, - 一度にコピーするようにした. + * eval.c (call_trace_func): block context switch in the trace + function. - * eval.c(rb_call): rubyで記述されたメソッドへの引数渡しをinline化. + * eval.c (rb_eval): clear method cache at class extention. - * eval.c: イテレータ判定処理の全面書き換え.不適切なイテレータ呼び - 出しをなくした.例えば「[foo(),bar()]{i|baz(i)}」でfooもbarもイ - テレータとして呼び出され*ない*. + * object.c (obj_type): returns object's class even if it defines + singleton methods. - * eval.c(rb_call): SCOPE処理をinline化.メソッド呼び出しの若干の高 - 速化. +Fri Aug 15 19:40:43 1997 WATANABE Hirofumi -Wed Dec 14 18:09:33 1994 Yukihiro Matsumoto (matz@ix-02) + * ext/socket/socket.c (Init_socket): small typo caused SEGV. - * node.h: nodeもオブジェクトにする.よってGCで回収される. +Wed Aug 13 17:51:46 1997 Yukihiro Matsumoto -Thu Dec 8 14:17:29 1994 Yukihiro Matsumoto (matz@ix-02) + * version 1.1 alpha0 released. - * 0.60 released - alpha test baseline. diff --git a/MANIFEST b/MANIFEST index 1ae2adcd41..2bdaf290b3 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,3 +1,4 @@ +COPYING ChangeLog MANIFEST Makefile.in @@ -32,10 +33,16 @@ glob.c hash.c inits.c install-sh +instruby.rb +intern.h io.c io.h +keywords +lex.c main.c +marshal.c math.c +mkconfig.rb node.h numeric.c object.c @@ -51,6 +58,7 @@ regex.h ruby.1 ruby.c ruby.h +rubytest.rb sig.h signal.c sprintf.c @@ -78,34 +86,41 @@ lib/cgi-lib.rb lib/complex.rb lib/date.rb lib/debug.rb +lib/delegate.rb lib/e2mmap.rb -lib/e2mmap1_0.rb +lib/eregex.rb lib/find.rb lib/finalize.rb lib/ftplib.rb +lib/ftools.rb lib/getopts.rb +lib/importenv.rb lib/jcode.rb lib/mailread.rb lib/mathn.rb lib/matrix.rb +lib/mkmf.rb lib/mutex_m.rb lib/observer.rb +lib/ostruct.rb lib/parsearg.rb lib/parsedate.rb lib/ping.rb +lib/pstore.rb lib/rational.rb +lib/shellwords.rb lib/sync.rb lib/thread.rb lib/thwait.rb lib/tk.rb -lib/tkcore.rb lib/tkcanvas.rb lib/tkclass.rb +lib/tkdialog.rb lib/tkentry.rb lib/tkscrollbox.rb lib/tktext.rb -lib/tkthcore.rb lib/tracer.rb +lib/weakref.rb missing/alloca.c missing/crypt.c missing/dir.h @@ -126,6 +141,7 @@ missing/strtol.c missing/strtoul.c missing/x68.c sample/biorhythm.rb +sample/cbreak.rb sample/clnt.rb sample/dbmtest.rb sample/dir.rb @@ -141,7 +157,6 @@ sample/freq.rb sample/from.rb sample/fullpath.rb sample/getopts.test -sample/io.rb sample/less.rb sample/list.rb sample/list2.rb @@ -155,6 +170,7 @@ sample/occur.rb sample/occur2.rb sample/philos.rb sample/pi.rb +sample/rbc.rb sample/rcs.awk sample/rcs.dat sample/rcs.rb @@ -180,6 +196,8 @@ win32/Makefile win32/config.h win32/ntsetup.bat win32/ruby.def +win32/sdbm.c +win32/sdbm.h x68/fconvert.c x68/select.c x68/_dtos18.c diff --git a/Makefile.in b/Makefile.in index ee0ac1fcfc..3c616d9983 100644 --- a/Makefile.in +++ b/Makefile.in @@ -7,9 +7,6 @@ VPATH = @srcdir@:@srcdir@/missing CC = @CC@ YACC = @YACC@ -INSTALL = @INSTALL@ -INSTALL_PROGRAM = @INSTALL_PROGRAM@ -INSTALL_DATA = @INSTALL_DATA@ PURIFY = @SET_MAKE@ @@ -18,14 +15,6 @@ LDFLAGS = @STATIC@ $(CFLAGS) @LDFLAGS@ LIBS = @LIBS@ $(EXTLIBS) MISSING = @LIBOBJS@ @ALLOCA@ -program_transform_name = -e @program_transform_name@ -RUBY_INSTALL_NAME = `t='$(program_transform_name)'; echo ruby | sed $$t` - -prefix = @prefix@ -exec_prefix = @exec_prefix@ -bindir = @bindir@ -libdir = @libdir@/$(RUBY_INSTALL_NAME) - binsuffix = @binsuffix@ #### End of system configuration section. #### @@ -33,7 +22,7 @@ binsuffix = @binsuffix@ LIBRUBY = libruby.a -EXTOBJS = dmyext.o +EXTOBJS = MAINOBJ = main.o @@ -54,6 +43,7 @@ OBJS = array.o \ inits.o \ io.o \ math.o \ + marshal.o \ numeric.o \ object.o \ pack.o \ @@ -75,15 +65,12 @@ OBJS = array.o \ version.o \ $(MISSING) -all: miniruby$(binsuffix) @srcdir@/ext/Setup - @if test -z "$$UNDER_EXTMAKE_RB"; \ - then echo "Compiling ext modules"; \ - UNDER_EXTMAKE_RB=yes; export UNDER_EXTMAKE_RB; \ - cd ext; ../miniruby ./extmk.rb @EXTSTATIC@; fi +all: miniruby$(binsuffix) rbconfig.rb + @cd ext; ../miniruby$(binsuffix) ./extmk.rb @EXTSTATIC@ -miniruby$(binsuffix): $(OBJS) $(MAINOBJ) $(EXTOBJS) +miniruby$(binsuffix): $(OBJS) $(MAINOBJ) dmyext.o @rm -f $@ - $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(LIBS) -o miniruby + $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(OBJS) dmyext.o $(LIBS) -o miniruby ruby$(binsuffix): $(LIBRUBY) $(MAINOBJ) $(EXTOBJS) @rm -f $@ @@ -93,36 +80,31 @@ $(LIBRUBY): $(OBJS) dmyext.o @AR@ rcu $(LIBRUBY) $(OBJS) dmyext.o @-@RANLIB@ $(LIBRUBY) 2> /dev/null || true -install:; $(INSTALL_PROGRAM) ruby$(binsuffix) $(bindir)/$(RUBY_INSTALL_NAME)$(binsuffix) - @-@STRIP@ $(bindir)/$(RUBY_INSTALL_NAME)$(binsuffix) - @test -d $(libdir) || mkdir $(libdir) - cd ext; ../miniruby ./extmk.rb install - @for rb in `grep '^lib/' @srcdir@/MANIFEST`; do \ - $(INSTALL_DATA) @srcdir@/$$rb $(libdir); \ - done +install: rbconfig.rb + ./miniruby$(binsuffix) $(srcdir)/instruby.rb -clean:; @rm -f $(OBJS) $(LIBRUBY) $(MAINOBJ) +clean:; @rm -f $(OBJS) $(LIBRUBY) $(MAINOBJ) rbconfig.rb @rm -f ext/extinit.c ext/extinit.o dmyext.o - cd ext; ../miniruby ./extmk.rb clean + @if test -f ./miniruby; then cd ext; ../miniruby ./extmk.rb clean; fi realclean: clean - @rm -f Makefile ext/extmk.rb ext/config.cache parse.c + @rm -f Makefile ext/extmk.rb ext/config.cache @rm -f config.cache config.h config.log config.status - @rm -f core ruby$(binsuffix) miniruby$(binsuffix) parse.c *~ *.core gmon.out - -test:; @-./ruby @srcdir@/sample/test.rb > ./ruby_test 2>&1; \ - if grep '^end of test' ./ruby_test > /dev/null; then \ - echo "test succeeded"; \ - else \ - grep '^sample/test.rb' ./ruby_test; \ - grep '^not' ./ruby_test; \ - echo "test failed";\ - fi;\ - rm -f ./ruby_test + @rm -f parse.c lex.c *~ core *.core gmon.out + @rm -f ruby$(binsuffix) miniruby$(binsuffix) + +test: miniruby$(binsuffix) + @./miniruby$(binsuffix) $(srcdir)/rubytest.rb + +rbconfig.rb: config.status miniruby$(binsuffix) + @./miniruby$(binsuffix) $(srcdir)/mkconfig.rb rbconfig.rb .c.o: $(CC) $(CFLAGS) $(CPPFLAGS) -c $< +lex.c: keywords + gperf -p -j1 -i 1 -g -o -t -N rb_reserved_word -k1,3,$$ keywords > lex.c + parse.c: parse.y $(YACC) $< mv -f y.tab.c parse.c @@ -178,42 +160,40 @@ x68.o: @srcdir@/missing/x68.c # Prevent GNU make v3 from overflowing arg limit on SysV. .NOEXPORT: ### -parse.o : parse.y ruby.h defines.h config.h env.h node.h st.h regex.h +parse.o : parse.y ruby.h defines.h config.h intern.h env.h node.h st.h regex.h lex.c ### -array.o: array.c ruby.h config.h defines.h -bignum.o: bignum.c ruby.h config.h defines.h -class.o: class.c ruby.h config.h defines.h node.h st.h -compar.o: compar.c ruby.h config.h defines.h -dir.o: dir.c ruby.h config.h defines.h +array.o: array.c ruby.h config.h defines.h intern.h +bignum.o: bignum.c ruby.h config.h defines.h intern.h +class.o: class.c ruby.h config.h defines.h intern.h node.h st.h +compar.o: compar.c ruby.h config.h defines.h intern.h +dir.o: dir.c ruby.h config.h defines.h intern.h dln.o: dln.c config.h defines.h dln.h st.h dmyext.o: dmyext.c -enum.o: enum.c ruby.h config.h defines.h -error.o: error.c ruby.h config.h defines.h env.h -eval.o: eval.c ruby.h config.h defines.h env.h node.h sig.h st.h dln.h -file.o: file.c ruby.h config.h defines.h io.h sig.h -fnmatch.o: fnmatch.c config.h fnmatch.h -gc.o: gc.c ruby.h config.h defines.h env.h sig.h st.h node.h re.h regex.h -glob.o: glob.c config.h fnmatch.h -hash.o: hash.c ruby.h config.h defines.h st.h -inits.o: inits.c ruby.h config.h defines.h -io.o: io.c ruby.h config.h defines.h io.h sig.h +enum.o: enum.c ruby.h config.h defines.h intern.h +error.o: error.c ruby.h config.h defines.h intern.h env.h +eval.o: eval.c ruby.h config.h defines.h intern.h env.h node.h sig.h st.h dln.h +file.o: file.c ruby.h config.h defines.h intern.h io.h sig.h +gc.o: gc.c ruby.h config.h defines.h intern.h env.h sig.h st.h node.h re.h regex.h +hash.o: hash.c ruby.h config.h defines.h intern.h st.h +inits.o: inits.c ruby.h config.h defines.h intern.h +io.o: io.c ruby.h config.h defines.h intern.h io.h sig.h main.o: main.c -math.o: math.c ruby.h config.h defines.h -numeric.o: numeric.c ruby.h config.h defines.h -object.o: object.c ruby.h config.h defines.h st.h -pack.o: pack.c ruby.h config.h defines.h -process.o: process.c ruby.h config.h defines.h sig.h st.h -random.o: random.c ruby.h config.h defines.h -range.o: range.c ruby.h config.h defines.h -re.o: re.c ruby.h config.h defines.h re.h regex.h -regex.o: regex.c config.h defines.h regex.h util.h -ruby.o: ruby.c ruby.h config.h defines.h re.h regex.h dln.h -signal.o: signal.c ruby.h config.h defines.h sig.h -sprintf.o: sprintf.c ruby.h config.h defines.h +marshal.o: marshal.c ruby.h config.h defines.h intern.h io.h sig.h st.h +math.o: math.c ruby.h config.h defines.h intern.h +numeric.o: numeric.c ruby.h config.h defines.h intern.h +object.o: object.c ruby.h config.h defines.h intern.h st.h +pack.o: pack.c ruby.h config.h defines.h intern.h +process.o: process.c ruby.h config.h defines.h intern.h sig.h st.h +random.o: random.c ruby.h config.h defines.h intern.h +range.o: range.c ruby.h config.h defines.h intern.h +re.o: re.c ruby.h config.h defines.h intern.h re.h regex.h +ruby.o: ruby.c ruby.h config.h defines.h intern.h re.h regex.h dln.h +signal.o: signal.c ruby.h config.h defines.h intern.h sig.h +sprintf.o: sprintf.c ruby.h config.h defines.h intern.h st.o: st.c config.h st.h -string.o: string.c ruby.h config.h defines.h re.h regex.h -struct.o: struct.c ruby.h config.h defines.h -time.o: time.c ruby.h config.h defines.h -util.o: util.c defines.h config.h util.h -variable.o: variable.c ruby.h config.h defines.h env.h st.h -version.o: version.c ruby.h config.h defines.h version.h +string.o: string.c ruby.h config.h defines.h intern.h re.h regex.h +struct.o: struct.c ruby.h config.h defines.h intern.h +time.o: time.c ruby.h config.h defines.h intern.h +util.o: util.c defines.h intern.h config.h util.h +variable.o: variable.c ruby.h config.h defines.h intern.h env.h st.h +version.o: version.c ruby.h config.h defines.h intern.h version.h diff --git a/README b/README index 6583bc889f..d41fb9f79a 100644 --- a/README +++ b/README @@ -5,7 +5,7 @@ easy object-oriented programming. It has many features to process text files and to do system management tasks (as in perl). It is simple, straight-forward, and extensible. -* Features of ruby +* Features of Ruby + Simple Syntax + *Normal* Object-Oriented features(ex. class, method calls) @@ -17,17 +17,15 @@ perl). It is simple, straight-forward, and extensible. + Dynamic Loading of Object files(on some architecture) + Highly Portable(works on many UNIX machines) -* How to get ruby +* How to get Ruby -** by ftp - -The ruby distribution can be found on +The Ruby distribution can be found on ftp://ftp.netlab.co.jp/pub/lang/ruby/ * How to compile and install -This is what you need to do to compile and install ruby: +This is what you need to do to compile and install Ruby: 1. Run ./configure, which will generate config.h and Makefile. @@ -41,40 +39,61 @@ This is what you need to do to compile and install ruby: 4. Run make. - 5. Optionally, run 'make test' to check that the compiled ruby + 5. Optionally, run 'make test' to check that the compiled Ruby interpreter works well. If you see the message "test succeeded", - your ruby works as it should. + your Ruby works as it should (hopefully). 6. Run 'make install' -If you fail to compile ruby, please send the detailed error report with +If you fail to compile Ruby, please send the detailed error report with the error log and machine/OS type, to help others. * Copying -Ruby is copyrighted by Yukihiro Matsumoto . +Ruby is copyrighted free software by Yukihiro Matsumoto . +You can redistribute it and/or modify it under either the terms of the GPL +(see COPYING file), or the conditions below: + + 1. You may make and give away verbatim copies of the source form of the + software without restriction, provided that you duplicate all of the + original copyright notices and associated disclaimers. + + 2. You may modify your copy of the software in any way, provided that + you do at least ONE of the following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet + or an equivalent medium, or by allowing the author to include your + modifications in the software. + + b) use the modified software only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided. + + d) make other distribution arrangements with the author. -This source is distributed under the conditions blow: + 3. You may distribute the software in object code or executable + form, provided that you do at least ONE of the following: - 1. You may make and give away verbatim copies of the source form of - the software without restriction, provided that you do not modify - the original distribution files. + a) distribute the executables and library files of the software, + together with instructions (in the manual page or equivalent) + on where to get the original distribution. - If you want to distribute the modified version in any way, contact - the author. + b) accompany the distribution with the machine-readable source of + the software. - 2. You may distribute the software in object code or executable - form, provided that you distribute it with instructions on where - to get the software. + c) give non-standard executables non-standard names, with + instructions on where to get the original software + distribution. - 3. You may modify the software in any way, provided that you do not - distribute the modified version. + d) make other distribution arrangements with the author. 4. You may modify and include the part of the software into any other software (possibly commercial). But some files in the distribution are not written by the author, so that they are not under this terms. - They are gc.c(partly),utils.c(partly), regex.[ch],fnmatch.[ch], - glob.c, st.[ch] and somme files under the ./missing directory. See + They are gc.c(partly), utils.c(partly), regex.[ch], fnmatch.[ch], + glob.c, st.[ch] and some files under the ./missing directory. See each files for the copying condition. 5. The scripts and library files supplied as input to or produced as @@ -88,9 +107,9 @@ This source is distributed under the conditions blow: WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. -* ruby home-page +* Ruby home-page - The URL of the ruby home-page is: +The URL of the Ruby home-page is: http://www.netlab.co.jp/ruby/ diff --git a/README.jp b/README.jp index 8a100106b1..00822a3658 100644 --- a/README.jp +++ b/README.jp @@ -9,6 +9,7 @@ Ruby です.さらにシンプルな文法と,例外処理やイテレータなどの機構 によって,より分かりやすいプログラミングが出来ます. + * Rubyの特長. + シンプルな文法 @@ -21,6 +22,7 @@ Ruby + ダイナミックローディング (アーキテクチャによる) + 移植性が高い.多くのUNIX上で動く + * 入手法 ** ftpで @@ -29,6 +31,7 @@ Ruby ftp://ftp.netlab.co.jp/pub/lang/ruby/ + * ホームページ RubyのホームページのURLは @@ -37,6 +40,7 @@ Ruby です. + * メイリングリスト Rubyに関わる話題のためのメイリングリストを開設しました.ア @@ -46,6 +50,7 @@ Ruby です.このアドレスにメイルを送れば,自動的に登録されます. + * コンパイル・インストール 以下の手順で行ってください. @@ -80,13 +85,14 @@ Ruby シン,OSの種類を含むできるだけ詳しいレポートを作者に送ってく ださると他の方のためにもなります. + * 移植 UNIXであればconfigureがほとんどの差異を吸収してくれるはずで すが,思わぬ見落としがあった場合(あるに違いない),作者にその ことをレポートすれば,解決できるかも知れません. -アークテクチャにもっとも依存するのはGC部です.rubyのGCは対象 +アークテクチャにもっとも依存するのはGC部です.RubyのGCは対象 のアーキテクチャがsetjmp()によって全てのレジスタを jmp_bufに 格納することと,jmp_bufとスタックが32bitアラインメントされて いることを仮定しています.特に前者が成立しない場合の対応は非 @@ -95,50 +101,63 @@ UNIX クするコードを追加するだけで済みます.「defined(THINK_C)」で 括られている部分を参考にしてください -# 実際にはrubyはThink Cではコンパイルできません. +# 実際にはRubyはThink Cではコンパイルできません. レジスタウィンドウを持つCPUでは,レジスタウィンドウをスタッ クにフラッシュするアセンブラコードを追加する必要があるかも知 れません. + * 配布条件 -作者は以下の条件のもとにrubyを配布します. +RUbyはフリーソフトウェアです.GPL(the GNU General Public +Licence)または以下に示す条件でRubyを再配布できます.GPLにつ +いてはCOPYINGファイルを参照して下さい. + + 1. 複製は制限なく自由です. + + 2. 以下の条件のいずれかを満たす時に手元のRubyのソースを自 + 由に変更できます. + + (a) ネットニューズにポストしたり,作者に変更を送付する + などの方法で,変更を公開する + + (b) 変更したRubyを自分の所属する組織内部だけで使う - + 再配布 + (c) 変更点を明示したうえ,ソフトウェアの名前を変更する. + そのソフトウェアを配布する時にはもとのRubyも同時に + 配布する - 配布した状態を維持する限り自由です.変更を行ったものを再 - 配布することを希望する時には作者に連絡してください. + (d) その他の変更条件を作者と合意する - 変更を行なわないrubyをコンパイルしたバイナリの配布は禁止 - しませんが,バイナリを受け取った人がソースを入手できるよ - うに,ソースの入手法を明示してください. + 3. 以下の条件のいずれかを満たす時にRubyをオブジェクトコー + ドや実行形式でも配布できます. - + 変更 + (a) バイナリを受け取った人がソースを入手できるようにソー + スの入手法を明示する - 再配布を行わない限り,いかなる目的であれ自由です.ただし, - 機能拡張やバグ修正は作者へのフィードバックを期待します - (もちろん強制ではありません). + (b) 機械可読なソースコードを添付する - + 他のプログラムへの引用 + (c) 変更を行ったバイナリは名前を変更したうえ,ソースの + 入手法を明示する - いかなる目的であれ自由です.ただし,rubyに含まれる他の作 - 者によるコードは,それぞれの作者の意向による制限が加えら - れます.具体的にはgc.c(一部),util.c(一部),regex.[ch], - fnmatch.[ch],glob.c,st.[ch]と./missingディレクトリ下の - ファイル群が該当します. + (d) その他の配布条件を作者と合意する - + Rubyスクリプトの権利 + 4. 他のプログラムへの引用はいかなる目的であれ自由です.た + だし,Rubyに含まれる他の作者によるコードは,それぞれの + 作者の意向による制限が加えられます.具体的にはgc.c(一部), + util.c(一部),st.[ch],regex.[ch], fnmatch.[ch], glob.c + および./missingディレクトリ下のファイル群が該当します. - 全てのrubyスクリプトの権利はそれぞれの著作者に属します. - 作者はこれらに関して一切の権利を主張しません.またrubyに - 組み込むための拡張モジュールに関しても同様です. + 5. Rubyへの入力となるスクリプトおよび,Rubyからの出力の権 + 利はRubyの作者ではなく,それぞれの入出力を生成した人に + 属します.また,Rubyに組み込むための拡張モジュールにつ + いても同様です. - + 無保証 + 6. Rubyは無保証です.作者はRubyをサポートする意志はありま + すが,Ruby自身のバグあるいはRubyスクリプトのバグなどか + ら発生するいかなる損害に対しても責任を持ちません. - Rubyは無保証です.作者はrubyをサポートする意志はあります - が,ruby自身のバグあるいはrubyスクリプトのバグなどから発 - 生するいかなる損害に対しても責任を持ちません. * 著者 diff --git a/array.c b/array.c index 39e10a35e3..388fb05bd7 100644 --- a/array.c +++ b/array.c @@ -12,9 +12,8 @@ #include "ruby.h" -VALUE cArray; -VALUE rb_to_a(); +VALUE cArray; #define ARY_DEFAULT_SIZE 16 @@ -90,22 +89,22 @@ ary_new3(n, va_alist) va_dcl { va_list ar; - struct RArray* ary; + VALUE ary; int i; if (n < 0) { IndexError("Negative number of items(%d)", n); } - ary = (struct RArray*)ary_new2(nptr[i] = va_arg(ar, VALUE); + RARRAY(ary)->ptr[i] = va_arg(ar, VALUE); } va_end(ar); - ary->len = n; - return (VALUE)ary; + RARRAY(ary)->len = n; + return ary; } VALUE @@ -113,27 +112,27 @@ ary_new4(n, elts) int n; VALUE *elts; { - struct RArray* ary; + VALUE ary; - ary = (struct RArray*)ary_new2(n); - MEMCPY(ary->ptr, elts, VALUE, n); - ary->len = n; + ary = ary_new2(n); + MEMCPY(RARRAY(ary)->ptr, elts, VALUE, n); + RARRAY(ary)->len = n; - return (VALUE)ary; + return ary; } VALUE assoc_new(car, cdr) VALUE car, cdr; { - struct RArray* ary; + VALUE ary; - ary = (struct RArray*)ary_new2(2); - ary->ptr[0] = car; - ary->ptr[1] = cdr; - ary->len = 2; + ary = ary_new2(2); + RARRAY(ary)->ptr[0] = car; + RARRAY(ary)->ptr[1] = cdr; + RARRAY(ary)->len = 2; - return (VALUE)ary; + return ary; } static VALUE @@ -179,7 +178,7 @@ ary_s_create(argc, argv, class) void ary_store(ary, idx, val) - struct RArray *ary; + VALUE ary; int idx; VALUE val; { @@ -188,69 +187,69 @@ ary_store(ary, idx, val) IndexError("negative index for array"); } - if (idx >= ary->capa) { - ary->capa = idx + ARY_DEFAULT_SIZE; - REALLOC_N(ary->ptr, VALUE, ary->capa); + if (idx >= RARRAY(ary)->capa) { + RARRAY(ary)->capa = idx + ARY_DEFAULT_SIZE; + REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa); } - if (idx > ary->len) { - memclear(ary->ptr+ary->len, idx-ary->len+1); + if (idx > RARRAY(ary)->len) { + memclear(RARRAY(ary)->ptr+RARRAY(ary)->len, idx-RARRAY(ary)->len+1); } - if (idx >= ary->len) { - ary->len = idx + 1; + if (idx >= RARRAY(ary)->len) { + RARRAY(ary)->len = idx + 1; } - ary->ptr[idx] = val; + RARRAY(ary)->ptr[idx] = val; } VALUE ary_push(ary, item) - struct RArray *ary; + VALUE ary; VALUE item; { - ary_store(ary, ary->len, item); - return (VALUE)ary; + ary_store(ary, RARRAY(ary)->len, item); + return ary; } static VALUE ary_push_method(argc, argv, ary) int argc; VALUE *argv; - struct RArray *ary; + VALUE ary; { while (argc--) { - ary_store(ary, ary->len, *argv++); + ary_store(ary, RARRAY(ary)->len, *argv++); } - return (VALUE)ary; + return ary; } VALUE ary_pop(ary) - struct RArray *ary; + VALUE ary; { - if (ary->len == 0) return Qnil; - if (ary->len * 10 < ary->capa && ary->capa > ARY_DEFAULT_SIZE) { - ary->capa = ary->len * 2; - REALLOC_N(ary->ptr, VALUE, ary->capa); + if (RARRAY(ary)->len == 0) return Qnil; + if (RARRAY(ary)->len * 10 < RARRAY(ary)->capa && RARRAY(ary)->capa > ARY_DEFAULT_SIZE) { + RARRAY(ary)->capa = RARRAY(ary)->len * 2; + REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa); } - return ary->ptr[--ary->len]; + return RARRAY(ary)->ptr[--RARRAY(ary)->len]; } VALUE ary_shift(ary) - struct RArray *ary; + VALUE ary; { VALUE top; - if (ary->len == 0) return Qnil; + if (RARRAY(ary)->len == 0) return Qnil; - top = ary->ptr[0]; - ary->len--; + top = RARRAY(ary)->ptr[0]; + RARRAY(ary)->len--; /* sliding items */ - MEMMOVE(ary->ptr, ary->ptr+1, VALUE, ary->len); - if (ary->len * 10 < ary->capa && ary->capa > ARY_DEFAULT_SIZE) { - ary->capa = ary->len * 2; - REALLOC_N(ary->ptr, VALUE, ary->capa); + MEMMOVE(RARRAY(ary)->ptr, RARRAY(ary)->ptr+1, VALUE, RARRAY(ary)->len); + if (RARRAY(ary)->len * 10 < RARRAY(ary)->capa && RARRAY(ary)->capa > ARY_DEFAULT_SIZE) { + RARRAY(ary)->capa = RARRAY(ary)->len * 2; + REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa); } return top; @@ -258,65 +257,64 @@ ary_shift(ary) VALUE ary_unshift(ary, item) - struct RArray *ary; - int item; + VALUE ary, item; { ary_modify(ary); - if (ary->len >= ary->capa) { - ary->capa+=ARY_DEFAULT_SIZE; - REALLOC_N(ary->ptr, VALUE, ary->capa); + if (RARRAY(ary)->len >= RARRAY(ary)->capa) { + RARRAY(ary)->capa+=ARY_DEFAULT_SIZE; + REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa); } /* sliding items */ - MEMMOVE(ary->ptr+1, ary->ptr, VALUE, ary->len); + MEMMOVE(RARRAY(ary)->ptr+1, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len); - ary->len++; - return ary->ptr[0] = item; + RARRAY(ary)->len++; + return RARRAY(ary)->ptr[0] = item; } VALUE ary_entry(ary, offset) - struct RArray *ary; + VALUE ary; int offset; { - if (ary->len == 0) return Qnil; + if (RARRAY(ary)->len == 0) return Qnil; if (offset < 0) { - offset = ary->len + offset; + offset = RARRAY(ary)->len + offset; } - if (offset < 0 || ary->len <= offset) { + if (offset < 0 || RARRAY(ary)->len <= offset) { return Qnil; } - return ary->ptr[offset]; + return RARRAY(ary)->ptr[offset]; } static VALUE ary_subseq(ary, beg, len) - struct RArray *ary; + VALUE ary; int beg, len; { - struct RArray *ary2; + VALUE ary2; if (beg < 0) { - beg = ary->len + beg; + beg = RARRAY(ary)->len + beg; if (beg < 0) beg = 0; } if (len < 0) { - IndexError("negative length %d", ary->len); + IndexError("negative length %d", RARRAY(ary)->len); } if (len == 0) { return ary_new2(0); } - if (beg + len > ary->len) { - len = ary->len - beg; + if (beg + len > RARRAY(ary)->len) { + len = RARRAY(ary)->len - beg; } - ary2 = (struct RArray*)ary_new2(len); - MEMCPY(ary2->ptr, ary->ptr+beg, VALUE, len); - ary2->len = len; + ary2 = ary_new2(len); + MEMCPY(RARRAY(ary2)->ptr, RARRAY(ary)->ptr+beg, VALUE, len); + RARRAY(ary2)->len = len; - return (VALUE)ary2; + return ary2; } static VALUE @@ -346,7 +344,6 @@ beg_len(range, begp, lenp, len) end = len + end; if (end < 0) end = -1; } - if (end > len) end = len; if (beg > end) { *lenp = 0; } @@ -357,11 +354,11 @@ beg_len(range, begp, lenp, len) return TRUE; } -static VALUE +VALUE ary_aref(argc, argv, ary) int argc; VALUE *argv; - struct RArray *ary; + VALUE ary; { VALUE arg1, arg2; int beg, len; @@ -381,7 +378,7 @@ ary_aref(argc, argv, ary) } else { /* check if idx is Range */ - if (beg_len(arg1, &beg, &len, ary->len)) { + if (beg_len(arg1, &beg, &len, RARRAY(ary)->len)) { return ary_subseq(ary, beg, len); } } @@ -393,13 +390,13 @@ ary_aref(argc, argv, ary) static VALUE ary_index(ary, val) - struct RArray *ary; + VALUE ary; VALUE val; { int i; - for (i=0; ilen; i++) { - if (rb_equal(ary->ptr[i], val)) + for (i=0; ilen; i++) { + if (rb_equal(RARRAY(ary)->ptr[i], val)) return INT2FIX(i); } return Qnil; @@ -407,7 +404,7 @@ ary_index(ary, val) static VALUE ary_indexes(ary, args) - struct RArray *ary, *args; + VALUE ary, args; { VALUE *p, *pend; VALUE new_ary; @@ -417,9 +414,9 @@ ary_indexes(ary, args) return ary_new2(0); } - new_ary = ary_new2(args->len); + new_ary = ary_new2(RARRAY(args)->len); - p = args->ptr; pend = p + args->len; + p = RARRAY(args)->ptr; pend = p + RARRAY(args)->len; while (p < pend) { ary_store(new_ary, i++, ary_entry(ary, NUM2INT(*p))); p++; @@ -429,49 +426,49 @@ ary_indexes(ary, args) static void ary_replace(ary, beg, len, rpl) - struct RArray *ary, *rpl; + VALUE ary, rpl; int beg, len; { ary_modify(ary); if (TYPE(rpl) != T_ARRAY) { - rpl = (struct RArray*)rb_to_a(rpl); + rpl = rb_Array(rpl); } if (beg < 0) { - beg = ary->len + beg; + beg = RARRAY(ary)->len + beg; if (beg < 0) beg = 0; } - if (beg >= ary->len) { - len = beg + rpl->len; - if (len >= ary->capa) { - ary->capa=len; - REALLOC_N(ary->ptr, VALUE, ary->capa); + if (beg >= RARRAY(ary)->len) { + len = beg + RARRAY(rpl)->len; + if (len >= RARRAY(ary)->capa) { + RARRAY(ary)->capa=len; + REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa); } - memclear(ary->ptr+ary->len, beg-ary->len); - MEMCPY(ary->ptr+beg, rpl->ptr, VALUE, rpl->len); - ary->len = len; + memclear(RARRAY(ary)->ptr+RARRAY(ary)->len, beg-RARRAY(ary)->len); + MEMCPY(RARRAY(ary)->ptr+beg, RARRAY(rpl)->ptr, VALUE, RARRAY(rpl)->len); + RARRAY(ary)->len = len; } else { int alen; - if (beg + len > ary->len) { - len = ary->len - beg; + if (beg + len > RARRAY(ary)->len) { + len = RARRAY(ary)->len - beg; } if (len < 0) { - IndexError("negative length %d", ary->len); + IndexError("negative length %d", RARRAY(ary)->len); } - alen = ary->len + rpl->len - len; - if (alen >= ary->capa) { - ary->capa=alen; - REALLOC_N(ary->ptr, VALUE, ary->capa); + alen = RARRAY(ary)->len + RARRAY(rpl)->len - len; + if (alen >= RARRAY(ary)->capa) { + RARRAY(ary)->capa=alen; + REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa); } if (len != RARRAY(rpl)->len) { - MEMMOVE(ary->ptr+beg+rpl->len, ary->ptr+beg+len, - VALUE, ary->len-(beg+len)); - ary->len = alen; + MEMMOVE(RARRAY(ary)->ptr+beg+RARRAY(rpl)->len, RARRAY(ary)->ptr+beg+len, + VALUE, RARRAY(ary)->len-(beg+len)); + RARRAY(ary)->len = alen; } - MEMCPY(ary->ptr+beg, rpl->ptr, VALUE, rpl->len); + MEMCPY(RARRAY(ary)->ptr+beg, RARRAY(rpl)->ptr, VALUE, RARRAY(rpl)->len); } } @@ -479,10 +476,9 @@ static VALUE ary_aset(argc, argv, ary) int argc; VALUE *argv; - struct RArray *ary; + VALUE ary; { - VALUE arg1, arg2; - struct RArray *arg3; + VALUE arg1, arg2, arg3; int offset; int beg, len; @@ -490,13 +486,13 @@ ary_aset(argc, argv, ary) beg = NUM2INT(arg1); len = NUM2INT(arg2); ary_replace(ary, beg, len, arg3); - return (VALUE)arg3; + return arg3; } else if (FIXNUM_P(arg1)) { offset = FIX2INT(arg1); goto fixnum; } - else if (beg_len(arg1, &beg, &len, ary->len)) { + else if (beg_len(arg1, &beg, &len, RARRAY(ary)->len)) { /* check if idx is Range */ ary_replace(ary, beg, len, arg2); return arg2; @@ -508,7 +504,7 @@ ary_aset(argc, argv, ary) offset = NUM2INT(arg1); fixnum: if (offset < 0) { - offset = ary->len + offset; + offset = RARRAY(ary)->len + offset; } ary_store(ary, offset, arg2); return arg2; @@ -516,23 +512,23 @@ ary_aset(argc, argv, ary) VALUE ary_each(ary) - struct RArray *ary; + VALUE ary; { int i; - for (i=0; ilen; i++) { - rb_yield(ary->ptr[i]); + for (i=0; ilen; i++) { + rb_yield(RARRAY(ary)->ptr[i]); } return Qnil; } static VALUE ary_each_index(ary) - struct RArray *ary; + VALUE ary; { int i; - for (i=0; ilen; i++) { + for (i=0; ilen; i++) { rb_yield(INT2FIX(i)); } return Qnil; @@ -540,69 +536,76 @@ ary_each_index(ary) static VALUE ary_reverse_each(ary) - struct RArray *ary; + VALUE ary; { - int len = ary->len; + int len = RARRAY(ary)->len; while (len--) { - rb_yield(ary->ptr[len]); + rb_yield(RARRAY(ary)->ptr[len]); } return Qnil; } static VALUE ary_length(ary) - struct RArray *ary; + VALUE ary; { - return INT2FIX(ary->len); + return INT2FIX(RARRAY(ary)->len); } static VALUE ary_empty_p(ary) - struct RArray *ary; + VALUE ary; { - if (ary->len == 0) + if (RARRAY(ary)->len == 0) return TRUE; return FALSE; } static VALUE ary_clone(ary) - struct RArray *ary; + VALUE ary; { - VALUE ary2 = ary_new2(ary->len); + VALUE ary2 = ary_new2(RARRAY(ary)->len); CLONESETUP(ary2, ary); - MEMCPY(RARRAY(ary2)->ptr, ary->ptr, VALUE, ary->len); - RARRAY(ary2)->len = ary->len; + MEMCPY(RARRAY(ary2)->ptr, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len); + RARRAY(ary2)->len = RARRAY(ary)->len; return ary2; } +static VALUE +ary_dup(ary) + VALUE ary; +{ + return ary_new4(RARRAY(ary)->len, RARRAY(ary)->ptr); +} + extern VALUE OFS; VALUE ary_join(ary, sep) - struct RArray *ary; - struct RString *sep; + VALUE ary; + VALUE sep; { int i; VALUE result, tmp; - if (ary->len == 0) return str_new(0, 0); + if (RARRAY(ary)->len == 0) return str_new(0, 0); - switch (TYPE(ary->ptr[0])) { + switch (TYPE(RARRAY(ary)->ptr[0])) { case T_STRING: - result = str_dup(ary->ptr[0]); + result = str_dup(RARRAY(ary)->ptr[0]); break; case T_ARRAY: - result = ary_join(ary->ptr[0], sep); + result = ary_join(RARRAY(ary)->ptr[0], sep); break; default: - result = obj_as_string(ary->ptr[0]); + result = obj_as_string(RARRAY(ary)->ptr[0]); break; } - for (i=1; ilen; i++) { - tmp = ary->ptr[i]; + for (i=1; ilen; i++) { + tmp = RARRAY(ary)->ptr[i]; switch (TYPE(tmp)) { case T_STRING: break; @@ -612,7 +615,7 @@ ary_join(ary, sep) default: tmp = obj_as_string(tmp); } - if (!NIL_P(sep)) str_cat(result, sep->ptr, sep->len); + if (!NIL_P(sep)) str_cat(result, RSTRING(sep)->ptr, RSTRING(sep)->len); str_cat(result, RSTRING(tmp)->ptr, RSTRING(tmp)->len); if (str_tainted(tmp)) str_taint(result); } @@ -624,7 +627,7 @@ static VALUE ary_join_method(argc, argv, ary) int argc; VALUE *argv; - struct RArray *ary; + VALUE ary; { VALUE sep; @@ -644,35 +647,19 @@ ary_to_s(ary) return str; } -VALUE -ary_print_on(ary, port) - struct RArray *ary; - VALUE port; -{ - int i; - - for (i=0; ilen; i++) { - if (!NIL_P(OFS) && i>0) { - io_write(port, OFS); - } - io_write(port, ary->ptr[i]); - } - return port; -} - static VALUE ary_inspect(ary) - struct RArray *ary; + VALUE ary; { int i, len; VALUE s, str; - if (ary->len == 0) return str_new2("[]"); + if (RARRAY(ary)->len == 0) return str_new2("[]"); str = str_new2("["); len = 1; - for (i=0; ilen; i++) { - s = rb_inspect(ary->ptr[i]); + for (i=0; ilen; i++) { + s = rb_inspect(RARRAY(ary)->ptr[i]); if (i > 0) str_cat(str, ", ", 2); str_cat(str, RSTRING(s)->ptr, RSTRING(s)->len); len += RSTRING(s)->len + 2; @@ -689,27 +676,15 @@ ary_to_a(ary) return ary; } -VALUE -rb_to_a(obj) - VALUE obj; -{ - if (TYPE(obj) == T_ARRAY) return obj; - obj = rb_funcall(obj, rb_intern("to_a"), 0); - if (TYPE(obj) != T_ARRAY) { - Bug("`to_a' did not return Array"); - } - return obj; -} - VALUE ary_reverse(ary) - struct RArray *ary; + VALUE ary; { VALUE *p1, *p2; VALUE tmp; - p1 = ary->ptr; - p2 = p1 + ary->len - 1; /* points last item */ + p1 = RARRAY(ary)->ptr; + p2 = p1 + RARRAY(ary)->len - 1; /* points last item */ while (p1 < p2) { tmp = *p1; @@ -718,12 +693,12 @@ ary_reverse(ary) p1++; p2--; } - return (VALUE)ary; + return ary; } static VALUE ary_reverse_method(ary) - struct RArray *ary; + VALUE ary; { return ary_reverse(ary_clone(ary)); } @@ -757,11 +732,11 @@ sort_2(a, b) VALUE ary_sort_bang(ary) - struct RArray *ary; + VALUE ary; { ary_modify(ary); - qsort(ary->ptr, ary->len, sizeof(VALUE), iterator_p()?sort_1:sort_2); - return (VALUE)ary; + qsort(RARRAY(ary)->ptr, RARRAY(ary)->len, sizeof(VALUE), iterator_p()?sort_1:sort_2); + return ary; } VALUE @@ -773,25 +748,25 @@ ary_sort(ary) VALUE ary_delete(ary, item) - struct RArray *ary; + VALUE ary; VALUE item; { int i1, i2; ary_modify(ary); - for (i1 = i2 = 0; i1 < ary->len; i1++) { - if (rb_equal(ary->ptr[i1], item)) continue; + for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) { + if (rb_equal(RARRAY(ary)->ptr[i1], item)) continue; if (i1 != i2) { - ary->ptr[i2] = ary->ptr[i1]; + RARRAY(ary)->ptr[i2] = RARRAY(ary)->ptr[i1]; } i2++; } - if (ary->len == i2) { + if (RARRAY(ary)->len == i2) { if (iterator_p()) rb_yield(item); return Qnil; } else { - ary->len = i2; + RARRAY(ary)->len = i2; } return item; @@ -799,7 +774,7 @@ ary_delete(ary, item) VALUE ary_delete_at(ary, at) - struct RArray *ary; + VALUE ary; VALUE at; { int i1, i2, pos; @@ -807,184 +782,184 @@ ary_delete_at(ary, at) ary_modify(ary); pos = NUM2INT(at); - for (i1 = i2 = 0; i1 < ary->len; i1++) { + for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) { if (i1 == pos) { - del = ary->ptr[i1]; + del = RARRAY(ary)->ptr[i1]; continue; } if (i1 != i2) { - ary->ptr[i2] = ary->ptr[i1]; + RARRAY(ary)->ptr[i2] = RARRAY(ary)->ptr[i1]; } i2++; } - ary->len = i2; + RARRAY(ary)->len = i2; return del; } static VALUE ary_delete_if(ary) - struct RArray *ary; + VALUE ary; { int i1, i2; ary_modify(ary); - for (i1 = i2 = 0; i1 < ary->len; i1++) { - if (rb_yield(ary->ptr[i1])) continue; + for (i1 = i2 = 0; i1 < RARRAY(ary)->len; i1++) { + if (rb_yield(RARRAY(ary)->ptr[i1])) continue; if (i1 != i2) { - ary->ptr[i2] = ary->ptr[i1]; + RARRAY(ary)->ptr[i2] = RARRAY(ary)->ptr[i1]; } i2++; } - ary->len = i2; + RARRAY(ary)->len = i2; - return (VALUE)ary; + return ary; } #if 0 static VALUE ary_replace(ary) - struct RArray *ary; + VALUE ary; { int i; - for (i = 0; i < ary->len; i++) { - ary->ptr[i] = rb_yield(ary->ptr[i]); + for (i = 0; i < RARRAY(ary)->len; i++) { + RARRAY(ary)->ptr[i] = rb_yield(RARRAY(ary)->ptr[i]); } - return (VALUE)ary; + return ary; } #endif static VALUE ary_clear(ary) - struct RArray *ary; + VALUE ary; { - ary->len = 0; - if (ARY_DEFAULT_SIZE*3 < ary->capa) { - ary->capa = ARY_DEFAULT_SIZE * 2; - REALLOC_N(ary->ptr, VALUE, ary->capa); + RARRAY(ary)->len = 0; + if (ARY_DEFAULT_SIZE*3 < RARRAY(ary)->capa) { + RARRAY(ary)->capa = ARY_DEFAULT_SIZE * 2; + REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa); } - return (VALUE)ary; + return ary; } static VALUE ary_fill(argc, argv, ary) int argc; VALUE *argv; - struct RArray *ary; + VALUE ary; { VALUE item, arg1, arg2; int beg, len, end; VALUE *p, *pend; rb_scan_args(argc, argv, "12", &item, &arg1, &arg2); - if (NIL_P(arg2) && beg_len(arg1, &beg, &len, ary->len)) { + if (NIL_P(arg2) && beg_len(arg1, &beg, &len, RARRAY(ary)->len)) { /* beg and len set already */ } else { beg = NUM2INT(arg1); if (beg < 0) { - beg = ary->len + beg; + beg = RARRAY(ary)->len + beg; if (beg < 0) beg = 0; } - if (arg2) { + if (!NIL_P(arg2)) { len = NUM2INT(arg2); } else { - len = ary->len - beg; + len = RARRAY(ary)->len - beg; } } end = beg + len; - if (end > ary->len) { - if (end >= ary->capa) { - ary->capa=end; - REALLOC_N(ary->ptr, VALUE, ary->capa); + if (end > RARRAY(ary)->len) { + if (end >= RARRAY(ary)->capa) { + RARRAY(ary)->capa=end; + REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->capa); } - if (beg > ary->len) { - memclear(ary->ptr+ary->len, end-ary->len); + if (beg > RARRAY(ary)->len) { + memclear(RARRAY(ary)->ptr+RARRAY(ary)->len, end-RARRAY(ary)->len); } - ary->len = end; + RARRAY(ary)->len = end; } - p = ary->ptr + beg; pend = p + len; + p = RARRAY(ary)->ptr + beg; pend = p + len; while (p < pend) { *p++ = item; } - return (VALUE)ary; + return ary; } VALUE ary_plus(x, y) - struct RArray *x, *y; + VALUE x, y; { - struct RArray *z; + VALUE z; if (TYPE(y) != T_ARRAY) { - return ary_plus(x, rb_to_a(y)); + return ary_plus(x, rb_Array(y)); } - z = (struct RArray*)ary_new2(x->len + y->len); - MEMCPY(z->ptr, x->ptr, VALUE, x->len); - MEMCPY(z->ptr+x->len, y->ptr, VALUE, y->len); - z->len = x->len + RARRAY(y)->len; - return (VALUE)z; + z = ary_new2(RARRAY(x)->len + RARRAY(y)->len); + MEMCPY(RARRAY(z)->ptr, RARRAY(x)->ptr, VALUE, RARRAY(x)->len); + MEMCPY(RARRAY(z)->ptr+RARRAY(x)->len, RARRAY(y)->ptr, VALUE, RARRAY(y)->len); + RARRAY(z)->len = RARRAY(x)->len + RARRAY(y)->len; + return z; } VALUE ary_concat(x, y) - struct RArray *x, *y; + VALUE x, y; { VALUE *p, *pend; if (TYPE(y) != T_ARRAY) { - return ary_concat(x, rb_to_a(y)); + return ary_concat(x, rb_Array(y)); } - p = y->ptr; - pend = p + y->len; + p = RARRAY(y)->ptr; + pend = p + RARRAY(y)->len; while (p < pend) { - ary_store(x, x->len, *p); + ary_store(x, RARRAY(x)->len, *p); p++; } - return (VALUE)x; + return x; } static VALUE ary_times(ary, times) - struct RArray *ary; + VALUE ary; VALUE times; { - struct RArray *ary2; + VALUE ary2; int i, len; if (TYPE(times) == T_STRING) { return ary_join(ary, times); } - len = NUM2INT(times) * ary->len; - ary2 = (struct RArray*)ary_new2(len); - ary2->len = len; + len = NUM2INT(times) * RARRAY(ary)->len; + ary2 = ary_new2(len); + RARRAY(ary2)->len = len; if (len < 0) { ArgError("negative argument"); } - for (i=0; ilen) { - MEMCPY(ary2->ptr+i, ary->ptr, VALUE, ary->len); + for (i=0; ilen) { + MEMCPY(RARRAY(ary2)->ptr+i, RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len); } - return (VALUE)ary2; + return ary2; } VALUE ary_assoc(ary, key) - struct RArray *ary; + VALUE ary; VALUE key; { VALUE *p, *pend; - p = ary->ptr; pend = p + ary->len; + p = RARRAY(ary)->ptr; pend = p + RARRAY(ary)->len; while (p < pend) { if (TYPE(*p) == T_ARRAY && RARRAY(*p)->len > 1 @@ -997,12 +972,12 @@ ary_assoc(ary, key) VALUE ary_rassoc(ary, value) - struct RArray *ary; + VALUE ary; VALUE value; { VALUE *p, *pend; - p = ary->ptr; pend = p + ary->len; + p = RARRAY(ary)->ptr; pend = p + RARRAY(ary)->len; while (p < pend) { if (TYPE(*p) == T_ARRAY && RARRAY(*p)->len > 1 @@ -1015,14 +990,14 @@ ary_rassoc(ary, value) static VALUE ary_equal(ary1, ary2) - struct RArray *ary1, *ary2; + VALUE ary1, ary2; { int i; if (TYPE(ary2) != T_ARRAY) return FALSE; - if (ary1->len != ary2->len) return FALSE; - for (i=0; ilen; i++) { - if (!rb_equal(ary1->ptr[i], ary2->ptr[i])) + if (RARRAY(ary1)->len != RARRAY(ary2)->len) return FALSE; + for (i=0; ilen; i++) { + if (!rb_equal(RARRAY(ary1)->ptr[i], RARRAY(ary2)->ptr[i])) return FALSE; } return TRUE; @@ -1030,14 +1005,15 @@ ary_equal(ary1, ary2) static VALUE ary_eql(ary1, ary2) - struct RArray *ary1, *ary2; + VALUE ary1, ary2; { int i; if (TYPE(ary2) != T_ARRAY) return FALSE; - if (ary1->len != ary2->len) return FALSE; - for (i=0; ilen; i++) { - if (!rb_eql(ary1->ptr[i], ary2->ptr[i])) + if (RARRAY(ary1)->len != RARRAY(ary2)->len) + return FALSE; + for (i=0; ilen; i++) { + if (!rb_eql(RARRAY(ary1)->ptr[i], RARRAY(ary2)->ptr[i])) return FALSE; } return TRUE; @@ -1045,25 +1021,25 @@ ary_eql(ary1, ary2) static VALUE ary_hash(ary) - struct RArray *ary; + VALUE ary; { int h, i; - h = ary->len; - for (i=0; ilen; i++) { - h ^= rb_hash(ary->ptr[i]); + h = RARRAY(ary)->len; + for (i=0; ilen; i++) { + h ^= rb_hash(RARRAY(ary)->ptr[i]); } return INT2FIX(h); } VALUE ary_includes(ary, item) - struct RArray *ary; + VALUE ary; VALUE item; { int i; - for (i=0; ilen; i++) { - if (rb_equal(ary->ptr[i], item)) { + for (i=0; ilen; i++) { + if (rb_equal(RARRAY(ary)->ptr[i], item)) { return TRUE; } } @@ -1072,34 +1048,34 @@ ary_includes(ary, item) static VALUE ary_diff(ary1, ary2) - struct RArray *ary1, *ary2; + VALUE ary1, ary2; { VALUE ary3; int i; Check_Type(ary2, T_ARRAY); ary3 = ary_new(); - for (i=0; ilen; i++) { - if (ary_includes(ary2, ary1->ptr[i])) continue; - if (ary_includes(ary3, ary1->ptr[i])) continue; - ary_push(ary3, ary1->ptr[i]); + for (i=0; ilen; i++) { + if (ary_includes(ary2, RARRAY(ary1)->ptr[i])) continue; + if (ary_includes(ary3, RARRAY(ary1)->ptr[i])) continue; + ary_push(ary3, RARRAY(ary1)->ptr[i]); } return ary3; } static VALUE ary_and(ary1, ary2) - struct RArray *ary1, *ary2; + VALUE ary1, ary2; { VALUE ary3; int i; Check_Type(ary2, T_ARRAY); ary3 = ary_new(); - for (i=0; ilen; i++) { - if (ary_includes(ary2, ary1->ptr[i]) - && !ary_includes(ary3, ary1->ptr[i])) { - ary_push(ary3, ary1->ptr[i]); + for (i=0; ilen; i++) { + if (ary_includes(ary2, RARRAY(ary1)->ptr[i]) + && !ary_includes(ary3, RARRAY(ary1)->ptr[i])) { + ary_push(ary3, RARRAY(ary1)->ptr[i]); } } return ary3; @@ -1107,63 +1083,63 @@ ary_and(ary1, ary2) static VALUE ary_or(ary1, ary2) - struct RArray *ary1, *ary2; + VALUE ary1, ary2; { VALUE ary3; int i; if (TYPE(ary2) != T_ARRAY) { - if (ary_includes(ary1, ary2)) return (VALUE)ary1; + if (ary_includes(ary1, ary2)) return ary1; else return ary_plus(ary1, ary2); } ary3 = ary_new(); - for (i=0; ilen; i++) { - if (!ary_includes(ary3, ary1->ptr[i])) - ary_push(ary3, ary1->ptr[i]); + for (i=0; ilen; i++) { + if (!ary_includes(ary3, RARRAY(ary1)->ptr[i])) + ary_push(ary3, RARRAY(ary1)->ptr[i]); } - for (i=0; ilen; i++) { - if (!ary_includes(ary3, ary2->ptr[i])) - ary_push(ary3, ary2->ptr[i]); + for (i=0; ilen; i++) { + if (!ary_includes(ary3, RARRAY(ary2)->ptr[i])) + ary_push(ary3, RARRAY(ary2)->ptr[i]); } return ary3; } static VALUE ary_compact_bang(ary) - struct RArray *ary; + VALUE ary; { VALUE *p, *t, *end; ary_modify(ary); - p = t = ary->ptr; - end = p + ary->len; + p = t = RARRAY(ary)->ptr; + end = p + RARRAY(ary)->len; while (t < end) { if (NIL_P(*t)) t++; else *p++ = *t++; } - ary->len = ary->capa = (p - ary->ptr); - REALLOC_N(ary->ptr, VALUE, ary->len); + RARRAY(ary)->len = RARRAY(ary)->capa = (p - RARRAY(ary)->ptr); + REALLOC_N(RARRAY(ary)->ptr, VALUE, RARRAY(ary)->len); - return (VALUE)ary; + return ary; } static VALUE ary_compact(ary) - struct RArray *ary; + VALUE ary; { return ary_compact_bang(ary_clone(ary)); } static VALUE ary_nitems(ary) - struct RArray *ary; + VALUE ary; { int n = 0; VALUE *p, *pend; - p = ary->ptr; - pend = p + ary->len; + p = RARRAY(ary)->ptr; + pend = p + RARRAY(ary)->len; while (p < pend) { if (!NIL_P(*p)) n++; p++; @@ -1209,6 +1185,7 @@ Init_Array() rb_define_method(cArray, "index", ary_index, 1); rb_define_method(cArray, "indexes", ary_indexes, -2); rb_define_method(cArray, "clone", ary_clone, 0); + rb_define_method(cArray, "dup", ary_dup, 0); rb_define_method(cArray, "join", ary_join_method, -1); rb_define_method(cArray, "reverse", ary_reverse_method, 0); rb_define_method(cArray, "reverse!", ary_reverse, 0); @@ -1223,6 +1200,7 @@ Init_Array() rb_define_method(cArray, "clear", ary_clear, 0); rb_define_method(cArray, "fill", ary_fill, -1); rb_define_method(cArray, "include?", ary_includes, 1); + rb_define_method(cArray, "===", ary_includes, 1); rb_define_method(cArray, "assoc", ary_assoc, 1); rb_define_method(cArray, "rassoc", ary_rassoc, 1); diff --git a/bignum.c b/bignum.c index 7b9581cbd2..17d9c839c5 100644 --- a/bignum.c +++ b/bignum.c @@ -18,8 +18,8 @@ VALUE cBignum; #define BDIGITS(x) RBIGNUM(x)->digits #define BITSPERDIG (sizeof(USHORT)*CHAR_BIT) #define BIGRAD (1L << BITSPERDIG) -#define DIGSPERLONG ((UINT)(sizeof(long)/sizeof(USHORT))) -#define BIGUP(x) ((unsigned long)(x) << BITSPERDIG) +#define DIGSPERINT ((UINT)(sizeof(INT)/sizeof(USHORT))) +#define BIGUP(x) ((UINT)(x) << BITSPERDIG) #define BIGDN(x) ((x) >> BITSPERDIG) #define BIGLO(x) ((x) & (BIGRAD-1)) @@ -42,19 +42,19 @@ bignew_1(class, len, sign) VALUE big_clone(x) - struct RBignum *x; + VALUE x; { - VALUE z = bignew_1(CLASS_OF(x), x->len, x->sign); + VALUE z = bignew_1(CLASS_OF(x), RBIGNUM(x)->len, RBIGNUM(x)->sign); - MEMCPY(BDIGITS(z), BDIGITS(x), USHORT, x->len); - return (VALUE)z; + MEMCPY(BDIGITS(z), BDIGITS(x), USHORT, RBIGNUM(x)->len); + return z; } void big_2comp(x) /* get 2's complement */ - struct RBignum *x; + VALUE x; { - UINT i = x->len; + UINT i = RBIGNUM(x)->len; USHORT *ds = BDIGITS(x); long num; @@ -64,26 +64,26 @@ big_2comp(x) /* get 2's complement */ num += (long)ds[i]; ds[i++] = BIGLO(num); num = BIGDN(num); - } while (i < x->len); + } while (i < RBIGNUM(x)->len); if (ds[0] == 1 || ds[0] == 0) { - for (i=1;ilen;i++) { + for (i=1;ilen;i++) { if (ds[i] != 0) return; } - REALLOC_N(BDIGITS(x), USHORT, x->len++); + REALLOC_N(BDIGITS(x), USHORT, RBIGNUM(x)->len++); ds = BDIGITS(x); - ds[x->len-1] = 1; + ds[RBIGNUM(x)->len-1] = 1; } } static VALUE bignorm(x) - struct RBignum *x; + VALUE x; { - UINT len = x->len; + UINT len = RBIGNUM(x)->len; USHORT *ds = BDIGITS(x); while (len-- && !ds[len]) ; - x->len = ++len; + RBIGNUM(x)->len = ++len; if (len*sizeof(USHORT) < sizeof(VALUE) || (len*sizeof(USHORT) == sizeof(VALUE) && @@ -92,19 +92,19 @@ bignorm(x) while (len--) { num = BIGUP(num) + ds[len]; } - if (x->sign) { + if (RBIGNUM(x)->sign) { if (POSFIXABLE(num)) return INT2FIX(num); } else if (NEGFIXABLE(-num)) return INT2FIX(-num); } - return (VALUE)x; + return x; } VALUE big_norm(x) VALUE x; { - return bignorm(x); + return bignorm(RBIGNUM(x)); } VALUE @@ -113,38 +113,38 @@ uint2big(n) { UINT i = 0; USHORT *digits; - struct RBignum *big; + VALUE big; i = 0; - big = (struct RBignum*)bignew(DIGSPERLONG, 1); + big = bignew(DIGSPERINT, 1); digits = BDIGITS(big); - while (i < DIGSPERLONG) { + while (i < DIGSPERINT) { digits[i++] = BIGLO(n); n = BIGDN(n); } - i = DIGSPERLONG; + i = DIGSPERINT; while (i-- && !digits[i]) ; - big->len = i+1; - return (VALUE)big; + RBIGNUM(big)->len = i+1; + return big; } VALUE int2big(n) - int n; + INT n; { - int neg = 0; - struct RBignum *big; + INT neg = 0; + VALUE big; if (n < 0) { n = -n; neg = 1; } - big = (struct RBignum*)uint2big(n); + big = uint2big(n); if (neg) { - big->sign = 0; + RBIGNUM(big)->sign = 0; } - return (VALUE)big; + return big; } VALUE @@ -157,7 +157,7 @@ uint2inum(n) VALUE int2inum(n) - int n; + INT n; { if (FIXABLE(n)) return INT2FIX(n); return int2big(n); @@ -209,7 +209,7 @@ str2inum(str, base) if (POSFIXABLE(val)) { if (sign) return INT2FIX(val); else { - int result = -(int)val; + INT result = -(INT)val; return INT2FIX(result); } } @@ -219,7 +219,7 @@ str2inum(str, base) return big; } } - len = (len/(sizeof(USHORT)*CHAR_BIT))+1; + len = (len/BITSPERDIG)+1; z = bignew(len, sign); zds = BDIGITS(z); @@ -264,7 +264,7 @@ str2inum(str, base) static char hexmap[] = "0123456789abcdef"; VALUE big2str(x, base) - struct RBignum *x; + VALUE x; int base; { VALUE t; @@ -276,7 +276,7 @@ big2str(x, base) if (FIXNUM_P(x)) { return fix2str(x, base); } - i = x->len; + i = RBIGNUM(x)->len; if (i == 0) return str_new2("0"); if (base == 10) { j = (sizeof(USHORT)/sizeof(char)*CHAR_BIT*i*241L)/800+2; @@ -305,7 +305,7 @@ big2str(x, base) ss = str_new(0, j); s = RSTRING(ss)->ptr; - s[0] = x->sign ? '+' : '-'; + s[0] = RBIGNUM(x)->sign ? '+' : '-'; while (i && j) { int k = i; unsigned long num = 0; @@ -324,8 +324,8 @@ big2str(x, base) } } while (s[j] == '0') j++; - RSTRING(ss)->len -= x->sign?j:j-1; - memmove(x->sign?s:s+1, s+j, RSTRING(ss)->len); + RSTRING(ss)->len -= RBIGNUM(x)->sign?j:j-1; + memmove(RBIGNUM(x)->sign?s:s+1, s+j, RSTRING(ss)->len); s[RSTRING(ss)->len] = '\0'; return ss; @@ -333,17 +333,17 @@ big2str(x, base) static VALUE big_to_s(x) - struct RBignum *x; + VALUE x; { return big2str(x, 10); } -int +INT big2int(x) - struct RBignum *x; + VALUE x; { - unsigned long num; - UINT len = x->len; + UINT num; + UINT len = RBIGNUM(x)->len; USHORT *ds; if (len > sizeof(long)/sizeof(USHORT)) @@ -354,7 +354,7 @@ big2int(x) num = BIGUP(num); num += ds[len]; } - if (!x->sign) return -num; + if (!RBIGNUM(x)->sign) return -num; return num; } @@ -393,16 +393,16 @@ dbl2big(d) double big2dbl(x) - struct RBignum *x; + VALUE x; { double d = 0.0; - UINT i = x->len; + UINT i = RBIGNUM(x)->len; USHORT *ds = BDIGITS(x); while (i--) { d = ds[i] + BIGRAD*d; } - if (!x->sign) d = -d; + if (!RBIGNUM(x)->sign) d = -d; return d; } @@ -415,13 +415,13 @@ big_to_f(x) static VALUE big_cmp(x, y) - struct RBignum *x, *y; + VALUE x, y; { - int xlen = x->len; + int xlen = RBIGNUM(x)->len; switch (TYPE(y)) { case T_FIXNUM: - y = (struct RBignum*)int2big(FIX2INT(y)); + y = int2big(FIX2INT(y)); break; case T_BIGNUM: @@ -431,18 +431,18 @@ big_cmp(x, y) return num_coerce_bin(x, y); } - if (x->sign > y->sign) return INT2FIX(1); - if (x->sign < y->sign) return INT2FIX(-1); - if (xlen < y->len) - return (x->sign) ? INT2FIX(-1) : INT2FIX(1); - if (xlen > y->len) - return (x->sign) ? INT2FIX(1) : INT2FIX(-1); + if (RBIGNUM(x)->sign > RBIGNUM(y)->sign) return INT2FIX(1); + if (RBIGNUM(x)->sign < RBIGNUM(y)->sign) return INT2FIX(-1); + if (xlen < RBIGNUM(y)->len) + return (RBIGNUM(x)->sign) ? INT2FIX(-1) : INT2FIX(1); + if (xlen > RBIGNUM(y)->len) + return (RBIGNUM(x)->sign) ? INT2FIX(1) : INT2FIX(-1); while(xlen-- && (BDIGITS(x)[xlen]==BDIGITS(y)[xlen])); if (-1 == xlen) return INT2FIX(0); return (BDIGITS(x)[xlen] > BDIGITS(y)[xlen]) ? - (x->sign ? INT2FIX(1) : INT2FIX(-1)) : - (x->sign ? INT2FIX(-1) : INT2FIX(1)); + (RBIGNUM(x)->sign ? INT2FIX(1) : INT2FIX(-1)) : + (RBIGNUM(x)->sign ? INT2FIX(-1) : INT2FIX(1)); } static VALUE @@ -455,26 +455,26 @@ big_eq(x, y) static VALUE big_uminus(x) - struct RBignum *x; + VALUE x; { VALUE z = big_clone(x); - RBIGNUM(z)->sign = !x->sign; + RBIGNUM(z)->sign = !RBIGNUM(x)->sign; return bignorm(z); } static VALUE big_neg(x) - struct RBignum *x; + VALUE x; { VALUE z = big_clone(x); - UINT i = x->len; + UINT i = RBIGNUM(x)->len; USHORT *ds = BDIGITS(z); - if (!x->sign) big_2comp(z); + if (!RBIGNUM(x)->sign) big_2comp(z); while (i--) ds[i] = ~ds[i]; - if (x->sign) big_2comp(z); + if (RBIGNUM(x)->sign) big_2comp(z); RBIGNUM(z)->sign = !RBIGNUM(z)->sign; return bignorm(z); @@ -482,19 +482,19 @@ big_neg(x) static VALUE bigsub(x, y) - struct RBignum *x, *y; + VALUE x, y; { - struct RBignum *z = 0; + VALUE z = 0; USHORT *zds; long num; UINT i; - i = x->len; + i = RBIGNUM(x)->len; /* if x is larger than y, swap */ - if (x->len < y->len) { + if (RBIGNUM(x)->len < RBIGNUM(y)->len) { z = x; x = y; y = z; /* swap x y */ } - else if (x->len == y->len) { + else if (RBIGNUM(x)->len == RBIGNUM(y)->len) { while (i > 0) { i--; if (BDIGITS(x)[i] > BDIGITS(y)[i]) { @@ -507,20 +507,20 @@ bigsub(x, y) } } - z = (struct RBignum*)bignew(x->len, (z == 0)?1:0); + z = bignew(RBIGNUM(x)->len, (z == 0)?1:0); zds = BDIGITS(z); - for (i = 0, num = 0; i < y->len; i++) { + for (i = 0, num = 0; i < RBIGNUM(y)->len; i++) { num += (long)BDIGITS(x)[i] - BDIGITS(y)[i]; zds[i] = BIGLO(num); num = BIGDN(num); } - while (num && i < x->len) { + while (num && i < RBIGNUM(x)->len) { num += BDIGITS(x)[i]; zds[i++] = BIGLO(num); num = BIGDN(num); } - while (i < x->len) { + while (i < RBIGNUM(x)->len) { zds[i] = BDIGITS(x)[i]; i++; } @@ -530,39 +530,40 @@ bigsub(x, y) static VALUE bigadd(x, y, sign) - struct RBignum *x, *y; + VALUE x, y; char sign; { - struct RBignum *z; + VALUE z; long num; UINT i, len; - if (x->sign == (y->sign ^ sign)) { - if (y->sign == sign) return bigsub(y, x); + + if (RBIGNUM(x)->sign == (RBIGNUM(y)->sign ^ sign)) { + if (RBIGNUM(y)->sign == sign) return bigsub(y, x); return bigsub(x, y); } - if (x->len > y->len) { - len = x->len + 1; + if (RBIGNUM(x)->len > RBIGNUM(y)->len) { + len = RBIGNUM(x)->len + 1; + z = x; x = y; y = z; } else { - len = y->len + 1; + len = RBIGNUM(y)->len + 1; } - z = (struct RBignum*)bignew(len, sign==y->sign); + z = bignew(len, sign==RBIGNUM(y)->sign); - if (x->len > y->len) { - struct RBignum* t = x; x = y; y = t; - } - for (i = 0, num = 0; i < x->len; i++) { - num += (long)(BDIGITS(x)[i]) + BDIGITS(y)[i]; + len = RBIGNUM(x)->len; + for (i = 0, num = 0; i < len; i++) { + num += (long)(BDIGITS(x)[i] + BDIGITS(y)[i]); BDIGITS(z)[i] = BIGLO(num); num = BIGDN(num); } - while (num && i < y->len) { + len = RBIGNUM(y)->len; + while (num && i < len) { num += BDIGITS(y)[i]; BDIGITS(z)[i++] = BIGLO(num); num = BIGDN(num); } - while (i < y->len) { + while (i < len) { BDIGITS(z)[i] = BDIGITS(y)[i]; i++; } @@ -611,17 +612,17 @@ big_minus(x, y) VALUE big_mul(x, y) - struct RBignum *x, *y; + VALUE x, y; { UINT i = 0, j; unsigned long n = 0; VALUE z; USHORT *zds; - if (FIXNUM_P(x)) x = (struct RBignum*)int2big(FIX2INT(x)); + if (FIXNUM_P(x)) x = int2big(FIX2INT(x)); switch (TYPE(y)) { case T_FIXNUM: - y = (struct RBignum*)int2big(FIX2INT(y)); + y = int2big(FIX2INT(y)); break; case T_BIGNUM: @@ -634,15 +635,15 @@ big_mul(x, y) return num_coerce_bin(x, y); } - j = x->len + y->len + 1; - z = bignew(j, x->sign==y->sign); + j = RBIGNUM(x)->len + RBIGNUM(y)->len + 1; + z = bignew(j, RBIGNUM(x)->sign==RBIGNUM(y)->sign); zds = BDIGITS(z); while (j--) zds[j] = 0; - for (i = 0; i < x->len; i++) { + for (i = 0; i < RBIGNUM(x)->len; i++) { unsigned long dd = BDIGITS(x)[i]; if (dd == 0) continue; n = 0; - for (j = 0; j < y->len; j++) { + for (j = 0; j < RBIGNUM(y)->len; j++) { int ee = n + dd * BDIGITS(y)[j]; n = zds[i + j] + ee; if (ee) zds[i + j] = BIGLO(n); @@ -658,10 +659,10 @@ big_mul(x, y) static void bigdivmod(x, y, div, mod) - struct RBignum *x, *y; + VALUE x, y; VALUE *div, *mod; { - UINT nx = x->len, ny = y->len, i, j; + UINT nx = RBIGNUM(x)->len, ny = RBIGNUM(y)->len, i, j; VALUE z; USHORT *xds, *yds, *zds, *tds; unsigned long t2; @@ -688,17 +689,17 @@ bigdivmod(x, y, div, mod) } if (div) *div = bignorm(z); if (mod) { - if (!y->sign) t2 = -t2; + if (!RBIGNUM(y)->sign) t2 = -t2; *mod = INT2FIX(t2); } return; } - z = bignew(nx==ny?nx+2:nx+1, x->sign==y->sign); + z = bignew(nx==ny?nx+2:nx+1, RBIGNUM(x)->sign==RBIGNUM(y)->sign); zds = BDIGITS(z); if (nx==ny) zds[nx+1] = 0; while (!yds[ny-1]) ny--; if ((dd = BIGRAD/(int)(yds[ny-1]+1)) != 1) { - y = (struct RBignum*)big_clone(y); + y = big_clone(y); tds = BDIGITS(y); j = 0; num = 0; @@ -771,7 +772,7 @@ bigdivmod(x, y, div, mod) } } RBIGNUM(*mod)->len = ny; - RBIGNUM(*mod)->sign = y->sign; + RBIGNUM(*mod)->sign = RBIGNUM(y)->sign; *mod = bignorm(*mod); } } @@ -897,7 +898,7 @@ big_pow(x, y) VALUE big_and(x, y) - struct RBignum *x, *y; + VALUE x, y; { VALUE z; USHORT *ds1, *ds2, *zds; @@ -905,35 +906,35 @@ big_and(x, y) char sign; if (FIXNUM_P(y)) { - y = (struct RBignum*)int2big(FIX2INT(y)); + y = int2big(FIX2INT(y)); } else { Check_Type(y, T_BIGNUM); } - if (!y->sign) { - y = (struct RBignum*)big_clone(y); + if (!RBIGNUM(y)->sign) { + y = big_clone(y); big_2comp(y); } - if (!x->sign) { - x = (struct RBignum*)big_clone(x); + if (!RBIGNUM(x)->sign) { + x = big_clone(x); big_2comp(x); } - if (x->len > y->len) { - l1 = y->len; - l2 = x->len; + if (RBIGNUM(x)->len > RBIGNUM(y)->len) { + l1 = RBIGNUM(y)->len; + l2 = RBIGNUM(x)->len; ds1 = BDIGITS(y); ds2 = BDIGITS(x); - sign = y->sign; + sign = RBIGNUM(y)->sign; } else { - l1 = x->len; - l2 = y->len; + l1 = RBIGNUM(x)->len; + l2 = RBIGNUM(y)->len; ds1 = BDIGITS(x); ds2 = BDIGITS(y); - sign = x->sign; + sign = RBIGNUM(x)->sign; } - z = bignew(l2, x->sign && y->sign); + z = bignew(l2, RBIGNUM(x)->sign && RBIGNUM(y)->sign); zds = BDIGITS(z); for (i=0; isign) { - y = (struct RBignum*)big_clone(y); + if (!RBIGNUM(y)->sign) { + y = big_clone(y); big_2comp(y); } - if (!x->sign) { - x = (struct RBignum*)big_clone(x); + if (!RBIGNUM(x)->sign) { + x = big_clone(x); big_2comp(x); } - if (x->len > y->len) { - l1 = y->len; - l2 = x->len; + if (RBIGNUM(x)->len > RBIGNUM(y)->len) { + l1 = RBIGNUM(y)->len; + l2 = RBIGNUM(x)->len; ds1 = BDIGITS(y); ds2 = BDIGITS(x); - sign = y->sign; + sign = RBIGNUM(y)->sign; } else { - l1 = x->len; - l2 = y->len; + l1 = RBIGNUM(x)->len; + l2 = RBIGNUM(y)->len; ds1 = BDIGITS(x); ds2 = BDIGITS(y); - sign = x->sign; + sign = RBIGNUM(x)->sign; } - z = bignew(l2, x->sign || y->sign); + z = bignew(l2, RBIGNUM(x)->sign || RBIGNUM(y)->sign); zds = BDIGITS(z); for (i=0; isign) { - y = (struct RBignum*)big_clone(y); + if (!RBIGNUM(y)->sign) { + y = big_clone(y); big_2comp(y); } - if (!x->sign) { - x = (struct RBignum*)big_clone(x); + if (!RBIGNUM(x)->sign) { + x = big_clone(x); big_2comp(x); } - if (x->len > y->len) { - l1 = y->len; - l2 = x->len; + if (RBIGNUM(x)->len > RBIGNUM(y)->len) { + l1 = RBIGNUM(y)->len; + l2 = RBIGNUM(x)->len; ds1 = BDIGITS(y); ds2 = BDIGITS(x); - sign = y->sign; + sign = RBIGNUM(y)->sign; } else { - l1 = x->len; - l2 = y->len; + l1 = RBIGNUM(x)->len; + l2 = RBIGNUM(y)->len; ds1 = BDIGITS(x); ds2 = BDIGITS(y); - sign = x->sign; + sign = RBIGNUM(x)->sign; } - x->sign = x->sign?1:0; - y->sign = y->sign?1:0; - z = bignew(l2, !(x->sign ^ y->sign)); + RBIGNUM(x)->sign = RBIGNUM(x)->sign?1:0; + RBIGNUM(y)->sign = RBIGNUM(y)->sign?1:0; + z = bignew(l2, !(RBIGNUM(x)->sign ^ RBIGNUM(y)->sign)); zds = BDIGITS(z); for (i=0; ilen; - z = bignew(len+s1+1, x->sign); + len = RBIGNUM(x)->len; + z = bignew(len+s1+1, RBIGNUM(x)->sign); zds = BDIGITS(z); for (i=0; ilen, j; + UINT i = RBIGNUM(x)->len; + UINT j; if (shift < 0) return big_lshift(x, INT2FIX(-shift)); - if (s1 > x->len) { - if (x->sign) + if (s1 > RBIGNUM(x)->len) { + if (RBIGNUM(x)->sign) return INT2FIX(0); else return INT2FIX(-1); } xds = BDIGITS(x); - i = x->len; j = i - s1; - z = bignew(j, x->sign); + i = RBIGNUM(x)->len; j = i - s1; + z = bignew(j, RBIGNUM(x)->sign); zds = BDIGITS(z); while (i--, j--) { num = (num | xds[i]) >> s2; @@ -1118,24 +1118,23 @@ big_rshift(x, y) static VALUE big_aref(x, y) - struct RBignum *x; - VALUE y; + VALUE x, y; { USHORT *xds; int shift = NUM2INT(y); UINT s1, s2; if (shift < 0) return INT2FIX(0); - s1 = shift/(sizeof(USHORT)*CHAR_BIT); - s2 = shift%(sizeof(USHORT)*CHAR_BIT); + s1 = shift/BITSPERDIG; + s2 = shift%BITSPERDIG; - if (!x->sign) { - if (s1 >= x->len) return INT2FIX(1); - x = (struct RBignum*)big_clone(x); + if (!RBIGNUM(x)->sign) { + if (s1 >= RBIGNUM(x)->len) return INT2FIX(1); + x = big_clone(x); big_2comp(x); } else { - if (s1 >= x->len) return INT2FIX(0); + if (s1 >= RBIGNUM(x)->len) return INT2FIX(0); } xds = BDIGITS(x); if (xds[s1] & (1<len; ilen; i++) { + for (i=0,len=RBIGNUM(x)->len; ilen; i++) { key ^= *digits++; } return INT2FIX(key); @@ -1159,8 +1158,7 @@ big_hash(x) static VALUE big_coerce(x, y) - struct RBignum *x; - VALUE y; + VALUE x, y; { if (FIXNUM_P(y)) { return assoc_new(int2big(FIX2INT(y)), x); @@ -1173,11 +1171,11 @@ big_coerce(x, y) static VALUE big_abs(x) - struct RBignum *x; + VALUE x; { - if (!x->sign) { - x = (struct RBignum*)big_clone(x); - x->sign = 1; + if (!RBIGNUM(x)->sign) { + x = big_clone(x); + RBIGNUM(x)->sign = 1; } return (VALUE)x; } @@ -1188,12 +1186,12 @@ big_abs(x) VALUE big_rand(max) - struct RBignum *max; + VALUE max; { struct RBignum *v; int len; - len = max->len; + len = RBIGNUM(max)->len; v = RBIGNUM(bignew(len,1)); while (len--) { #ifdef HAVE_RANDOM @@ -1208,9 +1206,9 @@ big_rand(max) static VALUE big_size(big) - struct RBignum *big; + VALUE big; { - return INT2FIX(big->len*2); + return INT2FIX(RBIGNUM(big)->len*sizeof(USHORT)); } void diff --git a/class.c b/class.c index b78b2aabe0..13c9298c1c 100644 --- a/class.c +++ b/class.c @@ -22,28 +22,27 @@ extern VALUE cModule; VALUE class_new(super) - struct RClass *super; + VALUE super; { - NEWOBJ(cls, struct RClass); - OBJSETUP(cls, cClass, T_CLASS); + NEWOBJ(klass, struct RClass); + OBJSETUP(klass, cClass, T_CLASS); - cls->super = super; - cls->iv_tbl = 0; - cls->m_tbl = 0; /* safe GC */ - cls->m_tbl = new_idhash(); + klass->super = super; + klass->iv_tbl = 0; + klass->m_tbl = 0; /* safe GC */ + klass->m_tbl = new_idhash(); - return (VALUE)cls; + return (VALUE)klass; } VALUE singleton_class_new(super) - struct RClass *super; + VALUE super; { - struct RClass *cls = (struct RClass*)class_new(super); - - FL_SET(cls, FL_SINGLETON); + VALUE klass = class_new(super); - return (VALUE)cls; + FL_SET(klass, FL_SINGLETON); + return klass; } static int @@ -57,40 +56,50 @@ clone_method(mid, body, tbl) } VALUE -singleton_class_clone(class) - struct RClass *class; +singleton_class_clone(klass) + VALUE klass; { - if (!FL_TEST(class, FL_SINGLETON)) - return (VALUE)class; + if (!FL_TEST(klass, FL_SINGLETON)) + return klass; else { /* copy singleton(unnamed) class */ NEWOBJ(clone, struct RClass); - CLONESETUP(clone, class); + CLONESETUP(clone, klass); - clone->super = class->super; + clone->super = RCLASS(klass)->super; clone->iv_tbl = 0; clone->m_tbl = 0; clone->m_tbl = new_idhash(); - st_foreach(class->m_tbl, clone_method, clone->m_tbl); + st_foreach(RCLASS(klass)->m_tbl, clone_method, clone->m_tbl); FL_SET(clone, FL_SINGLETON); return (VALUE)clone; } } +void +singleton_class_attached(klass, obj) + VALUE klass, obj; +{ + if (FL_TEST(klass, FL_SINGLETON)) + rb_iv_set(klass, "__attached__", obj); +} + VALUE rb_define_class_id(id, super) ID id; - struct RBasic *super; + VALUE super; { - struct RClass *cls; + VALUE klass; - if (!super) super = (struct RBasic*)cClass; - cls = (struct RClass*)class_new(super); - rb_name_class(cls, id); + if (!super) super = cObject; + klass = class_new(super); + rb_name_class(klass, id); /* make metaclass */ - RBASIC(cls)->class = singleton_class_new(super->class); + RBASIC(klass)->class = singleton_class_new(RBASIC(super)->class); + singleton_class_attached(RBASIC(klass)->class, klass); + rb_funcall(super, rb_intern("inherited"), 1, klass); - return (VALUE)cls; + return (VALUE)klass; } VALUE @@ -98,14 +107,14 @@ rb_define_class(name, super) char *name; VALUE super; { - VALUE class; + VALUE klass; ID id; id = rb_intern(name); - class = rb_define_class_id(id, super); - st_add_direct(rb_class_tbl, id, class); + klass = rb_define_class_id(id, super); + st_add_direct(rb_class_tbl, id, klass); - return class; + return klass; } VALUE @@ -114,15 +123,15 @@ rb_define_class_under(under, name, super) char *name; VALUE super; { - VALUE class; + VALUE klass; ID id; id = rb_intern(name); - class = rb_define_class_id(id, super); - rb_const_set(under, id, class); - rb_set_class_path(class, under, name); + klass = rb_define_class_id(id, super); + rb_const_set(under, id, klass); + rb_set_class_path(klass, under, name); - return class; + return klass; } VALUE @@ -144,11 +153,11 @@ rb_define_module_id(id) ID id; { extern st_table *rb_class_tbl; - struct RClass *mdl = (struct RClass*)module_new(); + VALUE mdl = module_new(); rb_name_class(mdl, id); - return (VALUE)mdl; + return mdl; } VALUE @@ -181,31 +190,31 @@ rb_define_module_under(under, name) return module; } -static struct RClass * +static VALUE include_class_new(module, super) - struct RClass *module, *super; + VALUE module, super; { - NEWOBJ(cls, struct RClass); - OBJSETUP(cls, cClass, T_ICLASS); + NEWOBJ(klass, struct RClass); + OBJSETUP(klass, cClass, T_ICLASS); - cls->m_tbl = module->m_tbl; - cls->iv_tbl = module->iv_tbl; - cls->super = super; + klass->m_tbl = RCLASS(module)->m_tbl; + klass->iv_tbl = RCLASS(module)->iv_tbl; + klass->super = super; if (TYPE(module) == T_ICLASS) { - RBASIC(cls)->class = RBASIC(module)->class; + RBASIC(klass)->class = RBASIC(module)->class; } else { - RBASIC(cls)->class = (VALUE)module; + RBASIC(klass)->class = module; } - return cls; + return (VALUE)klass; } void -rb_include_module(class, module) - VALUE class, module; +rb_include_module(klass, module) + VALUE klass, module; { - struct RClass *p; + VALUE p; if (NIL_P(module)) return; @@ -217,71 +226,233 @@ rb_include_module(class, module) Check_Type(module, T_MODULE); } - if (class == module) return; + if (klass == module) return; rb_clear_cache(); while (module) { /* ignore if the module included already in superclasses */ - for (p = RCLASS(class)->super; p; p = p->super) { - if (BUILTIN_TYPE(p) == T_ICLASS && p->m_tbl == RCLASS(module)->m_tbl) + for (p = RCLASS(klass)->super; p; p = RCLASS(p)->super) { + if (BUILTIN_TYPE(p) == T_ICLASS && + RCLASS(p)->m_tbl == RCLASS(module)->m_tbl) return; } - RCLASS(class)->super = include_class_new(module, RCLASS(class)->super); - class = (VALUE)RCLASS(class)->super; - module = (VALUE)RCLASS(module)->super; + RCLASS(klass)->super = + include_class_new(module, RCLASS(klass)->super); + klass = RCLASS(klass)->super; + module = RCLASS(module)->super; + } +} + +VALUE +mod_included_modules(mod) + VALUE mod; +{ + VALUE ary = ary_new(); + VALUE p; + + for (p = RCLASS(mod)->super; p; p = RCLASS(p)->super) { + if (BUILTIN_TYPE(p) == T_ICLASS) { + ary_push(ary, RBASIC(p)->class); + } } + return ary; +} + +VALUE +mod_ancestors(mod) + VALUE mod; +{ + VALUE ary = ary_new(); + VALUE p; + + for (p = mod; p; p = RCLASS(p)->super) { + if (BUILTIN_TYPE(p) == T_ICLASS) { + ary_push(ary, RBASIC(p)->class); + } + else { + ary_push(ary, p); + } + } + return ary; +} + +static int +ins_methods_i(key, body, ary) + ID key; + NODE *body; + VALUE ary; +{ + if (!body->nd_noex) { + VALUE name = str_new2(rb_id2name(key)); + + if (!ary_includes(ary, name)) { + if (!body->nd_body) { + ary_push(ary, Qnil); + } + ary_push(ary, name); + } + } + else if (nd_type(body->nd_body) == NODE_ZSUPER) { + ary_push(ary, Qnil); + ary_push(ary, str_new2(rb_id2name(key))); + } + return ST_CONTINUE; +} + +static int +ins_methods_priv_i(key, body, ary) + ID key; + NODE *body; + VALUE ary; +{ + if (!body->nd_body) { + ary_push(ary, Qnil); + ary_push(ary, str_new2(rb_id2name(key))); + } + else if (body->nd_noex) { + VALUE name = str_new2(rb_id2name(key)); + + if (!ary_includes(ary, name)) { + ary_push(ary, name); + } + } + else if (nd_type(body->nd_body) == NODE_ZSUPER) { + ary_push(ary, Qnil); + ary_push(ary, str_new2(rb_id2name(key))); + } + return ST_CONTINUE; +} + +static VALUE +method_list(mod, option, func) + VALUE mod; + int option; + int (*func)(); +{ + VALUE ary; + VALUE klass; + VALUE *p, *q, *pend; + + ary = ary_new(); + for (klass = mod; klass; klass = RCLASS(klass)->super) { + st_foreach(RCLASS(klass)->m_tbl, func, ary); + if (!option) break; + } + p = q = RARRAY(ary)->ptr; pend = p + RARRAY(ary)->len; + while (p < pend) { + if (*p == Qnil) { + p+=2; + continue; + } + *q++ = *p++; + } + RARRAY(ary)->len = q - RARRAY(ary)->ptr; + return ary; +} + +VALUE +class_instance_methods(argc, argv, mod) + int argc; + VALUE *argv; + VALUE mod; +{ + VALUE option; + + rb_scan_args(argc, argv, "01", &option); + return method_list(mod, RTEST(option), ins_methods_i); +} + +VALUE +class_private_instance_methods(argc, argv, mod) + int argc; + VALUE *argv; + VALUE mod; +{ + VALUE option; + + rb_scan_args(argc, argv, "01", &option); + return method_list(mod, RTEST(option), ins_methods_priv_i); +} + +VALUE +obj_singleton_methods(obj) + VALUE obj; +{ + VALUE ary; + VALUE klass; + VALUE *p, *q, *pend; + + ary = ary_new(); + klass = CLASS_OF(obj); + while (klass && FL_TEST(klass, FL_SINGLETON)) { + st_foreach(RCLASS(klass)->m_tbl, ins_methods_i, ary); + klass = RCLASS(klass)->super; + } + p = q = RARRAY(ary)->ptr; pend = p + RARRAY(ary)->len; + while (p < pend) { + if (*p == Qnil) { + p+=2; + continue; + } + *q++ = *p++; + } + RARRAY(ary)->len = q - RARRAY(ary)->ptr; + + return ary; } void -rb_define_method_id(class, name, func, argc) - struct RClass *class; +rb_define_method_id(klass, name, func, argc) + VALUE klass; ID name; VALUE (*func)(); int argc; { - rb_add_method(class, name, NEW_CFUNC(func, argc), NOEX_PUBLIC); + rb_add_method(klass, name, NEW_CFUNC(func, argc), NOEX_PUBLIC); } void -rb_define_method(class, name, func, argc) - VALUE class; +rb_define_method(klass, name, func, argc) + VALUE klass; char *name; VALUE (*func)(); int argc; { - rb_add_method(class, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PUBLIC); + rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PUBLIC); } void -rb_undef_method(class, name) - VALUE class; +rb_undef_method(klass, name) + VALUE klass; char *name; { - rb_add_method(class, rb_intern(name), 0, NOEX_PUBLIC); + rb_add_method(klass, rb_intern(name), 0, NOEX_PUBLIC); } void -rb_define_private_method(class, name, func, argc) - struct RClass *class; +rb_define_private_method(klass, name, func, argc) + VALUE klass; char *name; VALUE (*func)(); int argc; { - rb_add_method(class, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PRIVATE); + rb_add_method(klass, rb_intern(name), NEW_CFUNC(func, argc), NOEX_PRIVATE); } VALUE rb_singleton_class(obj) - struct RBasic *obj; + VALUE obj; { - if (rb_special_const_p((VALUE)obj)) { + if (rb_special_const_p(obj)) { TypeError("cannot define singleton"); } - if (FL_TEST(obj->class, FL_SINGLETON)) { - return (VALUE)obj->class; + if (FL_TEST(RBASIC(obj)->class, FL_SINGLETON)) { + return (VALUE)RBASIC(obj)->class; } - return obj->class = singleton_class_new(obj->class); + RBASIC(obj)->class = singleton_class_new(RBASIC(obj)->class); + singleton_class_attached(RBASIC(obj)->class, obj); + return RBASIC(obj)->class; } void @@ -305,7 +476,7 @@ rb_define_module_function(module, name, func, argc) rb_define_singleton_method(module, name, func, argc); } -VALUE mKernel; +extern VALUE mKernel; void rb_define_global_function(name, func, argc) @@ -317,18 +488,18 @@ rb_define_global_function(name, func, argc) } void -rb_define_alias(class, name1, name2) - VALUE class; +rb_define_alias(klass, name1, name2) + VALUE klass; char *name1, *name2; { - rb_alias(class, rb_intern(name1), rb_intern(name2)); + rb_alias(klass, rb_intern(name1), rb_intern(name2)); } void -rb_define_attr(class, id, pub) - VALUE class; +rb_define_attr(klass, id, read, write) + VALUE klass; ID id; - int pub; + int read, write; { char *name; char *buf; @@ -341,11 +512,11 @@ rb_define_attr(class, id, pub) attreq = rb_intern(buf); sprintf(buf, "@%s", name); attriv = rb_intern(buf); - if (!rb_method_boundp(class, attr, NOEX_PRIVATE)) { - rb_add_method(class, attr, NEW_IVAR(attriv), 0); + if (read) { + rb_add_method(klass, attr, NEW_IVAR(attriv), 0); } - if (pub && !rb_method_boundp(class, attreq, NOEX_PRIVATE)) { - rb_add_method(class, attreq, NEW_ATTRSET(attriv), 0); + if (write) { + rb_add_method(klass, attreq, NEW_ATTRSET(attriv), 0); } } diff --git a/defines.h b/defines.h index 74736ad629..a24f9ebff7 100644 --- a/defines.h +++ b/defines.h @@ -38,7 +38,7 @@ #define FLUSH_REGISTER_WINDOWS /* empty */ #endif -#ifdef __human68k__ +#if defined(__human68k__) || defined(__CYGWIN32__) #undef HAVE_RANDOM #undef HAVE_SETITIMER #endif diff --git a/dir.c b/dir.c index d8f56f5d5f..29ce261272 100644 --- a/dir.c +++ b/dir.c @@ -13,15 +13,16 @@ #include "ruby.h" #include -#ifdef HAVE_UNISTD_H -#include -#endif +#include #ifdef HAVE_SYS_PARAM_H # include #else # define MAXPATHLEN 1024 #endif +#ifdef HAVE_UNISTD_H +#include +#endif #if HAVE_DIRENT_H # include @@ -60,22 +61,21 @@ free_dir(dir) static VALUE dir_s_open(dir_class, dirname) - VALUE dir_class; - struct RString *dirname; + VALUE dir_class, dirname; { VALUE obj; DIR *dirp; Check_SafeStr(dirname); - dirp = opendir(dirname->ptr); + dirp = opendir(RSTRING(dirname)->ptr); if (dirp == NULL) { if (errno == EMFILE || errno == ENFILE) { - gc(); - dirp = opendir(dirname->ptr); + gc_gc(); + dirp = opendir(RSTRING(dirname)->ptr); } if (dirp == NULL) { - rb_sys_fail(dirname->ptr); + rb_sys_fail(RSTRING(dirname)->ptr); } } @@ -178,7 +178,7 @@ dir_s_chdir(argc, argv, obj) rb_secure(2); rb_scan_args(argc, argv, "01", &path); - if (path) { + if (!NIL_P(path)) { Check_SafeStr(path); dist = RSTRING(path)->ptr; } @@ -259,13 +259,12 @@ dir_s_mkdir(argc, argv, obj) static VALUE dir_s_rmdir(obj, dir) - VALUE obj; - struct RString *dir; + VALUE obj, dir; { rb_secure(2); Check_SafeStr(dir); - if (rmdir(dir->ptr) < 0) - rb_sys_fail(dir->ptr); + if (rmdir(RSTRING(dir)->ptr) < 0) + rb_sys_fail(RSTRING(dir)->ptr); return TRUE; } @@ -342,18 +341,18 @@ push_braces(ary, s) } static VALUE -dir_s_glob(dir, str) - VALUE dir; - struct RString *str; +dir_s_glob(dir, vstr) + VALUE dir, vstr; { char *p, *pend; char buf[MAXPATHLEN]; char *t, *t0; int nest; VALUE ary; + struct RString *str; - Check_SafeStr(str); - + Check_SafeStr(vstr); + str = RSTRING(vstr); ary = ary_new(); p = str->ptr; @@ -386,8 +385,7 @@ dir_s_glob(dir, str) static VALUE dir_foreach(io, dirname) - VALUE io; - struct RString *dirname; + VALUE io, dirname; { VALUE dir; diff --git a/dln.c b/dln.c index 23edc6f3fc..f4ab012021 100644 --- a/dln.c +++ b/dln.c @@ -24,6 +24,12 @@ char *dln_argv0; #include #endif +#ifdef HAVE_STRING_H +# include +#else +# include +#endif + void *xmalloc(); void *xcalloc(); void *xrealloc(); @@ -47,15 +53,8 @@ void *xrealloc(); # include #endif -#if defined (HAVE_STRING_H) -# include -#else -# include -#endif - #ifndef NT char *strdup(); - char *getenv(); #endif @@ -1069,7 +1068,6 @@ dln_sym(name) #ifdef _AIX #include /* for isdigit() */ #include /* for global errno */ -#include /* for strerror() */ #include #endif @@ -1077,6 +1075,10 @@ dln_sym(name) /*#include */ #endif +#ifdef _WIN32 +#include +#endif + static char * dln_strerror() { @@ -1104,6 +1106,20 @@ dln_strerror() #ifdef USE_DLN_DLOPEN return (char*)dlerror(); #endif + +#ifdef _WIN32 + static char message[1024]; + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + GetLastError(), + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + message, + sizeof message, + NULL); + + return message; +#endif } @@ -1159,6 +1175,43 @@ void dln_load(file) char *file; { +#ifdef _WIN32 + HINSTANCE handle; + char winfile[255]; + void (*init_fct)(); + char buf[MAXPATHLEN]; + + /* Load the file as an object one */ + init_funcname(buf, file); + +#ifdef __CYGWIN32__ + cygwin32_conv_to_win32_path(file, winfile); +#else + strcpy(winfile, file); +#endif + + /* Load file */ + if ((handle = + LoadLibraryExA(winfile, NULL, LOAD_WITH_ALTERED_SEARCH_PATH)) == NULL) { + printf("LoadLibraryExA\n"); + goto failed; + } + +#ifdef __CYGWIN32__ + init_fct = (void(*)())GetProcAddress(handle, "impure_setup"); + + if (init_fct) + init_fct(_impure_ptr); +#endif + + if ((init_fct = (void(*)())GetProcAddress(handle, buf)) == NULL) { + printf("GetProcAddress %s\n", buf); + goto failed; + } + /* Call the init code */ + (*init_fct)(); + return; +#else #ifdef USE_DLN_A_OUT if (load(file) == -1) { goto failed; @@ -1175,7 +1228,6 @@ dln_load(file) { void *handle; void (*init_fct)(); - int len = strlen(file); # ifndef RTLD_LAZY # define RTLD_LAZY 1 @@ -1280,6 +1332,7 @@ dln_load(file) #endif #endif /* USE_DLN_A_OUT */ +#endif #if !defined(_AIX) && !defined(NeXT) failed: LoadError("%s - %s", dln_strerror(), file); diff --git a/enum.c b/enum.c index 5074170310..d8e2fcdc8b 100644 --- a/enum.c +++ b/enum.c @@ -15,29 +15,31 @@ VALUE mEnumerable; static ID id_each, id_eqq, id_cmp; -void +VALUE rb_each(obj) VALUE obj; { - rb_funcall(obj, id_each, 0, 0); + return rb_funcall(obj, id_each, 0, 0); } -static void +static VALUE grep_i(i, arg) VALUE i, *arg; { if (RTEST(rb_funcall(arg[0], id_eqq, 1, i))) { ary_push(arg[1], i); } + return Qnil; } -static void +static VALUE grep_iter_i(i, pat) VALUE i, pat; { if (RTEST(rb_funcall(pat, id_eqq, 1, i))) { rb_yield(i); } + return Qnil; } static VALUE @@ -52,7 +54,7 @@ enum_grep(obj, pat) VALUE tmp, arg[2]; arg[0] = pat; arg[1] = tmp = ary_new(); - rb_iterate(rb_each, obj, grep_i, arg); + rb_iterate(rb_each, obj, grep_i, (VALUE)arg); return tmp; } @@ -63,7 +65,7 @@ struct find_arg { VALUE val; }; -static void +static VALUE find_i(i, arg) VALUE i; struct find_arg *arg; @@ -71,14 +73,15 @@ find_i(i, arg) if (RTEST(rb_yield(i))) { arg->found = TRUE; arg->val = i; - rb_break(); + rb_iter_break(); } + return Qnil; } static VALUE enum_find(argc, argv, obj) int argc; - VALUE argv; + VALUE* argv; VALUE obj; { struct find_arg arg; @@ -86,7 +89,7 @@ enum_find(argc, argv, obj) rb_scan_args(argc, argv, "01", &if_none); arg.found = FALSE; - rb_iterate(rb_each, obj, find_i, &arg); + rb_iterate(rb_each, obj, find_i, (VALUE)&arg); if (arg.found) { return arg.val; } @@ -96,13 +99,14 @@ enum_find(argc, argv, obj) return Qnil; } -static void +static VALUE find_all_i(i, tmp) VALUE i, tmp; { if (RTEST(rb_yield(i))) { ary_push(tmp, i); } + return Qnil; } static VALUE @@ -117,7 +121,7 @@ enum_find_all(obj) return tmp; } -static void +static VALUE collect_i(i, tmp) VALUE i, tmp; { @@ -127,6 +131,7 @@ collect_i(i, tmp) if (RTEST(retval)) { ary_push(tmp, retval); } + return Qnil; } static VALUE @@ -141,11 +146,12 @@ enum_collect(obj) return tmp; } -static void +static VALUE reverse_i(i, tmp) VALUE i, tmp; { ary_unshift(tmp, i); + return Qnil; } static VALUE @@ -160,11 +166,12 @@ enum_reverse(obj) return tmp; } -static void +static VALUE enum_all(i, ary) VALUE i, ary; { ary_push(ary, i); + return Qnil; } static VALUE @@ -186,7 +193,7 @@ enum_sort(obj) return ary_sort(enum_to_a(obj)); } -static void +static VALUE min_i(i, min) VALUE i, *min; { @@ -199,9 +206,10 @@ min_i(i, min) if (FIX2INT(cmp) < 0) *min = i; } + return Qnil; } -static void +static VALUE min_ii(i, min) VALUE i, *min; { @@ -214,6 +222,7 @@ min_ii(i, min) if (FIX2INT(cmp) < 0) *min = i; } + return Qnil; } static VALUE @@ -222,11 +231,11 @@ enum_min(obj) { VALUE min = Qnil; - rb_iterate(rb_each, obj, iterator_p()?min_ii:min_i, &min); + rb_iterate(rb_each, obj, iterator_p()?min_ii:min_i, (VALUE)&min); return min; } -static void +static VALUE max_i(i, max) VALUE i, *max; { @@ -239,9 +248,10 @@ max_i(i, max) if (FIX2INT(cmp) > 0) *max = i; } + return Qnil; } -static void +static VALUE max_ii(i, max) VALUE i, *max; { @@ -254,6 +264,7 @@ max_ii(i, max) if (FIX2INT(cmp) > 0) *max = i; } + return Qnil; } static VALUE @@ -262,7 +273,7 @@ enum_max(obj) { VALUE max = Qnil; - rb_iterate(rb_each, obj, iterator_p()?max_ii:max_i, &max); + rb_iterate(rb_each, obj, iterator_p()?max_ii:max_i, (VALUE)&max); return max; } @@ -272,18 +283,19 @@ struct i_v_pair { int found; }; -static void +static VALUE index_i(item, iv) VALUE item; struct i_v_pair *iv; { if (rb_equal(item, iv->v)) { iv->found = 1; - rb_break(); + rb_iter_break(); } else { iv->i++; } + return Qnil; } static VALUE @@ -295,20 +307,21 @@ enum_index(obj, val) iv.i = 0; iv.v = val; iv.found = 0; - rb_iterate(rb_each, obj, index_i, &iv); + rb_iterate(rb_each, obj, index_i, (VALUE)&iv); if (iv.found) return INT2FIX(iv.i); return Qnil; /* not found */ } -static void +static VALUE member_i(item, iv) VALUE item; struct i_v_pair *iv; { if (rb_equal(item, iv->v)) { iv->i = 1; - rb_break(); + rb_iter_break(); } + return Qnil; } static VALUE @@ -319,17 +332,18 @@ enum_member(obj, val) iv.i = 0; iv.v = val; - rb_iterate(rb_each, obj, member_i, &iv); + rb_iterate(rb_each, obj, member_i, (VALUE)&iv); if (iv.i) return TRUE; return FALSE; } -static void +static VALUE length_i(i, length) VALUE i; int *length; { (*length)++; + return Qnil; } VALUE @@ -338,7 +352,7 @@ enum_length(obj) { int length = 0; - rb_iterate(rb_each, obj, length_i, &length); + rb_iterate(rb_each, obj, length_i, (VALUE)&length); return INT2FIX(length); } diff --git a/env.h b/env.h index fb7b941d4d..ebcfcc5d31 100644 --- a/env.h +++ b/env.h @@ -15,7 +15,7 @@ extern struct FRAME { int argc; VALUE *argv; ID last_func; - struct RClass *last_class; + VALUE last_class; VALUE cbase; struct FRAME *prev; char *file; @@ -23,6 +23,8 @@ extern struct FRAME { int iter; } *the_frame; +void gc_mark_frame _((struct FRAME *)); + extern struct SCOPE { struct RBasic super; ID *local_tbl; @@ -36,7 +38,7 @@ extern struct SCOPE { extern int rb_in_eval; -extern struct RClass *the_class; +extern VALUE the_class; struct RVarmap { struct RBasic super; diff --git a/error.c b/error.c index 39e63ddfd5..7163f62609 100644 --- a/error.c +++ b/error.c @@ -102,7 +102,7 @@ Warning(fmt, va_alist) char buf[BUFSIZ]; va_list args; - if (!verbose) return; + if (!RTEST(verbose)) return; sprintf(buf, "warning: %s", fmt); @@ -225,11 +225,10 @@ exc_new2(etype, s) VALUE exc_new3(etype, str) - VALUE etype; - struct RString *str; + VALUE etype, str; { Check_Type(str, T_STRING); - return exc_new(etype, str->ptr, str->len); + return exc_new(etype, RSTRING(str)->ptr, RSTRING(str)->len); } static VALUE @@ -251,14 +250,20 @@ static VALUE exc_inspect(exc) VALUE exc; { - struct RString *classpath = RSTRING(rb_class_path(CLASS_OF(exc))); - VALUE str = str_new(classpath->ptr, classpath->len); + VALUE str, klass; - str_cat(str, ":", 1); + klass = CLASS_OF(exc); if (RSTRING(exc)->len == 0) { - str_cat(str, "\"\"", 2); + return rb_class_path(klass); } + + str = str_new2("#<"); + klass = rb_class_path(klass); + str_cat(str, RSTRING(klass)->ptr, RSTRING(klass)->len); + str_cat(str, ":", 1); str_cat(str, RSTRING(exc)->ptr, RSTRING(exc)->len); + str_cat(str, ">", 1); + return str; } @@ -285,7 +290,7 @@ exception(argc, argv) } } for (i=0; i -#else +#ifndef HAVE_STRING_H char *strrchr(); #endif +#ifdef HAVE_UNISTD_H +#include +#endif + #ifndef setjmp #ifdef HAVE__SETJMP #define setjmp(env) _setjmp(env) @@ -34,9 +36,13 @@ char *strrchr(); #endif extern VALUE cData; + VALUE cProc; -static VALUE proc_call(); -static VALUE f_binding(); +static VALUE proc_call _((VALUE,VALUE)); +static VALUE f_binding _((VALUE)); +static void f_END _((void)); + +#define SCOPE_PRIVATE FL_USER4 #define CACHE_SIZE 0x200 #define CACHE_MASK 0x1ff @@ -45,8 +51,8 @@ static VALUE f_binding(); struct cache_entry { /* method hash table. */ ID mid; /* method's id */ ID mid0; /* method's original id */ - struct RClass *class; /* receiver's class */ - struct RClass *origin; /* where method defined */ + VALUE class; /* receiver's class */ + VALUE origin; /* where method defined */ NODE *method; int noex; }; @@ -65,29 +71,58 @@ rb_clear_cache() } } +static void +rb_clear_cache_by_id(id) + ID id; +{ + struct cache_entry *ent, *end; + + ent = cache; end = ent + CACHE_SIZE; + while (ent < end) { + if (ent->mid == id) { + ent->mid = 0; + } + ent++; + } +} + void rb_add_method(class, mid, node, noex) - struct RClass *class; + VALUE class; ID mid; NODE *node; int noex; { NODE *body; - if (NIL_P(class)) class = (struct RClass*)cObject; + if (NIL_P(class)) class = cObject; body = NEW_METHOD(node, noex); - st_insert(class->m_tbl, mid, body); + st_insert(RCLASS(class)->m_tbl, mid, body); +} + +void +rb_remove_method(class, mid) + VALUE class; + ID mid; +{ + NODE *body; + + if (!st_delete(RCLASS(class)->m_tbl, &mid, &body)) { + NameError("method `%s' not defined in %s", + rb_id2name(mid), rb_class2name(class)); + } + rb_clear_cache_by_id(mid); } static NODE* search_method(class, id, origin) - struct RClass *class, **origin; + VALUE class, *origin; ID id; { NODE *body; - while (!st_lookup(class->m_tbl, id, &body)) { - class = class->super; + while (!st_lookup(RCLASS(class)->m_tbl, id, &body)) { + class = (VALUE)RCLASS(class)->super; if (!class) return 0; } @@ -97,14 +132,14 @@ search_method(class, id, origin) static NODE* rb_get_method_body(classp, idp, noexp) - struct RClass **classp; + VALUE *classp; ID *idp; int *noexp; { ID id = *idp; - struct RClass *class = *classp; + VALUE class = *classp; + VALUE origin; NODE *body; - struct RClass *origin; struct cache_entry *ent; if ((body = search_method(class, id, &origin)) == 0) { @@ -119,12 +154,14 @@ rb_get_method_body(classp, idp, noexp) body = body->nd_body; if (nd_type(body) == NODE_FBODY) { ent->mid = id; - *classp = ent->origin = (struct RClass*)body->nd_orig; + *classp = body->nd_orig; + ent->origin = body->nd_orig; *idp = ent->mid0 = body->nd_mid; body = ent->method = body->nd_head; } else { - *classp = ent->origin = origin; + *classp = (VALUE)origin; + ent->origin = origin; ent->mid = ent->mid0 = id; ent->method = body; } @@ -135,10 +172,10 @@ rb_get_method_body(classp, idp, noexp) void rb_alias(class, name, def) - struct RClass *class; + VALUE class; ID name, def; { - struct RClass *origin; + VALUE origin; NODE *orig, *body; if (name == def) return; @@ -156,16 +193,16 @@ rb_alias(class, name, def) if (nd_type(body) == NODE_FBODY) { /* was alias */ body = body->nd_head; def = body->nd_mid; - origin = (struct RClass*)body->nd_orig; + origin = body->nd_orig; } - st_insert(class->m_tbl, name, + st_insert(RCLASS(class)->m_tbl, name, NEW_METHOD(NEW_FBODY(body, def, origin), orig->nd_noex)); } static void rb_export_method(class, name, noex) - struct RClass *class; + VALUE class; ID name; int noex; { @@ -178,14 +215,14 @@ rb_export_method(class, name, noex) } if (!body) { NameError("undefined method `%s' for `%s'", - rb_id2name(name), rb_class2name((VALUE)class)); + rb_id2name(name), rb_class2name(class)); } if (body->nd_noex != noex) { - if (class == origin) { + if (class == (VALUE)origin) { body->nd_noex = noex; } else { - rb_clear_cache(); + rb_clear_cache_by_id(name); rb_add_method(class, name, NEW_ZSUPER(), noex); } } @@ -193,7 +230,7 @@ rb_export_method(class, name, noex) static VALUE method_boundp(class, id, ex) - struct RClass *class; + VALUE class; ID id; int ex; { @@ -208,18 +245,19 @@ method_boundp(class, id, ex) } int -rb_method_boundp(class, id, priv) +rb_method_boundp(class, id, ex) VALUE class; ID id; - int priv; + int ex; { - if (method_boundp(class, id, priv?NOEX_PRIVATE:NOEX_PUBLIC)) + if (method_boundp(class, id, ex)) return TRUE; return FALSE; } -static ID init, eqq, each, aref, aset; +static ID init, eqq, each, aref, aset, match; VALUE errinfo = Qnil, errat = Qnil; +extern NODE *eval_tree0; extern NODE *eval_tree; extern int nerrs; @@ -244,15 +282,15 @@ static struct FRAME *top_frame; static struct SCOPE *top_scope; #define PUSH_FRAME() { \ - struct FRAME _frame; \ - _frame.prev = the_frame; \ - _frame.file = sourcefile; \ - _frame.line = sourceline; \ - _frame.iter = the_iter->iter; \ - _frame.cbase = the_frame->cbase; \ - the_frame = &_frame; \ + struct FRAME *_frame = ALLOCA_N(struct FRAME,1);\ + _frame->prev = the_frame; \ + _frame->file = sourcefile; \ + _frame->line = sourceline; \ + _frame->iter = the_iter->iter; \ + _frame->cbase = the_frame->cbase; \ + the_frame = _frame; \ -#define POP_FRAME() the_frame = _frame.prev; } +#define POP_FRAME() the_frame = _frame->prev; } struct BLOCK { NODE *var; @@ -260,8 +298,8 @@ struct BLOCK { VALUE self; struct FRAME frame; struct SCOPE *scope; - struct RClass *class; - int level; + VALUE class; + struct tag *tag; int iter; struct RVarmap *d_vars; #ifdef THREAD @@ -271,26 +309,26 @@ struct BLOCK { } *the_block; #define PUSH_BLOCK(v,b) { \ - struct BLOCK _block; \ - _block.level = (int)prot_tag; \ - _block.var = v; \ - _block.body = b; \ - _block.self = self; \ - _block.frame = *the_frame; \ - _block.class = the_class; \ - _block.frame.file = sourcefile; \ - _block.frame.line = sourceline; \ - _block.scope = the_scope; \ - _block.d_vars = the_dyna_vars; \ - _block.prev = the_block; \ - _block.iter = the_iter->iter; \ - the_block = &_block; \ + struct BLOCK *_block = ALLOCA_N(struct BLOCK,1);\ + _block->tag = prot_tag; \ + _block->var = v; \ + _block->body = b; \ + _block->self = self; \ + _block->frame = *the_frame; \ + _block->class = the_class; \ + _block->frame.file = sourcefile; \ + _block->frame.line = sourceline; \ + _block->scope = the_scope; \ + _block->d_vars = the_dyna_vars; \ + _block->prev = the_block; \ + _block->iter = the_iter->iter; \ + the_block = _block; #define PUSH_BLOCK2(b) { \ - struct BLOCK _block; \ - _block = *b; \ - _block.prev = the_block; \ - the_block = &_block; + struct BLOCK *_block = ALLOCA_N(struct BLOCK,1);\ + *_block = *b; \ + _block->prev = the_block; \ + the_block = _block; #define POP_BLOCK() \ the_block = the_block->prev; \ @@ -378,35 +416,53 @@ static struct iter { the_iter = _iter.prev; \ } +#ifdef C_ALLOCA +/* need to protect retval in struct tag from GC. */ +#define tag_retval_dcl VALUE *dd_retval +#define tag_retval_init VALUE _tag_retval = Qnil;\ + _tag->dd_retval = &_tag_retval; +#define tag_retval dd_retval[0] +#else +#define tag_retval_dcl VALUE retval +#define tag_retval_init _tag->retval = Qnil +#define tag_retval retval +#endif + static struct tag { jmp_buf buf; struct FRAME *frame; struct iter *iter; + ID tag; + tag_retval_dcl; + ID dst; struct tag *prev; } *prot_tag; -#define PUSH_TAG() { \ - struct tag _tag; \ - _tag.frame = the_frame; \ - _tag.iter = the_iter; \ - _tag.prev = prot_tag; \ - prot_tag = &_tag; +#define PUSH_TAG(ptag) { \ + struct tag *_tag = ALLOCA_N(struct tag,1);\ + tag_retval_init; \ + _tag->frame = the_frame; \ + _tag->iter = the_iter; \ + _tag->prev = prot_tag; \ + _tag->tag_retval = Qnil; \ + _tag->tag = ptag; \ + _tag->dst = 0; \ + prot_tag = _tag; -#define EXEC_TAG() ((NODE*)setjmp(prot_tag->buf)) +#define PROT_NONE 0 +#define PROT_FUNC -1 +#define PROT_THREAD -2 + +#define EXEC_TAG() setjmp(prot_tag->buf) #define JUMP_TAG(st) { \ the_frame = prot_tag->frame; \ the_iter = prot_tag->iter; \ - longjmp(prot_tag->buf,(int)(st)); \ + longjmp(prot_tag->buf,(st)); \ } -#define JUMP_TAG3(val,data1,data2) \ - JUMP_TAG(node_newnode(NODE_TAG,(val),(data1),(data2))) - -#define JUMP_TAG2(val,data) JUMP_TAG3((val),(data),0) - #define POP_TAG() \ - prot_tag = _tag.prev; \ + prot_tag = _tag->prev; \ } #define TAG_RETURN 0x1 @@ -417,13 +473,12 @@ static struct tag { #define TAG_RAISE 0x6 #define TAG_THROW 0x7 #define TAG_FATAL 0x8 +#define TAG_MASK 0xf -#define IN_BLOCK 0x10 - -struct RClass *the_class; +VALUE the_class; -#define PUSH_CLASS() { \ - struct RClass *_class = the_class; \ +#define PUSH_CLASS() { \ + VALUE _class = the_class; \ #define POP_CLASS() the_class = _class; } @@ -581,23 +636,35 @@ error_print() fprintf(stderr, ": unhandled exception\n"); } else { - PUSH_TAG(); - if (EXEC_TAG() == 0) { - VALUE epath = rb_class_path(eclass); - if (RSTRING(epath)->ptr[0] != '#') { - fprintf(stderr, ": "); - fwrite(RSTRING(epath)->ptr, 1, RSTRING(epath)->len, stderr); - } - } - POP_TAG(); + VALUE epath; - if (RSTRING(errinfo)->len > 0) { + epath = rb_class_path(eclass); + if (RSTRING(errinfo)->len == 0) { fprintf(stderr, ": "); - fwrite(RSTRING(errinfo)->ptr, 1, RSTRING(errinfo)->len, stderr); - } - if (RSTRING(errinfo)->ptr[RSTRING(errinfo)->len - 1] != '\n') { + fwrite(RSTRING(epath)->ptr, 1, RSTRING(epath)->len, stderr); putc('\n', stderr); } + else { + unsigned char *tail = 0; + int len = RSTRING(errinfo)->len; + + if (RSTRING(epath)->ptr[0] == '#') epath = 0; + if (tail = strchr(RSTRING(errinfo)->ptr, '\n')) { + len = tail - RSTRING(errinfo)->ptr; + tail++; /* skip newline */ + } + fprintf(stderr, ": "); + fwrite(RSTRING(errinfo)->ptr, 1, len, stderr); + if (epath) { + fprintf(stderr, " ("); + fwrite(RSTRING(epath)->ptr, 1, RSTRING(epath)->len, stderr); + fprintf(stderr, ")\n"); + } + if (tail) { + fwrite(tail, 1, RSTRING(errinfo)->len-len-1, stderr); + putc('\n', stderr); + } + } } if (!NIL_P(errat)) { @@ -608,6 +675,7 @@ error_print() #define TRACE_HEAD 8 #define TRACE_TAIL 5 + ep = RARRAY(errat); for (i=1; ilen; i++) { fprintf(stderr, "\tfrom %s\n", RSTRING(ep->ptr[i])->ptr); if (i == TRACE_HEAD && ep->len > TRACE_MAX) { @@ -624,12 +692,18 @@ extern char **environ; #endif char **origenviron; +void rb_call_inits _((void)); +void init_stack _((void)); +void init_heap _((void)); +void Init_ext _((void)); +void gc_call_finalizer_at_exit _((void)); + void ruby_init() { static struct FRAME frame; static struct iter iter; - NODE *state; + int state; the_frame = top_frame = &frame; the_iter = &iter; @@ -641,11 +715,13 @@ ruby_init() the_scope->local_vars = 0; the_scope->local_tbl = 0; top_scope = the_scope; + /* default visibility is private at toplevel */ + FL_SET(top_scope, SCOPE_PRIVATE); - PUSH_TAG() + PUSH_TAG(PROT_NONE) if ((state = EXEC_TAG()) == 0) { rb_call_inits(); - the_class = (struct RClass*)cObject; + the_class = cObject; the_frame->cbase = (VALUE)node_newnode(NODE_CREF,cObject,0,0); rb_define_global_const("TOPLEVEL_BINDING", f_binding(TopSelf)); ruby_prog_init(); @@ -663,16 +739,17 @@ ruby_options(argc, argv) int argc; char **argv; { - NODE *state; + int state; - PUSH_TAG() + PUSH_TAG(PROT_NONE) if ((state = EXEC_TAG()) == 0) { NODE *save; - Init_ext(); - ext_init = 1; ruby_process_options(argc, argv); save = eval_tree; + eval_tree = 0; + Init_ext(); + ext_init = 1; rb_require_modules(); eval_tree = save; } @@ -690,6 +767,12 @@ eval_node(self) VALUE result = Qnil; NODE *tree; + if (eval_tree0) { + tree = eval_tree0; + eval_tree0 = 0; + rb_eval(self, tree); + } + if (!eval_tree) return Qnil; tree = eval_tree; @@ -709,18 +792,20 @@ static VALUE thread_current(); static int exit_status; +static void exec_end_proc(); + void ruby_run() { - NODE *state; - static NODE *ex; + int state; + static int ex; if (nerrs > 0) exit(nerrs); init_stack(); errat = Qnil; /* clear for execution */ - PUSH_TAG(); + PUSH_TAG(PROT_NONE); PUSH_ITER(ITER_NOT); if ((state = EXEC_TAG()) == 0) { if (!ext_init) Init_ext(); @@ -730,7 +815,7 @@ ruby_run() POP_TAG(); if (state && !ex) ex = state; - PUSH_TAG(); + PUSH_TAG(PROT_NONE); PUSH_ITER(ITER_NOT); if ((state = EXEC_TAG()) == 0) { rb_trap_exit(); @@ -738,6 +823,8 @@ ruby_run() thread_cleanup(); thread_wait_other_threads(); #endif + exec_end_proc(); + gc_call_finalizer_at_exit(); } else { ex = state; @@ -745,12 +832,10 @@ ruby_run() POP_ITER(); POP_TAG(); - if (!ex) { + switch (ex & 0xf) { + case 0: exit(0); - } - switch (ex->nd_tag) { - case IN_BLOCK|TAG_RETURN: case TAG_RETURN: error_pos(); fprintf(stderr, "unexpected return\n"); @@ -761,7 +846,6 @@ ruby_run() fprintf(stderr, "unexpected next\n"); exit(1); break; - case IN_BLOCK|TAG_BREAK: case TAG_BREAK: error_pos(); fprintf(stderr, "unexpected break\n"); @@ -785,13 +869,8 @@ ruby_run() error_print(); exit(1); break; - case TAG_THROW: - error_pos(); - fprintf(stderr, "uncaught throw `%s'\n", rb_id2name(ex->nd_tlev)); - exit(1); - break; default: - Bug("Unknown longjmp status %d", ex->nd_tag); + Bug("Unknown longjmp status %d", ex); break; } } @@ -804,9 +883,12 @@ compile_error(at) mesg = errinfo; nerrs = 0; - errinfo = exc_new2(eSyntaxError, "compile error in "); - str_cat(errinfo, at, strlen(at)); - str_cat(errinfo, ":\n", 2); + errinfo = exc_new2(eSyntaxError, "compile error"); + if (at) { + str_cat(errinfo, " in ", 4); + str_cat(errinfo, at, strlen(at)); + } + str_cat(errinfo, "\n", 1); str_cat(errinfo, RSTRING(mesg)->ptr, RSTRING(mesg)->len); rb_raise(errinfo); } @@ -829,23 +911,23 @@ void rb_eval_cmd(cmd, arg) VALUE cmd, arg; { - NODE *state; + int state; struct SCOPE *saved_scope; volatile int safe = rb_safe_level(); if (TYPE(cmd) != T_STRING) { - if (obj_is_kind_of(cmd, cProc)) { - proc_call(cmd, arg); - return; - } + Check_Type(arg, T_ARRAY); + rb_funcall2(cmd, rb_intern("call"), + RARRAY(arg)->len, RARRAY(arg)->ptr); + return; } PUSH_CLASS(); - PUSH_TAG(); + PUSH_TAG(PROT_NONE); saved_scope = the_scope; the_scope = top_scope; - the_class = (struct RClass*)cObject; + the_class = cObject; if (str_tainted(cmd)) { safe_level = 5; } @@ -859,8 +941,9 @@ rb_eval_cmd(cmd, arg) POP_TAG(); POP_CLASS(); - if (state == 0) return; - switch (state->nd_tag) { + switch (state) { + case 0: + break; case TAG_RETURN: Raise(eLocalJumpError, "unexpected return"); break; @@ -887,9 +970,9 @@ rb_trap_eval(cmd, sig) VALUE cmd; int sig; { - NODE *state; + int state; - PUSH_TAG(); + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { rb_eval_cmd(cmd, ary_new3(1, INT2FIX(sig))); } @@ -905,25 +988,23 @@ superclass(self, node) VALUE self; NODE *node; { - VALUE val = 0; - NODE *state; + VALUE val = 0; /* OK */ + int state; - PUSH_TAG(); + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { val = rb_eval(self, node); } POP_TAG(); - if (state) { - if (state->nd_tag == TAG_RAISE) { - superclass_error: - switch (nd_type(node)) { - case NODE_COLON2: - TypeError("undefined superclass `%s'", rb_id2name(node->nd_mid)); - case NODE_CVAR: - TypeError("undefined superclass `%s'", rb_id2name(node->nd_vid)); - default: - TypeError("superclass undefined"); - } + if (state == TAG_RAISE) { + superclass_error: + switch (nd_type(node)) { + case NODE_COLON2: + TypeError("undefined superclass `%s'", rb_id2name(node->nd_mid)); + case NODE_CVAR: + TypeError("undefined superclass `%s'", rb_id2name(node->nd_vid)); + default: + TypeError("superclass undefined"); } JUMP_TAG(state); } @@ -974,6 +1055,64 @@ ev_const_get(cref, id) return rb_const_get(cref->nd_clss, id); } +static VALUE +mod_nesting() +{ + NODE *cbase = (NODE*)the_frame->cbase; + VALUE ary = ary_new(); + + while (cbase && cbase->nd_clss != cObject) { + ary_push(ary, cbase->nd_clss); + cbase = cbase->nd_next; + } + return ary; +} + +static VALUE +mod_s_constants() +{ + NODE *cbase = (NODE*)the_frame->cbase; + VALUE ary = ary_new(); + + while (cbase && cbase->nd_clss != cObject) { + mod_const_at(cbase->nd_clss, ary); + cbase = cbase->nd_next; + } + + mod_const_of(((NODE*)the_frame->cbase)->nd_clss, ary); + return ary; +} + +static VALUE +mod_remove_method(mod, name) + VALUE mod, name; +{ + rb_remove_method(mod, rb_to_id(name)); + return mod; +} + +static VALUE +mod_undef_method(mod, name) + VALUE mod, name; +{ + ID id = rb_to_id(name); + + rb_add_method(mod, id, 0, NOEX_PUBLIC); + rb_clear_cache_by_id(id); + return mod; +} + +static VALUE +mod_alias_method(mod, new, old) + VALUE mod, new, old; +{ + ID id = rb_to_id(new); + + rb_alias(mod, id, rb_to_id(old)); + rb_clear_cache_by_id(id); + return mod; +} + #define SETUP_ARGS(anode) {\ NODE *n = anode;\ if (!n) {\ @@ -983,15 +1122,16 @@ ev_const_get(cref, id) else if (nd_type(n) == NODE_ARRAY) {\ argc=n->nd_alen;\ if (argc > 0) {\ - int i;\ + char *file = sourcefile;\ int line = sourceline;\ + int i;\ n = anode;\ argv = ALLOCA_N(VALUE,argc);\ for (i=0;ind_head);\ n=n->nd_next;\ }\ - sourcefile = anode->file;\ + sourcefile = file;\ sourceline = line;\ }\ else {\ @@ -1001,26 +1141,49 @@ ev_const_get(cref, id) }\ else {\ VALUE args = rb_eval(self,n);\ + char *file = sourcefile;\ int line = sourceline;\ if (TYPE(args) != T_ARRAY)\ - args = rb_to_a(args);\ + args = rb_Array(args);\ argc = RARRAY(args)->len;\ argv = ALLOCA_N(VALUE, argc);\ MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);\ - sourcefile = anode->file;\ + sourcefile = file;\ sourceline = line;\ }\ } -int -rb_test_false_or_nil(v) - VALUE v; -{ - return (v != Qnil) && (v != FALSE); -} - #define MATCH_DATA the_scope->local_vars[node->nd_cnt] +static char* is_defined _((VALUE, NODE*, char*)); + +static char* +arg_defined(self, node, buf, type) + VALUE self; + NODE *node; + char *buf; + char *type; +{ + int argc; + int i; + + if (!node) return type; /* no args */ + if (nd_type(node) == NODE_ARRAY) { + argc=node->nd_alen; + if (argc > 0) { + for (i=0;ind_head, buf)) + return 0; + node = node->nd_next; + } + } + } + else if (!is_defined(self, node, buf)) { + return 0; + } + return type; +} + static char* is_defined(self, node, buf) VALUE self; @@ -1028,16 +1191,17 @@ is_defined(self, node, buf) char *buf; { VALUE val; /* OK */ - NODE *state; - - node = node->nd_head; + int state; switch (nd_type(node)) { case NODE_SUPER: case NODE_ZSUPER: if (the_frame->last_func == 0) return 0; - else if (method_boundp(the_frame->last_class->super, + else if (method_boundp(RCLASS(the_frame->last_class)->super, the_frame->last_func, 1)) { + if (nd_type(node) == NODE_SUPER) { + return arg_defined(self, node->nd_args, buf, "super"); + } return "super"; } break; @@ -1048,7 +1212,8 @@ is_defined(self, node, buf) goto check_bound; case NODE_CALL: - PUSH_TAG(); + if (!is_defined(self, node->nd_recv, buf)) return 0; + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { val = rb_eval(self, node->nd_recv); val = CLASS_OF(val); @@ -1058,12 +1223,15 @@ is_defined(self, node, buf) return 0; } check_bound: - if (method_boundp(val, node->nd_mid, - nd_type(node)== NODE_CALL)) { - return "method"; + if (method_boundp(val, node->nd_mid, nd_type(node)== NODE_CALL)) { + return arg_defined(self, node->nd_args, buf, "method"); } break; + case NODE_MATCH2: + case NODE_MATCH3: + return "method"; + case NODE_YIELD: if (iterator_p()) { return "yield"; @@ -1076,6 +1244,12 @@ is_defined(self, node, buf) case NODE_NIL: return "nil"; + case NODE_TRUE: + return "true"; + + case NODE_FALSE: + return "false"; + case NODE_ATTRSET: case NODE_OP_ASGN1: case NODE_OP_ASGN2: @@ -1110,7 +1284,7 @@ is_defined(self, node, buf) break; case NODE_COLON2: - PUSH_TAG(); + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { val = rb_eval(self, node->nd_head); } @@ -1143,7 +1317,7 @@ is_defined(self, node, buf) break; default: - PUSH_TAG(); + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { rb_eval(self, node); } @@ -1163,17 +1337,16 @@ static void blk_free(); static VALUE set_trace_func(obj, trace) - VALUE obj; - struct RData *trace; + VALUE obj, trace; { if (NIL_P(trace)) { trace_func = 0; return Qnil; } - if (TYPE(trace) != T_DATA || trace->dfree != blk_free) { + if (TYPE(trace) != T_DATA || RDATA(trace)->dfree != blk_free) { TypeError("trace_func needs to be Proc"); } - return trace_func = (VALUE)trace; + return trace_func = trace; } static void @@ -1184,7 +1357,7 @@ call_trace_func(event, file, line, self, id) VALUE self; ID id; { - NODE *state; + int state; volatile VALUE trace; struct FRAME *prev; @@ -1198,12 +1371,12 @@ call_trace_func(event, file, line, self, id) prev = the_frame; PUSH_FRAME(); - *the_frame = *_frame.prev; + *the_frame = *_frame->prev; the_frame->prev = prev; the_frame->line = sourceline = line; the_frame->file = sourcefile = file; - PUSH_TAG(); + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { proc_call(trace, ary_new3(5, str_new2(event), str_new2(sourcefile), @@ -1221,12 +1394,13 @@ call_trace_func(event, file, line, self, id) if (state) JUMP_TAG(state); } +static void return_value _((VALUE val)); static VALUE rb_eval(self, node) VALUE self; NODE * volatile node; { - NODE *state; + int state; volatile VALUE result = Qnil; #define RETURN(v) { result = (v); goto finish; } @@ -1234,10 +1408,6 @@ rb_eval(self, node) again: if (!node) RETURN(Qnil); -#if 0 - sourceline = nd_line(node); - sourcefile = node->file; -#endif switch (nd_type(node)) { case NODE_BLOCK: while (node) { @@ -1246,6 +1416,12 @@ rb_eval(self, node) } break; + case NODE_POSTEXE: + f_END(); + nd_set_type(node, NODE_NIL); /* exec just once */ + result = Qnil; + break; + /* begin .. end without clauses */ case NODE_BEGIN: node = node->nd_body; @@ -1256,6 +1432,26 @@ rb_eval(self, node) result = reg_match2(node->nd_head->nd_lit); break; + /* nodes for speed-up(literal match) */ + case NODE_MATCH2: + result = reg_match(rb_eval(self,node->nd_recv), + rb_eval(self,node->nd_value)); + break; + + /* nodes for speed-up(literal match) */ + case NODE_MATCH3: + { + VALUE r = rb_eval(self,node->nd_recv); + VALUE l = rb_eval(self,node->nd_value); + if (TYPE(r) == T_STRING) { + result = reg_match(l, r); + } + else { + result = rb_funcall(r, match, 1, l); + } + } + break; + /* nodes for speed-up(top-level loop for -n/-p) */ case NODE_OPT_N: while (!NIL_P(f_gets())) { @@ -1269,7 +1465,14 @@ rb_eval(self, node) case NODE_NIL: RETURN(Qnil); + case NODE_TRUE: + RETURN(TRUE); + + case NODE_FALSE: + RETURN(FALSE); + case NODE_IF: + sourceline = nd_line(node); if (RTEST(rb_eval(self, node->nd_cond))) { node = node->nd_body; } @@ -1293,9 +1496,10 @@ rb_eval(self, node) tag = node->nd_head; while (tag) { if (trace_func) { - call_trace_func("line", tag->file, nd_line(tag), + call_trace_func("line", tag->nd_file, nd_line(tag), self, the_frame->last_func); } + sourceline = nd_line(tag); if (RTEST(rb_funcall2(rb_eval(self, tag->nd_head),eqq,1,&val))){ node = node->nd_body; goto again; @@ -1308,8 +1512,10 @@ rb_eval(self, node) RETURN(Qnil); case NODE_WHILE: - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { + PUSH_TAG(PROT_NONE); + switch (state = EXEC_TAG()) { + case 0: + sourceline = nd_line(node); if (node->nd_state && !RTEST(rb_eval(self, node->nd_cond))) goto while_out; do { @@ -1318,20 +1524,18 @@ rb_eval(self, node) while_next: ; } while (RTEST(rb_eval(self, node->nd_cond))); - } - else { - switch (state->nd_tag) { - case TAG_REDO: - state = 0; - goto while_redo; - case TAG_NEXT: - state = 0; - goto while_next; - case TAG_BREAK: - state = 0; - default: - break; - } + break; + + case TAG_REDO: + state = 0; + goto while_redo; + case TAG_NEXT: + state = 0; + goto while_next; + case TAG_BREAK: + state = 0; + default: + break; } while_out: POP_TAG(); @@ -1341,8 +1545,9 @@ rb_eval(self, node) RETURN(Qnil); case NODE_UNTIL: - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { + PUSH_TAG(PROT_NONE); + switch (state = EXEC_TAG()) { + case 0: if (node->nd_state && RTEST(rb_eval(self, node->nd_cond))) goto until_out; do { @@ -1351,20 +1556,18 @@ rb_eval(self, node) until_next: ; } while (!RTEST(rb_eval(self, node->nd_cond))); - } - else { - switch (state->nd_tag) { - case TAG_REDO: - state = 0; - goto until_redo; - case TAG_NEXT: - state = 0; - goto until_next; - case TAG_BREAK: - state = 0; - default: - break; - } + break; + + case TAG_REDO: + state = 0; + goto until_redo; + case TAG_NEXT: + state = 0; + goto until_next; + case TAG_BREAK: + state = 0; + default: + break; } until_out: POP_TAG(); @@ -1376,11 +1579,9 @@ rb_eval(self, node) case NODE_ITER: case NODE_FOR: { - int tag_level; - iter_retry: PUSH_BLOCK(node->nd_var, node->nd_body); - PUSH_TAG(); + PUSH_TAG(PROT_FUNC); state = EXEC_TAG(); if (state == 0) { @@ -1391,34 +1592,37 @@ rb_eval(self, node) } else { VALUE recv; + char *file = sourcefile; int line = sourceline; recv = rb_eval(self, node->nd_iter); PUSH_ITER(ITER_PRE); - sourcefile = node->file; + sourcefile = file; sourceline = line; result = rb_call(CLASS_OF(recv),recv,each,0,0,0); POP_ITER(); } } + else if (the_block->tag->dst == state) { + state &= TAG_MASK; + if (state == TAG_RETURN) { + result = prot_tag->tag_retval; + } + } POP_TAG(); - tag_level = the_block->level; POP_BLOCK(); - if (state == 0) break; - switch (state->nd_tag) { + switch (state) { + case 0: + break; + case TAG_RETRY: goto iter_retry; - case IN_BLOCK|TAG_BREAK: - if (state->nd_tlev != tag_level) { - JUMP_TAG(state); - } + case TAG_BREAK: result = Qnil; break; - case IN_BLOCK|TAG_RETURN: - if (state->nd_tlev == tag_level) { - state->nd_tag &= ~IN_BLOCK; - } + case TAG_RETURN: + return_value(result); /* fall through */ default: JUMP_TAG(state); @@ -1426,6 +1630,22 @@ rb_eval(self, node) } break; + case NODE_BREAK: + JUMP_TAG(TAG_BREAK); + break; + + case NODE_NEXT: + JUMP_TAG(TAG_NEXT); + break; + + case NODE_REDO: + JUMP_TAG(TAG_REDO); + break; + + case NODE_RETRY: + JUMP_TAG(TAG_RETRY); + break; + case NODE_YIELD: result = rb_yield_0(rb_eval(self, node->nd_stts), 0); break; @@ -1435,44 +1655,42 @@ rb_eval(self, node) { volatile VALUE e_info = errinfo, e_at = errat; - PUSH_TAG(); + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { result = rb_eval(self, node->nd_head); } POP_TAG(); - if (state) { - if (state->nd_tag == TAG_RAISE) { - NODE * volatile resq = node->nd_resq; - while (resq) { - if (handle_rescue(self, resq)) { + if (state == TAG_RAISE) { + NODE * volatile resq = node->nd_resq; + while (resq) { + if (handle_rescue(self, resq)) { + state = 0; + PUSH_TAG(PROT_NONE); + if ((state = EXEC_TAG()) == 0) { + result = rb_eval(self, resq->nd_body); + } + POP_TAG(); + if (state == 0) { + errinfo = e_info; + errat = e_at; + } + else if (state == TAG_RETRY) { state = 0; - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { - result = rb_eval(self, resq->nd_body); - } - POP_TAG(); - if (state == 0) { - errinfo = e_info; - errat = e_at; - } - else if (state->nd_tag == TAG_RETRY) { - state = 0; - goto retry_entry; - } - break; + goto retry_entry; } - resq = resq->nd_head; /* next rescue */ + break; } - } - if (state) { - JUMP_TAG(state); + resq = resq->nd_head; /* next rescue */ } } + if (state) { + JUMP_TAG(state); + } } break; case NODE_ENSURE: - PUSH_TAG(); + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { result = rb_eval(self, node->nd_head); } @@ -1539,7 +1757,10 @@ rb_eval(self, node) break; case NODE_RETURN: - JUMP_TAG2(TAG_RETURN,(node->nd_stts)?rb_eval(self, node->nd_stts):Qnil); + if (node->nd_stts) { + return_value(rb_eval(self, node->nd_stts)); + } + JUMP_TAG(TAG_RETURN); break; case NODE_CALL: @@ -1586,7 +1807,7 @@ rb_eval(self, node) } PUSH_ITER(the_iter->iter?ITER_PRE:ITER_NOT); - result = rb_call(the_frame->last_class->super, self, + result = rb_call(RCLASS(the_frame->last_class)->super, self, the_frame->last_func, argc, argv, 1); POP_ITER(); } @@ -1597,7 +1818,7 @@ rb_eval(self, node) VALUE save = the_frame->cbase; PUSH_SCOPE(); - PUSH_TAG(); + PUSH_TAG(PROT_NONE); if (node->nd_rval) the_frame->cbase = (VALUE)node->nd_rval; if (node->nd_tbl) { VALUE *vars = ALLOCA_N(VALUE, node->nd_tbl[0]+1); @@ -1694,7 +1915,8 @@ rb_eval(self, node) val = rb_eval(self, node->nd_value); /* check for static scope constants */ - if (verbose && ev_const_defined(the_frame->cbase, node->nd_vid)) { + if (RTEST(verbose) && + ev_const_defined(the_frame->cbase, node->nd_vid)) { Warning("already initialized constant %s", rb_id2name(node->nd_vid)); } @@ -1826,6 +2048,7 @@ rb_eval(self, node) else { if (nd_type(list->nd_head) == NODE_EVSTR) { rb_in_eval++; + eval_tree = 0; list->nd_head = compile(list->nd_head->nd_lit); rb_in_eval--; if (nerrs > 0) { @@ -1884,15 +2107,27 @@ rb_eval(self, node) body = search_method(the_class, node->nd_mid, &origin); if (body) { if (origin == (VALUE)the_class) { - Warning("redefine %s", rb_id2name(node->nd_mid)); + Warning("discarding old %s", rb_id2name(node->nd_mid)); } - rb_clear_cache(); + rb_clear_cache_by_id(node->nd_mid); } - if (body) noex = body->nd_noex; - else noex = node->nd_noex; /* default(1 for toplevel) */ - + if (FL_TEST(the_scope,SCOPE_PRIVATE)) { + noex = NOEX_PRIVATE; + } + else { + noex = NOEX_PUBLIC; + } rb_add_method(the_class, node->nd_mid, node->nd_defn, noex); + if (FL_TEST(the_class, FL_SINGLETON)) { + VALUE recv = rb_iv_get(the_class, "__attached__"); + rb_funcall(recv, rb_intern("singleton_method_added"), + 1, INT2FIX(node->nd_mid)); + } + else { + rb_funcall(the_class, rb_intern("method_added"), + 1, INT2FIX(node->nd_mid)); + } result = Qnil; } break; @@ -1920,17 +2155,17 @@ rb_eval(self, node) if (st_lookup(RCLASS(class)->m_tbl, node->nd_mid, &body)) { Warning("redefine %s", rb_id2name(node->nd_mid)); } - rb_clear_cache(); + rb_clear_cache_by_id(node->nd_mid); + rb_add_method(class, node->nd_mid, node->nd_defn, NOEX_PUBLIC); rb_funcall(recv, rb_intern("singleton_method_added"), 1, INT2FIX(node->nd_mid)); - rb_add_method(class, node->nd_mid, node->nd_defn, NOEX_PUBLIC); result = Qnil; } break; case NODE_UNDEF: { - struct RClass *origin; + VALUE origin; NODE *body; body = search_method(the_class, node->nd_mid, &origin); @@ -1938,7 +2173,7 @@ rb_eval(self, node) NameError("undefined method `%s' for class `%s'", rb_id2name(node->nd_mid), rb_class2name((VALUE)the_class)); } - rb_clear_cache(); + rb_clear_cache_by_id(node->nd_mid); rb_add_method(the_class, node->nd_mid, 0, NOEX_PUBLIC); result = Qnil; } @@ -1946,6 +2181,8 @@ rb_eval(self, node) case NODE_ALIAS: rb_alias(the_class, node->nd_new, node->nd_old); + rb_funcall(the_class, rb_intern("method_added"), + 1, INT2FIX(node->nd_mid)); result = Qnil; break; @@ -1956,8 +2193,7 @@ rb_eval(self, node) case NODE_CLASS: { - VALUE super, class; - struct RClass *tmp; + VALUE super, class, tmp; if (node->nd_super) { super = superclass(self, node->nd_super); @@ -1982,7 +2218,7 @@ rb_eval(self, node) while (TYPE(tmp) == T_ICLASS) { tmp = RCLASS(tmp)->super; } - if (tmp != RCLASS(super)) { + if (tmp != super) { TypeError("superclass mismatch for %s", rb_id2name(node->nd_cname)); } @@ -1991,7 +2227,6 @@ rb_eval(self, node) Raise(eSecurityError, "extending class prohibited"); } rb_clear_cache(); - Warning("extending class %s", rb_id2name(node->nd_cname)); } else { if (!super) super = cObject; @@ -2000,7 +2235,7 @@ rb_eval(self, node) rb_set_class_path(class,the_class,rb_id2name(node->nd_cname)); } - result = module_setup(class, node->nd_body); + return module_setup(class, node->nd_body); } break; @@ -2019,7 +2254,6 @@ rb_eval(self, node) if (safe_level >= 4) { Raise(eSecurityError, "extending module prohibited"); } - Warning("extending module %s", rb_id2name(node->nd_cname)); } else { module = rb_define_module_id(node->nd_cname); @@ -2047,8 +2281,8 @@ rb_eval(self, node) } if (FL_TEST(CLASS_OF(class), FL_SINGLETON)) { rb_clear_cache(); + class = rb_singleton_class(class); } - class = rb_singleton_class(class); result = module_setup(class, node->nd_body); } @@ -2057,7 +2291,7 @@ rb_eval(self, node) case NODE_DEFINED: { char buf[20]; - char *desc = is_defined(self, node, buf); + char *desc = is_defined(self, node->nd_head, buf); if (desc) result = str_new2(desc); else result = FALSE; @@ -2065,7 +2299,7 @@ rb_eval(self, node) break; case NODE_NEWLINE: - sourcefile = node->file; + sourcefile = node->nd_file; sourceline = node->nd_nth; if (trace_func) { call_trace_func("line", sourcefile, sourceline, @@ -2087,16 +2321,18 @@ module_setup(module, node) VALUE module; NODE * volatile node; { - NODE *state; + int state; VALUE save = the_frame->cbase; VALUE result; /* OK */ + char *file = sourcefile; + int line = sourceline; /* fill c-ref */ node->nd_clss = module; node = node->nd_body; PUSH_CLASS(); - the_class = (struct RClass*)module; + the_class = module; PUSH_SCOPE(); if (node->nd_rval) the_frame->cbase = node->nd_rval; @@ -2112,10 +2348,10 @@ module_setup(module, node) the_scope->local_tbl = 0; } - PUSH_TAG(); + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { if (trace_func) { - call_trace_func("class", node->file, nd_line(node), + call_trace_func("class", file, line, the_class, the_frame->last_func); } result = rb_eval((VALUE)the_class, node->nd_body); @@ -2123,10 +2359,10 @@ module_setup(module, node) POP_TAG(); POP_SCOPE(); POP_CLASS(); + the_frame->cbase = save; if (trace_func) { - call_trace_func("end", node->file, nd_line(node), 0, - the_frame->last_func); + call_trace_func("end", file, line, 0, the_frame->last_func); } if (state) JUMP_TAG(state); @@ -2213,51 +2449,53 @@ f_abort() } void -rb_break() -{ - JUMP_TAG2(TAG_BREAK, 0); -} - -static VALUE -f_break() +rb_iter_break() { - JUMP_TAG2(TAG_BREAK, 0); + JUMP_TAG(TAG_BREAK); } -static VALUE -f_next() -{ - JUMP_TAG2(TAG_NEXT, 0); -} +#ifdef __GNUC__ +static volatile voidfn rb_longjmp; +#endif -static VALUE -f_redo() -{ - JUMP_TAG2(TAG_REDO, 0); -} +static VALUE make_backtrace(); static VALUE -f_retry() +check_errat(val) + VALUE val; { - JUMP_TAG2(TAG_RETRY, 0); -} + int i; + static char *err = "value of $@ must be Array of String"; -#ifdef __GNUC__ -static volatile voidfn rb_longjmp; -#endif + if (!NIL_P(val)) { + int t = TYPE(val); -static VALUE make_backtrace(); + if (t == T_STRING) return ary_new3(1, val); + if (t != T_ARRAY) { + TypeError(err); + } + for (i=0;ilen;i++) { + if (TYPE(RARRAY(val)->ptr[i]) != T_STRING) { + TypeError(err); + } + } + } + return val; +} static void -rb_longjmp(tag, mesg) +rb_longjmp(tag, mesg, at) int tag; - VALUE mesg; + VALUE mesg, at; { if (NIL_P(errinfo) && NIL_P(mesg)) { errinfo = exc_new(eRuntimeError, 0, 0); } - if (sourcefile && (NIL_P(errat) || !NIL_P(mesg))) { + if (!NIL_P(at)) { + errat = check_errat(at); + } + else if (sourcefile && (NIL_P(errat) || !NIL_P(mesg))) { errat = make_backtrace(); } @@ -2271,21 +2509,21 @@ rb_longjmp(tag, mesg) str_freeze(errinfo); } - JUMP_TAG2(tag, 0); + JUMP_TAG(tag); } void rb_raise(mesg) VALUE mesg; { - rb_longjmp(TAG_RAISE, mesg); + rb_longjmp(TAG_RAISE, mesg, Qnil); } void rb_fatal(mesg) VALUE mesg; { - rb_longjmp(TAG_FATAL, mesg); + rb_longjmp(TAG_FATAL, mesg, Qnil); } void @@ -2299,17 +2537,18 @@ f_raise(argc, argv) int argc; VALUE *argv; { - VALUE arg1, arg2; + VALUE arg1, arg2, arg3; VALUE etype, mesg; int n; etype = eRuntimeError; mesg = Qnil; - switch (n = rb_scan_args(argc, argv, "02", &arg1, &arg2)) { + switch (n = rb_scan_args(argc, argv, "03", &arg1, &arg2, &arg3)) { case 1: mesg = arg1; break; case 2: + case 3: etype = arg1; if (obj_is_kind_of(etype, eGlobalExit)) { etype = CLASS_OF(etype); @@ -2317,7 +2556,7 @@ f_raise(argc, argv) else { Check_Type(etype, T_CLASS); } - mesg = arg2; + mesg = arg2; break; } @@ -2329,8 +2568,8 @@ f_raise(argc, argv) } PUSH_FRAME(); /* fake frame */ - *the_frame = *_frame.prev->prev; - rb_raise(mesg); + *the_frame = *_frame->prev->prev; + rb_longjmp(TAG_RAISE, mesg, arg3); POP_FRAME(); } @@ -2354,11 +2593,12 @@ rb_yield_0(val, self) volatile VALUE self; { NODE *node; - NODE *state; volatile VALUE result = Qnil; struct BLOCK *block; struct SCOPE *old_scope; struct FRAME frame; + int state; + static USHORT serial = 1; if (!iterator_p()) { Raise(eLocalJumpError, "yield called out of iterator"); @@ -2384,21 +2624,21 @@ rb_yield_0(val, self) assign(self, block->var, val); } PUSH_ITER(block->iter); - PUSH_TAG(); + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { redo: if (!node) { result = Qnil; } else if (nd_type(node) == NODE_CFUNC) { - result = (*node->nd_cfnc)(val, node->nd_argc, self); + result = (*node->nd_cfnc)(val, node->nd_tval, self); } else { result = rb_eval(self, node); } } else { - switch (state->nd_tag) { + switch (state) { case TAG_REDO: state = 0; goto redo; @@ -2408,8 +2648,9 @@ rb_yield_0(val, self) break; case TAG_BREAK: case TAG_RETURN: - state->nd_tlev = block->level; - state->nd_tag = IN_BLOCK|state->nd_tag; + state |= (serial++ << 8); + state |= 0x10; + block->tag->dst = state; break; default: break; @@ -2452,7 +2693,7 @@ massign(self, node, val) if (val) { if (TYPE(val) != T_ARRAY) { - val = rb_to_a(val); + val = rb_Array(val); } len = RARRAY(val)->len; for (i=0; list && itag->dst == state) { + state &= TAG_MASK; + if (state == TAG_RETURN) { + retval = prot_tag->tag_retval; + } + } POP_TAG(); - - tag_level = the_block->level; POP_BLOCK(); POP_ITER(); - if (state) { - switch (state->nd_tag) { - case TAG_RETRY: - goto iter_retry; + switch (state) { + case 0: + break; - case IN_BLOCK|TAG_BREAK: - if (state->nd_tlev != tag_level) { - JUMP_TAG(state); - } - retval = Qnil; - break; + case TAG_RETRY: + goto iter_retry; - case IN_BLOCK|TAG_RETURN: - if (state->nd_tlev == tag_level) { - state->nd_tag &= ~IN_BLOCK; - } - /* fall through */ - default: - JUMP_TAG(state); - } + case TAG_BREAK: + retval = Qnil; + break; + + case TAG_RETURN: + return_value(retval); + /* fall through */ + default: + JUMP_TAG(state); } return retval; } @@ -2609,36 +2849,34 @@ handle_rescue(self, node) VALUE rb_rescue(b_proc, data1, r_proc, data2) VALUE (*b_proc)(), (*r_proc)(); - void *data1, *data2; + VALUE data1, data2; { - NODE *state; + int state; volatile VALUE result; - PUSH_TAG(); + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { retry_entry: result = (*b_proc)(data1); } - else { - if (state->nd_tag == TAG_RAISE) { - if (r_proc) { - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { - result = (*r_proc)(data2, errinfo); - } - POP_TAG(); - if (state && state->nd_tag == TAG_RETRY) { - state = 0; - goto retry_entry; - } + else if (state == TAG_RAISE && obj_is_kind_of(errinfo, eException)) { + if (r_proc) { + PUSH_TAG(PROT_NONE); + if ((state = EXEC_TAG()) == 0) { + result = (*r_proc)(data2, errinfo); } - else { - result = Qnil; + POP_TAG(); + if (state == TAG_RETRY) { state = 0; + goto retry_entry; } - if (state == 0) { - errat = Qnil; - } + } + else { + result = Qnil; + state = 0; + } + if (state == 0) { + errat = Qnil; } } POP_TAG(); @@ -2649,13 +2887,14 @@ rb_rescue(b_proc, data1, r_proc, data2) VALUE rb_ensure(b_proc, data1, e_proc, data2) - VALUE (*b_proc)(), (*e_proc)(); - void *data1, *data2; + VALUE (*b_proc)(); + void (*e_proc)(); + VALUE data1, data2; { - NODE *state; + int state; volatile VALUE result = Qnil; - PUSH_TAG(); + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { result = (*b_proc)(data1); } @@ -2706,20 +2945,20 @@ f_missing(argc, argv, obj) } if (desc) { if (last_call_status & CSTAT_NOEX) { - format = "private method `%s' called for %s(%s)"; + format = "private method `%s' called for %s"; } else if (iterator_p()) { - format = "undefined iterator `%s' for %s(%s)"; + format = "undefined iterator `%s' for %s"; } else if (last_call_status & CSTAT_VCALL) { char *mname = rb_id2name(id); if (('a' <= mname[0] && mname[0] <= 'z') || mname[0] == '_') { - format = "undefined local variable or method `%s' for %s(%s)"; + format = "undefined local variable or method `%s' for %s"; } } if (!format) { - format = "undefined method `%s' for %s(%s)"; + format = "undefined method `%s' for %s"; } if (RSTRING(desc)->len > 65) { desc = any_to_s(obj); @@ -2729,12 +2968,11 @@ f_missing(argc, argv, obj) sourcefile = file; sourceline = line; PUSH_FRAME(); /* fake frame */ - *the_frame = *_frame.prev->prev; + *the_frame = *_frame->prev->prev; NameError(format, rb_id2name(id), - desc?(char*)RSTRING(desc)->ptr:"", - desc?rb_class2name(CLASS_OF(obj)):""); + desc?(char*)RSTRING(desc)->ptr:""); POP_FRAME(); return Qnil; /* not reached */ @@ -2785,8 +3023,7 @@ stack_length() static VALUE rb_call(class, recv, mid, argc, argv, scope) - struct RClass *class; - VALUE recv; + VALUE class, recv; ID mid; int argc; /* OK */ VALUE *argv; /* OK */ @@ -2806,7 +3043,7 @@ rb_call(class, recv, mid, argc, argv, scope) ent = cache + EXPR1(class, mid); if (ent->mid == mid && ent->class == class) { class = ent->origin; - id = ent->mid0; + id = ent->mid0; noex = ent->noex; body = ent->method; } @@ -2833,19 +3070,19 @@ rb_call(class, recv, mid, argc, argv, scope) /* for re-scoped/renamed method */ mid = id; if (scope == 0) scope = 1; - if (class->super == 0) { + if (RCLASS(class)->super == 0) { /* origin is the Module, so need to scan superclass hierarchy. */ - struct RClass *cl = class; + struct RClass *cl = RCLASS(class); - class = (struct RClass*)RBASIC(recv)->class; + class = RBASIC(recv)->class; while (class) { - if (class->m_tbl == cl->m_tbl) + if (RCLASS(class)->m_tbl == cl->m_tbl) break; - class = class->super; + class = RCLASS(class)->super; } } else { - class = class->super; + class = RCLASS(class)->super; } goto again; } @@ -2981,8 +3218,8 @@ rb_call(class, recv, mid, argc, argv, scope) default: { - NODE *state; - VALUE *local_vars; + int state; + VALUE *local_vars; /* OK */ PUSH_SCOPE(); @@ -3000,7 +3237,7 @@ rb_call(class, recv, mid, argc, argv, scope) } b2 = body = body->nd_body; - PUSH_TAG(); + PUSH_TAG(PROT_FUNC); PUSH_VARS(); if ((state = EXEC_TAG()) == 0) { @@ -3058,11 +3295,15 @@ rb_call(class, recv, mid, argc, argv, scope) body = 0; } if (trace_func) { - call_trace_func("call", b2->file, nd_line(b2), + call_trace_func("call", b2->nd_file, nd_line(b2), recv, the_frame->last_func); } result = rb_eval(recv, body); } + else if (state == TAG_RETURN) { + result = prot_tag->tag_retval; + state = 0; + } POP_VARS(); POP_TAG(); POP_SCOPE(); @@ -3075,27 +3316,25 @@ rb_call(class, recv, mid, argc, argv, scope) } call_trace_func("return", file, line, 0, the_frame->last_func); } - if (state) { - switch (state->nd_tag) { - case TAG_NEXT: - Raise(eLocalJumpError, "unexpected next"); - break; - case TAG_BREAK: - Raise(eLocalJumpError, "unexpected break"); - break; - case TAG_REDO: - Raise(eLocalJumpError, "unexpected redo"); - break; - case TAG_RETURN: - result = state->nd_tval; - break; - case TAG_RETRY: - if (!iterator_p()) { - Raise(eLocalJumpError, "retry outside of rescue clause"); - } - default: - JUMP_TAG(state); + switch (state) { + case 0: + break; + + case TAG_NEXT: + Raise(eLocalJumpError, "unexpected next"); + break; + case TAG_BREAK: + Raise(eLocalJumpError, "unexpected break"); + break; + case TAG_REDO: + Raise(eLocalJumpError, "unexpected redo"); + break; + case TAG_RETRY: + if (!iterator_p()) { + Raise(eLocalJumpError, "retry outside of rescue clause"); } + default: + JUMP_TAG(state); } } } @@ -3107,8 +3346,8 @@ rb_call(class, recv, mid, argc, argv, scope) VALUE rb_apply(recv, mid, args) VALUE recv; - struct RArray *args; ID mid; + VALUE args; { int argc; VALUE *argv; @@ -3274,13 +3513,13 @@ rb_frame_last_func() static NODE* compile(src) - struct RString *src; + VALUE src; { NODE *node; Check_Type(src, T_STRING); - node = compile_string(sourcefile, src->ptr, src->len); + node = compile_string(sourcefile, RSTRING(src)->ptr, RSTRING(src)->len); if (nerrs == 0) return node; return 0; @@ -3288,23 +3527,21 @@ compile(src) static VALUE eval(self, src, scope) - VALUE self; - struct RString *src; - struct RData *scope; + VALUE self, src, scope; { struct BLOCK *data; volatile VALUE result = Qnil; - NODE *state; - volatile VALUE old_block; - volatile VALUE old_scope; - volatile VALUE old_d_vars; + struct SCOPE * volatile old_scope; + struct BLOCK * volatile old_block; + struct RVarmap * volatile old_d_vars; struct FRAME frame; char *file = sourcefile; int line = sourceline; volatile int iter = the_frame->iter; + int state; if (!NIL_P(scope)) { - if (TYPE(scope) != T_DATA || scope->dfree != blk_free) { + if (TYPE(scope) != T_DATA || RDATA(scope)->dfree != blk_free) { TypeError("wrong argument type %s (expected Proc/Binding)", rb_class2name(CLASS_OF(scope))); } @@ -3315,11 +3552,11 @@ eval(self, src, scope) frame = data->frame; frame.prev = the_frame; the_frame = &(frame); - old_scope = (VALUE)the_scope; + old_scope = the_scope; the_scope = data->scope; - old_block = (VALUE)the_block; + old_block = the_block; the_block = data->prev; - old_d_vars = (VALUE)the_dyna_vars; + old_d_vars = the_dyna_vars; the_dyna_vars = data->d_vars; self = data->self; @@ -3331,17 +3568,18 @@ eval(self, src, scope) } } PUSH_CLASS(); - the_class = (struct RClass*)((NODE*)the_frame->cbase)->nd_clss; + the_class = ((NODE*)the_frame->cbase)->nd_clss; rb_in_eval++; if (TYPE(the_class) == T_ICLASS) { - the_class = (struct RClass*)RBASIC(the_class)->class; + the_class = RBASIC(the_class)->class; } - PUSH_TAG(); + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { + eval_tree = 0; compile(src); if (nerrs > 0) { - compile_error("eval()"); + compile_error(0); } result = eval_node(self); } @@ -3350,22 +3588,21 @@ eval(self, src, scope) rb_in_eval--; if (!NIL_P(scope)) { the_frame = the_frame->prev; - the_scope = (struct SCOPE*)old_scope; - the_block = (struct BLOCK*)old_block; - the_dyna_vars = (struct RVarmap*)old_d_vars; + the_scope = old_scope; + the_block = old_block; + the_dyna_vars = old_d_vars; } else { the_frame->iter = iter; } if (state) { - VALUE err ; + VALUE err; - switch (state->nd_tag) { - case TAG_RAISE: + if (state == TAG_RAISE) { sourcefile = file; sourceline = line; if (strcmp(sourcefile, "(eval)") == 0) { - err = errinfo; + err = str_dup(errinfo); if (sourceline > 1) { err = RARRAY(errat)->ptr[0]; str_cat(err, ": ", 2); @@ -3396,6 +3633,48 @@ f_eval(argc, argv, self) return eval(self, src, scope); } +static VALUE +eval_under(under, self, src) + VALUE under, self, src; +{ + VALUE val; /* OK */ + int state; + VALUE cbase = the_frame->cbase; + + PUSH_CLASS(); + the_class = under; + PUSH_FRAME(); + the_frame->last_func = _frame->last_func; + the_frame->last_class = _frame->last_class; + the_frame->argc = 1; + the_frame->argv = &src; + the_frame->cbase = (VALUE)node_newnode(NODE_CREF,under,0,cbase); + PUSH_TAG(PROT_NONE); + if ((state = EXEC_TAG()) == 0) { + val = eval(self, src, Qnil); + } + POP_TAG(); + POP_FRAME(); + POP_CLASS(); + if (state) JUMP_TAG(state); + + return val; +} + +static VALUE +obj_instance_eval(self, src) + VALUE self, src; +{ + return eval_under(CLASS_OF(self), self, src); +} + +static VALUE +mod_module_eval(mod, src) + VALUE mod, src; +{ + return eval_under(mod, mod, src); +} + VALUE rb_load_path; char *dln_find_file(); @@ -3438,23 +3717,22 @@ find_file(file) VALUE f_load(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { - NODE *state; + int state; char *file; volatile ID last_func; Check_SafeStr(fname); - if (fname->ptr[0] == '~') { - fname = (struct RString*)file_s_expand_path(0, fname); + if (RSTRING(fname)->ptr[0] == '~') { + fname = file_s_expand_path(0, fname); } - file = find_file(fname->ptr); - if (!file) LoadError("No such file to load -- %s", fname->ptr); + file = find_file(RSTRING(fname)->ptr); + if (!file) LoadError("No such file to load -- %s", RSTRING(fname)->ptr); - PUSH_TAG(); + PUSH_TAG(PROT_NONE); PUSH_CLASS(); - the_class = (struct RClass*)cObject; + the_class = cObject; PUSH_SCOPE(); if (top_scope->local_tbl) { int len = top_scope->local_tbl[0]+1; @@ -3466,6 +3744,8 @@ f_load(obj, fname) the_scope->local_tbl = tbl; the_scope->local_vars = vars; } + /* default visibility is private at loading toplevel */ + FL_SET(the_scope, SCOPE_PRIVATE); state = EXEC_TAG(); last_func = the_frame->last_func; @@ -3546,27 +3826,26 @@ rb_provide(feature) VALUE f_require(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { - char *ext, *file, *feature, *buf; - volatile VALUE load; + char *ext, *file, *feature, *buf; /* OK */ + VALUE load; Check_SafeStr(fname); - if (rb_provided(fname->ptr)) + if (rb_provided(RSTRING(fname)->ptr)) return FALSE; - ext = strrchr(fname->ptr, '.'); + ext = strrchr(RSTRING(fname)->ptr, '.'); if (ext) { if (strcmp(".rb", ext) == 0) { - feature = file = fname->ptr; + feature = file = RSTRING(fname)->ptr; file = find_file(file); if (file) goto rb_load; } else if (strcmp(".o", ext) == 0) { - file = feature = fname->ptr; + file = feature = RSTRING(fname)->ptr; if (strcmp(".o", DLEXT) != 0) { - buf = ALLOCA_N(char, strlen(fname->ptr)+sizeof(DLEXT)+1); + buf = ALLOCA_N(char, strlen(file)+sizeof(DLEXT)+1); strcpy(buf, feature); ext = strrchr(buf, '.'); strcpy(ext, DLEXT); @@ -3575,33 +3854,33 @@ f_require(obj, fname) if (file) goto dyna_load; } else if (strcmp(DLEXT, ext) == 0) { - feature = fname->ptr; + feature = RSTRING(fname)->ptr; file = find_file(feature); if (file) goto dyna_load; } } - buf = ALLOCA_N(char, strlen(fname->ptr) + 5); - sprintf(buf, "%s.rb", fname->ptr); + buf = ALLOCA_N(char, strlen(RSTRING(fname)->ptr) + 5); + sprintf(buf, "%s.rb", RSTRING(fname)->ptr); file = find_file(buf); if (file) { - fname = (struct RString*)str_new2(file); + fname = str_new2(file); feature = buf; goto rb_load; } - sprintf(buf, "%s%s", fname->ptr, DLEXT); + sprintf(buf, "%s%s", RSTRING(fname)->ptr, DLEXT); file = find_file(buf); if (file) { feature = buf; goto dyna_load; } - LoadError("No such file to load -- %s", fname->ptr); + LoadError("No such file to load -- %s", RSTRING(fname)->ptr); dyna_load: #ifdef THREAD if (thread_loading(feature)) return FALSE; else { - NODE *state; - PUSH_TAG(); + int state; + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { #endif load = str_new2(file); @@ -3621,8 +3900,8 @@ f_require(obj, fname) #ifdef THREAD if (thread_loading(feature)) return FALSE; else { - NODE *state; - PUSH_TAG(); + int state; + PUSH_TAG(PROT_NONE); if ((state = EXEC_TAG()) == 0) { #endif f_load(obj, fname); @@ -3657,7 +3936,12 @@ mod_public(argc, argv, module) VALUE *argv; VALUE module; { - set_method_visibility(module, argc, argv, NOEX_PUBLIC); + if (argc == 0) { + FL_UNSET(the_scope, SCOPE_PRIVATE); + } + else { + set_method_visibility(module, argc, argv, NOEX_PUBLIC); + } return module; } @@ -3667,7 +3951,12 @@ mod_private(argc, argv, module) VALUE *argv; VALUE module; { - set_method_visibility(module, argc, argv, NOEX_PRIVATE); + if (argc == 0) { + FL_SET(the_scope, SCOPE_PRIVATE); + } + else { + set_method_visibility(module, argc, argv, NOEX_PRIVATE); + } return module; } @@ -3691,6 +3980,22 @@ mod_private_method(argc, argv, obj) return obj; } +static VALUE +top_public(argc, argv) + int argc; + VALUE *argv; +{ + return mod_public(argc, argv, cObject); +} + +static VALUE +top_private(argc, argv) + int argc; + VALUE *argv; +{ + return mod_private(argc, argv, cObject); +} + static VALUE mod_modfunc(argc, argv, module) int argc; @@ -3715,6 +4020,23 @@ mod_modfunc(argc, argv, module) return module; } +static VALUE +mod_append_features(module, include) + VALUE module, include; +{ + switch (TYPE(include)) { + case T_CLASS: + case T_MODULE: + break; + default: + Check_Type(include, T_CLASS); + break; + } + rb_include_module(include, module); + + return module; +} + static VALUE mod_include(argc, argv, module) int argc; @@ -3725,30 +4047,11 @@ mod_include(argc, argv, module) for (i=0; ilen;i++) { - if (TYPE(RARRAY(val)->ptr[i]) != T_STRING) { - TypeError(err); - } - } - } - *var = val; +VALUE f_global_variables(); +static VALUE f_catch(); +static VALUE f_throw(); + +struct end_proc_data { + void (*func)(); + VALUE data; + struct end_proc_data *next; +} *end_proc_data; + +void +rb_set_end_proc(func, data) + void (*func)(); + VALUE data; +{ + struct end_proc_data *link = ALLOC(struct end_proc_data); + + link->next = end_proc_data; + link->func = func; + link->data = data; + rb_global_variable(&link->data); + end_proc_data = link; } -static VALUE -f_catch(dmy, tag) - VALUE dmy, tag; +static void +call_end_proc(data) + VALUE data; { - NODE *state; - ID t; - VALUE val; + proc_call(data, Qnil); +} - t = rb_to_id(tag); - PUSH_TAG(); - if ((state = EXEC_TAG()) == 0) { - val = rb_yield(tag); - } - POP_TAG(); - if (state) { - if (state->nd_tag == TAG_THROW && state->nd_tlev == t) { - return state->nd_tval; - } - JUMP_TAG(state); - } - return val; +static void +f_END() +{ + PUSH_FRAME(); + rb_set_end_proc(call_end_proc, f_lambda()); + POP_FRAME(); } static VALUE -f_throw(argc, argv) - int argc; - VALUE *argv; +f_at_exit() { - VALUE tag, value; - ID t; + VALUE proc; - rb_scan_args(argc, argv, "11", &tag, &value); - t = rb_to_id(tag); - JUMP_TAG3(TAG_THROW, value, t); - /* not reached */ + proc = f_lambda(); + + rb_set_end_proc(call_end_proc, proc); + return proc; +} + +static void +exec_end_proc() +{ + struct end_proc_data *link = end_proc_data; + + while (link) { + (*link->func)(link->data); + link = link->next; + } } void @@ -3879,10 +4193,12 @@ Init_eval() aref = rb_intern("[]"); aset = rb_intern("[]="); + match = rb_intern("=~"); - rb_global_variable(&top_scope); - rb_global_variable(&eval_tree); - rb_global_variable(&the_dyna_vars); + rb_global_variable((VALUE*)&top_scope); + rb_global_variable((VALUE*)&eval_tree0); + rb_global_variable((VALUE*)&eval_tree); + rb_global_variable((VALUE*)&the_dyna_vars); rb_define_hooked_variable("$@", &errat, 0, errat_setter); rb_define_hooked_variable("$!", &errinfo, 0, rb_str_setter); @@ -3894,15 +4210,6 @@ Init_eval() rb_define_method(mKernel, "respond_to?", obj_respond_to, -1); - rb_define_global_function("break", f_break, 0); - rb_define_alias(mKernel, "break!", "break"); - rb_define_global_function("next", f_next, 0); - rb_define_alias(mKernel, "next!", "next"); - rb_define_alias(mKernel, "continue", "next"); - rb_define_global_function("redo", f_redo, 0); - rb_define_alias(mKernel, "redo!", "redo"); - rb_define_global_function("retry", f_retry, 0); - rb_define_alias(mKernel, "retry!", "retry"); rb_define_global_function("raise", f_raise, -1); rb_define_alias(mKernel, "fail", "raise"); @@ -3911,21 +4218,37 @@ Init_eval() rb_define_global_function("exit", f_exit, -1); rb_define_global_function("abort", f_abort, 0); + rb_define_global_function("at_exit", f_at_exit, 0); + rb_define_global_function("catch", f_catch, 1); rb_define_global_function("throw", f_throw, -1); + rb_define_global_function("global_variables", f_global_variables, 0); rb_define_method(mKernel, "send", f_send, -1); + rb_define_method(mKernel, "instance_eval", obj_instance_eval, 1); + rb_define_private_method(cModule, "append_features", mod_append_features, 1); + rb_define_private_method(cModule, "extend_object", mod_extend_object, 1); rb_define_private_method(cModule, "include", mod_include, -1); rb_define_private_method(cModule, "public", mod_public, -1); rb_define_private_method(cModule, "private", mod_private, -1); rb_define_private_method(cModule, "module_function", mod_modfunc, -1); rb_define_method(cModule, "method_defined?", mod_method_defined, 1); - rb_define_method(cModule, "extend_object", mod_extend_object, 1); rb_define_method(cModule, "public_class_method", mod_public_method, -1); rb_define_method(cModule, "private_class_method", mod_private_method, -1); + rb_define_method(cModule, "module_eval", mod_module_eval, 1); + + rb_define_method(cModule, "remove_method", mod_remove_method, -1); + rb_define_method(cModule, "undef_method", mod_undef_method, 1); + rb_define_method(cModule, "alias_method", mod_alias_method, 2); + + rb_define_singleton_method(cModule, "nesting", mod_nesting, 0); + rb_define_singleton_method(cModule, "constants", mod_s_constants, 0); + + rb_define_singleton_method(TopSelf, "include", top_include, -1); + rb_define_singleton_method(TopSelf, "public", top_public, -1); + rb_define_singleton_method(TopSelf, "private", top_private, -1); - rb_define_method(CLASS_OF(TopSelf), "include", top_include, -1); rb_define_method(mKernel, "extend", obj_extend, -1); rb_define_global_function("trace_var", f_trace_var, -1); @@ -4027,7 +4350,7 @@ static VALUE proc_s_new(class) VALUE class; { - VALUE proc; + volatile VALUE proc; struct BLOCK *data; if (!iterator_p() && !f_iterator_p()) { @@ -4071,19 +4394,18 @@ f_lambda() static VALUE proc_call(proc, args) - VALUE proc, args; + VALUE proc, args; /* OK */ { struct BLOCK *data; volatile VALUE result = Qnil; - NODE *state; - int tag_level; + int state; volatile int orphan; volatile int safe = safe_level; if (TYPE(args) == T_ARRAY) { switch (RARRAY(args)->len) { case 0: - args = 0; + args = Qnil; break; case 1: args = RARRAY(args)->ptr[0]; @@ -4132,7 +4454,7 @@ proc_call(proc, args) } } - PUSH_TAG(); + PUSH_TAG(PROT_NONE); state = EXEC_TAG(); if (state == 0) { result = rb_yield(args); @@ -4140,31 +4462,26 @@ proc_call(proc, args) POP_TAG(); POP_ITER(); - tag_level = the_block->level; + if (the_block->tag->dst == state) { + state &= TAG_MASK; + } POP_BLOCK(); safe_level = safe; if (state) { if (orphan) {/* orphan procedure */ - switch (state->nd_tag) { - case TAG_BREAK: /* never happen */ - case IN_BLOCK|TAG_BREAK: - if (state->nd_tlev == tag_level) - Raise(eLocalJumpError, "break from proc-closure"); + switch (state) { + case TAG_BREAK: + Raise(eLocalJumpError, "break from proc-closure"); break; case TAG_RETRY: Raise(eLocalJumpError, "retry from proc-closure"); break; - case TAG_RETURN: /* never happen */ - case IN_BLOCK|TAG_RETURN: - if (state->nd_tlev == tag_level) - Raise(eLocalJumpError, "return from proc-closure"); + case TAG_RETURN: + Raise(eLocalJumpError, "return from proc-closure"); break; } } - else if (state->nd_tlev == tag_level) { - state->nd_tag &= ~IN_BLOCK; - } JUMP_TAG(state); } return result; @@ -4241,11 +4558,11 @@ struct thread { struct FRAME *frame; struct SCOPE *scope; - struct RClass *class; struct RVarmap *dyna_vars; struct BLOCK *block; struct iter *iter; struct tag *tag; + VALUE class; VALUE trace; @@ -4358,13 +4675,13 @@ thread_free(th) static thread_t thread_check(data) - struct RData *data; + VALUE data; { - if (TYPE(data) != T_DATA || data->dfree != thread_free) { + if (TYPE(data) != T_DATA || RDATA(data)->dfree != thread_free) { TypeError("wrong argument type %s (expected Thread)", rb_class2name(CLASS_OF(data))); } - return (thread_t)data->data; + return (thread_t)RDATA(data)->data; } VALUE lastline_get(); @@ -4472,7 +4789,7 @@ thread_restore_context(th, exit) switch (ex) { case 1: - JUMP_TAG2(TAG_FATAL, INT2FIX(0)); + JUMP_TAG(TAG_FATAL); break; case 2: @@ -4540,7 +4857,7 @@ thread_deadlock() void thread_schedule() { - thread_t next; + thread_t next; /* OK */ thread_t th; thread_t curr; @@ -4564,8 +4881,6 @@ thread_schedule() END_FOREACH_FROM(curr,th); if (num_waiting_on_join) { - curr_thread->file = sourcefile; - curr_thread->line = sourceline; FOREACH_THREAD_FROM(curr,th) { if ((th->wait_for & WAIT_JOIN) && thread_dead(th->join)) { th->join = 0; @@ -4581,7 +4896,7 @@ thread_schedule() if (num_waiting_on_fd > 0 || num_waiting_on_timer > 0) { fd_set readfds; struct timeval delay_tv, *delay_ptr; - double delay, now; + double delay, now; /* OK */ int n, max; @@ -4664,6 +4979,8 @@ thread_schedule() } if (!next) { + curr_thread->file = sourcefile; + curr_thread->line = sourceline; FOREACH_THREAD_FROM(curr,th) { fprintf(stderr, "%s:%d:deadlock 0x%x: %d:%d %s\n", th->file, th->line, th->thread, th->status, @@ -4969,6 +5286,8 @@ thread_stop() return Qnil; } +struct timeval time_timeval(); + void thread_sleep(sec) int sec; @@ -5111,7 +5430,7 @@ thread_create(fn, arg) void *arg; { thread_t th = thread_alloc(); - NODE *state; + int state; #if defined(HAVE_SETITIMER) && !defined(__BOW__) static init = 0; @@ -5139,7 +5458,7 @@ thread_create(fn, arg) return th->thread; } - PUSH_TAG(); + PUSH_TAG(PROT_THREAD); if ((state = EXEC_TAG()) == 0) { thread_save_context(th); if (setjmp(th->context) == 0) { @@ -5148,47 +5467,34 @@ thread_create(fn, arg) } } POP_TAG(); - if (state) { - if (state->nd_tag == TAG_THROW) { - char *mesg; - char *tag = rb_id2name(state->nd_tlev); - - mesg = ALLOCA_N(char, strlen(tag) + 64); - - sprintf(mesg, "uncaught throw `%s' in thread 0x%x\n", - tag, th->thread); - curr_thread->errinfo = exc_new2(eThreadError, mesg); - curr_thread->errat = make_backtrace(); - } - else if (th->status != THREAD_TO_KILL && !NIL_P(errinfo)) { - if (state->nd_tag == TAG_FATAL || - obj_is_kind_of(errinfo, eSystemExit)) { - /* fatal error or global exit within this thread */ - /* need to stop whole script */ - main_thread->errat = errat; - main_thread->errinfo = errinfo; - thread_cleanup(); - } - else if (thread_abort || curr_thread->abort) { - f_abort(); - } - else { - curr_thread->errat = errat; - curr_thread->errinfo = errinfo; - } + if (state && th->status != THREAD_TO_KILL && !NIL_P(errinfo)) { + if (state == TAG_FATAL || obj_is_kind_of(errinfo, eSystemExit)) { + /* fatal error or global exit within this thread */ + /* need to stop whole script */ + main_thread->errat = errat; + main_thread->errinfo = errinfo; + thread_cleanup(); + } + else if (thread_abort || curr_thread->abort || RTEST(debug)) { + f_abort(); + } + else { + curr_thread->errat = errat; + curr_thread->errinfo = errinfo; } } thread_remove(); return 0; } -static void +static VALUE thread_yield(arg, th) int arg; thread_t th; { scope_dup(the_block->scope); rb_yield(th->thread); + return th->thread; } static VALUE @@ -5400,3 +5706,83 @@ Init_Thread() main_thread = thread_alloc(); } #endif + +static VALUE +f_catch(dmy, tag) + VALUE dmy, tag; +{ + int state; + ID t; + VALUE val; /* OK */ + + t = rb_to_id(tag); + PUSH_TAG(t); + if ((state = EXEC_TAG()) == 0) { + val = rb_yield(tag); + } + else if (state == TAG_THROW && prot_tag->tag == prot_tag->dst) { + val = prot_tag->tag_retval; + state = 0; + } + POP_TAG(); + if (state) JUMP_TAG(state); + + return val; +} + +static VALUE +f_throw(argc, argv) + int argc; + VALUE *argv; +{ + VALUE tag, value; + ID t; + struct tag *tt = prot_tag; + + rb_scan_args(argc, argv, "11", &tag, &value); + t = rb_to_id(tag); + + while (tt) { + if (tt->tag == t) { + tt->dst = t; + tt->tag_retval = value; + break; + } +#ifdef THREAD + if (tt->tag == PROT_THREAD) { + Raise(eThreadError, "uncaught throw `%s' in thread 0x%x\n", + rb_id2name(t), + curr_thread); + } +#endif + tt = tt->prev; + } + + if (!tt) { + NameError("uncaught throw `%s'\n", rb_id2name(t)); + } + JUMP_TAG(TAG_THROW); + /* not reached */ +} + +static void +return_value(val) + VALUE val; +{ + struct tag *tt = prot_tag; + + while (tt) { + if (tt->tag == PROT_FUNC) { + tt->tag_retval = val; + break; + } +#ifdef THREAD + if (tt->tag == PROT_THREAD) { + Raise(eThreadError, "return from within thread 0x%x\n", + curr_thread); + } +#endif + tt = tt->prev; + } +} + diff --git a/ext/Setup b/ext/Setup index a5dd7978c3..c92ac53e00 100644 --- a/ext/Setup +++ b/ext/Setup @@ -6,7 +6,7 @@ #etc #fcntl #kconv -#marshal #md5 #socket #tkutil +#tcltklib diff --git a/ext/curses/curses.c b/ext/curses/curses.c index 6e8e49684f..3ae8db192d 100644 --- a/ext/curses/curses.c +++ b/ext/curses/curses.c @@ -32,7 +32,8 @@ struct windata { WINDOW *window; }; -#define NUM2CHAR(x) (char)NUM2INT(x) +#define NUM2CHAR(x) ((TYPE(x) == T_STRING)&&(RSTRING(x)->len>=1))?\ + RSTRING(x)->ptr[0]:(char)NUM2INT(x) #define CHAR2FIX(x) INT2FIX((int)x) static void @@ -46,13 +47,7 @@ no_window() if (winp->window == 0) no_window();\ } -static void -curses_err() -{ - Fail("curses error"); -} - -#define CHECK(c) if ((c)==ERR) {curses_err();} +#define CHECK(c) c static void free_window(winp) @@ -99,7 +94,7 @@ curses_init_screen() static VALUE curses_stdscr() { - if (!rb_stdscr) curses_init_screen(); + if (rb_stdscr == 0) curses_init_screen(); return rb_stdscr; } @@ -107,7 +102,7 @@ curses_stdscr() static VALUE curses_close_screen() { - CHECK(endwin()); + endwin(); return Qnil; } @@ -139,7 +134,7 @@ static VALUE curses_refresh(obj) VALUE obj; { - CHECK(refresh()); + refresh(); return Qnil; } @@ -148,7 +143,7 @@ static VALUE curses_doupdate(obj) VALUE obj; { - CHECK(doupdate()); + doupdate(); return Qnil; } @@ -157,7 +152,7 @@ static VALUE curses_echo(obj) VALUE obj; { - CHECK(echo()); + echo(); return Qnil; } @@ -166,7 +161,7 @@ static VALUE curses_noecho(obj) VALUE obj; { - CHECK(noecho()); + noecho(); return Qnil; } @@ -175,7 +170,7 @@ static VALUE curses_raw(obj) VALUE obj; { - CHECK(raw()); + raw(); return Qnil; } @@ -184,7 +179,7 @@ static VALUE curses_noraw(obj) VALUE obj; { - CHECK(noraw()); + noraw(); return Qnil; } @@ -193,7 +188,7 @@ static VALUE curses_cbreak(obj) VALUE obj; { - CHECK(cbreak()); + cbreak(); return Qnil; } @@ -202,7 +197,7 @@ static VALUE curses_nocbreak(obj) VALUE obj; { - CHECK(nocbreak()); + nocbreak(); return Qnil; } @@ -211,7 +206,7 @@ static VALUE curses_nl(obj) VALUE obj; { - CHECK(nl()); + nl(); return Qnil; } @@ -220,7 +215,7 @@ static VALUE curses_nonl(obj) VALUE obj; { - CHECK(nonl()); + nonl(); return Qnil; } @@ -251,7 +246,7 @@ curses_ungetch(obj, ch) VALUE ch; { #ifdef HAVE_UNGETCH - CHECK(ungetch(NUM2INT(ch))); + ungetch(NUM2INT(ch)); #else rb_notimplement(); #endif @@ -265,7 +260,7 @@ curses_setpos(obj, y, x) VALUE y; VALUE x; { - CHECK(move(NUM2INT(y), NUM2INT(x))); + move(NUM2INT(y), NUM2INT(x)); return Qnil; } @@ -301,7 +296,7 @@ curses_addch(obj, ch) VALUE obj; VALUE ch; { - CHECK(addch(NUM2CHAR(ch))); + addch(NUM2CHAR(ch)); return Qnil; } @@ -311,7 +306,7 @@ curses_insch(obj, ch) VALUE obj; VALUE ch; { - CHECK(insch(NUM2CHAR(ch))); + insch(NUM2CHAR(ch)); return Qnil; } @@ -339,7 +334,7 @@ curses_getstr(obj) VALUE obj; { char rtn[1024]; /* This should be big enough.. I hope */ - CHECK(getstr(rtn)); + getstr(rtn); return str_taint(str_new2(rtn)); } @@ -348,7 +343,7 @@ static VALUE curses_delch(obj) VALUE obj; { - CHECK(delch()); + delch(); return Qnil; } @@ -357,7 +352,7 @@ static VALUE curses_deleteln(obj) VALUE obj; { - CHECK(deleteln()); + deleteln(); return Qnil; } @@ -443,7 +438,7 @@ window_refresh(obj) struct windata *winp; GetWINDOW(obj, winp); - CHECK(wrefresh(winp->window)); + wrefresh(winp->window); return Qnil; } @@ -474,7 +469,7 @@ window_move(obj, y, x) struct windata *winp; GetWINDOW(obj, winp); - CHECK(mvwin(winp->window, NUM2INT(y), NUM2INT(x))); + mvwin(winp->window, NUM2INT(y), NUM2INT(x)); return Qnil; } @@ -489,7 +484,7 @@ window_setpos(obj, y, x) struct windata *winp; GetWINDOW(obj, winp); - CHECK(wmove(winp->window, NUM2INT(y), NUM2INT(x))); + wmove(winp->window, NUM2INT(y), NUM2INT(x)); return Qnil; } @@ -639,7 +634,7 @@ window_addch(obj, ch) struct windata *winp; GetWINDOW(obj, winp); - CHECK(waddch(winp->window, NUM2CHAR(ch))); + waddch(winp->window, NUM2CHAR(ch)); return Qnil; } @@ -653,7 +648,7 @@ window_insch(obj, ch) struct windata *winp; GetWINDOW(obj, winp); - CHECK(winsch(winp->window, NUM2CHAR(ch))); + winsch(winp->window, NUM2CHAR(ch)); return Qnil; } @@ -667,7 +662,7 @@ window_addstr(obj, str) struct windata *winp; GetWINDOW(obj, winp); - CHECK(waddstr(winp->window, RSTRING(str)->ptr)); + waddstr(winp->window, RSTRING(str)->ptr); return Qnil; } @@ -702,7 +697,7 @@ window_getstr(obj) char rtn[1024]; /* This should be big enough.. I hope */ GetWINDOW(obj, winp); - CHECK(wgetstr(winp->window, rtn)); + wgetstr(winp->window, rtn); return str_taint(str_new2(rtn)); } @@ -714,7 +709,7 @@ window_delch(obj) struct windata *winp; GetWINDOW(obj, winp); - CHECK(wdelch(winp->window)); + wdelch(winp->window); return Qnil; } @@ -726,7 +721,7 @@ window_deleteln(obj) struct windata *winp; GetWINDOW(obj, winp); - CHECK(wdeleteln(winp->window)); + wdeleteln(winp->window); return Qnil; } diff --git a/ext/dbm/dbm.c b/ext/dbm/dbm.c index ea0ac1930f..b416802241 100644 --- a/ext/dbm/dbm.c +++ b/ext/dbm/dbm.c @@ -122,17 +122,15 @@ fdbm_fetch(obj, keystr) } static VALUE -fdbm_indexes(obj, args) - VALUE obj; - struct RArray *args; +fdbm_indexes(obj, ag) + VALUE obj, ag; { VALUE *p, *pend; VALUE new; int i = 0; + struct RArray *args = RARRAY(rb_Array(ag)); - args = (struct RArray*)rb_to_a(args); new = ary_new2(args->len); - p = args->ptr; pend = p + args->len; while (p < pend) { ary_push(new, fdbm_fetch(obj, *p++)); diff --git a/ext/dbm/depend b/ext/dbm/depend index 40139962a7..d7f1f419d4 100644 --- a/ext/dbm/depend +++ b/ext/dbm/depend @@ -1 +1 @@ -dbm.o: dbm.c ../../ruby.h ../../config.h ../../defines.h +dbm.o: dbm.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h diff --git a/ext/etc/depend b/ext/etc/depend index 5c95ef117a..fb3318a0c6 100644 --- a/ext/etc/depend +++ b/ext/etc/depend @@ -1 +1 @@ -etc.o : etc.c ../../ruby.h ../../config.h ../../defines.h +etc.o : etc.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h diff --git a/ext/extmk.rb.in b/ext/extmk.rb.in index 78fe3070a2..e1d318d19c 100644 --- a/ext/extmk.rb.in +++ b/ext/extmk.rb.in @@ -1,5 +1,7 @@ #! /usr/local/bin/ruby +$".push 'mkmf.rb' + if ARGV[0] == 'static' $force_static = TRUE ARGV.shift @@ -21,16 +23,17 @@ $topdir = "@top_srcdir@" if $topdir !~ "^/" # get absolute path save = Dir.pwd - Dir.chdir ".." + Dir.chdir $topdir $topdir = Dir.pwd Dir.chdir save end +$dots = if "@INSTALL@" =~ /^\// then "" else "#{$topdir}/ext/" end if File.exist?("config.cache") then f = open("config.cache", "r") while f.gets case $_ - when /^lib: ([\w_]+) (yes|no)/ + when /^lib: (.+) (yes|no)/ $lib_cache[$1] = $2 when /^func: ([\w_]+) (yes|no)/ $func_cache[$1] = $2 @@ -215,6 +218,8 @@ SHELL = /bin/sh srcdir = #{$srcdir} VPATH = #{$srcdir} +hdrdir = #{$topdir} + CC = @CC@ CFLAGS = %s -I#{$topdir} %s #$CFLAGS %s @@ -233,20 +238,22 @@ libdir = @libdir@/$(RUBY_INSTALL_NAME)/@arch@ @SET_MAKE@ #### End of system configuration section. #### + " mfile.printf "LOCAL_LIBS = %s\n", $local_libs if $local_libs mfile.printf "LIBS = %s\n", $libs mfile.printf "OBJS = " if !$objs then - $objs = Dir["#{$topdir}/ext/#{target}/*.c"] - for f in $objs - f.sub!(/\.c$/, ".o") + $objs = [] + for f in Dir["#{$topdir}/ext/#{target}/*.{c,cc}"] + f = File.basename(f) + f.sub!(/\.(c|cc)$/, ".o") + $objs.push f end end mfile.printf $objs.join(" ") mfile.printf "\n" - dots = if "@INSTALL@" =~ /^\// then "" else "#{$topdir}/ext/" end mfile.printf "\ TARGET = %s.%s @@ -262,28 +269,29 @@ clean:; @rm -f *.o *.so *.sl realclean: clean ", target, - if $static then "o" else "@DLEXT@" end, dots + if $static then "o" else "@DLEXT@" end, $dots - if !$static - mfile.printf "\ + mfile.printf "\ install: +" + if !$static + mfile.printf " @test -d $(libdir) || mkdir $(libdir) $(INSTALL) $(TARGET) $(libdir)/$(TARGET) -" - else - mfile.printf "\ - -install:; " end + for rb in Dir["lib/*.rb"] + mfile.printf "\t$(INSTALL) %s @libdir@/$(RUBY_INSTALL_NAME)\n", rb + end + mfile.printf "\n" if !$static && "@DLEXT@" != "o" mfile.printf "\ $(TARGET): $(OBJS) $(LDSHARED) $(DLDFLAGS) -o $(TARGET) $(OBJS) $(LOCAL_LIBS) $(LIBS) " - elsif not File.exist?(target + ".c") + elsif not File.exist?(target + ".c") and not File.exist?(target + ".cc") if PLATFORM == "m68k-human" mfile.printf "\ $(TARGET): $(OBJS) @@ -316,9 +324,6 @@ $(TARGET): $(OBJS) dfile.close end mfile.close - if $static - $extlist.push [$static,target] - end end def extmake(target) @@ -343,16 +348,19 @@ def extmake(target) !File.exist?("./Makefile") || older("./Makefile", "#{$topdir}/ext/@setup@") || older("./Makefile", "../extmk.rb") || - older("./Makefile", "./extconf.rb") + older("./Makefile", "#{$topdir}/ext/#{target}/extconf.rb") then $defs = [] - if File.exist?("extconf.rb") - load "extconf.rb" + if File.exist?("#{$topdir}/ext/#{target}/extconf.rb") + load "#{$topdir}/ext/#{target}/extconf.rb" else create_makefile(target); end end if File.exist?("./Makefile") + if $static + $extlist.push [$static,target] + end if $install system "make install" elsif $clean @@ -373,19 +381,22 @@ end # get static-link modules $static_ext = {} -if File.file? "#{$topdir}/ext/@setup@" - f = open("#{$topdir}/ext/@setup@") - while f.gets() - $_.chop! - sub!(/#.*$/, '') - next if /^\s*$/ - if /^option +nodynamic/ - $nodynamic = TRUE - next +for setup in ["@setup@", "#{$topdir}/ext/@setup@"] + if File.file? setup + f = open(setup) + while f.gets() + $_.chop! + sub!(/#.*$/, '') + next if /^\s*$/ + if /^option +nodynamic/ + $nodynamic = TRUE + next + end + $static_ext[$_.split[0]] = TRUE end - $static_ext[$_.split[0]] = TRUE + f.close + break end - f.close end for d in Dir["#{$topdir}/ext/*"] @@ -418,6 +429,7 @@ if $cache_mod end exit if $install or $clean +$extinit += "" if $extlist.size > 0 for s,t in $extlist f = format("%s/%s.o", s, t) diff --git a/ext/extmk.rb.nt b/ext/extmk.rb.nt index 04b9e4071d..6792f2717b 100644 --- a/ext/extmk.rb.nt +++ b/ext/extmk.rb.nt @@ -18,7 +18,8 @@ $lib_cache = {} $func_cache = {} $hdr_cache = {} -$dllopt = '-MD' +#$dllopt = '-MD' +$dllopt = '' if File.exist?("config.cache") then f = open("config.cache", "r") @@ -48,11 +49,15 @@ def older(file1, file2) return FALSE end -LINK = "cl -o conftest -I../.. -Zi -O -I. %s %s conftest.c %s > nul" -CPP = "cl -E -I../.. -I../../missing -I. -Zi -O %s conftest.c > nul" +#LINK = "cl -o conftest.exe -I../.. -Zi -O -I. %s conftest.c %s > nul" +LINK = "cl -o conftest.exe -Zi -O %s conftest.c %s > nul" +CPP = "cl -E -I../.. -I../../missing -I../../win32 -I. -Zi -O %s conftest.c > nul" def try_link(libs) - system(format(LINK, $CFLAGS, $LDFLAGS, libs)) + #print(format("try #{LINK}", $CFLAGS, $LDFLAGS, libs)) + #system(format(LINK, $CFLAGS, $LDFLAGS, libs)) + print(format("try #{LINK}\n", $CFLAGS, libs)) + system(format(LINK, $CFLAGS, libs)) end def try_cpp @@ -60,12 +65,13 @@ def try_cpp end def have_library(lib, func) + #print format("have_library(%s, %s)\n", lib, func) if $lib_cache[lib] if $lib_cache[lib] == "yes" - if $libs - $libs = "-l" + lib + " " + $libs + if $libs# + $libs = lib + ".lib " + $libs else - $libs = "-l" + lib + $libs = lib + ".lib " end return TRUE else @@ -75,6 +81,8 @@ def have_library(lib, func) cfile = open("conftest.c", "w") cfile.printf "\ +#include +#include int main() { return 0; } int t() { %s(); return 0; } ", func @@ -86,7 +94,9 @@ int t() { %s(); return 0; } else libs = lib + ".lib" end + #print "libs=#{libs}\n" unless try_link(libs) + #print "fail : #{libs}\n" $lib_cache[lib] = 'no' $cache_mod = TRUE return FALSE @@ -113,7 +123,9 @@ def have_func(func) cfile = open("conftest.c", "w") cfile.printf "\ -char %s(); +#include +#include +//char %s(); int main() { return 0; } int t() { %s(); return 0; } ", func, func @@ -123,6 +135,7 @@ int t() { %s(); return 0; } libs = "" if libs == nil begin + #print "libs=#{libs}\n" unless try_link(libs) $func_cache[func] = 'no' $cache_mod = TRUE @@ -186,7 +199,7 @@ def create_makefile(target) if $libs and "obj" == "obj" libs = $libs.split for lib in libs - lib.sub!(/(.*)/, '"lib\1.lib"') + lib.sub!(/(.*)/, '"\1.lib"') if /.lib$/ !~ lib end $defs.push(format("-DEXTLIB='%s'", libs.join(","))) end @@ -203,7 +216,7 @@ VPATH = . CC = cl -CFLAGS = %s -I../.. -I../../missing -I. -O -DNT %s #$CFLAGS %s +CFLAGS = %s -I../.. -I../../missing -I../../win32 -I. -O -DNT %s #$CFLAGS %s RUBYLIB = ../../ruby.lib DLDFLAGS = /DLL @@ -211,9 +224,9 @@ LDSHARED = ", if $static then "" else "-fpic" end, $dllopt, $defs.join(" ") if $force_static - print "static\n" + print "static\n" else - print "non static\n" + print "non static\n" end mfile.printf "\ @@ -245,7 +258,7 @@ DEFFILE = %s.def all: $(TARGET) -clean:; @rm -f *.obj *.lib *.exp *.pdb *.bak +clean:; @rm -f *.obj *.lib *.exp vc*.pdb *.bak *.def @rm -f Makefile extconf.h conftest.* realclean: clean @@ -274,8 +287,8 @@ $(TARGET): $(OBJS) lib /OUT:$(TARGET) $(OBJS) " else - mfile.printf "\ -$(DEFFILE): + mfile.printf "\ +$(DEFFILE): echo $(DEFFILE) $(TARGET): $(OBJS) $(DEFFILE) @@ -293,11 +306,28 @@ $(TARGET): $(OBJS) $(DEFFILE) end mfile.close if $static - printf format("push %s,%s\n", $static, target); ##debug print## + #printf format("push %s,%s\n", $static, target); ##debug print## $extlist.push [$static,target] end end +#template of .def file. +def create_def(basename) + defname = sprintf("%s.def", basename) + f = open(defname, "w") + f.printf "\ +LIBRARY %s.dll +CODE LOADONCALL +DATA LOADONCALL +DESCRIPTION 'win32 %s.dll' +EXPORTS + + Init_%s +", basename, basename, basename + f.close + +end + def extmake(target) if $force_static or $static_ext[target] $static = target @@ -328,6 +358,11 @@ def extmake(target) create_makefile(target); end end + + if !File.exist?("#{target}.def") + create_def(target) + end + if File.exist?("./Makefile") if $install system "nmake install" @@ -339,10 +374,12 @@ def extmake(target) elsif $clean system "nmake clean" else + #print "!!!make!!!\n" system "nmake all" end end if $static + #$extlibs = " " $extlibs += " " + $LDFLAGS if $LDFLAGS $extlibs += " " + $local_libs if $local_libs $extlibs += " " + $libs if $libs @@ -360,7 +397,8 @@ if File.file? "./Setup" $_.chop! sub!(/#.*$/, '') next if /^\s*$/ - print $_, "\n" + #print $_, "\n" + if /^option +nodynamic/ $nodynamic = TRUE next @@ -401,20 +439,19 @@ end exit if $install or $clean if $extlist.size > 0 - #for s,t in $extlist - for s,t in $static_ext + for s,t in $extlist + #for s,t in $static_ext #f = format("%s/%s.obj", s, t) #f = format("%s/%s.obj", s, s) - l = format("%s/%s.lib", s, s) - #print format("%s/%s.obj\n", s, s) ##debug print## + l = format("%s/%s.lib", s, s) if File.exist?(l) $extinit += format("\ \tInit_%s();\n\ \trb_provide(\"%s.o\");\n\ ", s, s) $extobjs += "ext/" - #$extobjs += f # *.obj - $extobjs += l # *.lib + #$extobjs += f # *.obj + $extobjs += l # *.lib $extobjs += " " else FALSE @@ -441,7 +478,12 @@ if $extlist.size > 0 end $extobjs = "ext/extinit.obj " + $extobjs - $extlibs = "" + #$extlibs = "" + #print "EXTLIBS=#{$extlibs}\n" + $extlibs.gsub!("-L/usr/local/lib", "") if $extlibs + $extlibs.gsub!(" +", " ") if $extlibs + #print "EXTLIBS=#{$extlibs}\n" + system format('nmake ruby.exe EXTOBJS="%s" EXTLIBS="%s"', $extobjs, $extlibs) else Dir.chdir ".." @@ -450,31 +492,6 @@ else `cp miniruby.exe ruby.exe` end end - -#template of .def file. -#LIBRARY kconv.dll -#CODE LOADONCALL -#DATA LOADONCALL -#DESCRIPTION 'win32 kconv.dll' -#EXPORTS -# -# Init_kconv -def makedef(basename) - defname = sprintf("%s.def", basename) - f = open(defname, "w") - f.printf "\ -LIBRARY %s.dll -CODE LOADONCALL -DATA LOADONCALL -DESCRIPTION 'win32 %s.dll' -EXPORTS - - Init_%s -", basename, basename - f.close - -end - #Local variables: # mode: ruby #end: diff --git a/ext/fcntl/depend b/ext/fcntl/depend index 3c7ef8485e..a7915c7d92 100644 --- a/ext/fcntl/depend +++ b/ext/fcntl/depend @@ -1 +1 @@ -fcntl.o: fcntl.c ../../ruby.h ../../config.h ../../defines.h +fcntl.o: fcntl.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h diff --git a/ext/kconv/depend b/ext/kconv/depend index e87b1fdea7..8f09d95130 100644 --- a/ext/kconv/depend +++ b/ext/kconv/depend @@ -1 +1 @@ -kconv.o: kconv.c ../../ruby.h ../../config.h ../../defines.h +kconv.o: kconv.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h diff --git a/ext/kconv/kconv.c b/ext/kconv/kconv.c index 3c59cb6acf..6778afcfe6 100644 --- a/ext/kconv/kconv.c +++ b/ext/kconv/kconv.c @@ -88,6 +88,9 @@ static char *Patchlevel = #define _JIS 1 #define _EUC 2 #define _SJIS 3 +#define _BINARY 4 +#define _NOCONV 4 +#define _UNKNOWN _AUTO #if (defined(__TURBOC__) || defined(LSI_C)) && !defined(MSDOS) #define MSDOS @@ -596,7 +599,7 @@ do_kconv(i, o, siz, out_code, in_code) outptr = o; /* output buffer */ outsiz = siz; /* output buffer size */ outlen = 0; /* current length of output string */ - x0201_f = FALSE; /* don't assume JISX0201 kana */ + x0201_f = TRUE; /* don't assume JISX0201 kana */ rot_f = FALSE; /* rot14/43 mode */ input_f = FALSE; /* non fixed input code */ alpha_f = FALSE; /* convert JISX0208 alphbet to ASCII */ @@ -1774,7 +1777,7 @@ kconv_kconv(argc, argv) int argc; VALUE *argv; { - struct RString *src, *dst; + VALUE src, dst; VALUE in, out; int in_code, out_code; @@ -1786,63 +1789,134 @@ kconv_kconv(argc, argv) } else { out_code = NUM2INT(out); + if (out_code == _NOCONV) return (VALUE)src; } if (NIL_P(in)) { in_code = _AUTO; } else { in_code = NUM2INT(in); + if (in_code == _NOCONV) return (VALUE)src; } - dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */ - dst->len = do_kconv(src->ptr, dst->ptr, dst->len, out_code, in_code); + dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */ + RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, out_code, in_code); - return (VALUE)dst; + return dst; } static VALUE kconv_tojis(obj, src) - VALUE obj; - struct RString *src; + VALUE obj, src; { - struct RString *dst; + VALUE dst; Check_Type(src, T_STRING); - dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */ - dst->len = do_kconv(src->ptr, dst->ptr, dst->len, _JIS, _AUTO); + dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */ + RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _JIS, _AUTO); - return (VALUE)dst; + return dst; } static VALUE kconv_toeuc(obj, src) - VALUE obj; - struct RString* src; + VALUE obj, src; { - struct RString *dst; + VALUE dst; Check_Type(src, T_STRING); - dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */ - dst->len = do_kconv(src->ptr, dst->ptr, dst->len, _EUC, _AUTO); + dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */ + RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _EUC, _AUTO); return (VALUE)dst; } static VALUE kconv_tosjis(obj, src) - VALUE obj; - struct RString* src; + VALUE obj, src; { - struct RString *dst; + VALUE dst; Check_Type(src, T_STRING); - dst = RSTRING(str_new(0, src->len*3+10)); /* large enough? */ - dst->len = do_kconv(src->ptr, dst->ptr, dst->len, _SJIS, _AUTO); + dst = str_new(0, RSTRING(src)->len*3+10); /* large enough? */ + RSTRING(dst)->len = do_kconv(RSTRING(src)->ptr, RSTRING(dst)->ptr, RSTRING(dst)->len, _SJIS, _AUTO); - return (VALUE)dst; + return dst; +} + +/* + * Character code detection - Algorithm described in: + * Ken Lunde. `Understanding Japanese Information Processing' + * Sebastopol, CA: O'Reilly & Associates. + */ + +static VALUE +kconv_guess(obj, src) + VALUE obj, src; +{ + unsigned char *p = RSTRING(src)->ptr; + unsigned char *pend = p + RSTRING(src)->len; + +#define INCR {p++;if (p==pend) return INT2FIX(_UNKNOWN);} + + while (p= 0x40) { + if (*p >= 0x81) { + if (0x8d <= *p || (0x8f <= *p && *p <= 0x9f)) { + return INT2FIX(_SJIS); + } + else if (0xfd <= *p && *p <= 0xfe) { + return INT2FIX(_EUC); + } + } + } + } + if (*p <= 0x9f) { + return INT2FIX(_SJIS); + } + } + if (0xf0 <= *p && *p <= 0xfe) { + return INT2FIX(_EUC); + } + if (0xe0 <= *p && *p <= 0xef) { + INCR; + if ((0x40 <= *p && *p <= 0x7e) || + (0x80 <= *p && *p <= 0xa0)) { + return INT2FIX(_SJIS); + } + if (0xfd <= *p && *p <= 0xfe) { + return INT2FIX(_EUC); + } + } + p++; + } + return INT2FIX(_UNKNOWN); } void @@ -1854,11 +1928,15 @@ Init_kconv() rb_define_module_function(mKconv, "tojis", kconv_tojis, 1); rb_define_module_function(mKconv, "toeuc", kconv_toeuc, 1); rb_define_module_function(mKconv, "tosjis", kconv_tosjis, 1); + rb_define_module_function(mKconv, "guess", kconv_guess, 1); rb_define_const(mKconv, "AUTO", INT2FIX(_AUTO)); rb_define_const(mKconv, "JIS", INT2FIX(_JIS)); rb_define_const(mKconv, "EUC", INT2FIX(_EUC)); rb_define_const(mKconv, "SJIS", INT2FIX(_SJIS)); + rb_define_const(mKconv, "BINARY", INT2FIX(_BINARY)); + rb_define_const(mKconv, "NOCONV", INT2FIX(_NOCONV)); + rb_define_const(mKconv, "UNKNOWN", INT2FIX(_UNKNOWN)); } /** diff --git a/ext/md5/depend b/ext/md5/depend index be56da89b9..abb2a47419 100644 --- a/ext/md5/depend +++ b/ext/md5/depend @@ -1,2 +1,2 @@ md5c.o: md5c.c md5.h -md5init.o: md5init.c ../../ruby.h ../../config.h ../../defines.h md5.h +md5init.o: md5init.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h md5.h diff --git a/ext/socket/depend b/ext/socket/depend index e6ede5a411..3d54fa073c 100644 --- a/ext/socket/depend +++ b/ext/socket/depend @@ -1 +1 @@ -socket.o : socket.c ../../ruby.h ../../config.h ../../defines.h ../../io.h ../../sig.h +socket.o : socket.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h $(hdrdir)/io.h $(hdrdir)/sig.h diff --git a/ext/socket/extconf.rb b/ext/socket/extconf.rb index bbde1a0c35..f719723864 100644 --- a/ext/socket/extconf.rb +++ b/ext/socket/extconf.rb @@ -1,9 +1,18 @@ $LDFLAGS = "-L/usr/local/lib" -have_library("wsock32", "cygwin32_socket") or have_library("socket", "socket") -have_library("inet", "gethostbyname") -have_library("nsl", "gethostbyname") +case PLATFORM +when /mswin32/ + test_func = "WSACleanup" + have_library("wsock32", "WSACleanup") +when /cygwin32/ + test_func = "cygwin32_socket" +else + test_func = "socket" + have_library("socket", "socket") + have_library("inet", "gethostbyname") + have_library("nsl", "gethostbyname") +end have_header("sys/un.h") -if have_func("socket") or have_func("cygwin32_socket") +if have_func(test_func) have_func("hsterror") unless have_func("gethostname") have_func("uname") diff --git a/ext/socket/socket.c b/ext/socket/socket.c index 9128e26de7..f5d191b056 100644 --- a/ext/socket/socket.c +++ b/ext/socket/socket.c @@ -12,9 +12,11 @@ #include "io.h" #include #include +#ifndef NT #include #include #include +#endif #include #ifdef HAVE_SYS_UN_H #include @@ -36,8 +38,10 @@ extern VALUE cIO; extern VALUE cInteger; VALUE cBasicSocket; +VALUE cIPsocket; VALUE cTCPsocket; VALUE cTCPserver; +VALUE cUDPsocket; #ifdef AF_UNIX VALUE cUNIXsocket; VALUE cUNIXserver; @@ -85,8 +89,6 @@ sock_new(class, fd) fp->f = rb_fdopen(fd, "r"); #ifdef NT fp->finalize = sock_finalize; -#else - setbuf(fp->f, NULL); #endif fp->f2 = rb_fdopen(fd, "w"); fp->mode = FMODE_READWRITE; @@ -254,24 +256,29 @@ bsock_send(argc, argv, sock) return INT2FIX(n); } -static VALUE tcpaddr _((struct sockaddr_in*)); +static VALUE ipaddr _((struct sockaddr_in*)); #ifdef HAVE_SYS_UN_H static VALUE unixaddr _((struct sockaddr_un*)); #endif +enum sock_recv_type { + RECV_RECV, /* BasicSocket#recv(no from) */ + RECV_TCP, /* TCPsocket#recvfrom */ + RECV_UDP, /* UDPsocket#recvfrom */ + RECV_UNIX, /* UNIXsocket#recvfrom */ + RECV_SOCKET, /* Socket#recvfrom */ +}; + static VALUE s_recv(sock, argc, argv, from) VALUE sock; int argc; VALUE *argv; - int from; /* 0 - recv, - 1 - TCPsocket#recvfrom, - 2 - UNIXsocket#recvfrom, - 3 - Socket#recvfrom */ + enum sock_recv_type from; { OpenFile *fptr; FILE f; - struct RString *str; + VALUE str; char buf[1024]; int fd, alen = sizeof buf; VALUE len, flg; @@ -282,7 +289,7 @@ s_recv(sock, argc, argv, from) if (flg == Qnil) flags = 0; else flags = NUM2INT(flg); - str = (struct RString*)str_new(0, NUM2INT(len)); + str = str_new(0, NUM2INT(len)); GetOpenFile(sock, fptr); fd = fileno(fptr->f); @@ -291,11 +298,11 @@ s_recv(sock, argc, argv, from) #endif TRAP_BEG; retry: - str->len = recvfrom(fd, str->ptr, str->len, flags, - (struct sockaddr*)buf, &alen); + RSTRING(str)->len = recvfrom(fd, RSTRING(str)->ptr, RSTRING(str)->len, flags, + (struct sockaddr*)buf, &alen); TRAP_END; - if (str->len < 0) { + if (RSTRING(str)->len < 0) { switch (errno) { case EINTR: case EWOULDBLOCK: @@ -311,21 +318,28 @@ s_recv(sock, argc, argv, from) } str_taint(str); switch (from) { - case 0: + case RECV_RECV: return (VALUE)str; - case 1: + case RECV_TCP: if (alen != sizeof(struct sockaddr_in)) { TypeError("sockaddr size differs - should not happen"); } - return assoc_new(str, tcpaddr((struct sockaddr_in *)buf)); + return assoc_new(str, ipaddr((struct sockaddr_in *)buf)); + case RECV_UDP: + { + VALUE addr = ipaddr((struct sockaddr_in *)buf); + + return assoc_new(str, assoc_new(RARRAY(addr)->ptr[2], + RARRAY(addr)->ptr[1])); + } #ifdef HAVE_SYS_UN_H - case 2: + case RECV_UNIX: if (alen != sizeof(struct sockaddr_un)) { TypeError("sockaddr size differs - should not happen"); } return assoc_new(str, unixaddr((struct sockaddr_un *)buf)); #endif - case 3: + case RECV_SOCKET: return assoc_new(str, str_new(buf, alen)); } } @@ -336,7 +350,7 @@ bsock_recv(argc, argv, sock) VALUE *argv; VALUE sock; { - return s_recv(sock, argc, argv, 0); + return s_recv(sock, argc, argv, RECV_RECV); } #if defined(THREAD) && defined(HAVE_FCNTL) @@ -470,7 +484,7 @@ open_inet(class, h, serv, type) Raise(eSocket, "no such proto %s", servent->s_proto); } - fd = socket(PF_INET, SOCK_STREAM, protoent->p_proto); + fd = socket(AF_INET, SOCK_STREAM, protoent->p_proto); memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.sin_family = AF_INET; @@ -515,9 +529,7 @@ open_inet(class, h, serv, type) if (type == INET_SERVER) listen(fd, 5); /* create new instance */ - sock = sock_new(class, fd); - - return sock; + return sock_new(class, fd); } static VALUE @@ -606,6 +618,15 @@ tcp_accept(sock) (struct sockaddr*)&from, &fromlen); } +static VALUE +tcp_recvfrom(argc, argv, sock) + int argc; + VALUE *argv; + VALUE sock; +{ + return s_recv(sock, argc, argv, RECV_TCP); +} + #ifdef HAVE_SYS_UN_H static VALUE open_unix(class, path, server) @@ -619,7 +640,7 @@ open_unix(class, path, server) OpenFile *fptr; Check_SafeStr(path); - fd = socket(PF_UNIX, SOCK_STREAM, 0); + fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) rb_sys_fail("socket(2)"); memset(&sockaddr, 0, sizeof(sockaddr)); @@ -700,7 +721,7 @@ mkipaddr(x) } static VALUE -tcpaddr(sockaddr) +ipaddr(sockaddr) struct sockaddr_in *sockaddr; { VALUE family, port, addr1, addr2; @@ -725,7 +746,7 @@ tcpaddr(sockaddr) } static VALUE -tcp_addr(sock) +ip_addr(sock) VALUE sock; { OpenFile *fptr; @@ -736,11 +757,11 @@ tcp_addr(sock) if (getsockname(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) rb_sys_fail("getsockname(2)"); - return tcpaddr(&addr); + return ipaddr(&addr); } static VALUE -tcp_peeraddr(sock) +ip_peeraddr(sock) VALUE sock; { OpenFile *fptr; @@ -751,24 +772,14 @@ tcp_peeraddr(sock) if (getpeername(fileno(fptr->f), (struct sockaddr*)&addr, &len) < 0) rb_sys_fail("getpeername(2)"); - return tcpaddr(&addr); + return ipaddr(&addr); } static VALUE -tcp_recvfrom(argc, argv, sock) - int argc; - VALUE *argv; - VALUE sock; -{ - return s_recv(sock, argc, argv, 1); -} - -static VALUE -tcp_s_getaddress(obj, host) +ip_s_getaddress(obj, host) VALUE obj, host; { struct sockaddr_in addr; - struct hostent *h; if (obj_is_kind_of(host, cInteger)) { int i = NUM2INT(host); @@ -782,6 +793,148 @@ tcp_s_getaddress(obj, host) return mkipaddr(addr.sin_addr.s_addr); } +static VALUE +udp_s_open(class) + VALUE class; +{ + return sock_new(class, socket(AF_INET, SOCK_DGRAM, 0)); +} + +static void +udp_addrsetup(host, port, addr) + VALUE host, port; + struct sockaddr_in *addr; +{ + struct hostent *hostent; + + memset(addr, 0, sizeof(struct sockaddr_in)); + addr->sin_family = AF_INET; + if (NIL_P(host)) { + addr->sin_addr.s_addr = INADDR_ANY; + } + else if (obj_is_kind_of(host, cInteger)) { + int i = NUM2INT(host); + addr->sin_addr.s_addr = htonl(i); + } + else { + Check_Type(host, T_STRING); + setipaddr(RSTRING(host)->ptr, addr); + } + if (FIXNUM_P(port)) { + addr->sin_port = FIX2INT(port); + } + else { + struct servent *servent; + + Check_Type(port, T_STRING); + servent = getservbyname(RSTRING(port)->ptr, "udp"); + if (servent) { + addr->sin_port = servent->s_port; + } + else { + int port = strtoul(RSTRING(port)->ptr, 0, 0); + + if (port == -1) { + Raise(eSocket, "no such servce %s", RSTRING(port)->ptr); + } + addr->sin_port = htons(port); + } + } +} + +static VALUE +udp_connect(sock, host, port) + VALUE sock, host, port; +{ + struct sockaddr_in addr; + OpenFile *fptr; + + udp_addrsetup(host, port, &addr); + GetOpenFile(sock, fptr); + retry: + if (connect(fileno(fptr->f), (struct sockaddr*)&addr, sizeof(addr))<0) { + switch (errno) { + case EINTR: + case EWOULDBLOCK: +#if EAGAIN != EWOULDBLOCK + case EAGAIN: +#endif +#ifdef THREAD + thread_schedule(); +#endif + goto retry; + } + rb_sys_fail("connect(2)"); + } + + return INT2FIX(0); +} + +static VALUE +udp_bind(sock, host, port) + VALUE sock, host, port; +{ + struct sockaddr_in addr; + OpenFile *fptr; + + udp_addrsetup(host, port, &addr); + GetOpenFile(sock, fptr); + if (bind(fileno(fptr->f), (struct sockaddr*)&addr, sizeof(addr))<0) { + rb_sys_fail("bind(2)"); + } + return INT2FIX(0); +} + +static VALUE +udp_send(argc, argv, sock) + int argc; + VALUE *argv; + VALUE sock; +{ + VALUE mesg, flags, host, port; + struct sockaddr_in addr; + OpenFile *fptr; + FILE *f; + int n; + + if (argc == 2) { + return bsock_send(argc, argv, sock); + } + rb_scan_args(argc, argv, "4", &mesg, &flags, &host, &port); + Check_Type(mesg, T_STRING); + + udp_addrsetup(host, port, &addr); + GetOpenFile(sock, fptr); + f = fptr->f2?fptr->f2:fptr->f; + retry: + n = sendto(fileno(f), RSTRING(mesg)->ptr, RSTRING(mesg)->len, + NUM2INT(flags), (struct sockaddr*)&addr, sizeof(addr)); + if (n < 0) { + switch (errno) { + case EINTR: + case EWOULDBLOCK: +#if EAGAIN != EWOULDBLOCK + case EAGAIN: +#endif +#ifdef THREAD + thread_schedule(); +#endif + goto retry; + } + rb_sys_fail("sendto(2)"); + } + return INT2FIX(n); +} + +static VALUE +udp_recvfrom(argc, argv, sock) + int argc; + VALUE *argv; + VALUE sock; +{ + return s_recv(sock, argc, argv, RECV_UDP); +} + #ifdef HAVE_SYS_UN_H static VALUE unix_s_sock_open(sock, path) @@ -820,7 +973,7 @@ unix_recvfrom(argc, argv, sock) VALUE *argv; VALUE sock; { - return s_recv(sock, argc, argv, 2); + return s_recv(sock, argc, argv, RECV_UNIX); } static VALUE @@ -884,7 +1037,25 @@ setup_domain_and_type(domain, dv, type, tv) if (TYPE(domain) == T_STRING) { ptr = RSTRING(domain)->ptr; - if (strcmp(ptr, "PF_INET") == 0) + if (strcmp(ptr, "AF_INET") == 0) + *dv = AF_INET; +#ifdef AF_UNIX + else if (strcmp(ptr, "AF_UNIX") == 0) + *dv = AF_UNIX; +#endif +#ifdef AF_ISO + else if (strcmp(ptr, "AF_ISO") == 0) + *dv = AF_ISO; +#endif +#ifdef AF_NS + else if (strcmp(ptr, "AF_NS") == 0) + *dv = AF_NS; +#endif +#ifdef AF_IMPLINK + else if (strcmp(ptr, "AF_IMPLINK") == 0) + *dv = AF_IMPLINK; +#endif + else if (strcmp(ptr, "PF_INET") == 0) *dv = PF_INET; #ifdef PF_UNIX else if (strcmp(ptr, "PF_UNIX") == 0) @@ -893,6 +1064,8 @@ setup_domain_and_type(domain, dv, type, tv) #ifdef PF_IMPLINK else if (strcmp(ptr, "PF_IMPLINK") == 0) *dv = PF_IMPLINK; + else if (strcmp(ptr, "AF_IMPLINK") == 0) + *dv = AF_IMPLINK; #endif #ifdef PF_AX25 else if (strcmp(ptr, "PF_AX25") == 0) @@ -978,8 +1151,7 @@ sock_s_socketpair(class, domain, type, protocol) static VALUE sock_connect(sock, addr) - VALUE sock; - struct RString *addr; + VALUE sock, addr; { OpenFile *fptr; @@ -988,7 +1160,7 @@ sock_connect(sock, addr) GetOpenFile(sock, fptr); retry: - if (connect(fileno(fptr->f), (struct sockaddr*)addr->ptr, addr->len) < 0) { + if (connect(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0) { switch (errno) { case EINTR: case EWOULDBLOCK: @@ -1008,8 +1180,7 @@ sock_connect(sock, addr) static VALUE sock_bind(sock, addr) - VALUE sock; - struct RString *addr; + VALUE sock, addr; { OpenFile *fptr; @@ -1017,7 +1188,7 @@ sock_bind(sock, addr) str_modify(addr); GetOpenFile(sock, fptr); - if (bind(fileno(fptr->f), (struct sockaddr*)addr->ptr, addr->len) < 0) + if (bind(fileno(fptr->f), (struct sockaddr*)RSTRING(addr)->ptr, RSTRING(addr)->len) < 0) rb_sys_fail("bind(2)"); return INT2FIX(0); @@ -1042,7 +1213,7 @@ sock_recvfrom(argc, argv, sock) VALUE *argv; VALUE sock; { - return s_recv(sock, argc, argv, 3); + return s_recv(sock, argc, argv, RECV_SOCKET); } static VALUE @@ -1185,7 +1356,7 @@ sock_s_getservbyaname(argc, argv) VALUE *argv; { VALUE service, protocol; - char *name, *proto; + char *proto; struct servent *sp; int port; @@ -1203,12 +1374,24 @@ sock_s_getservbyaname(argc, argv) return INT2FIX(port); } +static VALUE mConst; + +static void +sock_define_const(name, value) + char *name; + INT value; +{ + rb_define_const(cSocket, name, INT2FIX(value)); + rb_define_const(mConst, name, INT2FIX(value)); +} + Init_socket() { eSocket = rb_define_class("SocketError", eException); cBasicSocket = rb_define_class("BasicSocket", cIO); rb_undef_method(CLASS_OF(cBasicSocket), "new"); + rb_undef_method(CLASS_OF(cBasicSocket), "open"); rb_define_method(cBasicSocket, "shutdown", bsock_shutdown, -1); rb_define_method(cBasicSocket, "setsockopt", bsock_setsockopt, 3); rb_define_method(cBasicSocket, "getsockopt", bsock_getsockopt, 2); @@ -1217,12 +1400,14 @@ Init_socket() rb_define_method(cBasicSocket, "send", bsock_send, -1); rb_define_method(cBasicSocket, "recv", bsock_recv, -1); - cTCPsocket = rb_define_class("TCPsocket", cBasicSocket); + cIPsocket = rb_define_class("IPsocket", cBasicSocket); + rb_define_method(cIPsocket, "addr", ip_addr, 0); + rb_define_method(cIPsocket, "peeraddr", ip_peeraddr, 0); + rb_define_singleton_method(cIPsocket, "getaddress", ip_s_getaddress, 1); + + cTCPsocket = rb_define_class("TCPsocket", cIPsocket); rb_define_singleton_method(cTCPsocket, "open", tcp_s_open, 2); rb_define_singleton_method(cTCPsocket, "new", tcp_s_open, 2); - rb_define_method(cTCPsocket, "addr", tcp_addr, 0); - rb_define_method(cTCPsocket, "peeraddr", tcp_peeraddr, 0); - rb_define_singleton_method(cTCPsocket, "getaddress", tcp_s_getaddress, 1); rb_define_method(cTCPsocket, "recvfrom", tcp_recvfrom, -1); #ifdef SOCKS @@ -1236,6 +1421,14 @@ Init_socket() rb_define_singleton_method(cTCPserver, "new", tcp_svr_s_open, -1); rb_define_method(cTCPserver, "accept", tcp_accept, 0); + cUDPsocket = rb_define_class("UDPsocket", cIPsocket); + rb_define_singleton_method(cUDPsocket, "open", udp_s_open, 0); + rb_define_singleton_method(cUDPsocket, "new", udp_s_open, 0); + rb_define_method(cUDPsocket, "connect", udp_connect, 2); + rb_define_method(cUDPsocket, "bind", udp_bind, 2); + rb_define_method(cUDPsocket, "send", udp_send, -1); + rb_define_method(cUDPsocket, "recvfrom", udp_recvfrom, -1); + #ifdef HAVE_SYS_UN_H cUNIXsocket = rb_define_class("UNIXsocket", cBasicSocket); rb_define_singleton_method(cUNIXsocket, "open", unix_s_sock_open, 1); @@ -1271,137 +1464,138 @@ Init_socket() rb_define_singleton_method(cSocket, "getservbyname", sock_s_getservbyaname, -1); /* constants */ - rb_define_const(cSocket, "SOCK_STREAM", INT2FIX(SOCK_STREAM)); - rb_define_const(cSocket, "SOCK_DGRAM", INT2FIX(SOCK_DGRAM)); - rb_define_const(cSocket, "SOCK_RAW", INT2FIX(SOCK_RAW)); + mConst = rb_define_module_under(cSocket, "Constants"); + sock_define_const("SOCK_STREAM", SOCK_STREAM); + sock_define_const("SOCK_DGRAM", SOCK_DGRAM); + sock_define_const("SOCK_RAW", SOCK_RAW); #ifdef SOCK_RDM - rb_define_const(cSocket, "SOCK_RDM", INT2FIX(SOCK_RDM)); + sock_define_const("SOCK_RDM", SOCK_RDM); #endif #ifdef SOCK_SEQPACKET - rb_define_const(cSocket, "SOCK_SEQPACKET", INT2FIX(SOCK_SEQPACKET)); + sock_define_const("SOCK_SEQPACKET", SOCK_SEQPACKET); #endif #ifdef SOCK_PACKET - rb_define_const(cSocket, "SOCK_PACKET", INT2FIX(SOCK_PACKET)); + sock_define_const("SOCK_PACKET", SOCK_PACKET); #endif - rb_define_const(cSocket, "AF_INET", INT2FIX(AF_INET)); - rb_define_const(cSocket, "PF_INET", INT2FIX(PF_INET)); + sock_define_const("AF_INET", AF_INET); + sock_define_const("PF_INET", PF_INET); #ifdef AF_UNIX - rb_define_const(cSocket, "AF_UNIX", INT2FIX(AF_UNIX)); - rb_define_const(cSocket, "PF_UNIX", INT2FIX(PF_UNIX)); + sock_define_const("AF_UNIX", AF_UNIX); + sock_define_const("PF_UNIX", PF_UNIX); #endif #ifdef AF_AX25 - rb_define_const(cSocket, "AF_AX25", INT2FIX(AF_AX25)); - rb_define_const(cSocket, "PF_AX25", INT2FIX(PF_AX25)); + sock_define_const("AF_AX25", AF_AX25); + sock_define_const("PF_AX25", PF_AX25); #endif #ifdef AF_IPX - rb_define_const(cSocket, "AF_IPX", INT2FIX(AF_IPX)); - rb_define_const(cSocket, "PF_IPX", INT2FIX(PF_IPX)); + sock_define_const("AF_IPX", AF_IPX); + sock_define_const("PF_IPX", PF_IPX); #endif #ifdef AF_APPLETALK - rb_define_const(cSocket, "AF_APPLETALK", INT2FIX(AF_APPLETALK)); - rb_define_const(cSocket, "PF_APPLETALK", INT2FIX(PF_APPLETALK)); + sock_define_const("AF_APPLETALK", AF_APPLETALK); + sock_define_const("PF_APPLETALK", PF_APPLETALK); #endif - rb_define_const(cSocket, "MSG_OOB", INT2FIX(MSG_OOB)); - rb_define_const(cSocket, "MSG_PEEK", INT2FIX(MSG_PEEK)); - rb_define_const(cSocket, "MSG_DONTROUTE", INT2FIX(MSG_DONTROUTE)); + sock_define_const("MSG_OOB", MSG_OOB); + sock_define_const("MSG_PEEK", MSG_PEEK); + sock_define_const("MSG_DONTROUTE", MSG_DONTROUTE); - rb_define_const(cSocket, "SOL_SOCKET", INT2FIX(SOL_SOCKET)); + sock_define_const("SOL_SOCKET", SOL_SOCKET); #ifdef SOL_IP - rb_define_const(cSocket, "SOL_IP", INT2FIX(SOL_IP)); + sock_define_const("SOL_IP", SOL_IP); #endif #ifdef SOL_IPX - rb_define_const(cSocket, "SOL_IPX", INT2FIX(SOL_IPX)); + sock_define_const("SOL_IPX", SOL_IPX); #endif #ifdef SOL_AX25 - rb_define_const(cSocket, "SOL_AX25", INT2FIX(SOL_AX25)); + sock_define_const("SOL_AX25", SOL_AX25); #endif #ifdef SOL_ATALK - rb_define_const(cSocket, "SOL_ATALK", INT2FIX(SOL_ATALK)); + sock_define_const("SOL_ATALK", SOL_ATALK); #endif #ifdef SOL_TCP - rb_define_const(cSocket, "SOL_TCP", INT2FIX(SOL_TCP)); + sock_define_const("SOL_TCP", SOL_TCP); #endif #ifdef SOL_UDP - rb_define_const(cSocket, "SOL_UDP", INT2FIX(SOL_UDP)); + sock_define_const("SOL_UDP", SOL_UDP); #endif #ifdef SO_DEBUG - rb_define_const(cSocket, "SO_DEBUG", INT2FIX(SO_DEBUG)); + sock_define_const("SO_DEBUG", SO_DEBUG); #endif - rb_define_const(cSocket, "SO_REUSEADDR", INT2FIX(SO_REUSEADDR)); + sock_define_const("SO_REUSEADDR", SO_REUSEADDR); #ifdef SO_TYPE - rb_define_const(cSocket, "SO_TYPE", INT2FIX(SO_TYPE)); + sock_define_const("SO_TYPE", SO_TYPE); #endif #ifdef SO_ERROR - rb_define_const(cSocket, "SO_ERROR", INT2FIX(SO_ERROR)); + sock_define_const("SO_ERROR", SO_ERROR); #endif #ifdef SO_DONTROUTE - rb_define_const(cSocket, "SO_DONTROUTE", INT2FIX(SO_DONTROUTE)); + sock_define_const("SO_DONTROUTE", SO_DONTROUTE); #endif #ifdef SO_BROADCAST - rb_define_const(cSocket, "SO_BROADCAST", INT2FIX(SO_BROADCAST)); + sock_define_const("SO_BROADCAST", SO_BROADCAST); #endif #ifdef SO_SNDBUF - rb_define_const(cSocket, "SO_SNDBUF", INT2FIX(SO_SNDBUF)); + sock_define_const("SO_SNDBUF", SO_SNDBUF); #endif #ifdef SO_RCVBUF - rb_define_const(cSocket, "SO_RCVBUF", INT2FIX(SO_RCVBUF)); + sock_define_const("SO_RCVBUF", SO_RCVBUF); #endif - rb_define_const(cSocket, "SO_KEEPALIVE", INT2FIX(SO_KEEPALIVE)); + sock_define_const("SO_KEEPALIVE", SO_KEEPALIVE); #ifdef SO_OOBINLINE - rb_define_const(cSocket, "SO_OOBINLINE", INT2FIX(SO_OOBINLINE)); + sock_define_const("SO_OOBINLINE", SO_OOBINLINE); #endif #ifdef SO_NO_CHECK - rb_define_const(cSocket, "SO_NO_CHECK", INT2FIX(SO_NO_CHECK)); + sock_define_const("SO_NO_CHECK", SO_NO_CHECK); #endif #ifdef SO_PRIORITY - rb_define_const(cSocket, "SO_PRIORITY", INT2FIX(SO_PRIORITY)); + sock_define_const("SO_PRIORITY", SO_PRIORITY); #endif - rb_define_const(cSocket, "SO_LINGER", INT2FIX(SO_LINGER)); + sock_define_const("SO_LINGER", SO_LINGER); #ifdef SOPRI_INTERACTIVE - rb_define_const(cSocket, "SOPRI_INTERACTIVE", INT2FIX(SOPRI_INTERACTIVE)); + sock_define_const("SOPRI_INTERACTIVE", SOPRI_INTERACTIVE); #endif #ifdef SOPRI_NORMAL - rb_define_const(cSocket, "SOPRI_NORMAL", INT2FIX(SOPRI_NORMAL)); + sock_define_const("SOPRI_NORMAL", SOPRI_NORMAL); #endif #ifdef SOPRI_BACKGROUND - rb_define_const(cSocket, "SOPRI_BACKGROUND", INT2FIX(SOPRI_BACKGROUND)); + sock_define_const("SOPRI_BACKGROUND", SOPRI_BACKGROUND); #endif #ifdef IP_MULTICAST_IF - rb_define_const(cSocket, "IP_MULTICAST_IF", INT2FIX(IP_MULTICAST_IF)); + sock_define_const("IP_MULTICAST_IF", IP_MULTICAST_IF); #endif #ifdef IP_MULTICAST_TTL - rb_define_const(cSocket, "IP_MULTICAST_TTL", INT2FIX(IP_MULTICAST_TTL)); + sock_define_const("IP_MULTICAST_TTL", IP_MULTICAST_TTL); #endif #ifdef IP_MULTICAST_LOOP - rb_define_const(cSocket, "IP_MULTICAST_LOOP", INT2FIX(IP_MULTICAST_LOOP)); + sock_define_const("IP_MULTICAST_LOOP", IP_MULTICAST_LOOP); #endif #ifdef IP_ADD_MEMBERSHIP - rb_define_const(cSocket, "IP_ADD_MEMBERSHIP", INT2FIX(IP_ADD_MEMBERSHIP)); + sock_define_const("IP_ADD_MEMBERSHIP", IP_ADD_MEMBERSHIP); #endif #ifdef IP_DEFAULT_MULTICAST_TTL - rb_define_const(cSocket, "IP_DEFAULT_MULTICAST_TTL", INT2FIX(IP_DEFAULT_MULTICAST_TTL)); + sock_define_const("IP_DEFAULT_MULTICAST_TTL", IP_DEFAULT_MULTICAST_TTL); #endif #ifdef IP_DEFAULT_MULTICAST_LOOP - rb_define_const(cSocket, "IP_DEFAULT_MULTICAST_LOOP", INT2FIX(IP_DEFAULT_MULTICAST_LOOP)); + sock_define_const("IP_DEFAULT_MULTICAST_LOOP", IP_DEFAULT_MULTICAST_LOOP); #endif #ifdef IP_MAX_MEMBERSHIPS - rb_define_const(cSocket, "IP_MAX_MEMBERSHIPS", INT2FIX(IP_MAX_MEMBERSHIPS)); + sock_define_const("IP_MAX_MEMBERSHIPS", IP_MAX_MEMBERSHIPS); #endif #ifdef IPX_TYPE - rb_define_const(cSocket, "IPX_TYPE", INT2FIX(IPX_TYPE)); + sock_define_const("IPX_TYPE", IPX_TYPE); #endif #ifdef TCP_NODELAY - rb_define_const(cSocket, "TCP_NODELAY", INT2FIX(TCP_NODELAY)); + sock_define_const("TCP_NODELAY", TCP_NODELAY); #endif #ifdef TCP_MAXSEG - rb_define_const(cSocket, "TCP_MAXSEG", INT2FIX(TCP_MAXSEG)); + sock_define_const("TCP_MAXSEG", TCP_MAXSEG); #endif } diff --git a/ext/tkutil/depend b/ext/tkutil/depend index ead83eda57..e325a82c0f 100644 --- a/ext/tkutil/depend +++ b/ext/tkutil/depend @@ -1 +1 @@ -tkutil.o: tkutil.c ../../ruby.h ../../config.h ../../defines.h +tkutil.o: tkutil.c $(hdrdir)/ruby.h $(hdrdir)/config.h $(hdrdir)/defines.h diff --git a/file.c b/file.c index 0caa98adb1..b60ec65d55 100644 --- a/file.c +++ b/file.c @@ -42,15 +42,11 @@ struct timeval { #include #endif -#ifdef HAVE_STRING_H -# include -#else +#ifndef HAVE_STRING_H char *strrchr(); #endif -#ifdef NT #include -#endif #ifndef NT char *strdup(); @@ -101,6 +97,10 @@ file_s_open(argc, argv, class) file = file_open(RSTRING(fname)->ptr, mode); RBASIC(file)->class = class; + if (iterator_p()) { + rb_ensure(rb_yield, file, io_close, file); + } + return file; } @@ -136,7 +136,8 @@ file_reopen(argc, argv, file) if (!fptr->f) { fptr->f = rb_fopen(RSTRING(fname)->ptr, mode); if (fptr->f2) { - fclose(fptr->f2); + if (fileno(fptr->f2) < 3) /* need to keep stdio */ + fclose(fptr->f2); fptr->f2 = NULL; } return file; @@ -155,13 +156,14 @@ file_reopen(argc, argv, file) } static int -apply2files(func, args, arg) +apply2files(func, vargs, arg) int (*func)(); - struct RArray *args; + VALUE vargs; void *arg; { int i; VALUE path; + struct RArray *args = RARRAY(vargs); for (i=0; ilen; i++) { Check_SafeStr(args->ptr[i]); @@ -269,7 +271,6 @@ file_isatty(obj) #else #include "missing/file.h" #endif -#include static VALUE stat_new(st) @@ -306,14 +307,13 @@ stat_new(st) static VALUE file_s_stat(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) == -1) { - rb_sys_fail(fname->ptr); + if (stat(RSTRING(fname)->ptr, &st) == -1) { + rb_sys_fail(RSTRING(fname)->ptr); } return stat_new(&st); } @@ -334,15 +334,14 @@ file_stat(obj) static VALUE file_s_lstat(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { #if !defined(MSDOS) && !defined(NT) struct stat st; Check_SafeStr(fname); - if (lstat(fname->ptr, &st) == -1) { - rb_sys_fail(fname->ptr); + if (lstat(RSTRING(fname)->ptr, &st) == -1) { + rb_sys_fail(RSTRING(fname)->ptr); } return stat_new(&st); #else @@ -424,19 +423,6 @@ eaccess(path, mode) return 0; } -#if defined(DJGPP) - { - int stat_mode = 0; - if (mode & X_OK) - stat_mode |= S_IXOTH; - if (mode & W_OK) - stat_mode |= S_IWOTH; - if (mode & R_OK) - stat_mode |= S_IROTH; - mode = stat_mode; - } -#endif - if (st.st_uid == euid) /* owner */ mode <<= 6; else if (group_member (st.st_gid)) @@ -452,8 +438,7 @@ eaccess(path, mode) static VALUE test_d(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { #ifndef S_ISDIR # define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR) @@ -462,15 +447,14 @@ test_d(obj, fname) struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) return FALSE; + if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE; if (S_ISDIR(st.st_mode)) return TRUE; return FALSE; } static VALUE test_p(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { #ifdef S_IFIFO # ifndef S_ISFIFO @@ -480,7 +464,7 @@ test_p(obj, fname) struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) return FALSE; + if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE; if (S_ISFIFO(st.st_mode)) return TRUE; #endif @@ -489,8 +473,7 @@ test_p(obj, fname) static VALUE test_l(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { #ifndef S_ISLNK # ifdef _S_ISLNK @@ -510,7 +493,7 @@ test_l(obj, fname) struct stat st; Check_SafeStr(fname); - if (lstat(fname->ptr, &st) < 0) return FALSE; + if (lstat(RSTRING(fname)->ptr, &st) < 0) return FALSE; if (S_ISLNK(st.st_mode)) return TRUE; #endif @@ -519,8 +502,7 @@ test_l(obj, fname) static VALUE test_S(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { #ifndef S_ISSOCK # ifdef _S_ISSOCK @@ -540,7 +522,7 @@ test_S(obj, fname) struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) return FALSE; + if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE; if (S_ISSOCK(st.st_mode)) return TRUE; #endif @@ -549,8 +531,7 @@ test_S(obj, fname) static VALUE test_b(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { #ifndef S_ISBLK # ifdef S_IFBLK @@ -564,7 +545,7 @@ test_b(obj, fname) struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) return FALSE; + if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE; if (S_ISBLK(st.st_mode)) return TRUE; #endif @@ -573,8 +554,7 @@ test_b(obj, fname) static VALUE test_c(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { #ifndef S_ISCHR # define S_ISCHR(m) ((m & S_IFMT) == S_IFCHR) @@ -583,7 +563,7 @@ test_c(obj, fname) struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) return FALSE; + if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE; if (S_ISBLK(st.st_mode)) return TRUE; return FALSE; @@ -591,73 +571,66 @@ test_c(obj, fname) static VALUE test_e(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) return FALSE; + if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE; return TRUE; } static VALUE test_r(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { Check_SafeStr(fname); - if (eaccess(fname->ptr, R_OK) < 0) return FALSE; + if (eaccess(RSTRING(fname)->ptr, R_OK) < 0) return FALSE; return TRUE; } static VALUE test_R(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { Check_SafeStr(fname); - if (access(fname->ptr, R_OK) < 0) return FALSE; + if (access(RSTRING(fname)->ptr, R_OK) < 0) return FALSE; return TRUE; } static VALUE test_w(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { Check_SafeStr(fname); - if (eaccess(fname->ptr, W_OK) < 0) return FALSE; + if (eaccess(RSTRING(fname)->ptr, W_OK) < 0) return FALSE; return TRUE; } static VALUE test_W(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { Check_SafeStr(fname); - if (access(fname->ptr, W_OK) < 0) return FALSE; + if (access(RSTRING(fname)->ptr, W_OK) < 0) return FALSE; return TRUE; } static VALUE test_x(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { Check_SafeStr(fname); - if (eaccess(fname->ptr, X_OK) < 0) return FALSE; + if (eaccess(RSTRING(fname)->ptr, X_OK) < 0) return FALSE; return TRUE; } static VALUE test_X(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { Check_SafeStr(fname); - if (access(fname->ptr, X_OK) < 0) return FALSE; + if (access(RSTRING(fname)->ptr, X_OK) < 0) return FALSE; return TRUE; } @@ -667,79 +640,73 @@ test_X(obj, fname) static VALUE test_f(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) return FALSE; + if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE; if (S_ISREG(st.st_mode)) return TRUE; return FALSE; } static VALUE test_z(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) return FALSE; + if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE; if (st.st_size == 0) return TRUE; return FALSE; } static VALUE test_s(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) return FALSE; + if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE; if (st.st_size == 0) return FALSE; return int2inum(st.st_size); } static VALUE test_owned(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) return FALSE; + if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE; if (st.st_uid == geteuid()) return TRUE; return FALSE; } static VALUE test_rowned(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) return FALSE; + if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE; if (st.st_uid == getuid()) return TRUE; return FALSE; } static VALUE test_grpowned(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { #ifndef NT struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) return FALSE; + if (stat(RSTRING(fname)->ptr, &st) < 0) return FALSE; if (st.st_gid == getegid()) return TRUE; #endif return FALSE; @@ -761,12 +728,11 @@ check3rdbyte(file, mode) static VALUE test_suid(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { #ifdef S_ISUID Check_SafeStr(fname); - return check3rdbyte(fname->ptr, S_ISUID); + return check3rdbyte(RSTRING(fname)->ptr, S_ISUID); #else return FALSE; #endif @@ -774,12 +740,11 @@ test_suid(obj, fname) static VALUE test_sgid(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { #ifndef NT Check_SafeStr(fname); - return check3rdbyte(fname->ptr, S_ISGID); + return check3rdbyte(RSTRING(fname)->ptr, S_ISGID); #else return FALSE; #endif @@ -787,12 +752,11 @@ test_sgid(obj, fname) static VALUE test_sticky(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { Check_Type(fname, T_STRING); #ifdef S_ISVTX - return check3rdbyte(fname->ptr, S_ISVTX); + return check3rdbyte(RSTRING(fname)->ptr, S_ISVTX); #else return FALSE; #endif @@ -800,26 +764,26 @@ test_sticky(obj, fname) static VALUE file_s_size(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr); + if (stat(RSTRING(fname)->ptr, &st) < 0) + rb_sys_fail(RSTRING(fname)->ptr); return int2inum(st.st_size); } static VALUE file_s_ftype(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { struct stat st; char *t; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr); + if (stat(RSTRING(fname)->ptr, &st) < 0) + rb_sys_fail(RSTRING(fname)->ptr); if (S_ISREG(st.st_mode)) { t = "file"; @@ -857,13 +821,13 @@ file_s_ftype(obj, fname) static VALUE file_s_atime(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr); + if (stat(RSTRING(fname)->ptr, &st) < 0) + rb_sys_fail(RSTRING(fname)->ptr); return time_new(st.st_atime, 0); } @@ -883,13 +847,13 @@ file_atime(obj) static VALUE file_s_mtime(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr); + if (stat(RSTRING(fname)->ptr, &st) < 0) + rb_sys_fail(RSTRING(fname)->ptr); return time_new(st.st_mtime, 0); } @@ -909,13 +873,13 @@ file_mtime(obj) static VALUE file_s_ctime(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { struct stat st; Check_SafeStr(fname); - if (stat(fname->ptr, &st) < 0) rb_sys_fail(fname->ptr); + if (stat(RSTRING(fname)->ptr, &st) < 0) + rb_sys_fail(RSTRING(fname)->ptr); return time_new(st.st_ctime, 0); } @@ -1118,32 +1082,26 @@ file_s_utime(argc, argv) static VALUE file_s_link(obj, from, to) - VALUE obj; - struct RString *from, *to; + VALUE obj, from, to; { -#ifndef __human68k__ Check_SafeStr(from); Check_SafeStr(to); - if (link(from->ptr, to->ptr) < 0) - rb_sys_fail(from->ptr); + if (link(RSTRING(from)->ptr, RSTRING(to)->ptr) < 0) + rb_sys_fail(RSTRING(from)->ptr); return INT2FIX(0); -#else - rb_notimplement(); -#endif } static VALUE file_s_symlink(obj, from, to) - VALUE obj; - struct RString *from, *to; + VALUE obj, from, to; { #if !defined(MSDOS) && !defined(NT) Check_SafeStr(from); Check_SafeStr(to); - if (symlink(from->ptr, to->ptr) < 0) - rb_sys_fail(from->ptr); + if (symlink(RSTRING(from)->ptr, RSTRING(to)->ptr) < 0) + rb_sys_fail(RSTRING(from)->ptr); return TRUE; #else rb_notimplement(); @@ -1152,8 +1110,7 @@ file_s_symlink(obj, from, to) static VALUE file_s_readlink(obj, path) - VALUE obj; - struct RString *path; + VALUE obj, path; { #if !defined(MSDOS) && !defined(NT) char buf[MAXPATHLEN]; @@ -1161,8 +1118,8 @@ file_s_readlink(obj, path) Check_SafeStr(path); - if ((cc = readlink(path->ptr, buf, MAXPATHLEN)) < 0) - rb_sys_fail(path->ptr); + if ((cc = readlink(RSTRING(path)->ptr, buf, MAXPATHLEN)) < 0) + rb_sys_fail(RSTRING(path)->ptr); return str_new(buf, cc); #else @@ -1180,8 +1137,7 @@ unlink_internal(path) static VALUE file_s_unlink(obj, args) - VALUE obj; - struct RArray *args; + VALUE obj, args; { int n; @@ -1191,14 +1147,13 @@ file_s_unlink(obj, args) static VALUE file_s_rename(obj, from, to) - VALUE obj; - struct RString *from, *to; + VALUE obj, from, to; { Check_SafeStr(from); Check_SafeStr(to); - if (rename(from->ptr, to->ptr) == -1) - rb_sys_fail(from->ptr); + if (rename(RSTRING(from)->ptr, RSTRING(to)->ptr) < 0) + rb_sys_fail(RSTRING(from)->ptr); return INT2FIX(0); } @@ -1225,14 +1180,13 @@ file_s_umask(argc, argv) VALUE file_s_expand_path(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { char *s, *p; char buf[MAXPATHLEN]; Check_Type(fname, T_STRING); - s = fname->ptr; + s = RSTRING(fname)->ptr; p = buf; if (s[0] == '~') { @@ -1326,6 +1280,11 @@ rmext(p, e) if (!e) return 0; l2 = strlen(e); + if (l2 == 2 && e[1] == '*') { + e = strrchr(p, *e); + if (!e) return 0; + return e - p; + } if (l1 < l2) return l1; if (strcmp(p+l1-l2, e) == 0) { @@ -1339,25 +1298,24 @@ file_s_basename(argc, argv) int argc; VALUE *argv; { - struct RString *fname; - struct RString *ext; + VALUE fname, ext; char *p; int f; rb_scan_args(argc, argv, "11", &fname, &ext); Check_Type(fname, T_STRING); if (!NIL_P(ext)) Check_Type(ext, T_STRING); - p = strrchr(fname->ptr, '/'); + p = strrchr(RSTRING(fname)->ptr, '/'); if (!p) { if (!NIL_P(ext)) { - f = rmext(fname->ptr, ext->ptr); - if (f) return str_new(fname->ptr, f); + f = rmext(RSTRING(fname)->ptr, RSTRING(ext)->ptr); + if (f) return str_new(RSTRING(fname)->ptr, f); } return (VALUE)fname; } p++; /* skip last `/' */ if (!NIL_P(ext)) { - f = rmext(p, ext->ptr); + f = rmext(p, RSTRING(ext)->ptr); if (f) return str_new(p, f); } return str_taint(str_new2(p)); @@ -1365,19 +1323,18 @@ file_s_basename(argc, argv) static VALUE file_s_dirname(obj, fname) - VALUE obj; - struct RString *fname; + VALUE obj, fname; { UCHAR *p; Check_Type(fname, T_STRING); - p = strrchr(fname->ptr, '/'); + p = strrchr(RSTRING(fname)->ptr, '/'); if (!p) { return str_new2("."); } - if (p == fname->ptr) + if (p == RSTRING(fname)->ptr) p++; - return str_taint(str_new(fname->ptr, p - fname->ptr)); + return str_taint(str_new(RSTRING(fname)->ptr, p - RSTRING(fname)->ptr)); } static VALUE @@ -1398,31 +1355,30 @@ file_s_join(obj, args) static VALUE file_s_truncate(obj, path, len) - VALUE obj, len; - struct RString *path; + VALUE obj, path, len; { Check_SafeStr(path); #ifdef HAVE_TRUNCATE - if (truncate(path->ptr, NUM2INT(len)) < 0) - rb_sys_fail(path->ptr); + if (truncate(RSTRING(path)->ptr, NUM2INT(len)) < 0) + rb_sys_fail(RSTRING(path)->ptr); #else # ifdef HAVE_CHSIZE { int tmpfd; # if defined(NT) - if ((tmpfd = open(path->ptr, O_RDWR)) < 0) { - rb_sys_fail(path->ptr); + if ((tmpfd = open(RSTRING(path)->ptr, O_RDWR)) < 0) { + rb_sys_fail(RSTRING(path)->ptr); } # else - if ((tmpfd = open(path->ptr, 0)) < 0) { - rb_sys_fail(path->ptr); + if ((tmpfd = open(RSTRING(path)->ptr, 0)) < 0) { + rb_sys_fail(RSTRING(path)->ptr); } # endif if (chsize(tmpfd, NUM2INT(len)) < 0) { close(tmpfd); - rb_sys_fail(path->ptr); + rb_sys_fail(RSTRING(path)->ptr); } close(tmpfd); } @@ -1635,6 +1591,8 @@ extern VALUE mKernel; void Init_File() { + VALUE mConst; + mFileTest = rb_define_module("FileTest"); rb_define_module_function(mFileTest, "directory?", test_d, 1); @@ -1649,6 +1607,7 @@ Init_File() rb_define_module_function(mFileTest, "file?", test_f, 1); rb_define_module_function(mFileTest, "zero?", test_z, 1); rb_define_module_function(mFileTest, "size?", test_s, 1); + rb_define_module_function(mFileTest, "size", test_s, 1); rb_define_module_function(mFileTest, "owned?", test_owned, 1); rb_define_module_function(mFileTest, "grpowned?", test_grpowned, 1); @@ -1740,11 +1699,17 @@ Init_File() # define LOCK_UN 8 # endif + mConst = rb_define_module_under(cFile, "Constants"); rb_define_const(cFile, "LOCK_SH", INT2FIX(LOCK_SH)); rb_define_const(cFile, "LOCK_EX", INT2FIX(LOCK_EX)); rb_define_const(cFile, "LOCK_UN", INT2FIX(LOCK_UN)); rb_define_const(cFile, "LOCK_NB", INT2FIX(LOCK_NB)); + rb_define_const(mConst, "LOCK_SH", INT2FIX(LOCK_SH)); + rb_define_const(mConst, "LOCK_EX", INT2FIX(LOCK_EX)); + rb_define_const(mConst, "LOCK_UN", INT2FIX(LOCK_UN)); + rb_define_const(mConst, "LOCK_NB", INT2FIX(LOCK_NB)); + rb_define_method(cFile, "path", file_path, 0); rb_define_global_function("test", f_test, -1); diff --git a/gc.c b/gc.c index 710f8d62b4..27065af1cb 100644 --- a/gc.c +++ b/gc.c @@ -34,8 +34,6 @@ void *alloca(); #endif -void gc(); -void gc_mark(); static void run_final(); #ifndef GC_MALLOC_LIMIT @@ -57,11 +55,11 @@ xmalloc(size) if (size == 0) size = 1; malloc_memories += size; if (malloc_memories > GC_MALLOC_LIMIT) { - gc(); + gc_gc(); } mem = malloc(size); if (!mem) { - gc(); + gc_gc(); mem = malloc(size); if (!mem) Fatal("failed to allocate memory"); @@ -92,7 +90,7 @@ xrealloc(ptr, size) if (!ptr) return xmalloc(size); mem = realloc(ptr, size); if (!mem) { - gc(); + gc_gc(); mem = realloc(ptr, size); if (!mem) Fatal("failed to allocate memory(realloc)"); @@ -235,19 +233,21 @@ add_heap() p++; } } +#define RANY(o) ((RVALUE*)(o)) -struct RBasic * +VALUE rb_newobj() { - struct RBasic *obj; + VALUE obj; + if (freelist) { retry: - obj = (struct RBasic*)freelist; + obj = (VALUE)freelist; freelist = freelist->as.free.next; return obj; } if (dont_gc) add_heap(); - else gc(); + else gc_gc(); goto retry; } @@ -259,8 +259,7 @@ data_object_alloc(class, datap, dmark, dfree) void (*dfree)(); void (*dmark)(); { - struct RData *data = (struct RData*)rb_newobj(); - + NEWOBJ(data, struct RData); OBJSETUP(data, class, T_DATA); data->data = datap; data->dfree = dfree; @@ -273,9 +272,10 @@ extern st_table *rb_class_tbl; VALUE *gc_stack_start; static int -looks_pointerp(p) - register RVALUE *p; +looks_pointerp(ptr) + void *ptr; { + register RVALUE *p = RANY(ptr); register RVALUE *heap_org; register long i; @@ -365,9 +365,11 @@ gc_mark_maybe(obj) } void -gc_mark(obj) - register RVALUE *obj; +gc_mark(ptr) + void *ptr; { + register RVALUE *obj = RANY(ptr); + Top: if (FIXNUM_P(obj)) return; /* fixnum not marked */ if (rb_special_const_p((VALUE)obj)) return; /* special const not marked */ @@ -403,16 +405,18 @@ gc_mark(obj) case NODE_SUPER: /* 3 */ case NODE_FCALL: case NODE_NEWLINE: - obj = (RVALUE*)obj->as.node.u3.node; + obj = RANY(obj->as.node.u3.node); goto Top; case NODE_WHILE: /* 1,2 */ case NODE_UNTIL: + case NODE_MATCH2: + case NODE_MATCH3: gc_mark(obj->as.node.u1.node); /* fall through */ case NODE_METHOD: /* 2 */ case NODE_NOT: - obj = (RVALUE*)obj->as.node.u2.node; + obj = RANY(obj->as.node.u2.node); goto Top; case NODE_HASH: /* 1 */ @@ -420,12 +424,13 @@ gc_mark(obj) case NODE_STR: case NODE_XSTR: case NODE_DEFINED: - obj = (RVALUE*)obj->as.node.u1.node; + case NODE_MATCH: + obj = RANY(obj->as.node.u1.node); goto Top; case NODE_SCOPE: /* 2,3 */ gc_mark(obj->as.node.u3.node); - obj = (RVALUE*)obj->as.node.u2.node; + obj = RANY(obj->as.node.u2.node); goto Top; case NODE_ZARRAY: /* - */ @@ -443,6 +448,7 @@ gc_mark(obj) case NODE_UNDEF: case NODE_SELF: case NODE_NIL: + case NODE_POSTEXE: break; default: @@ -453,7 +459,7 @@ gc_mark(obj) gc_mark(obj->as.node.u2.node); } if (looks_pointerp(obj->as.node.u3.node)) { - obj = (RVALUE*)obj->as.node.u3.node; + obj = RANY(obj->as.node.u3.node); goto Top; } } @@ -491,7 +497,7 @@ gc_mark(obj) case T_STRING: if (obj->as.string.orig) { - obj = (RVALUE*)obj->as.string.orig; + obj = RANY(obj->as.string.orig); goto Top; } break; @@ -512,14 +518,14 @@ gc_mark(obj) case T_MATCH: if (obj->as.match.str) { - obj = (RVALUE*)obj->as.match.str; + obj = RANY(obj->as.match.str); goto Top; } break; case T_VARMAP: gc_mark(obj->as.varmap.val); - obj = (RVALUE*)obj->as.varmap.next; + obj = RANY(obj->as.varmap.next); goto Top; break; @@ -604,20 +610,20 @@ gc_sweep() void gc_force_recycle(p) - RVALUE *p; + VALUE p; { - p->as.free.flag = 0; - p->as.free.next = freelist; - freelist = p; + RANY(p)->as.free.flag = 0; + RANY(p)->as.free.next = freelist; + freelist = RANY(p); } static int need_call_final = 0; static void obj_free(obj) - RVALUE *obj; + VALUE obj; { - switch (obj->as.basic.flags & T_MASK) { + switch (RANY(obj)->as.basic.flags & T_MASK) { case T_NIL: case T_FIXNUM: case T_TRUE: @@ -629,40 +635,44 @@ obj_free(obj) if (need_call_final) { run_final(obj); } - switch (obj->as.basic.flags & T_MASK) { + switch (RANY(obj)->as.basic.flags & T_MASK) { case T_OBJECT: - if (obj->as.object.iv_tbl) st_free_table(obj->as.object.iv_tbl); + if (RANY(obj)->as.object.iv_tbl) { + st_free_table(RANY(obj)->as.object.iv_tbl); + } break; case T_MODULE: case T_CLASS: rb_clear_cache(); - st_free_table(obj->as.class.m_tbl); - if (obj->as.object.iv_tbl) st_free_table(obj->as.object.iv_tbl); + st_free_table(RANY(obj)->as.class.m_tbl); + if (RANY(obj)->as.object.iv_tbl) { + st_free_table(RANY(obj)->as.object.iv_tbl); + } break; case T_STRING: - if (!obj->as.string.orig) free(obj->as.string.ptr); + if (!RANY(obj)->as.string.orig) free(RANY(obj)->as.string.ptr); break; case T_ARRAY: - if (obj->as.array.ptr) free(obj->as.array.ptr); + if (RANY(obj)->as.array.ptr) free(RANY(obj)->as.array.ptr); break; case T_HASH: - st_free_table(obj->as.hash.tbl); + st_free_table(RANY(obj)->as.hash.tbl); break; case T_REGEXP: - reg_free(obj->as.regexp.ptr); - free(obj->as.regexp.str); + reg_free(RANY(obj)->as.regexp.ptr); + free(RANY(obj)->as.regexp.str); break; case T_DATA: - if (obj->as.data.dfree && DATA_PTR(obj)) - (*obj->as.data.dfree)(DATA_PTR(obj)); + if (RANY(obj)->as.data.dfree && DATA_PTR(obj)) + (*RANY(obj)->as.data.dfree)(DATA_PTR(obj)); break; case T_MATCH: - re_free_registers(obj->as.match.regs); - free(obj->as.match.regs); + re_free_registers(RANY(obj)->as.match.regs); + free(RANY(obj)->as.match.regs); break; case T_FILE: - io_fptr_finalize(obj->as.file.fptr); - free(obj->as.file.fptr); + io_fptr_finalize(RANY(obj)->as.file.fptr); + free(RANY(obj)->as.file.fptr); break; case T_ICLASS: /* iClass shares table with the module */ @@ -673,30 +683,30 @@ obj_free(obj) break; case T_BIGNUM: - if (obj->as.bignum.digits) free(obj->as.bignum.digits); + if (RANY(obj)->as.bignum.digits) free(RANY(obj)->as.bignum.digits); break; case T_NODE: - if (nd_type(obj) == NODE_SCOPE && obj->as.node.u1.tbl) { - free(obj->as.node.u1.tbl); + if (nd_type(obj) == NODE_SCOPE && RANY(obj)->as.node.u1.tbl) { + free(RANY(obj)->as.node.u1.tbl); } return; /* no need to free iv_tbl */ case T_SCOPE: - if (obj->as.scope.local_vars) { - VALUE *vars = obj->as.scope.local_vars-1; + if (RANY(obj)->as.scope.local_vars) { + VALUE *vars = RANY(obj)->as.scope.local_vars-1; if (vars[0] == 0) - free(obj->as.scope.local_tbl); - if (obj->as.scope.flag&SCOPE_MALLOC) + free(RANY(obj)->as.scope.local_tbl); + if (RANY(obj)->as.scope.flag&SCOPE_MALLOC) free(vars); } break; case T_STRUCT: - free(obj->as.rstruct.ptr); + free(RANY(obj)->as.rstruct.ptr); break; default: - Bug("gc_sweep(): unknown data type %d", obj->as.basic.flags & T_MASK); + Bug("gc_sweep(): unknown data type %d", RANY(obj)->as.basic.flags & T_MASK); } } @@ -750,7 +760,7 @@ int rb_setjmp (rb_jmp_buf); #endif /* __GNUC__ */ void -gc() +gc_gc() { struct gc_list *list; struct FRAME *frame; @@ -806,7 +816,7 @@ gc() static VALUE gc_method() { - gc(); + gc_gc(); return Qnil; } @@ -851,7 +861,7 @@ os_live_obj() case T_CLASS: if (FL_TEST(p, FL_SINGLETON)) continue; default: - rb_yield(p); + rb_yield((VALUE)p); n++; } } @@ -883,8 +893,8 @@ os_obj_of(of) case T_CLASS: if (FL_TEST(p, FL_SINGLETON)) continue; default: - if (obj_is_kind_of(p, of)) { - rb_yield(p); + if (obj_is_kind_of((VALUE)p, of)) { + rb_yield((VALUE)p); n++; } } @@ -957,10 +967,45 @@ run_final(obj) if (!FL_TEST(obj, FL_FINALIZE)) return; - obj |= FIXNUM_FLAG; /* make obj into id */ + obj = INT2NUM((int)obj); /* make obj into id */ for (i=0; ilen; i++) { - rb_eval_cmd(RARRAY(finalizers)->ptr[i], obj); + rb_eval_cmd(RARRAY(finalizers)->ptr[i], ary_new3(1,obj)); + } +} + +void +gc_call_finalizer_at_exit() +{ + RVALUE *p, *pend; + int i; + + for (i = 0; i < heaps_used; i++) { + p = heaps[i]; pend = p + HEAP_SLOTS; + while (p < pend) { + run_final(p); + if (BUILTIN_TYPE(p) == T_DATA && + DATA_PTR(p) && + RANY(p)->as.data.dfree) + (*RANY(p)->as.data.dfree)(DATA_PTR(p)); + p++; + } + } +} + +static VALUE +id2ref(obj, id) + VALUE obj, id; +{ + INT ptr = NUM2INT(id); + + if (FIXNUM_P(ptr)) return (VALUE)ptr; + if (!looks_pointerp(ptr)) { + IndexError("0x%x is not the id value", ptr); + } + if (RANY(ptr)->as.free.flag == 0) { + IndexError("0x%x is recycled object", ptr); } + return (VALUE)ptr; } extern VALUE cModule; @@ -978,11 +1023,12 @@ Init_GC() mObSpace = rb_define_module("ObjectSpace"); rb_define_module_function(mObSpace, "each_object", os_each_obj, -1); - rb_define_module_function(mObSpace, "garbage_collect", gc, 0); + rb_define_module_function(mObSpace, "garbage_collect", gc_method, 0); rb_define_module_function(mObSpace, "add_finalizer", add_final, 1); rb_define_module_function(mObSpace, "remove_finalizer", rm_final, 1); rb_define_module_function(mObSpace, "finalizers", finals, 0); rb_define_module_function(mObSpace, "call_finalizer", call_final, 1); + rb_define_module_function(mObSpace, "id2ref", id2ref, 1); rb_global_variable(&finalizers); finalizers = ary_new(); diff --git a/hash.c b/hash.c index fe9dfbaa26..49be7de6aa 100644 --- a/hash.c +++ b/hash.c @@ -14,15 +14,44 @@ #include "st.h" #include "sig.h" -#ifdef HAVE_STRING_H -# include -#else +#include + +#ifndef HAVE_STRING_H char *strchr(); #endif #define HASH_DELETED 0x1 #define HASH_REHASHED 0x2 +#define HASH_FREEZE FL_USER1 + +static void +hash_modify(hash) + VALUE hash; +{ + rb_secure(5); + if (FL_TEST(hash, HASH_FREEZE)) { + TypeError("can't modify frozen hash"); + } +} + +VALUE +hash_freeze(hash) + VALUE hash; +{ + FL_SET(hash, HASH_FREEZE); + return hash; +} + +static VALUE +hash_frozen_p(hash) + VALUE hash; +{ + if (FL_TEST(hash, HASH_FREEZE)) + return TRUE; + return FALSE; +} + #ifndef NT char *getenv(); #endif @@ -90,7 +119,7 @@ static struct st_hash_type objhash = { }; struct hash_foreach_arg { - struct RHash *hash; + VALUE hash; enum st_retval (*func)(); char *arg; }; @@ -104,7 +133,7 @@ hash_foreach_iter(key, value, arg) if (key == Qnil) return ST_CONTINUE; status = (*arg->func)(key, value, arg->arg); - if (arg->hash->status & HASH_REHASHED) return ST_STOP; + if (RHASH(arg->hash)->status & HASH_REHASHED) return ST_STOP; return status; } @@ -112,7 +141,7 @@ static VALUE hash_foreach_call(arg) struct hash_foreach_arg *arg; { - st_foreach(arg->hash->tbl, hash_foreach_iter, arg); + st_foreach(RHASH(arg->hash)->tbl, hash_foreach_iter, arg); return Qnil; } @@ -126,31 +155,31 @@ hash_delete_nil(key, value) static void hash_foreach_ensure(hash) - struct RHash *hash; + VALUE hash; { - hash->iter_lev--; + RHASH(hash)->iter_lev--; - if (hash->iter_lev == 0) { - if (hash->status & HASH_DELETED) { - st_foreach(hash->tbl, hash_delete_nil, 0); + if (RHASH(hash)->iter_lev == 0) { + if (RHASH(hash)->status & HASH_DELETED) { + st_foreach(RHASH(hash)->tbl, hash_delete_nil, 0); } - hash->status = 0; + RHASH(hash)->status = 0; } } static int hash_foreach(hash, func, farg) - struct RHash *hash; + VALUE hash; enum st_retval (*func)(); char *farg; { struct hash_foreach_arg arg; - hash->iter_lev++; + RHASH(hash)->iter_lev++; arg.hash = hash; arg.func = func; arg.arg = farg; - return rb_ensure(hash_foreach_call, &arg, hash_foreach_ensure, hash); + return rb_ensure(hash_foreach_call, (VALUE)&arg, hash_foreach_ensure, (VALUE)hash); } static VALUE @@ -177,7 +206,7 @@ hash_s_new(argc, argv, class) return (VALUE)hash; } -VALUE +static VALUE hash_new2(class) VALUE class; { @@ -196,7 +225,7 @@ hash_s_create(argc, argv, class) VALUE *argv; VALUE class; { - struct RHash *hash; + VALUE hash; int i; if (argc == 1 && TYPE(argv[0]) == T_HASH) { @@ -216,18 +245,18 @@ hash_s_create(argc, argv, class) if (argc % 2 != 0) { ArgError("odd number args for Hash"); } - hash = (struct RHash*)hash_new2(class); + hash = hash_new2(class); for (i=0; itbl, argv[i], argv[i+1]); + st_insert(RHASH(hash)->tbl, argv[i], argv[i+1]); } - return (VALUE)hash; + return hash; } static VALUE hash_clone(hash) - struct RHash *hash; + VALUE hash; { NEWOBJ(hash2, struct RHash); CLONESETUP(hash2, hash); @@ -235,7 +264,22 @@ hash_clone(hash) hash2->iter_lev = 0; hash2->status = 0; hash2->tbl = 0; /* avoid GC crashing */ - hash2->tbl = (st_table*)st_copy(hash->tbl); + hash2->tbl = (st_table*)st_copy(RHASH(hash)->tbl); + + return (VALUE)hash2; +} + +static VALUE +hash_dup(hash) + VALUE hash; +{ + NEWOBJ(hash2, struct RHash); + OBJSETUP(hash2, CLASS_OF(hash), T_HASH); + + hash2->iter_lev = 0; + hash2->status = 0; + hash2->tbl = 0; /* avoid GC crashing */ + hash2->tbl = (st_table*)st_copy(RHASH(hash)->tbl); return (VALUE)hash2; } @@ -253,26 +297,26 @@ hash_rehash_i(key, value, tbl) static VALUE hash_rehash(hash) - struct RHash *hash; + VALUE hash; { - st_table *tbl = st_init_table_with_size(&objhash, hash->tbl->num_entries); + st_table *tbl; - st_foreach(hash->tbl, hash_rehash_i, tbl); - st_free_table(hash->tbl); - hash->tbl = tbl; - if (hash->iter_lev > 0) hash->status |= HASH_REHASHED; + tbl = st_init_table_with_size(&objhash, RHASH(hash)->tbl->num_entries); + st_foreach(RHASH(hash)->tbl, hash_rehash_i, tbl); + st_free_table(RHASH(hash)->tbl); + RHASH(hash)->tbl = tbl; + if (RHASH(hash)->iter_lev > 0) RHASH(hash)->status |= HASH_REHASHED; return (VALUE)hash; } VALUE hash_aref(hash, key) - struct RHash *hash; - VALUE key; + VALUE hash, key; { VALUE val; - if (!st_lookup(hash->tbl, key, &val)) { + if (!st_lookup(RHASH(hash)->tbl, key, &val)) { return Qnil; } return val; @@ -282,30 +326,30 @@ static VALUE hash_indexes(argc, argv, hash) int argc; VALUE *argv; - struct RHash *hash; + VALUE hash; { - struct RArray *indexes; + VALUE indexes; int i; - indexes = (struct RArray*)ary_new2(argc); + indexes = ary_new2(argc); for (i=0; iptr[i] = hash_aref(hash, argv[i]); + RARRAY(indexes)->ptr[i] = hash_aref(hash, argv[i]); } - indexes->len = i; - return (VALUE)indexes; + RARRAY(indexes)->len = i; + return indexes; } static VALUE hash_delete(hash, key) - struct RHash *hash; - VALUE key; + VALUE hash, key; { VALUE val; - rb_secure(5); - if (hash->iter_lev > 0 && st_delete_safe(hash->tbl, &key, &val, Qnil)) + hash_modify(hash); + if (RHASH(hash)->iter_lev > 0 + && st_delete_safe(RHASH(hash)->tbl, &key, &val, Qnil)) return val; - else if (st_delete(hash->tbl, &key, &val)) + else if (st_delete(RHASH(hash)->tbl, &key, &val)) return val; if (iterator_p()) rb_yield(key); return Qnil; @@ -332,13 +376,13 @@ shift_i(key, value, var) static VALUE hash_shift(hash) - struct RHash *hash; + VALUE hash; { struct shift_var var; - rb_secure(5); + hash_modify(hash); var.stop = 0; - st_foreach(hash->tbl, shift_i, &var); + st_foreach(RHASH(hash)->tbl, shift_i, &var); if (var.stop == 0) return Qnil; return assoc_new(var.key, var.val); @@ -356,9 +400,9 @@ delete_if_i(key, value) static VALUE hash_delete_if(hash) - struct RHash *hash; + VALUE hash; { - rb_secure(5); + hash_modify(hash); hash_foreach(hash, delete_if_i, 0); return (VALUE)hash; @@ -373,20 +417,19 @@ clear_i(key, value) static VALUE hash_clear(hash) - struct RHash *hash; + VALUE hash; { - rb_secure(5); - st_foreach(hash->tbl, clear_i); + hash_modify(hash); + st_foreach(RHASH(hash)->tbl, clear_i); return (VALUE)hash; } VALUE hash_aset(hash, key, val) - struct RHash *hash; - VALUE key, val; + VALUE hash, key, val; { - rb_secure(5); + hash_modify(hash); if (NIL_P(val)) { hash_delete(hash, key); return Qnil; @@ -394,22 +437,22 @@ hash_aset(hash, key, val) if (TYPE(key) == T_STRING) { key = str_dup_freezed(key); } - st_insert(hash->tbl, key, val); + st_insert(RHASH(hash)->tbl, key, val); return val; } static VALUE hash_length(hash) - struct RHash *hash; + VALUE hash; { - return INT2FIX(hash->tbl->num_entries); + return INT2FIX(RHASH(hash)->tbl->num_entries); } -VALUE +static VALUE hash_empty_p(hash) - struct RHash *hash; + VALUE hash; { - if (hash->tbl->num_entries == 0) + if (RHASH(hash)->tbl->num_entries == 0) return TRUE; return FALSE; } @@ -425,7 +468,7 @@ each_value_i(key, value) static VALUE hash_each_value(hash) - struct RHash *hash; + VALUE hash; { hash_foreach(hash, each_value_i); return (VALUE)hash; @@ -442,7 +485,7 @@ each_key_i(key, value) static VALUE hash_each_key(hash) - struct RHash *hash; + VALUE hash; { hash_foreach(hash, each_key_i); return (VALUE)hash; @@ -459,7 +502,7 @@ each_pair_i(key, value) static VALUE hash_each_pair(hash) - struct RHash *hash; + VALUE hash; { hash_foreach(hash, each_pair_i); return (VALUE)hash; @@ -476,25 +519,24 @@ to_a_i(key, value, ary) static VALUE hash_to_a(hash) - struct RHash *hash; + VALUE hash; { VALUE ary; ary = ary_new(); - st_foreach(hash->tbl, to_a_i, ary); + st_foreach(RHASH(hash)->tbl, to_a_i, ary); return ary; } static int inspect_i(key, value, str) - VALUE key, value; - struct RString *str; + VALUE key, value, str; { VALUE str2; if (key == Qnil) return ST_CONTINUE; - if (str->len > 1) { + if (RSTRING(str)->len > 1) { str_cat(str, ", ", 2); } str2 = rb_inspect(key); @@ -508,12 +550,12 @@ inspect_i(key, value, str) static VALUE hash_inspect(hash) - struct RHash *hash; + VALUE hash; { VALUE str; str = str_new2("{"); - st_foreach(hash->tbl, inspect_i, str); + st_foreach(RHASH(hash)->tbl, inspect_i, str); str_cat(str, "}", 1); return str; @@ -537,12 +579,12 @@ keys_i(key, value, ary) static VALUE hash_keys(hash) - struct RHash *hash; + VALUE hash; { VALUE ary; ary = ary_new(); - st_foreach(hash->tbl, keys_i, ary); + st_foreach(RHASH(hash)->tbl, keys_i, ary); return ary; } @@ -558,22 +600,22 @@ values_i(key, value, ary) static VALUE hash_values(hash) - struct RHash *hash; + VALUE hash; { VALUE ary; ary = ary_new(); - st_foreach(hash->tbl, values_i, ary); + st_foreach(RHASH(hash)->tbl, values_i, ary); return ary; } static VALUE hash_has_key(hash, key) - struct RHash *hash; + VALUE hash; VALUE key; { - if (st_lookup(hash->tbl, key, 0)) { + if (st_lookup(RHASH(hash)->tbl, key, 0)) { return TRUE; } return FALSE; @@ -593,14 +635,14 @@ hash_search_value(key, value, data) static VALUE hash_has_value(hash, val) - struct RHash *hash; + VALUE hash; VALUE val; { VALUE data[2]; data[0] = FALSE; data[1] = val; - st_foreach(hash->tbl, hash_search_value, data); + st_foreach(RHASH(hash)->tbl, hash_search_value, data); return data[0]; } @@ -630,17 +672,17 @@ equal_i(key, val1, data) static VALUE hash_equal(hash1, hash2) - struct RHash *hash1, *hash2; + VALUE hash1, hash2; { struct equal_data data; if (TYPE(hash2) != T_HASH) return FALSE; - if (hash1->tbl->num_entries != hash2->tbl->num_entries) + if (RHASH(hash1)->tbl->num_entries != RHASH(hash2)->tbl->num_entries) return FALSE; - data.tbl = hash2->tbl; + data.tbl = RHASH(hash2)->tbl; data.result = TRUE; - st_foreach(hash1->tbl, equal_i, &data); + st_foreach(RHASH(hash1)->tbl, equal_i, &data); return data.result; } @@ -648,7 +690,7 @@ hash_equal(hash1, hash2) static int hash_invert_i(key, value, hash) VALUE key, value; - struct RHash *hash; + VALUE hash; { if (key == Qnil) return ST_CONTINUE; hash_aset(hash, value, key); @@ -657,15 +699,36 @@ hash_invert_i(key, value, hash) static VALUE hash_invert(hash) - struct RHash *hash; + VALUE hash; { VALUE h = hash_new(); - st_foreach(hash->tbl, hash_invert_i, h); + st_foreach(RHASH(hash)->tbl, hash_invert_i, h); return h; } -int env_path_tainted = 0; +static int +hash_update_i(key, value, hash) + VALUE key, value; + VALUE hash; +{ + if (key == Qnil) return ST_CONTINUE; + hash_aset(hash, key, value); + return ST_CONTINUE; +} + +static VALUE +hash_update(hash1, hash2) + VALUE hash1, hash2; +{ + Check_Type(hash2, T_HASH); + + st_foreach(RHASH(hash2)->tbl, hash_update_i, hash1); + return hash1; +} + +int env_path_tainted(); +static int path_tainted = -1; #ifndef NT extern char **environ; @@ -673,17 +736,16 @@ extern char **environ; static VALUE env_delete(obj, name) - VALUE obj; - struct RString *name; + VALUE obj, name; { int i, len; char *nam, *val = 0; rb_secure(4); Check_Type(name, T_STRING); - nam = name->ptr; + nam = RSTRING(name)->ptr; len = strlen(nam); - if (strcmp(nam, "PATH") == 0) env_path_tainted = 0; + if (strcmp(nam, "PATH") == 0) path_tainted = 0; for(i=0; environ[i]; i++) { if (strncmp(environ[i], nam, len) == 0 && environ[i][len] == '=') { val = environ[i]+len+1; @@ -700,31 +762,98 @@ env_delete(obj, name) return Qnil; } +static VALUE +env_delete_method(obj, name) + VALUE obj, name; +{ + VALUE val = env_delete(obj, name); + if (iterator_p()) rb_yield(name); + return val; +} + static VALUE f_getenv(obj, name) - VALUE obj; - struct RString *name; + VALUE obj, name; { char *env; Check_Type(name, T_STRING); - if (strlen(name->ptr) != name->len) + if (strlen(RSTRING(name)->ptr) != RSTRING(name)->len) ArgError("Bad environment name"); - env = getenv(name->ptr); + env = getenv(RSTRING(name)->ptr); if (env) { - if (strcmp(name->ptr, "PATH") == 0 && !env_path_tainted) + if (strcmp(RSTRING(name)->ptr, "PATH") == 0 && !env_path_tainted()) return str_new2(env); return str_taint(str_new2(env)); } return Qnil; } +static int +path_check_1(path) + char *path; +{ + struct stat st; + char *p = 0; + char *s; + + for (;;) { + if (stat(path, &st) == 0 && (st.st_mode & 2)) { + return 0; + } + s = strrchr(path, '/'); + if (p) *p = '/'; + if (!s || s == path) return 1; + p = s; + *p = '\0'; + } +} + +static void +path_check(path) + char *path; +{ + char *p = path; + char *pend = strchr(path, ':'); + + if (!path) { + path_tainted = 0; + } + + p = path; + pend = strchr(path, ':'); + + for (;;) { + int safe; + + if (pend) *pend = '\0'; + safe = path_check_1(p); + if (!pend) break; + *pend = ':'; + if (!safe) { + path_tainted = 1; + return; + } + p = pend + 1; + pend = strchr(p, ':'); + } + path_tainted = 0; +} + +int +env_path_tainted() +{ + if (path_tainted < 0) { + path_check(getenv("PATH")); + } + return path_tainted; +} + static VALUE f_setenv(obj, name, value) - VALUE obj; - struct RString *name, *value; + VALUE obj, name, value; { if (rb_safe_level() >= 4) { extern VALUE eSecurityError; @@ -738,13 +867,23 @@ f_setenv(obj, name, value) } Check_SafeStr(value); - if (strlen(name->ptr) != name->len) + if (strlen(RSTRING(name)->ptr) != RSTRING(name)->len) ArgError("Bad environment name"); - if (strlen(value->ptr) != value->len) + if (strlen(RSTRING(value)->ptr) != RSTRING(value)->len) ArgError("Bad environment value"); - setenv(name->ptr, value->ptr, 1); - if (strcmp(name->ptr, "PATH") == 0) env_path_tainted = 0; + setenv(RSTRING(name)->ptr, RSTRING(value)->ptr, 1); + if (strcmp(RSTRING(name)->ptr, "PATH") == 0) { + char *p, pend; + + if (str_tainted(value)) { + /* already tainted, no check */ + path_tainted = 1; + return TRUE; + } + + path_check(RSTRING(name)->ptr); + } return TRUE; } @@ -941,15 +1080,19 @@ Init_Hash() rb_define_singleton_method(cHash, "new", hash_s_new, -1); rb_define_singleton_method(cHash, "[]", hash_s_create, -1); - rb_define_method(cHash,"clone", hash_clone, 0); - rb_define_method(cHash,"rehash", hash_rehash, 0); + rb_define_method(cHash,"clone", hash_clone, 0); + rb_define_method(cHash,"dup", hash_dup, 0); + rb_define_method(cHash,"rehash", hash_rehash, 0); + + rb_define_method(cHash,"freeze", hash_freeze, 0); + rb_define_method(cHash,"frozen?",hash_frozen_p, 0); - rb_define_method(cHash,"to_a", hash_to_a, 0); - rb_define_method(cHash,"to_s", hash_to_s, 0); - rb_define_method(cHash,"inspect", hash_inspect, 0); + rb_define_method(cHash,"to_a", hash_to_a, 0); + rb_define_method(cHash,"to_s", hash_to_s, 0); + rb_define_method(cHash,"inspect", hash_inspect, 0); - rb_define_method(cHash,"==", hash_equal, 1); - rb_define_method(cHash,"[]", hash_aref, 1); + rb_define_method(cHash,"==", hash_equal, 1); + rb_define_method(cHash,"[]", hash_aref, 1); rb_define_method(cHash,"[]=", hash_aset, 2); rb_define_method(cHash,"indexes", hash_indexes, -1); rb_define_method(cHash,"length", hash_length, 0); @@ -969,6 +1112,7 @@ Init_Hash() rb_define_method(cHash,"delete_if", hash_delete_if, 0); rb_define_method(cHash,"clear", hash_clear, 0); rb_define_method(cHash,"invert", hash_invert, 0); + rb_define_method(cHash,"update", hash_update, 1); rb_define_method(cHash,"include?", hash_has_key, 1); rb_define_method(cHash,"has_key?", hash_has_key, 1); @@ -985,7 +1129,7 @@ Init_Hash() rb_define_singleton_method(envtbl,"each_pair", env_each, 0); rb_define_singleton_method(envtbl,"each_key", env_each_key, 0); rb_define_singleton_method(envtbl,"each_value", env_each_value, 0); - rb_define_singleton_method(envtbl,"delete", env_delete, 1); + rb_define_singleton_method(envtbl,"delete", env_delete_method, 1); rb_define_singleton_method(envtbl,"delete_if", env_delete_if, 0); rb_define_singleton_method(envtbl,"to_s", env_to_s, 0); rb_define_singleton_method(envtbl,"rehash", env_none, 0); diff --git a/inits.c b/inits.c index ebfc0f9c3a..123b32c989 100644 --- a/inits.c +++ b/inits.c @@ -12,20 +12,51 @@ #include "ruby.h" +void Init_Array _((void)); +void Init_Bignum _((void)); +void Init_Comparable _((void)); +void Init_Dir _((void)); +void Init_Enumerable _((void)); +void Init_Exception _((void)); +void Init_eval _((void)); +void Init_load _((void)); +void Init_Proc _((void)); +void Init_Thread _((void)); +void Init_File _((void)); +void Init_GC _((void)); +void Init_Hash _((void)); +void Init_IO _((void)); +void Init_Math _((void)); +void Init_marshal _((void)); +void Init_Numeric _((void)); +void Init_Object _((void)); +void Init_pack _((void)); +void Init_sym _((void)); +void Init_process _((void)); +void Init_Random _((void)); +void Init_Range _((void)); +void Init_Regexp _((void)); +void Init_signal _((void)); +void Init_String _((void)); +void Init_Struct _((void)); +void Init_Time _((void)); +void Init_var_tables _((void)); +void Init_version _((void)); + void rb_call_inits() { Init_sym(); Init_var_tables(); Init_Object(); + Init_Exception(); #ifdef THREAD Init_Thread(); #endif - Init_eval(); Init_Comparable(); Init_Enumerable(); + Init_eval(); Init_String(); - Init_Exception(); Init_Numeric(); Init_Bignum(); Init_Array(); @@ -44,5 +75,6 @@ rb_call_inits() Init_Proc(); Init_Math(); Init_GC(); + Init_marshal(); Init_version(); } diff --git a/io.c b/io.c index adf4b746f3..f84e15e447 100644 --- a/io.c +++ b/io.c @@ -49,6 +49,10 @@ struct timeval { # define NOFILE 64 #endif +#ifdef HAVE_UNISTD_H +#include +#endif + VALUE rb_ad_string(); VALUE cIO; @@ -130,16 +134,15 @@ closed() /* writing functions */ VALUE io_write(io, str) - VALUE io; - struct RString *str; + VALUE io, str; { OpenFile *fptr; FILE *f; int n; if (TYPE(str) != T_STRING) - str = (struct RString*)obj_as_string(str); - if (str->len == 0) return INT2FIX(0); + str = obj_as_string(str); + if (RSTRING(str)->len == 0) return INT2FIX(0); if (BUILTIN_TYPE(io) != T_FILE) { return rb_funcall(io, id_write, 1, str); @@ -164,7 +167,7 @@ io_write(io, str) if (ferror(f)) rb_sys_fail(fptr->path); #else - n = fwrite(str->ptr, 1, str->len, f); + n = fwrite(RSTRING(str)->ptr, 1, RSTRING(str)->len, f); if (n == 0 || ferror(f)) { rb_sys_fail(fptr->path); } @@ -177,7 +180,7 @@ io_write(io, str) } static VALUE -io_puts(io, str) +io_addstr(io, str) VALUE io, str; { io_write(io, str); @@ -265,29 +268,53 @@ io_fileno(io) } /* reading functions */ + +#ifndef S_ISREG +# define S_ISREG(m) ((m & S_IFMT) == S_IFREG) +#endif + +#define SMALLBUF 100 + static VALUE read_all(port) VALUE port; { OpenFile *fptr; VALUE str = Qnil; - char buf[BUFSIZ]; + char *buf; + struct stat st; + int siz = BUFSIZ; + int bytes = 0; int n; GetOpenFile(port, fptr); io_readable(fptr); if (fptr->f == NULL) closed(); + if (fstat(fileno(fptr->f), &st) == 0 && S_ISREG(st.st_mode)) { + if (st.st_size == 0) return Qnil; + else { + int pos = ftell(fptr->f); + if (st.st_size > pos && pos >= 0) { + siz = st.st_size - pos + 1; + } + } + } + str = str_new(0, siz); for (;;) { READ_CHECK(fptr->f); TRAP_BEG; - n = fread(buf, 1, BUFSIZ, fptr->f); + n = fread(RSTRING(str)->ptr+bytes, 1, siz-bytes, fptr->f); TRAP_END; if (n == 0) break; - if (n < 0) rb_sys_fail(0); - if (NIL_P(str)) str = str_new(buf, n); - else str_cat(str, buf, n); - } + if (n < 0) rb_sys_fail(fptr->path); + bytes += n; + if (bytes < siz) break; + siz += BUFSIZ; + str_resize(str, siz); + } + if (bytes == 0) return Qnil; + if (bytes != siz) str_resize(str, bytes); return str_taint(str); } @@ -298,26 +325,26 @@ io_read(argc, argv, io) VALUE io; { OpenFile *fptr; - int n, lgt; - VALUE len, str; + int n, len; + VALUE length, str; - if (rb_scan_args(argc, argv, "01", &len) == 0) { + if (rb_scan_args(argc, argv, "01", &length) == 0) { return read_all(io); } - lgt = NUM2INT(len); + len = NUM2INT(length); GetOpenFile(io, fptr); io_readable(fptr); if (fptr->f == NULL) closed(); - str = str_new(0, lgt); + str = str_new(0, len); READ_CHECK(fptr->f); TRAP_BEG; - n = fread(RSTRING(str)->ptr, 1, RSTRING(str)->len, fptr->f); + n = fread(RSTRING(str)->ptr, 1, len, fptr->f); TRAP_END; - if (n == 0) { - if (feof(fptr->f)) return Qnil; + if (n == 0) return Qnil; + if (n < 0) { rb_sys_fail(fptr->path); } @@ -332,12 +359,12 @@ static VALUE lineno; VALUE io_gets_method(argc, argv, io) int argc; - VALUE argv; + VALUE *argv; VALUE io; { OpenFile *fptr; FILE *f; - struct RString *str; + VALUE str = Qnil; int c, newline; char *rsptr; int rslen, rspara = 0; @@ -415,7 +442,7 @@ io_gets_method(argc, argv, io) if (c == EOF) { if (!append && cnt == 0) { - str = RSTRING(Qnil); + str = Qnil; goto return_gets; } } @@ -423,12 +450,12 @@ io_gets_method(argc, argv, io) if (append) str_cat(str, buf, cnt); else - str = (struct RString*)str_new(buf, cnt); + str = str_new(buf, cnt); if (c != EOF && (!rslen || - str->len < rslen || - memcmp(str->ptr+str->len-rslen, rsptr, rslen))) { + RSTRING(str)->len < rslen || + memcmp(RSTRING(str)->ptr+RSTRING(str)->len-rslen, rsptr, rslen))) { append = 1; goto again; } @@ -448,13 +475,14 @@ io_gets_method(argc, argv, io) } } - if (str) { + if (!NIL_P(str)) { fptr->lineno++; lineno = INT2FIX(fptr->lineno); + str_taint(str); } lastline_set(str); - return str_taint(str); + return str; } VALUE @@ -467,7 +495,7 @@ io_gets(io) static VALUE io_readline(argc, argv, io) int argc; - VALUE argv; + VALUE *argv; VALUE io; { VALUE line = io_gets_method(argc, argv, io); @@ -481,7 +509,7 @@ io_readline(argc, argv, io) static VALUE io_readlines(argc, argv, io) int argc; - VALUE argv; + VALUE *argv; VALUE io; { VALUE line, ary; @@ -496,7 +524,7 @@ io_readlines(argc, argv, io) static VALUE io_each_line(argc, argv, io) int argc; - VALUE argv; + VALUE *argv; VALUE io; { VALUE str; @@ -582,6 +610,7 @@ io_ungetc(io, c) if (ungetc(FIX2INT(c), fptr->f) == EOF) rb_sys_fail(fptr->path); + return Qnil; } static VALUE @@ -777,7 +806,7 @@ rb_fopen(fname, mode) f = fopen(fname, mode); if (f == NULL) { if (errno == EMFILE || errno == ENFILE) { - gc(); + gc_gc(); f = fopen(fname, mode); } if (f == NULL) { @@ -945,16 +974,9 @@ pipe_open(pname, mode) } if (doexec) { - VALUE serr = io_fileno(rb_stderr); - int fd = FIX2INT(serr); extern char *sourcefile; extern int sourceline; - - if (fd != 2) { - close(2); - dup2(fd, 2); - close(fd); - } + int fd; for (fd = 3; fd < NOFILE; fd++) close(fd); @@ -1043,13 +1065,13 @@ io_open(fname, mode) } static VALUE -f_open(argc, argv, self) +f_open(argc, argv) int argc; VALUE *argv; - VALUE self; { char *mode; VALUE pname, pmode; + VALUE port; rb_scan_args(argc, argv, "11", &pname, &pmode); Check_SafeStr(pname); @@ -1062,13 +1084,35 @@ f_open(argc, argv, self) ArgError("illegal access mode"); mode = RSTRING(pmode)->ptr; } - return io_open(RSTRING(pname)->ptr, mode); + + port = io_open(RSTRING(pname)->ptr, mode); + if (iterator_p()) { + rb_ensure(rb_yield, port, io_close, port); + } + + return port; } #ifndef NT extern char *strdup(); #endif +static char* +io_mode_string(fptr) + OpenFile *fptr; +{ + switch (fptr->mode & FMODE_READWRITE) { + case FMODE_READABLE: + default: + return "r"; + case FMODE_WRITABLE: + return "w"; + case FMODE_READWRITE: + return "r+"; + } + return "r"; +} + VALUE io_reopen(io, nfile) VALUE io, nfile; @@ -1097,25 +1141,17 @@ io_reopen(io, nfile) else fptr->path = 0; fptr->finalize = orig->finalize; - switch (fptr->mode & FMODE_READWRITE) { - case FMODE_READABLE: - default: - mode = "r"; break; - case FMODE_WRITABLE: - mode = "w"; break; - case FMODE_READWRITE: - if (orig->f2) mode = "r"; - else mode = "r+"; - break; - } + mode = io_mode_string(fptr); fd = fileno(fptr->f); - fclose(fptr->f); + if (fileno(fptr->f) < 3) /* need to keep stdio */ + fclose(fptr->f); dup2(fileno(orig->f), fd); fptr->f = rb_fdopen(fd, mode); if (fptr->f2) { fd = fileno(fptr->f2); - fclose(fptr->f2); + if (fileno(fptr->f2) < 3) + fclose(fptr->f2); if (orig->f2) { dup2(fileno(orig->f2), fd); fptr->f = rb_fdopen(fd, "w"); @@ -1179,7 +1215,7 @@ io_clone(io) fptr->f = rb_fdopen(fd, "w"); } if (fptr->mode & FMODE_BINMODE) { - io_binmode(obj); + io_binmode((VALUE)obj); } return (VALUE)obj; @@ -1226,7 +1262,7 @@ io_print(argc, argv, out) VALUE *argv; VALUE out; { - int i; + int i, j; VALUE line; /* if no argument given, print `$_' */ @@ -1244,7 +1280,12 @@ io_print(argc, argv, out) io_write(out, str_new2("nil")); break; case T_ARRAY: - ary_print_on(argv[i], out); + for (j=0; jlen; j++) { + if (!NIL_P(OFS) && j>0) { + io_write(out, OFS); + } + io_write(out, RARRAY(argv[i])->ptr[j]); + } break; default: io_write(out, argv[i]); @@ -1267,6 +1308,53 @@ f_print(argc, argv) return Qnil; } +static VALUE +io_puts(argc, argv, out) + int argc; + VALUE *argv; + VALUE out; +{ + int i, j; + VALUE line; + + /* if no argument given, print newline. */ + if (argc == 0) { + io_write(out, str_new2("\n")); + return Qnil; + } + for (i=0; ilen; j++) { + io_puts(1, &RARRAY(argv[i])->ptr[j], out); + } + continue; + default: + line = argv[i]; + break; + } + line = obj_as_string(line); + io_write(out, line); + if (RSTRING(line)->ptr[RSTRING(line)->len-1] != '\n') { + io_write(out, str_new2("\n")); + } + } + + return Qnil; +} + +static VALUE +f_puts(argc, argv) + int argc; + VALUE *argv; +{ + io_puts(argc, argv, rb_defout); + return Qnil; +} + static VALUE f_p(obj, val) VALUE obj, val; @@ -1279,6 +1367,13 @@ f_p(obj, val) return Qnil; } +void +rb_p(obj) /* for debug print within C code */ + VALUE obj; +{ + f_p(Qnil, obj); +} + static void io_defset(val, id) VALUE val; @@ -1294,6 +1389,41 @@ io_defset(val, id) rb_defout = val; } +static void +io_errset(val, id) + VALUE val; + ID id; +{ + OpenFile *fptr; + int fd; + + if (TYPE(val) != T_FILE) { + TypeError("$stderr must be IO Object"); + } + GetOpenFile(val, fptr); + io_writable(fptr); + rb_stderr = val; + + fd = fileno(fptr->f2?fptr->f2:fptr->f); + if (fd != 2) { + FILE *f; + + fflush(stderr); + dup2(fd, 2); + f = rb_fdopen(2, io_mode_string(fptr)); + if (fptr->f2) { + if (fileno(fptr->f2) < 3) /* need to keep stdio */ + fclose(fptr->f2); + fptr->f2 = f; + } + else { + if (fileno(fptr->f) < 3) + fclose(fptr->f); + fptr->f = f; + } + } +} + static VALUE prep_stdio(f, mode) FILE *f; @@ -1336,11 +1466,11 @@ static int init_p = 0, next_p = 0; static int next_argv() { - extern VALUE Argv; + extern VALUE rb_argv; char *fn; if (init_p == 0) { - if (RARRAY(Argv)->len > 0) { + if (RARRAY(rb_argv)->len > 0) { next_p = 1; } else { @@ -1354,8 +1484,8 @@ next_argv() retry: if (next_p == 1) { next_p = 0; - if (RARRAY(Argv)->len > 0) { - filename = ary_shift(Argv); + if (RARRAY(rb_argv)->len > 0) { + filename = ary_shift(rb_argv); fn = RSTRING(filename)->ptr; if (RSTRING(filename)->len == 1 && fn[0] == '-') { file = rb_stdin; @@ -1371,7 +1501,7 @@ next_argv() VALUE str; FILE *fw; - if (rb_defout != rb_stdout) { + if (TYPE(rb_defout) == T_FILE && rb_defout != rb_stdout) { io_close(rb_defout); } fstat(fileno(fr), &st); @@ -1539,13 +1669,12 @@ rb_str_setter(val, id, var) static VALUE f_backquote(obj, str) - VALUE obj; - struct RString *str; + VALUE obj, str; { VALUE port, result; Check_SafeStr(str); - port = pipe_open(str->ptr, "r"); + port = pipe_open(RSTRING(str)->ptr, "r"); result = read_all(port); io_close(port); @@ -1719,8 +1848,7 @@ f_select(argc, argv, obj) static VALUE io_ctl(io, req, arg, io_p) - VALUE io, req; - struct RString *arg; + VALUE io, req, arg; int io_p; { #if !defined(MSDOS) && !defined(__human68k__) @@ -1757,12 +1885,14 @@ io_ctl(io, req, arg, io_p) #endif str_modify(arg); - if (len < arg->len) { - len = arg->len; + if (len <= RSTRING(arg)->len) { + len = RSTRING(arg)->len; } - str_resize(arg, len+1); - arg->ptr[len] = 17; /* a little sanity check here */ - narg = (long)arg->ptr; + if (RSTRING(arg)->len < len) { + str_resize(arg, len+1); + } + RSTRING(arg)->ptr[len] = 17; /* a little sanity check here */ + narg = (long)RSTRING(arg)->ptr; } fd = fileno(fptr->f); #ifdef HAVE_FCNTL @@ -1774,7 +1904,7 @@ io_ctl(io, req, arg, io_p) retval = ioctl(fd, cmd, narg); #endif if (retval < 0) rb_sys_fail(fptr->path); - if (TYPE(arg) == T_STRING && arg->ptr[len] != 17) { + if (TYPE(arg) == T_STRING && RSTRING(arg)->ptr[len] != 17) { ArgError("return value overflowed string"); } return INT2NUM(retval); @@ -1957,14 +2087,14 @@ io_s_foreach(argc, argv, io) VALUE *argv; VALUE io; { - struct RString *fname; + VALUE fname; struct foreach_arg arg; rb_scan_args(argc, argv, "11", &fname, &arg.sep); Check_SafeStr(fname); arg.argc = argc - 1; - arg.io = io_open(fname->ptr, "r"); + arg.io = io_open(RSTRING(fname)->ptr, "r"); return rb_ensure(io_foreach_line, &arg, io_close, arg.io); } @@ -1988,14 +2118,14 @@ io_s_readlines(argc, argv, io) VALUE *argv; VALUE io; { - struct RString *fname; + VALUE fname; struct foreach_arg arg; rb_scan_args(argc, argv, "11", &fname, &arg.sep); Check_SafeStr(fname); arg.argc = argc - 1; - arg.io = io_open(fname->ptr, "r"); + arg.io = io_open(RSTRING(fname)->ptr, "r"); return rb_ensure(io_readline_line, &arg, io_close, arg.io); } @@ -2139,22 +2269,20 @@ opt_i_get() static void opt_i_set(val) - struct RString *val; + VALUE val; { if (NIL_P(val)) { inplace = 0; return; } Check_Type(val, T_STRING); - inplace = val->ptr; + inplace = RSTRING(val)->ptr; } -extern VALUE mEnumerable; - void Init_IO() { - extern VALUE mKernel; + extern VALUE mEnumerable; extern VALUE eException; eEOFError = rb_define_class("EOFError", eException); @@ -2166,6 +2294,7 @@ Init_IO() rb_define_global_function("open", f_open, -1); rb_define_global_function("printf", f_printf, -1); rb_define_global_function("print", f_print, -1); + rb_define_global_function("puts", f_puts, -1); rb_define_global_function("gets", f_gets_method, -1); rb_define_global_function("readline", f_readline, -1); rb_define_global_function("eof", f_eof, 0); @@ -2209,6 +2338,7 @@ Init_IO() rb_define_method(cIO, "reopen", io_reopen, 1); rb_define_method(cIO, "print", io_print, -1); + rb_define_method(cIO, "puts", io_puts, -1); rb_define_method(cIO, "printf", io_printf, -1); rb_define_method(cIO, "each", io_each_line, -1); @@ -2233,8 +2363,7 @@ Init_IO() rb_define_method(cIO, "getc", io_getc, 0); rb_define_method(cIO, "readchar", io_readchar, 0); rb_define_method(cIO, "ungetc",io_ungetc, 1); - rb_define_method(cIO, "puts", io_puts, 1); - rb_define_method(cIO, "<<", io_puts, 1); + rb_define_method(cIO, "<<", io_addstr, 1); rb_define_method(cIO, "flush", io_flush, 0); rb_define_method(cIO, "eof", io_eof, 0); rb_define_method(cIO, "eof?", io_eof, 0); @@ -2254,7 +2383,7 @@ Init_IO() rb_stdout = prep_stdio(stdout, FMODE_WRITABLE); rb_define_readonly_variable("$stdout", &rb_stdout); rb_stderr = prep_stdio(stderr, FMODE_WRITABLE); - rb_define_readonly_variable("$stderr", &rb_stderr); + rb_define_hooked_variable("$stderr", &rb_stderr, 0, io_errset); rb_defout = rb_stdout; rb_define_hooked_variable("$>", &rb_defout, 0, io_defset); diff --git a/io.h b/io.h index cc87677d0c..c671fca8ed 100644 --- a/io.h +++ b/io.h @@ -48,6 +48,11 @@ typedef struct OpenFile { #define GetWriteFile(fptr) (((fptr)->f2) ? (fptr)->f2 : (fptr)->f) -FILE *rb_fopen(); +FILE *rb_fopen _((char *, char *)); +FILE *rb_fdopen _((int, char *)); +void io_writable _((OpenFile *)); +void io_readable _((OpenFile *)); +void io_fptr_finalize _((OpenFile *)); +void io_unbuffered _((OpenFile *)); #endif diff --git a/lib/cgi-lib.rb b/lib/cgi-lib.rb index afadbff3b6..5234e046cc 100644 --- a/lib/cgi-lib.rb +++ b/lib/cgi-lib.rb @@ -9,29 +9,59 @@ # foo.keys <== array of fields # foo.inputs <== hash of { => } +# if running on Windows(IIS or PWS) then change cwd. +if ENV['SERVER_SOFTWARE'] =~ /^Microsoft-/ then + Dir.chdir ENV['PATH_TRANSLATED'].sub(/[^\\]+$/, '') +end + +require "shellwords.rb" + class CGI + include Shellwords + attr("inputs") + + # original is CGI.pm + def read_from_cmdline + words = shellwords(if not ARGV.empty? then + ARGV.join(' ') + else + print "(offline mode: enter name=value pairs on standard input)\n" + readlines.join(' ').gsub(/\n/, '') + end.gsub(/\\=/, '%3D').gsub(/\\&/, '%26')) + + if words.find{|x| x =~ /=/} then words.join('&') else words.join('+') end + end + # escape url encode + def escape(str) + str.gsub!(/[^a-zA-Z0-9_\-.]/n){ sprintf("%%%02X", $&.unpack("C")[0]) } + str + end + + # unescape url encoded + def unescape(str) + str.gsub! /\+/, ' ' + str.gsub!(/%([0-9a-fA-F]{2})/){ [$1.hex].pack("c") } + str + end + module_function :escape, :unescape + def initialize - str = if ENV['REQUEST_METHOD'] == "GET" - ENV['QUERY_STRING'] - elsif ENV['REQUEST_METHOD'] == "POST" - $stdin.read ENV['CONTENT_LENGTH'].to_i - else - "" - end - arr = str.split(/&/) + # exception messages should be printed to stdout. + STDERR.reopen(STDOUT) + @inputs = {} - arr.each do |x| - x.gsub!(/\+/, ' ') - key, val = x.split(/=/, 2) - val = "" unless val - - key.gsub!(/%(..)/) { [$1.hex].pack("c") } - val.gsub!(/%(..)/) { [$1.hex].pack("c") } - - @inputs[key] += "\0" if @inputs[key] - @inputs[key] += val + case ENV['REQUEST_METHOD'] + when "GET" + ENV['QUERY_STRING'] or "" + when "POST" + $stdin.read ENV['CONTENT_LENGTH'].to_i + else + read_from_cmdline + end.split(/&/).each do |x| + key, val = x.split(/=/,2).collect{|x|unescape(x)} + @inputs[key] += ("\0" if @inputs[key]) + (val or "") end end @@ -53,4 +83,15 @@ class CGI TRUE end + def CGI.error + m = $!.dup + m.gsub!(/&/, '&') + m.gsub!(//, '>') + msgs = ["
ERROR: #{m}"]
+    msgs << $@
+    msgs << "
" + CGI.message(msgs.join("\n"), "ERROR") + exit + end end diff --git a/lib/finalize.rb b/lib/finalize.rb index e934753e19..9b2ffefcf5 100644 --- a/lib/finalize.rb +++ b/lib/finalize.rb @@ -1,9 +1,9 @@ # -# finalize.rb - -# $Release Version: $ -# $Revision: 1.2 $ -# $Date: 1997/07/25 02:43:00 $ -# by Keiju ISHITSUKA(SHL Japan Inc.) +# finalizer.rb - +# $Release Version: 0.2$ +# $Revision: 1.3 $ +# $Date: 1998/01/09 08:09:49 $ +# by Keiju ISHITSUKA # # -- # @@ -44,14 +44,14 @@ # 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 $-' + RCS_ID='-$Header: /home/keiju/var/src/var.lib/ruby/RCS/finalize.rb,v 1.3 1998/01/09 08:09:49 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) + method = method.intern unless method.kind_of?(Integer) assoc = [dependant, method].concat(opt) if dep = @dependency[obj.id] dep.push assoc @@ -63,8 +63,8 @@ module Finalizer # 依存関係 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) + id = id.id unless id.kind_of?(Integer) + method = method.intern unless method.kind_of?(Integer) for assoc in @dependency[id] assoc.delete_if do |d, m, *o| @@ -77,8 +77,8 @@ module Finalizer # 依存関係 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) + id = id.id unless id.kind_of?(Integer) + method = method.intern unless method.kind_of?(Integer) for assoc in @dependency[id] assoc.delete_if do |d, m, *o| @@ -90,8 +90,8 @@ module Finalizer # 依存関係 R_method(*, dependant) の削除 def delete_by_dependant(dependant, method = :finalize) - method = method.id unless method.kind_of?(Fixnum) - for id in @dependency.keys + method = method.intern unless method.kind_of?(Integer) + for id in Dependency.keys delete(id, dependant, method) end end @@ -106,8 +106,8 @@ module Finalizer # 依存関連 R_method(obj, dependtant) で結ばれるdependantをfinalizeす # る. def finalize_dependency(id, dependant, method = :finalize) - id = id.id unless id.kind_of?(Fixnum) - method = method.id unless method.kind_of?(Fixnum) + id = id.id unless id.kind_of?(Integer) + method = method.intern unless method.kind_of?(Integer) for assocs in @dependency[id] assocs.delete_if do |d, m, *o| @@ -121,8 +121,8 @@ module Finalizer # 依存関連 R_*(obj, dependtant) で結ばれるdependantをfinalizeする. def finalize_all_dependency(id, dependant) - id = id.id unless id.kind_of?(Fixnum) - method = method.id unless method.kind_of?(Fixnum) + id = id.id unless id.kind_of?(Integer) + method = method.intern unless method.kind_of?(Integer) for assoc in @dependency[id] assoc.delete_if do |d, m, *o| @@ -134,7 +134,7 @@ module Finalizer # 依存関連 R_method(*, dependtant) で結ばれるdependantをfinalizeする. def finalize_by_dependant(dependant, method = :finalize) - method = method.id unless method.kind_of?(Fixnum) + method = method.intern unless method.kind_of?(Integer) for id in @dependency.keys finalize(id, dependant, method) end diff --git a/lib/mailread.rb b/lib/mailread.rb index d9feffbb7a..a5d60c84b4 100644 --- a/lib/mailread.rb +++ b/lib/mailread.rb @@ -1,36 +1,35 @@ class Mail - def Mail.new(f) + + def initialize(f) unless f.kind_of?(IO) f = open(f, "r") - me = super(f) - f.close - else - me = super + opened = true end - return me - end - def initialize(f) @header = {} @body = [] - while f.gets() - $_.chop! - next if /^From / # skip From-line - break if /^$/ # end of header + begin + while f.gets() + $_.chop! + next if /^From / # skip From-line + break if /^$/ # end of header - if /^(\S+):\s*(.*)/ - @header[attr = $1.capitalize!] = $2 - elsif attr - sub!(/^\s*/, '') - @header[attr] += "\n" + $_ + if /^(\S+):\s*(.*)/ + @header[attr = $1.capitalize!] = $2 + elsif attr + sub!(/^\s*/, '') + @header[attr] += "\n" + $_ + end end - end - return unless $_ + return unless $_ - while f.gets() - break if /^From / - @body.push($_) + while f.gets() + break if /^From / + @body.push($_) + end + ensure + f.close if opened end end diff --git a/lib/sync.rb b/lib/sync.rb index 3e57ed0e57..b5a3fc32b3 100644 --- a/lib/sync.rb +++ b/lib/sync.rb @@ -1,13 +1,19 @@ # # sync.rb - カウント付2-フェーズロッククラス -# $Release Version: 0.1$ +# $Release Version: 0.2$ # $Revision$ # $Date$ # by Keiju ISHITSUKA # # -- +# Sync_m, Synchronizer_m # Usage: -# Sync_m, Synchronizer_m +# obj.extend(Sync_m) +# or +# class Foo +# Sync_m.include_to self +# : +# end # # Sync_m#sync_mode # Sync_m#sync_locked?, locked? @@ -19,8 +25,9 @@ # # Sync, Synchronicer: # include Sync_m -# +# Usage: # sync = Sync.new +# # Sync#mode # Sync#locked? # Sync#shared? @@ -36,15 +43,17 @@ unless defined? Thread fail "Thread not available for this ruby interpreter" end -require "finalize.rb" +require "finalize" module Sync_m RCS_ID='-$Header$-' + # lock mode UN = :UN SH = :SH EX = :EX + # 例外定義 class Err < Exception def Err.Fail(*opt) fail self, sprintf(self::Message, *opt) @@ -68,21 +77,53 @@ module Sync_m end end - def Sync_m.extend_object(obj) + # include and extend initialize methods. + def Sync_m.extendable_module(obj) if Fixnum === obj or TRUE === obj or FALSE === obj or nil == obj raise TypeError, "Sync_m can't extend to this class(#{obj.type})" else begin - eval "class << obj - @sync_locked - end" - obj.extend(For_primitive_object) + obj.instance_eval "@sync_locked" + For_general_object rescue TypeError - obj.extend(For_general_object) + For_primitive_object end end end + def Sync_m.includable_module(cl) + begin + dummy = cl.new + Sync_m.extendable_module(dummy) + rescue NameError + # newが定義されていない時は, DATAとみなす. + For_primitive_object + end + end + + def Sync_m.extend_class(cl) + return super if cl.instance_of?(Module) + + # モジュールの時は何もしない. クラスの場合, 適切なモジュールの決定 + # とaliasを行う. + real = includable_module(cl) + cl.module_eval %q{ + include real + + alias locked? sync_locked? + alias shared? sync_shared? + alias exclusive? sync_exclusive? + alias lock sync_lock + alias unlock sync_unlock + alias try_lock sync_try_lock + alias synchronize sync_synchronize + } + end + + def Sync_m.extend_object(obj) + obj.extend(Sync_m.extendable_module(obj)) + end + def sync_extended unless (defined? locked? and defined? shared? and @@ -94,7 +135,7 @@ module Sync_m eval "class << self alias locked? sync_locked? alias shared? sync_shared? - alias excluive? sync_exclusive? + alias exclusive? sync_exclusive? alias lock sync_lock alias unlock sync_unlock alias try_lock sync_try_lock @@ -103,6 +144,7 @@ module Sync_m end end + # accessing def sync_locked? sync_mode != UN end @@ -115,6 +157,7 @@ module Sync_m sync_mode == EX end + # locking methods. def sync_try_lock(mode = EX) return unlock if sync_mode == UN @@ -238,7 +281,6 @@ module Sync_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 @@ -262,6 +304,7 @@ module Sync_m end end + # internal class module For_primitive_object include Sync_m @@ -281,12 +324,18 @@ module Sync_m Finalizer.add(obj, For_primitive_object, :sync_finalize) end - def sync_extended + def initialize super Sync_Locked[id] = LockState.new(UN, [], [], Hash.new, nil, 0 ) + self + end + + def sync_extended + super + initialize end - def sync_finalize + def For_primitive_object.sync_finalize(id) wait = Sync_Locked.delete(id) # waiting == [] ときだけ GCされるので, 待ち行列の解放は意味がない. end @@ -343,7 +392,7 @@ module Sync_m obj.sync_extended end - def sync_extended + def initialize super @sync_mode = UN @sync_waiting = [] @@ -351,6 +400,12 @@ module Sync_m @sync_sh_locker = Hash.new @sync_ex_locker = nil @sync_ex_count = 0 + self + end + + def sync_extended + super + initialize end attr :sync_mode, TRUE @@ -366,10 +421,11 @@ end Synchronizer_m = Sync_m class Sync - include Sync_m::For_general_object + Sync_m.extend_class self + #include Sync_m def initialize - sync_extended + super end end diff --git a/lib/tk.rb b/lib/tk.rb index df68874b13..2cbbec02a8 100644 --- a/lib/tk.rb +++ b/lib/tk.rb @@ -1,12 +1,483 @@ # -# tk.rb - Tk interface for ruby +# tk.rb - Tk interface modue using tcltklib # $Date$ -# by Yukihiro Matsumoto +# by Yukihiro Matsumoto -if defined? Thread and $tk_thread_safe - require "tkthcore" -else - require "tkcore" +# use Shigehiro's tcltklib +require "tcltklib" +require "tkutil" + +module TkComm + None = Object.new + def None.to_s + 'None' + end + + Tk_CMDTBL = {} + Tk_WINDOWS = {} + + def error_at + frames = caller(1) + frames.delete_if do |c| + c =~ %r!/tk(|core|thcore|canvas|text|entry|scrollbox)\.rb:\d+! + end + frames + end + private :error_at + + def tk_tcl2ruby(val) + case val + when /^-?\d+$/ + val.to_i + when /^\./ + Tk_WINDOWS[val] + when /^rb_out (c\d+)/ + Tk_CMDTBL[$1] + when / / + val.split.collect{|elt| + tk_tcl2ruby(elt) + } + when /^-?\d+\.\d*$/ + val.to_f + else + val + end + end + + def tk_split_list(str) + idx = str.index('{') + return tk_tcl2ruby(str) if not idx + + list = tk_tcl2ruby(str[0,idx]) + str = str[idx+1..-1] + i = -1 + brace = 1 + str.each_byte {|c| + i += 1 + brace += 1 if c == ?{ + brace -= 1 if c == ?} + break if brace == 0 + } + if str[0, i] == ' ' + list.push ' ' + else + list.push tk_split_list(str[0, i]) + end + list += tk_split_list(str[i+1..-1]) + list + end + private :tk_tcl2ruby, :tk_split_list + + def hash_kv(keys) + conf = [] + if keys and keys != None + for k, v in keys + conf.push("-#{k}") + v = install_cmd(v) if v.kind_of? Proc + conf.push(v) + end + end + conf + end + private :hash_kv + + def bool(val) + case val + when "1", 1, 'yes', 'true' + TRUE + else + FALSE + end + end + def number(val) + case val + when /^-?\d+$/ + val.to_i + when /^-?\d+\.\d*$/ + val.to_f + else + val + end + end + def string(val) + if val == "{}" + '' + elsif val[0] == ?{ + val[1..-2] + else + val + end + end + def list(val) + tk_split_list(val) + end + def window(val) + Tk_WINDOWS[val] + end + def procedure(val) + if val =~ /^rb_out (c\d+)/ + Tk_CMDTBL[$1] + else + nil + end + end + private :bool, :number, :string, :list, :window, :procedure + + Tk_IDs = [0] # [0]-cmdid, [1]-winid + def _curr_cmd_id + id = format("c%.4d", Tk_IDs[0]) + end + def _next_cmd_id + id = _curr_cmd_id + Tk_IDs[0] += 1 + end + def install_cmd(cmd) + return '' if cmd == '' + id = _next_cmd_id + Tk_CMDTBL[id] = cmd + @cmdtbl = [] if not @cmdtbl + @cmdtbl.push id + return format("rb_out %s", id); + end + def uninstall_cmd(id) + Tk_CMDTBL[id] = nil + end + private :install_cmd, :uninstall_cmd + + def install_win(ppath) + id = format("w%.4d", Tk_IDs[0]) + Tk_IDs[0] += 1 + if !ppath or ppath == "." + @path = format(".%s", id); + else + @path = format("%s.%s", ppath, id) + end + Tk_WINDOWS[@path] = self + end + + def uninstall_win() + Tk_WINDOWS[@path] = nil + end + + class Event + def initialize(seq,b,f,h,k,s,t,w,x,y,aa,ee,kk,nn,ww,tt,xx,yy) + @serial = seq + @num = b + @focus = (f == 1) + @height = h + @keycode = k + @state = s + @time = t + @width = w + @x = x + @y = y + @char = aa + @send_event = (ee == 1) + @keysym = kk + @keysym_num = nn + @type = tt + @widget = ww + @x_root = xx + @y_root = yy + end + attr :serial + attr :num + attr :focus + attr :height + attr :keycode + attr :state + attr :time + attr :width + attr :x + attr :y + attr :char + attr :send_event + attr :keysym + attr :keysym_num + attr :type + attr :widget + attr :x_root + attr :y_root + end + + def install_bind(cmd, args=nil) + if args + id = install_cmd(proc{|arg| + TkUtil.eval_cmd cmd, *arg + }) + id + " " + args + else + id = install_cmd(proc{|arg| + TkUtil.eval_cmd cmd, Event.new(*arg) + }) + id + ' %# %b %f %h %k %s %t %w %x %y %A %E %K %N %W %T %X %Y' + end + end + + def _bind(path, context, cmd, args=nil) + begin + id = install_bind(cmd, args) + tk_call 'bind', path, "<#{context}>", id + rescue + uninstall_cmd(id) + fail + end + end + private :install_bind, :_bind + + def bind_all(context, cmd=Proc.new, args=nil) + _bind 'all', context, cmd, args + end + + def pack(*args) + TkPack.configure *args + end + + def after(ms, cmd=Proc.new) + myid = _curr_cmd_id + tk_call 'after', ms, + install_cmd(proc{ + TkUtil.eval_cmd cmd + uninstall_cmd myid + }) + end +end + +module TkCore + include TkComm + extend TkComm + + INTERP = TclTkIp.new + INTERP._eval("proc rb_out {args} { ruby [format \"TkCore.callback %%Q!%s!\" $args] }") + + def TkCore.callback(arg) + arg = Array(tk_split_list(arg)) + TkUtil.eval_cmd Tk_CMDTBL[arg.shift], *arg + end + + def mainloop + TclTkLib.mainloop + end + + def _get_eval_string(*args) + argstr = "" + args.each{|arg| + next if arg == None + if arg.kind_of?(Hash) + str = hash_kv(arg).join(" ") + elsif arg == nil + str = "" + elsif arg == false + str = "0" + elsif arg == true + str = "1" + elsif (arg.respond_to?(:to_eval)) + str = arg.to_eval() + else + str = arg.to_s() + end + argstr += " " if argstr != "" + argstr += '"' + str.gsub(/[][$"]/, '\\\\\&') + '"' + } + return argstr + end + + def tk_call(*args) + argstr = _get_eval_string(*args) + + res = INTERP._eval(argstr) + if INTERP._return_value() != 0 + fail RuntimeError, res, error_at + end + return res + end +end + +module Tk + include TkCore + extend Tk + + def root + TkRoot.new + end + + def bell + tk_call 'bell' + end + + def mainloop + TclTkLib.mainloop + end + + module Scrollable + def xscrollcommand(cmd=Proc.new) + configure_cmd 'xscrollcommand', cmd + end + def yscrollcommand(cmd=Proc.new) + configure_cmd 'yscrollcommand', cmd + end + end + + module Wm + def aspect(*args) + w = window(tk_call('wm', 'grid', path, *args)) + w.split.collect{|s|s.to_i} if args.length == 0 + end + def client(name=None) + tk_call 'wm', 'client', path, name + end + def colormapwindows(*args) + list(tk_call('wm', 'colormapwindows', path, *args)) + end + def wm_command(value=None) + string(tk_call('wm', 'command', path, value)) + end + def deiconify + tk_call 'wm', 'deiconify', path + end + def focusmodel(*args) + tk_call 'wm', 'focusmodel', path, *args + end + def frame + tk_call 'wm', 'frame', path + end + def geometry(*args) + list(tk_call('wm', 'geometry', path, *args)) + end + def grid(*args) + w = tk_call('wm', 'grid', path, *args) + list(w) if args.size == 0 + end + def group(*args) + tk_call 'wm', 'path', path, *args + end + def iconbitmap(*args) + tk_call 'wm', 'bitmap', path, *args + end + def iconify + tk_call 'wm', 'iconify' + end + def iconmask(*args) + tk_call 'wm', 'iconmask', path, *args + end + def iconname(*args) + tk_call 'wm', 'iconname', path, *args + end + def iconposition(*args) + w = tk_call('wm', 'iconposition', path, *args) + list(w) if args.size == 0 + end + def iconwindow(*args) + tk_call 'wm', 'iconwindow', path, *args + end + def maxsize(*args) + w = tk_call('wm', 'maxsize', path, *args) + list(w) if not args.size == 0 + end + def minsize(*args) + w = tk_call('wm', 'minsize', path, *args) + list(w) if args.size == 0 + end + def overrideredirect(bool=None) + if bool == None + bool(tk_call('wm', 'overrideredirect', path)) + else + tk_call 'wm', 'overrideredirect', path, bool + end + end + def positionfrom(*args) + tk_call 'wm', 'positionfrom', path, *args + end + def protocol(name, func=None) + func = install_cmd(func) if not func == None + tk_call 'wm', 'command', path, name, func + end + def resizable(*args) + w = tk_call('wm', 'resizable', path, *args) + if args.length == 0 + list(w).collect{|e| bool(e)} + end + end + def sizefrom(*args) + list(tk_call('wm', 'sizefrom', path, *args)) + end + def state + tk_call 'wm', 'state', path + end + def title(*args) + tk_call 'wm', 'title', path, *args + end + def transient(*args) + tk_call 'wm', 'transient', path, *args + end + def withdraw + tk_call 'wm', 'withdraw', path + end + end +end + +class TkVariable + include Tk + + Tk_VARIABLE_ID = ["v00000"] + def initialize(val="") + @id = Tk_VARIABLE_ID[0] + Tk_VARIABLE_ID[0] = Tk_VARIABLE_ID[0].succ + INTERP._eval(format('global %s; set %s %s', @id, @id, _get_eval_string(val))) + end + + def id + @id + end + + def value + INTERP._eval(format('global %s; set %s', @id, @id)) + end + + def value=(val) + INTERP._eval(format('global %s; set %s %s', @id, @id, _get_eval_string(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 "", @id + end + + def ==(other) + case other + when TkVariable + self.equal(self) + when String + self.to_s == other + when Integer + self.to_i == other + when Float + self.to_f == other + when Array + self.to_a == other + else + false + end + end + + def to_a + list(value) + end + + def to_eval + @id + end end module TkSelection @@ -290,7 +761,7 @@ module TkPack end def propagate(master, bool=None) - bool(tk_call('pack', 'propagate', mastaer.epath, bool)) + bool(tk_call('pack', 'propagate', master.epath, bool)) end module_function :configure, :forget, :propagate end @@ -324,6 +795,10 @@ class TkObject", @id - end - - def to_a - list(value) - end -end - class TkWindow VALUE mMath; -VALUE float_new(); -VALUE f_float(); - -#define Need_Float(x) \ -if (FIXNUM_P(x)) {\ - (x) = (struct RFloat*)float_new((double)FIX2INT(x));\ -} else {\ - (x) = (struct RFloat*)f_float(x, x);\ -} +#define Need_Float(x) (x) = rb_Float(x) #define Need_Float2(x,y) {\ Need_Float(x);\ Need_Float(y);\ @@ -31,79 +23,71 @@ if (FIXNUM_P(x)) {\ static VALUE math_atan2(obj, x, y) - VALUE obj; - struct RFloat *x, *y; + VALUE obj, x, y; { Need_Float2(x, y); - return float_new(atan2(x->value, y->value)); + return float_new(atan2(RFLOAT(x)->value, RFLOAT(y)->value)); } static VALUE math_cos(obj, x) - VALUE obj; - struct RFloat *x; + VALUE obj, x; { Need_Float(x); - return float_new(cos(x->value)); + return float_new(cos(RFLOAT(x)->value)); } static VALUE math_sin(obj, x) - VALUE obj; - struct RFloat *x; + VALUE obj, x; { Need_Float(x); - return float_new(sin(x->value)); + return float_new(sin(RFLOAT(x)->value)); } static VALUE math_tan(obj, x) - VALUE obj; - struct RFloat *x; + VALUE obj, x; { Need_Float(x); - return float_new(tan(x->value)); + return float_new(tan(RFLOAT(x)->value)); } static VALUE math_exp(obj, x) - VALUE obj; - struct RFloat *x; + VALUE obj, x; { Need_Float(x); - return float_new(exp(x->value)); + return float_new(exp(RFLOAT(x)->value)); } static VALUE math_log(obj, x) - VALUE obj; - struct RFloat *x; + VALUE obj, x; { Need_Float(x); - return float_new(log(x->value)); + return float_new(log(RFLOAT(x)->value)); } static VALUE math_log10(obj, x) - VALUE obj; - struct RFloat *x; + VALUE obj, x; { Need_Float(x); - return float_new(log10(x->value)); + return float_new(log10(RFLOAT(x)->value)); } static VALUE math_sqrt(obj, x) - VALUE obj; - struct RFloat *x; + VALUE obj, x; { Need_Float(x); - if (x->value < 0.0) ArgError("square root for negative number"); - return float_new(sqrt(x->value)); + if (RFLOAT(x)->value < 0.0) ArgError("square root for negative number"); + return float_new(sqrt(RFLOAT(x)->value)); } void diff --git a/missing/dir.h b/missing/dir.h index 5c6281fdc2..34be77b9c0 100644 --- a/missing/dir.h +++ b/missing/dir.h @@ -183,66 +183,3 @@ void rewinddir(DIR *dirp); void closedir(DIR *dirp); #endif /* __DIR_INCLUDED */ -/* $RCSfile: dir.h,v $$Revision: 4.0.1.1 $$Date: 91/06/07 11:22:10 $ - * - * (C) Copyright 1987, 1990 Diomidis Spinellis. - * - * You may distribute under the terms of either the GNU General Public - * License or the Artistic License, as specified in the README file. - * - * $Log: dir.h,v $ - * Revision 4.0.1.1 91/06/07 11:22:10 lwall - * patch4: new copyright notice - * - * Revision 4.0 91/03/20 01:34:20 lwall - * 4.0 baseline. - * - * Revision 3.0.1.1 90/03/27 16:07:08 lwall - * patch16: MSDOS support - * - * Revision 1.1 90/03/18 20:32:29 dds - * Initial revision - * - * - */ - -/* - * defines the type returned by the directory(3) functions - */ - -#ifndef __DIR_INCLUDED -#define __DIR_INCLUDED - -/*Directory entry size */ -#ifdef DIRSIZ -#undef DIRSIZ -#endif -#define DIRSIZ(rp) (sizeof(struct direct)) - -/* - * Structure of a directory entry - */ -struct direct { - ino_t d_ino; /* inode number (not used by MS-DOS) */ - int d_namlen; /* Name length */ - char d_name[256]; /* file name */ -}; - -struct _dir_struc { /* Structure used by dir operations */ - char *start; /* Starting position */ - char *curr; /* Current position */ - long size; /* Size of string table */ - long nfiles; /* number if filenames in table */ - struct direct dirstr; /* Directory structure to return */ -}; - -typedef struct _dir_struc DIR; /* Type returned by dir operations */ - -DIR *cdecl opendir(char *filename); -struct direct *readdir(DIR *dirp); -long telldir(DIR *dirp); -void seekdir(DIR *dirp,long loc); -void rewinddir(DIR *dirp); -void closedir(DIR *dirp); - -#endif /* __DIR_INCLUDED */ diff --git a/missing/nt.c b/missing/nt.c index 1cd81fd28c..703556cad7 100644 --- a/missing/nt.c +++ b/missing/nt.c @@ -149,8 +149,8 @@ flock(int fd, int oper) #undef LK_LEN -#undef const -FILE *fdopen(int, const char *); +//#undef const +//FILE *fdopen(int, const char *); #if 0 void @@ -185,7 +185,7 @@ NtInitialize(int *argc, char ***argv) { tzset(); // Initialize Winsock - // StartSockets(); + StartSockets(); } @@ -501,7 +501,6 @@ mypopen (char *cmd, char *mode) return fp; } - fRet = CreatePipe(&hInFile, &hOutFile, &sa, 2048L); if (!fRet) Fatal("cannot open pipe \"%s\" (%s)", cmd, strerror(errno)); @@ -1572,7 +1571,7 @@ valid_filename(char *s) // FILE * -fdopen (int fd, const char *mode) +myfdopen (int fd, const char *mode) { FILE *fp; char sockbuf[80]; @@ -1580,6 +1579,8 @@ fdopen (int fd, const char *mode) int retval; extern int errno; + //fprintf(stderr, "myfdopen()\n"); + retval = getsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen); if (retval == SOCKET_ERROR) { int iRet; @@ -1951,8 +1952,10 @@ mysocket (int af, int type, int protocol) if (!NtSocketsInitialized++) { StartSockets(); } - if ((s = socket (af, type, protocol)) == INVALID_SOCKET) + if ((s = socket (af, type, protocol)) == INVALID_SOCKET) { errno = WSAGetLastError(); + //fprintf(stderr, "socket fail (%d)", WSAGetLastError()); + } return s; } diff --git a/missing/nt.h b/missing/nt.h index 5977a59a1d..830b9edf13 100644 --- a/missing/nt.h +++ b/missing/nt.h @@ -147,6 +147,29 @@ extern char *NtGetLib(void); extern char *NtGetBin(void); extern FILE *mypopen(char *, char *); extern int flock(int fd, int oper); +extern FILE * myfdopen(int, char*); +extern SOCKET myaccept(SOCKET, struct sockaddr *, int *); +extern int mybind(SOCKET, struct sockaddr *, int); +extern int myconnect(SOCKET, struct sockaddr *, int); +extern int mygetpeername(SOCKET, struct sockaddr *, int *); +extern int mygetsockname(SOCKET, struct sockaddr *, int *); +extern int mygetsockopt(SOCKET, int, int, char *, int *); +extern int myioctlsocket(SOCKET, long, u_long *); +extern int mylisten(SOCKET, int); +extern int myrecv(SOCKET, char *, int, int); +extern int myrecvfrom(SOCKET, char *, int, int, struct sockaddr *, int *); +extern int mysend(SOCKET, char *, int, int); +extern int mysendto(SOCKET, char *, int, int, struct sockaddr *, int); +extern int mysetsockopt(SOCKET, int, int, char *, int); +extern int myshutdown(SOCKET, int); +extern SOCKET mysocket(int, int, int); +extern struct hostent * mygethostbyaddr(char *, int, int); +extern struct hostent * mygethostbyname(char *); +extern int mygethostname(char *, int); +extern struct protoent * mygetprotobyname(char *); +extern struct protoent * mygetprotobynumber(int); +extern struct servent * mygetservbyname(char *, char *); +extern struct servent * mygetservbyport(int, char *); // // define this so we can do inplace editing @@ -222,4 +245,118 @@ extern char *mystrerror(int); #undef va_start #undef va_end +#ifdef fdopen +#undef fdopen +#endif +#define fdopen myfdopen + +#ifdef accept +#undef accept +#endif +#define accept myaccept + +#ifdef bind +#undef bind +#endif +#define bind mybind + +#ifdef connect +#undef connect +#endif +#define connect myconnect + +#ifdef getpeername +#undef getpeername +#endif +#define getpeername mygetpeername + +#ifdef getsockname +#undef getsockname +#endif +#define getsockname mygetsockname + +#ifdef getsockopt +#undef getsockopt +#endif +#define getsockopt mygetsockopt + +#ifdef ioctlsocket +#undef ioctlsocket +#endif +#define ioctlsocket myioctlsocket + +#ifdef listen +#undef listen +#endif +#define listen mylisten + +#ifdef recv +#undef recv +#endif +#define recv myrecv + +#ifdef recvfrom +#undef recvfrom +#endif +#define recvfrom myrecvfrom + +#ifdef send +#undef send +#endif +#define send mysend + +#ifdef sendto +#undef sendto +#endif +#define sendto mysendto + +#ifdef setsockopt +#undef setsockopt +#endif +#define setsockopt mysetsockopt + +#ifdef shutdown +#undef shutdown +#endif +#define shutdown myshutdown + +#ifdef socket +#undef socket +#endif +#define socket mysocket + +#ifdef gethostbyaddr +#undef gethostbyaddr +#endif +#define gethostbyaddr mygethostbyaddr + +#ifdef gethostbyname +#undef gethostbyname +#endif +#define gethostbyname mygethostbyname + +#ifdef gethostname +#undef gethostname +#endif +#define gethostname mygethostname + +#ifdef getprotobyname +#undef getprotobyname +#endif +#define getprotobyname mygetprotobyname + +#ifdef getprotobynumber +#undef getprotobynumber +#endif +#define getprotobynumber mygetprotobynumber + +#ifdef getservbyname +#undef getservbyname +#endif +#define getservbyname mygetservbyname + +#ifdef getservbyport +#undef getservbyport +#endif +#define getservbyport mygetservbyport #endif diff --git a/missing/setenv.c b/missing/setenv.c index b7b43a674b..c9cb4b20e0 100644 --- a/missing/setenv.c +++ b/missing/setenv.c @@ -16,6 +16,10 @@ extern char **origenviron; char *strdup(); #endif +#ifdef USE_WIN32_RTL_ENV +#include +#endif + static int envix(nam) char *nam; @@ -29,9 +33,11 @@ char *nam; return i; } +#ifndef WIN32 void -setenv(nam,val) +setenv(nam,val, n) char *nam, *val; +int n; { register int i=envix(nam); /* where does it go? */ @@ -75,3 +81,69 @@ char *nam, *val; (void)sprintf(environ[i] + strlen(nam),"=%s",val); #endif /* MSDOS */ } +#else /* if WIN32 */ +void +setenv(nam,val, n) +char *nam, *val; +int n; +{ +#ifdef USE_WIN32_RTL_ENV + + register char *envstr; + STRLEN namlen = strlen(nam); + STRLEN vallen; + char *oldstr = environ[envix(nam)]; + + /* putenv() has totally broken semantics in both the Borland + * and Microsoft CRTLs. They either store the passed pointer in + * the environment without making a copy, or make a copy and don't + * free it. And on top of that, they dont free() old entries that + * are being replaced/deleted. This means the caller must + * free any old entries somehow, or we end up with a memory + * leak every time setenv() is called. One might think + * one could directly manipulate environ[], like the UNIX code + * above, but direct changes to environ are not allowed when + * calling putenv(), since the RTLs maintain an internal + * *copy* of environ[]. Bad, bad, *bad* stink. + * GSAR 97-06-07 + */ + + if (!val) { + if (!oldstr) + return; + val = ""; + vallen = 0; + } + else + vallen = strlen(val); + envstr = ALLOC_N(char, namelen + vallen + 3); + (void)sprintf(envstr,"%s=%s",nam,val); + (void)putenv(envstr); + if (oldstr) + free(oldstr); +#ifdef _MSC_VER + free(envstr); /* MSVCRT leaks without this */ +#endif + +#else /* !USE_WIN32_RTL_ENV */ + + /* The sane way to deal with the environment. + * Has these advantages over putenv() & co.: + * * enables us to store a truly empty value in the + * environment (like in UNIX). + * * we don't have to deal with RTL globals, bugs and leaks. + * * Much faster. + * Why you may want to enable USE_WIN32_RTL_ENV: + * * environ[] and RTL functions will not reflect changes, + * which might be an issue if extensions want to access + * the env. via RTL. This cuts both ways, since RTL will + * not see changes made by extensions that call the Win32 + * functions directly, either. + * GSAR 97-06-07 + */ + SetEnvironmentVariable(nam,val); + +#endif +} + +#endif /* WIN32 */ diff --git a/node.h b/node.h index db5824bbc5..cdb354c007 100644 --- a/node.h +++ b/node.h @@ -13,8 +13,6 @@ #ifndef NODE_H #define NODE_H -struct global_entry *rb_global_entry(); - enum node_type { NODE_METHOD, NODE_FBODY, @@ -29,6 +27,10 @@ enum node_type { NODE_UNTIL, NODE_ITER, NODE_FOR, + NODE_BREAK, + NODE_NEXT, + NODE_REDO, + NODE_RETRY, NODE_BEGIN, NODE_RESCUE, NODE_RESBODY, @@ -64,6 +66,8 @@ enum node_type { NODE_MATCH_REF, NODE_LASTLINE, NODE_MATCH, + NODE_MATCH2, + NODE_MATCH3, NODE_LIT, NODE_STR, NODE_DSTR, @@ -91,14 +95,17 @@ enum node_type { NODE_ATTRSET, NODE_SELF, NODE_NIL, + NODE_TRUE, + NODE_FALSE, NODE_DEFINED, NODE_TAG, NODE_NEWLINE, + NODE_POSTEXE, }; typedef struct RNode { UINT flags; - char *file; + char *nd_file; union { struct RNode *node; ID id; @@ -185,7 +192,7 @@ typedef struct RNode { #define nd_argc u2.argc #define nd_cname u1.id -#define nd_super u3.id +#define nd_super u3.node #define nd_modl u1.id #define nd_clss u1.value @@ -201,8 +208,6 @@ typedef struct RNode { #define nd_tlev u3.cnt #define nd_tval u2.value -#define nd_file file - #define NEW_METHOD(n,x) node_newnode(NODE_METHOD,x,n,0) #define NEW_FBODY(n,i,o) node_newnode(NODE_FBODY,n,i,o) #define NEW_DEFN(i,a,d,p) node_newnode(NODE_DEFN,p,i,NEW_RFUNC(a,d)) @@ -220,6 +225,10 @@ typedef struct RNode { #define NEW_UNTIL(c,b,n) node_newnode(NODE_UNTIL,c,b,n) #define NEW_FOR(v,i,b) node_newnode(NODE_FOR,v,b,i) #define NEW_ITER(v,i,b) node_newnode(NODE_ITER,v,b,i) +#define NEW_BREAK() node_newnode(NODE_BREAK,0,0,0) +#define NEW_NEXT() node_newnode(NODE_NEXT,0,0,0) +#define NEW_REDO() node_newnode(NODE_REDO,0,0,0) +#define NEW_RETRY() node_newnode(NODE_RETRY,0,0,0) #define NEW_BEGIN(b) node_newnode(NODE_BEGIN,0,b,0) #define NEW_RESCUE(b,res) node_newnode(NODE_RESCUE,b,res,0) #define NEW_RESBODY(a,ex,n) node_newnode(NODE_RESBODY,n,ex,a) @@ -248,6 +257,8 @@ typedef struct RNode { #define NEW_NTH_REF(n) node_newnode(NODE_NTH_REF,0,n,local_cnt('~')) #define NEW_BACK_REF(n) node_newnode(NODE_BACK_REF,0,n,local_cnt('~')) #define NEW_MATCH(c) node_newnode(NODE_MATCH,c,0,0) +#define NEW_MATCH2(n1,n2) node_newnode(NODE_MATCH2,n1,n2,0) +#define NEW_MATCH3(r,n2) node_newnode(NODE_MATCH3,r,n2,0) #define NEW_LIT(l) node_newnode(NODE_LIT,l,0,0) #define NEW_STR(s) node_newnode(NODE_STR,s,0,0) #define NEW_DSTR(s) node_newnode(NODE_DSTR,s,0,0) @@ -275,8 +286,12 @@ typedef struct RNode { #define NEW_ATTRSET(a) node_newnode(NODE_ATTRSET,a,0,0) #define NEW_SELF() node_newnode(NODE_SELF,0,0,0) #define NEW_NIL() node_newnode(NODE_NIL,0,0,0) +#define NEW_TRUE() node_newnode(NODE_TRUE,0,0,0) +#define NEW_FALSE() node_newnode(NODE_FALSE,0,0,0) #define NEW_DEFINED(e) node_newnode(NODE_DEFINED,e,0,0) #define NEW_NEWLINE(n) node_newnode(NODE_NEWLINE,0,0,n) +#define NEW_PREEXE(b) NEW_SCOPE(b) +#define NEW_POSTEXE() node_newnode(NODE_POSTEXE,0,0,0) NODE *node_newnode(); VALUE rb_method_booundp(); @@ -284,7 +299,19 @@ VALUE rb_method_booundp(); #define NOEX_PUBLIC 0 #define NOEX_PRIVATE 1 -NODE *compile_string(); -NODE *compile_file(); +NODE *compile_string _((char *, char *, int)); +NODE *compile_file _((char *, VALUE, int)); + +void rb_add_method _((VALUE, ID, NODE *, int)); +void rb_remove_method _((VALUE, ID)); +NODE *node_newnode(); + +enum node_type nodetype _((NODE *)); +int nodeline _((NODE *)); + +struct global_entry *rb_global_entry _((ID)); +VALUE rb_gvar_get _((struct global_entry *)); +VALUE rb_gvar_set _((struct global_entry *, VALUE)); +VALUE rb_gvar_defined _((struct global_entry *)); #endif diff --git a/numeric.c b/numeric.c index 242d13c14e..b0d5f7f522 100644 --- a/numeric.c +++ b/numeric.c @@ -12,11 +12,6 @@ #include "ruby.h" #include -#if defined (HAVE_STRING_H) -# include -#else -# include -#endif static ID coerce; static ID to_i; @@ -42,7 +37,7 @@ static VALUE num_coerce(x, y) VALUE x, y; { - return assoc_new(f_float(x,x),f_float(y,y)); + return assoc_new(rb_Float(x),rb_Float(y)); } VALUE @@ -116,7 +111,7 @@ num_chr(num) VALUE num; { char c; - int i = NUM2INT(num); + INT i = NUM2INT(num); if (i < 0 || 0xff < i) Fail("%d out of char range", i); @@ -147,11 +142,11 @@ float_new(d) static VALUE flo_to_s(flt) - struct RFloat *flt; + VALUE flt; { char buf[32]; - sprintf(buf, "%g", flt->value); + sprintf(buf, "%g", RFLOAT(flt)->value); if (strchr(buf, '.') == 0) { int len = strlen(buf); char *ind = strchr(buf, 'e'); @@ -172,27 +167,27 @@ static VALUE flo_coerce(x, y) VALUE x, y; { - return assoc_new(f_float(x, y), x); + return assoc_new(rb_Float(y), x); } static VALUE flo_uminus(flt) - struct RFloat *flt; + VALUE flt; { - return float_new(-flt->value); + return float_new(-RFLOAT(flt)->value); } static VALUE flo_plus(x, y) - struct RFloat *x, *y; + VALUE x, y; { switch (TYPE(y)) { case T_FIXNUM: - return float_new(x->value + (double)FIX2INT(y)); + return float_new(RFLOAT(x)->value + (double)FIX2INT(y)); case T_BIGNUM: - return float_new(x->value + big2dbl(y)); + return float_new(RFLOAT(x)->value + big2dbl(y)); case T_FLOAT: - return float_new(x->value + y->value); + return float_new(RFLOAT(x)->value + RFLOAT(y)->value); case T_STRING: return str_plus(obj_as_string(x), y); default: @@ -202,15 +197,15 @@ flo_plus(x, y) static VALUE flo_minus(x, y) - struct RFloat *x, *y; + VALUE x, y; { switch (TYPE(y)) { case T_FIXNUM: - return float_new(x->value - (double)FIX2INT(y)); + return float_new(RFLOAT(x)->value - (double)FIX2INT(y)); case T_BIGNUM: - return float_new(x->value - big2dbl(y)); + return float_new(RFLOAT(x)->value - big2dbl(y)); case T_FLOAT: - return float_new(x->value - y->value); + return float_new(RFLOAT(x)->value - RFLOAT(y)->value); default: return num_coerce_bin(x, y); } @@ -218,17 +213,17 @@ flo_minus(x, y) static VALUE flo_mul(x, y) - struct RFloat *x, *y; + VALUE x, y; { switch (TYPE(y)) { case T_FIXNUM: - return float_new(x->value * (double)FIX2INT(y)); + return float_new(RFLOAT(x)->value * (double)FIX2INT(y)); case T_BIGNUM: - return float_new(x->value * big2dbl(y)); + return float_new(RFLOAT(x)->value * big2dbl(y)); case T_FLOAT: - return float_new(x->value * y->value); + return float_new(RFLOAT(x)->value * RFLOAT(y)->value); case T_STRING: - return str_times(y, INT2FIX((int)x->value)); + return str_times(y, INT2FIX((int)RFLOAT(x)->value)); default: return num_coerce_bin(x, y); } @@ -236,23 +231,23 @@ flo_mul(x, y) static VALUE flo_div(x, y) - struct RFloat *x, *y; + VALUE x, y; { - int f_y; + INT f_y; double d; switch (TYPE(y)) { case T_FIXNUM: f_y = FIX2INT(y); if (f_y == 0) num_zerodiv(); - return float_new(x->value / (double)f_y); + return float_new(RFLOAT(x)->value / (double)f_y); case T_BIGNUM: d = big2dbl(y); if (d == 0.0) num_zerodiv(); - return float_new(x->value / d); + return float_new(RFLOAT(x)->value / d); case T_FLOAT: - if (y->value == 0.0) num_zerodiv(); - return float_new(x->value / y->value); + if (RFLOAT(y)->value == 0.0) num_zerodiv(); + return float_new(RFLOAT(x)->value / RFLOAT(y)->value); default: return num_coerce_bin(x, y); } @@ -260,7 +255,7 @@ flo_div(x, y) static VALUE flo_mod(x, y) - struct RFloat *x, *y; + VALUE x, y; { double value; @@ -272,16 +267,16 @@ flo_mod(x, y) value = big2dbl(y); break; case T_FLOAT: - value = y->value; + value = RFLOAT(y)->value; break; default: return num_coerce_bin(x, y); } #ifdef HAVE_FMOD - value = fmod(x->value, value); + value = fmod(RFLOAT(x)->value, value); #else { - double value1 = x->value; + double value1 = RFLOAT(x)->value; double value2; modf(value1/value, &value2); @@ -294,15 +289,15 @@ flo_mod(x, y) VALUE flo_pow(x, y) - struct RFloat *x, *y; + VALUE x, y; { switch (TYPE(y)) { case T_FIXNUM: - return float_new(pow(x->value, (double)FIX2INT(y))); + return float_new(pow(RFLOAT(x)->value, (double)FIX2INT(y))); case T_BIGNUM: - return float_new(pow(x->value, big2dbl(y))); + return float_new(pow(RFLOAT(x)->value, big2dbl(y))); case T_FLOAT: - return float_new(pow(x->value, y->value)); + return float_new(pow(RFLOAT(x)->value, RFLOAT(y)->value)); default: return num_coerce_bin(x, y); } @@ -327,16 +322,16 @@ num_equal(x, y) static VALUE flo_eq(x, y) - struct RFloat *x, *y; + VALUE x, y; { switch (TYPE(y)) { case T_FIXNUM: - if (x->value == FIX2INT(y)) return TRUE; + if (RFLOAT(x)->value == FIX2INT(y)) return TRUE; return FALSE; case T_BIGNUM: - return (x->value == big2dbl(y))?TRUE:FALSE; + return (RFLOAT(x)->value == big2dbl(y))?TRUE:FALSE; case T_FLOAT: - return (x->value == y->value)?TRUE:FALSE; + return (RFLOAT(x)->value == RFLOAT(y)->value)?TRUE:FALSE; default: return num_equal(x, y); } @@ -344,13 +339,13 @@ flo_eq(x, y) static VALUE flo_hash(num) - struct RFloat *num; + VALUE num; { double d; char *c; int i, hash; - d = num->value; + d = RFLOAT(num)->value; c = (char*)&d; for (hash=0, i=0; ivalue; + a = RFLOAT(x)->value; switch (TYPE(y)) { case T_FIXNUM: b = (double)FIX2INT(y); @@ -376,7 +371,7 @@ flo_cmp(x, y) break; case T_FLOAT: - b = y->value; + b = RFLOAT(y)->value; break; default: @@ -389,19 +384,20 @@ flo_cmp(x, y) static VALUE flo_eql(x, y) - struct RFloat *x, *y; + VALUE x, y; { if (TYPE(y) == T_FLOAT) { - if (x->value == y->value) return TRUE; + if (RFLOAT(x)->value == RFLOAT(y)->value) return TRUE; } + return FALSE; } static VALUE flo_to_i(num) - struct RFloat *num; + VALUE num; { - double f = num->value; - int val; + double f = RFLOAT(num)->value; + INT val; if (!FIXABLE(f)) { return dbl2big(f); @@ -419,9 +415,9 @@ flo_to_f(num) static VALUE flo_abs(flt) - struct RFloat *flt; + VALUE flt; { - double val = fabs(flt->value); + double val = fabs(RFLOAT(flt)->value); return float_new(val); } @@ -472,7 +468,7 @@ VALUE num2fix(val) VALUE val; { - int v; + INT v; if (NIL_P(val)) return INT2FIX(0); switch (TYPE(val)) { @@ -515,12 +511,12 @@ fix2str(x, base) VALUE x; int base; { - char fmt[3], buf[12]; + char fmt[4], buf[22]; - fmt[0] = '%'; fmt[2] = '\0'; - if (base == 10) fmt[1] = 'd'; - else if (base == 16) fmt[1] = 'x'; - else if (base == 8) fmt[1] = 'o'; + fmt[0] = '%'; fmt[1] = 'l'; fmt[3] = '\0'; + if (base == 10) fmt[2] = 'd'; + else if (base == 16) fmt[2] = 'x'; + else if (base == 8) fmt[2] = 'o'; else Fatal("fixnum cannot treat base %d", base); sprintf(buf, fmt, FIX2INT(x)); @@ -536,13 +532,12 @@ fix_to_s(in) static VALUE fix_plus(x, y) - VALUE x; - struct RFloat *y; + VALUE x, y; { switch (TYPE(y)) { case T_FIXNUM: { - int a, b, c; + INT a, b, c; VALUE r; a = FIX2INT(x); @@ -556,7 +551,7 @@ fix_plus(x, y) return r; } case T_FLOAT: - return float_new((double)FIX2INT(x) + y->value); + return float_new((double)FIX2INT(x) + RFLOAT(y)->value); default: return num_coerce_bin(x, y); } @@ -564,13 +559,12 @@ fix_plus(x, y) static VALUE fix_minus(x, y) - VALUE x; - struct RFloat *y; + VALUE x, y; { switch (TYPE(y)) { case T_FIXNUM: { - int a, b, c; + INT a, b, c; VALUE r; a = FIX2INT(x); @@ -584,7 +578,7 @@ fix_minus(x, y) return r; } case T_FLOAT: - return float_new((double)FIX2INT(x) - y->value); + return float_new((double)FIX2INT(x) - RFLOAT(y)->value); default: return num_coerce_bin(x, y); } @@ -592,13 +586,12 @@ fix_minus(x, y) static VALUE fix_mul(x, y) - VALUE x; - struct RFloat *y; + VALUE x, y; { switch (TYPE(y)) { case T_FIXNUM: { - int a, b, c; + INT a, b, c; VALUE r; a = FIX2INT(x); @@ -614,7 +607,7 @@ fix_mul(x, y) return r; } case T_FLOAT: - return float_new((double)FIX2INT(x) * y->value); + return float_new((double)FIX2INT(x) * RFLOAT(y)->value); default: return num_coerce_bin(x, y); } @@ -622,10 +615,9 @@ fix_mul(x, y) static VALUE fix_div(x, y) - VALUE x; - struct RFloat *y; + VALUE x, y; { - int i; + INT i; if (TYPE(y) == T_FIXNUM) { i = FIX2INT(y); @@ -640,7 +632,7 @@ static VALUE fix_mod(x, y) VALUE x, y; { - int i; + INT i; if (TYPE(y) == T_FIXNUM) { i = FIX2INT(y); @@ -656,7 +648,7 @@ fix_pow(x, y) VALUE x, y; { if (FIXNUM_P(y)) { - int a, b; + INT a, b; b = FIX2INT(y); if (b == 0) return INT2FIX(1); @@ -689,7 +681,7 @@ fix_cmp(x, y) VALUE x, y; { if (FIXNUM_P(y)) { - int a = FIX2INT(x), b = FIX2INT(y); + INT a = FIX2INT(x), b = FIX2INT(y); if (a == b) return INT2FIX(0); if (a > b) return INT2FIX(1); @@ -705,7 +697,7 @@ fix_gt(x, y) VALUE x, y; { if (FIXNUM_P(y)) { - int a = FIX2INT(x), b = FIX2INT(y); + INT a = FIX2INT(x), b = FIX2INT(y); if (a > b) return TRUE; return FALSE; @@ -720,7 +712,7 @@ fix_ge(x, y) VALUE x, y; { if (FIXNUM_P(y)) { - int a = FIX2INT(x), b = FIX2INT(y); + INT a = FIX2INT(x), b = FIX2INT(y); if (a >= b) return TRUE; return FALSE; @@ -735,7 +727,7 @@ fix_lt(x, y) VALUE x, y; { if (FIXNUM_P(y)) { - int a = FIX2INT(x), b = FIX2INT(y); + INT a = FIX2INT(x), b = FIX2INT(y); if (a < b) return TRUE; return FALSE; @@ -750,7 +742,7 @@ fix_le(x, y) VALUE x, y; { if (FIXNUM_P(y)) { - int a = FIX2INT(x), b = FIX2INT(y); + INT a = FIX2INT(x), b = FIX2INT(y); if (a <= b) return TRUE; return FALSE; @@ -876,14 +868,14 @@ static VALUE fix_type(fix) VALUE fix; { - return str_new2("Fixnum"); + return cFixnum; } static VALUE fix_abs(fix) VALUE fix; { - int i = FIX2INT(fix); + INT i = FIX2INT(fix); if (i < 0) i = -i; @@ -903,7 +895,7 @@ static VALUE fix_succ(fix) VALUE fix; { - int i = FIX2INT(fix) + 1; + INT i = FIX2INT(fix) + 1; return int2inum(i); } @@ -912,7 +904,7 @@ static VALUE fix_size(fix) VALUE fix; { - return INT2FIX(sizeof(VALUE)); + return INT2FIX(sizeof(INT)); } VALUE @@ -951,7 +943,7 @@ num_step(from, to, step) ID cmp; if (step == INT2FIX(0)) { - IndexError("step cannot be 0"); + ArgError("step cannot be 0"); } if (RTEST(rb_funcall(step, '>', 1, INT2FIX(0)))) { @@ -986,7 +978,7 @@ VALUE fix_upto(from, to) VALUE from, to; { - int i, end; + INT i, end; if (!FIXNUM_P(to)) return num_upto(from, to); end = FIX2INT(to); @@ -1001,7 +993,7 @@ static VALUE fix_downto(from, to) VALUE from, to; { - int i, end; + INT i, end; if (!FIXNUM_P(to)) return num_downto(from, to); end = FIX2INT(to); @@ -1016,7 +1008,7 @@ static VALUE fix_step(from, to, step) VALUE from, to, step; { - int i, end, diff; + INT i, end, diff; if (!FIXNUM_P(to) || !FIXNUM_P(step)) return num_step(from, to, step); @@ -1044,7 +1036,7 @@ static VALUE fix_dotimes(num) VALUE num; { - int i, end; + INT i, end; end = FIX2INT(num); for (i=0; isuper; + } + return cl; } static VALUE @@ -91,13 +96,13 @@ obj_clone(obj) if (TYPE(obj) != T_OBJECT) { TypeError("can't clone %s", rb_class2name(CLASS_OF(obj))); } - clone = obj_alloc(RBASIC(obj)->class); + CLONESETUP(clone,obj); if (ROBJECT(obj)->iv_tbl) { ROBJECT(clone)->iv_tbl = st_copy(ROBJECT(obj)->iv_tbl); - } RBASIC(clone)->class = singleton_class_clone(RBASIC(obj)->class); RBASIC(clone)->flags = RBASIC(obj)->flags; + } return clone; } @@ -130,15 +135,15 @@ static int inspect_i(id, value, str) ID id; VALUE value; - struct RString *str; + VALUE str; { VALUE str2; char *ivname; /* need not to show internal data */ if (CLASS_OF(value) == 0) return ST_CONTINUE; - if (str->ptr[0] == '-') { - str->ptr[0] = '#'; + if (RSTRING(str)->ptr[0] == '-') { + RSTRING(str)->ptr[0] = '#'; str_cat(str, ": ", 2); } else { @@ -160,17 +165,18 @@ inspect_i(id, value, str) static VALUE obj_inspect(obj) - struct RObject *obj; + VALUE obj; { if (TYPE(obj) == T_OBJECT - && obj->iv_tbl && obj->iv_tbl->num_entries > 0) { + && ROBJECT(obj)->iv_tbl + && ROBJECT(obj)->iv_tbl->num_entries > 0) { VALUE str; char *b; str = str_new2("-<"); b = rb_class2name(CLASS_OF(obj)); str_cat(str, b, strlen(b)); - st_foreach(obj->iv_tbl, inspect_i, str); + st_foreach(ROBJECT(obj)->iv_tbl, inspect_i, str); str_cat(str, ">", 1); return str; @@ -182,7 +188,7 @@ VALUE obj_is_instance_of(obj, c) VALUE obj, c; { - struct RClass *class = (struct RClass*)CLASS_OF(obj); + VALUE cl; switch (TYPE(c)) { case T_MODULE: @@ -205,10 +211,11 @@ obj_is_instance_of(obj, c) TypeError("class or module required"); } - while (FL_TEST(class, FL_SINGLETON)) { - class = class->super; + cl = CLASS_OF(obj); + while (FL_TEST(cl, FL_SINGLETON)) { + cl = RCLASS(cl)->super; } - if (c == (VALUE)class) return TRUE; + if (c == cl) return TRUE; return FALSE; } @@ -216,7 +223,7 @@ VALUE obj_is_kind_of(obj, c) VALUE obj, c; { - struct RClass *class = (struct RClass*)CLASS_OF(obj); + VALUE cl = CLASS_OF(obj); switch (TYPE(c)) { case T_MODULE: @@ -239,33 +246,33 @@ obj_is_kind_of(obj, c) TypeError("class or module required"); } - while (class) { - if ((VALUE)class == c || RCLASS(class)->m_tbl == RCLASS(c)->m_tbl) + while (cl) { + if (cl == c || RCLASS(cl)->m_tbl == RCLASS(c)->m_tbl) return TRUE; - class = class->super; + cl = RCLASS(cl)->super; } return FALSE; } static VALUE -obj_initialize(obj) +obj_dummy(obj) VALUE obj; { return Qnil; } static VALUE -obj_s_added(obj, id) - VALUE obj, id; +nil_to_s(obj) + VALUE obj; { - return Qnil; + return str_new2(""); } static VALUE -nil_to_s(obj) +nil_to_a(obj) VALUE obj; { - return str_new2(""); + return ary_new2(0); } static VALUE @@ -279,7 +286,7 @@ static VALUE nil_type(obj) VALUE obj; { - return str_new2("nil"); + return cNilClass; } static VALUE @@ -311,28 +318,28 @@ static VALUE true_to_s(obj) VALUE obj; { - return str_new2("TRUE"); + return str_new2("true"); } static VALUE true_type(obj) VALUE obj; { - return str_new2("TRUE"); + return cTrueClass; } static VALUE false_to_s(obj) VALUE obj; { - return str_new2("FALSE"); + return str_new2("false"); } static VALUE false_type(obj) VALUE obj; { - return str_new2("FALSE"); + return cFalseClass; } static VALUE @@ -362,15 +369,15 @@ obj_alloc(class) static VALUE mod_clone(module) - struct RClass *module; + VALUE module; { NEWOBJ(clone, struct RClass); OBJSETUP(clone, CLASS_OF(module), TYPE(module)); - clone->super = module->super; + clone->super = RCLASS(module)->super; clone->iv_tbl = 0; clone->m_tbl = 0; /* avoid GC crashing */ - clone->m_tbl = st_copy(module->m_tbl); + clone->m_tbl = st_copy(RCLASS(module)->m_tbl); return (VALUE)clone; } @@ -389,15 +396,89 @@ mod_eqq(mod, arg) return obj_is_kind_of(arg, mod); } +static VALUE +mod_le(mod, arg) + VALUE mod, arg; +{ + switch (TYPE(arg)) { + case T_MODULE: + case T_CLASS: + break; + default: + TypeError("compared with non class/module"); + } + + while (mod) { + if (RCLASS(mod)->m_tbl == RCLASS(arg)->m_tbl) + return TRUE; + mod = RCLASS(mod)->super; + } + + return FALSE; +} + +static VALUE +mod_lt(mod, arg) + VALUE mod, arg; +{ + if (mod == arg) return FALSE; + return mod_le(mod, arg); +} + +static VALUE +mod_ge(mod, arg) + VALUE mod, arg; +{ + switch (TYPE(arg)) { + case T_MODULE: + case T_CLASS: + break; + default: + TypeError("compared with non class/module"); + } + + return mod_lt(arg, mod); +} + +static VALUE +mod_gt(mod, arg) + VALUE mod, arg; +{ + if (mod == arg) return FALSE; + return mod_ge(mod, arg); +} + +static VALUE +mod_cmp(mod, arg) + VALUE mod, arg; +{ + if (mod == arg) return INT2FIX(0); + + switch (TYPE(arg)) { + case T_MODULE: + case T_CLASS: + break; + default: + TypeError("<=> requires Class or Module (%s given)", + rb_class2name(CLASS_OF(arg))); + break; + } + + if (mod_le(mod, arg)) { + return INT2FIX(-1); + } + return INT2FIX(1); +} + VALUE module_new(); VALUE class_new_instance(); static VALUE -class_s_new(argc, argv, class) +class_s_new(argc, argv) int argc; VALUE *argv; { - VALUE super, cls; + VALUE super, klass; rb_scan_args(argc, argv, "01", &super); if (NIL_P(super)) super = cObject; @@ -405,26 +486,33 @@ class_s_new(argc, argv, class) if (FL_TEST(super, FL_SINGLETON)) { TypeError("can't make subclass of virtual class"); } - cls = class_new(super); + klass = class_new(super); /* make metaclass */ - RBASIC(cls)->class = singleton_class_new(RBASIC(super)->class); + RBASIC(klass)->class = singleton_class_new(RBASIC(super)->class); + singleton_class_attached(RBASIC(klass)->class, klass); - return cls; + return klass; } +VALUE mod_name(); +VALUE mod_included_modules(); +VALUE mod_ancestors(); +VALUE class_instance_methods(); +VALUE class_private_instance_methods(); + static VALUE -class_superclass(class) - struct RClass *class; +class_superclass(cl) + VALUE cl; { - struct RClass *super = class->super; + VALUE super = RCLASS(cl)->super; while (TYPE(super) == T_ICLASS) { - super = super->super; + super = RCLASS(super)->super; } if (!super) { return Qnil; } - return (VALUE)super; + return super; } ID @@ -447,10 +535,101 @@ mod_attr(argc, argv, class) VALUE name, pub; rb_scan_args(argc, argv, "11", &name, &pub); - rb_define_attr(class, rb_to_id(name), RTEST(pub)); + rb_define_attr(class, rb_to_id(name), 1, RTEST(pub)); + return Qnil; +} + +static VALUE +mod_attr_reader(argc, argv, class) + int argc; + VALUE *argv; + VALUE class; +{ + int i; + + for (i=0; ivalue; +} + static VALUE f_string(obj, arg) VALUE obj, arg; @@ -518,11 +721,37 @@ f_string(obj, arg) return rb_funcall(arg, rb_intern("to_s"), 0); } +VALUE +rb_String(val) + VALUE val; +{ + return f_string(Qnil, val); +} + static VALUE f_array(obj, arg) VALUE obj, arg; { - return rb_funcall(arg, rb_intern("to_a"), 0); + if (TYPE(arg) == T_ARRAY) return arg; + arg = rb_funcall(arg, rb_intern("to_a"), 0); + if (TYPE(arg) != T_ARRAY) { + TypeError("`to_a' did not return Array"); + } + return arg; +} + +VALUE +rb_Array(val) + VALUE val; +{ + return f_array(Qnil, val); +} + +VALUE +rb_to_a(val) /* backward compatibility */ + VALUE val; +{ + return f_array(Qnil, val); } static VALUE @@ -531,7 +760,7 @@ boot_defclass(name, super) VALUE super; { extern st_table *rb_class_tbl; - struct RClass *obj = (struct RClass*)class_new(super); + VALUE obj = class_new(super); ID id = rb_intern(name); rb_name_class(obj, id); @@ -551,30 +780,6 @@ rb_class_of(obj) return RBASIC(obj)->class; } -int -rb_type(obj) - VALUE obj; -{ - if (FIXNUM_P(obj)) return T_FIXNUM; - if (obj == Qnil) return T_NIL; - if (obj == FALSE) return T_FALSE; - if (obj == TRUE) return T_TRUE; - - return BUILTIN_TYPE(obj); -} - -int -rb_special_const_p(obj) - VALUE obj; -{ - if (FIXNUM_P(obj)) return TRUE; - if (obj == Qnil) return TRUE; - if (obj == FALSE) return TRUE; - if (obj == TRUE) return TRUE; - - return FALSE; -} - VALUE TopSelf; void @@ -587,11 +792,15 @@ Init_Object() cClass = boot_defclass("Class", cModule); metaclass = RBASIC(cObject)->class = singleton_class_new(cClass); + singleton_class_attached(metaclass, cObject); metaclass = RBASIC(cModule)->class = singleton_class_new(metaclass); + singleton_class_attached(metaclass, cModule); metaclass = RBASIC(cClass)->class = singleton_class_new(metaclass); + singleton_class_attached(metaclass, cClass); mKernel = rb_define_module("Kernel"); rb_include_module(cObject, mKernel); + rb_define_private_method(cClass, "inherited", obj_dummy, 1); /* * Ruby's Class Hierarchy Chart @@ -621,6 +830,7 @@ Init_Object() rb_define_method(mKernel, "==", obj_equal, 1); rb_define_alias(mKernel, "equal?", "=="); rb_define_alias(mKernel, "===", "=="); + rb_define_method(mKernel, "=~", rb_false, 1); rb_define_method(mKernel, "eql?", obj_equal, 1); @@ -634,6 +844,11 @@ Init_Object() rb_define_method(mKernel, "to_a", any_to_a, 0); rb_define_method(mKernel, "to_s", any_to_s, 0); rb_define_method(mKernel, "inspect", obj_inspect, 0); + rb_define_method(mKernel, "methods", obj_methods, 0); + rb_define_method(mKernel, "singleton_methods", obj_singleton_methods, 0); + rb_define_method(mKernel, "private_methods", obj_private_methods, 0); + rb_define_method(mKernel, "instance_variables", obj_instance_variables, 0); + rb_define_method(mKernel, "remove_instance_variable", obj_remove_instance_variable, 0); rb_define_method(mKernel, "instance_of?", obj_is_instance_of, 1); rb_define_method(mKernel, "kind_of?", obj_is_kind_of, 1); @@ -651,27 +866,53 @@ Init_Object() cNilClass = rb_define_class("NilClass", cObject); rb_define_method(cNilClass, "type", nil_type, 0); rb_define_method(cNilClass, "to_s", nil_to_s, 0); + rb_define_method(cNilClass, "to_a", nil_to_a, 0); rb_define_method(cNilClass, "inspect", nil_inspect, 0); - rb_define_method(cNilClass, "=~", rb_equal, 1); rb_define_method(cNilClass, "nil?", rb_true, 0); rb_undef_method(CLASS_OF(cNilClass), "new"); + rb_define_global_const("NIL", Qnil); /* default addition */ rb_define_method(cNilClass, "+", nil_plus, 1); - rb_define_global_function("initialize", obj_initialize, -1); - rb_define_global_function("singleton_method_added", obj_s_added, 1); + rb_define_global_function("initialize", obj_dummy, -1); + rb_define_global_function("singleton_method_added", obj_dummy, 1); rb_define_method(cModule, "===", mod_eqq, 1); + rb_define_method(cModule, "<=>", mod_cmp, 1); + rb_define_method(cModule, "<", mod_lt, 1); + rb_define_method(cModule, "<=", mod_le, 1); + rb_define_method(cModule, ">", mod_gt, 1); + rb_define_method(cModule, ">=", mod_ge, 1); + rb_define_method(cModule, "clone", mod_clone, 0); rb_define_method(cModule, "to_s", mod_to_s, 0); + rb_define_method(cModule, "included_modules", mod_included_modules, 0); + rb_define_method(cModule, "name", mod_name, 0); + rb_define_method(cModule, "ancestors", mod_ancestors, 0); rb_define_private_method(cModule, "attr", mod_attr, -1); + rb_define_private_method(cModule, "attr_reader", mod_attr_reader, -1); + rb_define_private_method(cModule, "attr_writer", mod_attr_writer, -1); + rb_define_private_method(cModule, "attr_accessor", mod_attr_accessor, -1); + rb_define_singleton_method(cModule, "new", module_new, 0); + rb_define_method(cModule, "instance_methods", class_instance_methods, -1); + rb_define_method(cModule, "private_instance_methods", class_private_instance_methods, -1); + + rb_define_method(cModule, "constants", mod_constants, 0); + rb_define_method(cModule, "const_get", mod_const_get, 1); + rb_define_method(cModule, "const_set", mod_const_set, 2); + rb_define_method(cModule, "const_defined?", mod_const_defined, 1); + rb_define_private_method(cModule, "method_added", obj_dummy, 1); rb_define_method(cClass, "new", class_new_instance, -1); rb_define_method(cClass, "superclass", class_superclass, 0); + rb_define_singleton_method(cClass, "new", class_s_new, -1); rb_undef_method(cClass, "extend_object"); + rb_undef_method(cClass, "append_features"); + + rb_define_singleton_method(cClass, "new", class_s_new, -1); cData = rb_define_class("Data", cObject); diff --git a/pack.c b/pack.c index 35052e3406..20d12d4003 100644 --- a/pack.c +++ b/pack.c @@ -85,8 +85,7 @@ static void encodes(); static VALUE pack_pack(ary, fmt) - struct RArray *ary; - struct RString *fmt; + VALUE ary, fmt; { static char *nul10 = "\0\0\0\0\0\0\0\0\0\0"; static char *spc10 = " "; @@ -99,14 +98,14 @@ pack_pack(ary, fmt) Check_Type(fmt, T_STRING); - p = fmt->ptr; - pend = fmt->ptr + fmt->len; + p = RSTRING(fmt)->ptr; + pend = RSTRING(fmt)->ptr + RSTRING(fmt)->len; res = str_new(0, 0); - items = ary->len; + items = RARRAY(ary)->len; idx = 0; -#define NEXTFROM (items-- > 0 ? ary->ptr[idx++] : (ArgError(toofew),0)) +#define NEXTFROM (items-- > 0 ? RARRAY(ary)->ptr[idx++] : (ArgError(toofew),0)) while (p < pend) { type = *p++; /* get data type */ @@ -285,7 +284,7 @@ pack_pack(ary, fmt) else { s = NUM2INT(from); } - str_cat(res, &s, sizeof(short)); + str_cat(res, (UCHAR*)&s, sizeof(short)); } break; @@ -299,7 +298,7 @@ pack_pack(ary, fmt) else { i = NUM2INT(from); } - str_cat(res, &i, sizeof(int)); + str_cat(res, (UCHAR*)&i, sizeof(int)); } break; @@ -313,7 +312,7 @@ pack_pack(ary, fmt) else { l = NUM2INT(from); } - str_cat(res, &l, sizeof(long)); + str_cat(res, (UCHAR*)&l, sizeof(long)); } break; @@ -327,7 +326,7 @@ pack_pack(ary, fmt) s = NUM2INT(from); } s = htons(s); - str_cat(res, &s, sizeof(short)); + str_cat(res, (UCHAR*)&s, sizeof(short)); } break; @@ -341,7 +340,7 @@ pack_pack(ary, fmt) l = NUM2INT(from); } l = htonl(l); - str_cat(res, &l, sizeof(long)); + str_cat(res, (UCHAR*)&l, sizeof(long)); } break; @@ -355,7 +354,7 @@ pack_pack(ary, fmt) s = NUM2INT(from); } s = htovs(s); - str_cat(res, &s, sizeof(short)); + str_cat(res, (UCHAR*)&s, sizeof(short)); } break; @@ -369,7 +368,7 @@ pack_pack(ary, fmt) l = NUM2INT(from); } l = htovl(l); - str_cat(res, &l, sizeof(long)); + str_cat(res, (UCHAR*)&l, sizeof(long)); } break; @@ -389,7 +388,7 @@ pack_pack(ary, fmt) f = (float)NUM2INT(from); break; } - str_cat(res, &f, sizeof(float)); + str_cat(res, (UCHAR*)&f, sizeof(float)); } break; @@ -409,7 +408,7 @@ pack_pack(ary, fmt) d = (double)NUM2INT(from); break; } - str_cat(res, &d, sizeof(double)); + str_cat(res, (UCHAR*)&d, sizeof(double)); } break; @@ -442,6 +441,7 @@ pack_pack(ary, fmt) break; case 'u': + case 'm': from = obj_as_string(NEXTFROM); ptr = RSTRING(from)->ptr; plen = RSTRING(from)->len; @@ -457,7 +457,7 @@ pack_pack(ary, fmt) todo = len; else todo = plen; - encodes(res, ptr, todo); + encodes(res, ptr, todo, type); plen -= todo; ptr += todo; } @@ -471,39 +471,55 @@ pack_pack(ary, fmt) return res; } +static char uu_table[] = +"`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"; +static char b64_table[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + static void -encodes(str, s, len) - struct RString *str; +encodes(str, s, len, type) + VALUE str; UCHAR *s; int len; + int type; { char hunk[4]; UCHAR *p, *pend; + char *trans = type == 'u' ? uu_table : b64_table; + int padding; - *hunk = len + ' '; - str_cat(str, hunk, 1); + if (type == 'u') { + *hunk = len + ' '; + str_cat(str, hunk, 1); + padding = '`'; + } + else { + padding = '='; + } while (len > 0) { - hunk[0] = ' ' + (077 & (*s >> 2)); - hunk[1] = ' ' + (077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))); - hunk[2] = ' ' + (077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))); - hunk[3] = ' ' + (077 & (s[2] & 077)); + hunk[0] = trans[077 & (*s >> 2)]; + hunk[1] = trans[077 & (((*s << 4) & 060) | ((s[1] >> 4) & 017))]; + hunk[2] = trans[077 & (((s[1] << 2) & 074) | ((s[2] >> 6) & 03))]; + hunk[3] = trans[077 & s[2]]; str_cat(str, hunk, 4); s += 3; len -= 3; } - p = str->ptr; - pend = str->ptr + str->len; - while (p < pend) { - if (*p == ' ') - *p = '`'; - p++; + p = RSTRING(str)->ptr; + pend = RSTRING(str)->ptr + RSTRING(str)->len; + if (len == -1) { + pend[-1] = padding; + } + else if (len == -2) { + pend[-2] = padding; + pend[-1] = padding; } str_cat(str, "\n", 1); } static VALUE pack_unpack(str, fmt) - struct RString *str, *fmt; + VALUE str, fmt; { static char *hexdigits = "0123456789abcdef0123456789ABCDEFx"; UCHAR *s, *send; @@ -514,10 +530,10 @@ pack_unpack(str, fmt) Check_Type(fmt, T_STRING); - s = str->ptr; - send = s + str->len; - p = fmt->ptr; - pend = p + fmt->len; + s = RSTRING(str)->ptr; + send = s + RSTRING(str)->len; + p = RSTRING(fmt)->ptr; + pend = p + RSTRING(fmt)->len; ary = ary_new(); while (p < pend) { @@ -851,12 +867,55 @@ pack_unpack(str, fmt) } break; + case 'm': + { + VALUE str = str_new(0, (send - s)*3/4); + UCHAR *ptr = RSTRING(str)->ptr; + int total = 0; + int a,b,c,d; + static int first = 1; + static int b64_xtable[256]; + + if (first) { + int i; + first = 0; + + for (i = 0; i < 256; i++) { + b64_xtable[i] = -1; + } + for (i = 0; i < 64; i++) { + b64_xtable[b64_table[i]] = i; + } + } + for (;;) { + while (s[0] == '\r' || s[0] == '\n') { s++; } + if ((a = b64_xtable[s[0]]) == -1) break; + if ((b = b64_xtable[s[1]]) == -1) break; + if ((c = b64_xtable[s[2]]) == -1) break; + if ((d = b64_xtable[s[3]]) == -1) break; + *ptr++ = a << 2 | b >> 4; + *ptr++ = b << 4 | c >> 2; + *ptr++ = c << 6 | d; + s += 4; + } + if (a != -1 && b != -1 && s[2] == '=') { + *ptr++ = a << 2 | b >> 4; + } + if (a != -1 && b != -1 && c != -1 && s[3] == '=') { + *ptr++ = a << 2 | b >> 4; + *ptr++ = b << 4 | c >> 2; + } + RSTRING(str)->len = ptr - RSTRING(str)->ptr; + ary_push(ary, str); + } + break; + case '@': - s = str->ptr + len; + s = RSTRING(str)->ptr + len; break; case 'X': - if (len > s - str->ptr) + if (len > s - RSTRING(str)->ptr) ArgError("X outside of string"); s -= len; break; diff --git a/parse.y b/parse.y index 02ff720bb3..4bf13cf398 100644 --- a/parse.y +++ b/parse.y @@ -44,6 +44,7 @@ struct op_tbl { char *name; }; +NODE *eval_tree0 = 0; NODE *eval_tree = 0; char *sourcefile; /* current source file */ @@ -58,6 +59,7 @@ static enum lex_state { EXPR_END, /* newline significant, +/- is a operator. */ EXPR_ARG, /* newline significant, +/- may be a sign. */ EXPR_FNAME, /* ignore newline, +/- is a operator. */ + EXPR_CLASS, /* immediate after `class' no here document. */ } lex_state; static int class_nest = 0; @@ -74,6 +76,7 @@ static void fixpos(); static NODE *block_append(); static NODE *list_append(); static NODE *list_concat(); +static NODE *arg_add(); static NODE *call_op(); static int in_defined = 0; @@ -83,6 +86,7 @@ static NODE *aryset(); static NODE *attrset(); static void backref_error(); +static NODE *match_gen(); static void local_push(); static void local_pop(); static int local_cnt(); @@ -112,40 +116,48 @@ static void top_local_setup(); struct RVarmap *vars; } -%token CLASS - MODULE - DEF - UNDEF - BEGIN - RESCUE - ENSURE - END - IF - UNLESS - THEN - ELSIF - ELSE - CASE - WHEN - WHILE - UNTIL - FOR - IN - DO - RETURN - YIELD - SUPER - SELF - NIL - AND - OR - NOT - IF_MOD - UNLESS_MOD - WHILE_MOD - UNTIL_MOD - ALIAS - DEFINED +%token kCLASS + kMODULE + kDEF + kUNDEF + kBEGIN + kRESCUE + kENSURE + kEND + kIF + kUNLESS + kTHEN + kELSIF + kELSE + kCASE + kWHEN + kWHILE + kUNTIL + kFOR + kBREAK + kNEXT + kREDO + kRETRY + kIN + kDO + kRETURN + kYIELD + kSUPER + kSELF + kNIL + kTRUE + kFALSE + kAND + kOR + kNOT + kIF_MOD + kUNLESS_MOD + kWHILE_MOD + kUNTIL_MOD + kALIAS + kDEFINED + klBEGIN + klEND %token IDENTIFIER FID GVAR IVAR CONSTANT %token INTEGER FLOAT STRING XSTRING REGEXP @@ -153,18 +165,18 @@ static void top_local_setup(); %type singleton %type literal numeric -%type compexpr exprs expr arg primary command_call method_call +%type compstmt stmts stmt expr arg primary command_call method_call %type if_tail opt_else case_body cases rescue ensure iterator -%type call_args call_args0 ret_args args mrhs opt_args var_ref +%type call_args call_args0 ret_args args mrhs opt_list var_ref %type superclass f_arglist f_args f_optarg f_opt %type array assoc_list assocs assoc undef_list %type iter_var opt_iter_var iter_block iter_do_block %type mlhs mlhs_head mlhs_tail lhs backref -%type variable symbol operation +%type variable symbol operation assoc_kw %type cname fname op rest_arg %type f_arg -%token UPLUS /* unary+ */ -%token UMINUS /* unary- */ +%token oUPLUS /* unary+ */ +%token MINUS /* unary- */ %token POW /* ** */ %token CMP /* <=> */ %token EQ /* == */ @@ -180,6 +192,7 @@ static void top_local_setup(); %token COLON2 /* :: */ %token OP_ASGN /* +=, -= etc. */ %token ASSOC /* => */ +%token KW_ASSOC /* -> */ %token LPAREN /* ( */ %token LBRACK /* [ */ %token LBRACE /* { */ @@ -190,10 +203,10 @@ static void top_local_setup(); * precedence table */ -%left IF_MOD UNLESS_MOD WHILE_MOD UNTIL_MOD -%left OR AND -%right NOT -%nonassoc DEFINED +%left kIF_MOD kUNLESS_MOD kWHILE_MOD kUNTIL_MOD +%left kOR kAND +%right kNOT +%nonassoc kDEFINED %right '=' OP_ASGN %nonassoc DOT2 DOT3 %left OROP @@ -218,7 +231,7 @@ program : { if ((VALUE)the_class == cObject) class_nest = 0; else class_nest = 1; } - compexpr + compstmt { eval_tree = block_append(eval_tree, $2); top_local_setup(); @@ -226,67 +239,44 @@ program : { class_nest = 0; } -compexpr : exprs opt_terms +compstmt : stmts opt_terms -exprs : /* none */ +stmts : /* none */ { $$ = 0; } - | expr + | stmt { $$ = newline_node($1); } - | exprs terms expr + | stmts terms stmt { $$ = block_append($1, newline_node($3)); } - | error expr + | error stmt { $$ = $2; } -expr : mlhs '=' mrhs - { - value_expr($3); - $1->nd_value = $3; - $$ = $1; - } - | assocs - { - $$ = NEW_HASH($1); - } - | RETURN ret_args - { - value_expr($2); - if (!cur_mid && !in_single) - yyerror("return appeared outside of method"); - $$ = NEW_RET($2); - } - | YIELD ret_args - { - value_expr($2); - $$ = NEW_YIELD($2); - } - | command_call - | iterator iter_do_block +stmt : iterator iter_do_block { $2->nd_iter = $1; $$ = $2; fixpos($$, $2); } - | ALIAS fname {lex_state = EXPR_FNAME;} fname + | kALIAS fname {lex_state = EXPR_FNAME;} fname { if (cur_mid || in_single) yyerror("alias within method"); $$ = NEW_ALIAS($2, $4); } - | ALIAS GVAR GVAR + | kALIAS GVAR GVAR { if (cur_mid || in_single) yyerror("alias within method"); $$ = NEW_VALIAS($2, $3); } - | ALIAS GVAR BACK_REF + | kALIAS GVAR BACK_REF { char buf[3]; @@ -295,28 +285,28 @@ expr : mlhs '=' mrhs sprintf(buf, "$%c", $3->nd_nth); $$ = NEW_VALIAS($2, rb_intern(buf)); } - | ALIAS GVAR NTH_REF + | kALIAS GVAR NTH_REF { yyerror("can't make alias for the number variables"); $$ = 0; } - | UNDEF undef_list + | kUNDEF undef_list { if (cur_mid || in_single) yyerror("undef within method"); $$ = $2; } - | expr IF_MOD expr + | stmt kIF_MOD expr { value_expr($3); - $$ = NEW_IF(cond($3), $1, 0); + $$ = node_newnode(NODE_AND, cond($3), $1); } - | expr UNLESS_MOD expr + | stmt kUNLESS_MOD expr { value_expr($3); - $$ = NEW_UNLESS(cond($3), $1, 0); + $$ = node_newnode(NODE_OR, cond($3), $1); } - | expr WHILE_MOD expr + | stmt kWHILE_MOD expr { value_expr($3); if (nd_type($1) == NODE_BEGIN) { @@ -326,7 +316,7 @@ expr : mlhs '=' mrhs $$ = NEW_WHILE(cond($3), $1, 1); } } - | expr UNTIL_MOD expr + | expr kUNTIL_MOD expr { value_expr($3); if (nd_type($1) == NODE_BEGIN) { @@ -336,15 +326,58 @@ expr : mlhs '=' mrhs $$ = NEW_UNTIL(cond($3), $1, 1); } } - | expr AND expr + | klBEGIN + { + if (cur_mid || in_single) { + yyerror("BEGIN in method"); + } + + local_push(); + } + '{' compstmt '}' + { + eval_tree0 = block_append(eval_tree0,NEW_PREEXE($4)); + local_pop(); + $$ = 0; + } + | klEND '{' compstmt '}' + { + if (cur_mid || in_single) { + yyerror("END in method; use at_exit"); + } + + $$ = NEW_ITER(0, NEW_POSTEXE(), $3); + } + | expr + +expr : mlhs '=' mrhs + { + value_expr($3); + $1->nd_value = $3; + $$ = $1; + } + | kRETURN ret_args + { + value_expr($2); + if (!cur_mid && !in_single) + yyerror("return appeared outside of method"); + $$ = NEW_RET($2); + } + | kYIELD ret_args + { + value_expr($2); + $$ = NEW_YIELD($2); + } + | command_call + | expr kAND expr { $$ = logop(NODE_AND, $1, $3); } - | expr OR expr + | expr kOR expr { $$ = logop(NODE_OR, $1, $3); } - | NOT expr + | kNOT expr { value_expr($2); $$ = NEW_NOT(cond($2)); @@ -367,7 +400,13 @@ command_call : operation call_args0 $$ = NEW_CALL($1, $3, $4); fixpos($$, $1); } - | SUPER call_args0 + | primary COLON2 operation call_args0 + { + value_expr($1); + $$ = NEW_CALL($1, $3, $4); + fixpos($$, $1); + } + | kSUPER call_args0 { if (!cur_mid && !in_single && !in_defined) yyerror("super called outside of method"); @@ -411,7 +450,7 @@ lhs : variable { $$ = assignable($1, 0); } - | primary '[' opt_args opt_nl ']' + | primary '[' call_args ']' { $$ = aryset($1, $3, 0); } @@ -487,21 +526,16 @@ arg : variable '=' arg $$ = assignable($1, $3); fixpos($$, $3); } - | primary '[' opt_args opt_nl ']' '=' arg + | primary '[' call_args ']' '=' arg { - $$ = aryset($1, $3, $7); - fixpos($$, $7); + $$ = aryset($1, $3, $6); + fixpos($$, $1); } | primary '.' IDENTIFIER '=' arg { $$ = attrset($1, $3, $5); fixpos($$, $5); } - | primary '.' CONSTANT '=' arg - { - $$ = attrset($1, $3, $5); - fixpos($$, $5); - } | backref '=' arg { value_expr($3); @@ -516,19 +550,24 @@ arg : variable '=' arg $$ = assignable($1, call_op(gettable($1), $2, 1, $3)); fixpos($$, $3); } - | primary '[' opt_args opt_nl ']' OP_ASGN arg + | primary '[' call_args ']' OP_ASGN arg { - NODE *args = NEW_LIST($7); + NODE *args = NEW_LIST($6); list_append($3, NEW_NIL()); list_concat(args, $3); - $$ = NEW_OP_ASGN1($1, $6, args); - fixpos($$, $7); + $$ = NEW_OP_ASGN1($1, $5, args); + fixpos($$, $1); } | primary '.' IDENTIFIER OP_ASGN arg { $$ = NEW_OP_ASGN2($1, $3, $4, $5); - fixpos($$, $5); + fixpos($$, $1); + } + | primary '.' CONSTANT OP_ASGN arg + { + $$ = NEW_OP_ASGN2($1, $3, $4, $5); + fixpos($$, $1); } | backref OP_ASGN arg { @@ -621,13 +660,11 @@ arg : variable '=' arg } | arg MATCH arg { - local_cnt('~'); - $$ = NEW_CALL($1, MATCH, NEW_LIST($3)); + $$ = match_gen($1, $3); } | arg NMATCH arg { - local_cnt('~'); - $$ = NEW_NOT(NEW_CALL($1, MATCH, NEW_LIST($3))); + $$ = NEW_NOT(match_gen($1, $3)); } | '!' arg { @@ -654,7 +691,7 @@ arg : variable '=' arg { $$ = logop(NODE_OR, $1, $3); } - | DEFINED opt_nl {in_defined = 1;} arg + | kDEFINED opt_nl {in_defined = 1;} arg { in_defined = 0; $$ = NEW_DEFINED($4); @@ -670,16 +707,25 @@ call_args : /* none */ } | call_args0 opt_nl -call_args0 : args - | command_call +call_args0 : command_call { value_expr($1); $$ = NEW_LIST($1); } + | args + | args ',' STAR arg + { + $$ = arg_add($1, $4); + } | assocs { $$ = NEW_LIST(NEW_HASH($1)); } + | assocs ',' STAR arg + { + $$ = NEW_LIST(NEW_HASH($1)); + $$ = arg_add($$, $4); + } | args ',' assocs { $$ = list_append($1, NEW_HASH($3)); @@ -687,11 +733,7 @@ call_args0 : args | args ',' assocs ',' STAR arg { $$ = list_append($1, NEW_HASH($3)); - $$ = call_op($$, '+', 1, $6); - } - | args ',' STAR arg - { - $$ = call_op($1, '+', 1, $4); + $$ = arg_add($$, $6); } | STAR arg { @@ -699,7 +741,7 @@ call_args0 : args $$ = $2; } -opt_args : /* none */ +opt_list : /* none */ { $$ = 0; } @@ -718,7 +760,9 @@ args : arg mrhs : args { - if ($1 && $1->nd_next == 0) { + if ($1 && + nd_type($1) == NODE_ARRAY && + $1->nd_next == 0) { $$ = $1->nd_head; } else { @@ -727,7 +771,7 @@ mrhs : args } | args ',' STAR arg { - $$ = call_op($1, '+', 1, $4); + $$ = arg_add($1, $4); } | STAR arg { @@ -774,19 +818,7 @@ primary : literal | DREGEXP | var_ref | backref - | SUPER '(' call_args ')' - { - if (!cur_mid && !in_single && !in_defined) - yyerror("super called outside of method"); - $$ = NEW_SUPER($3); - } - | SUPER - { - if (!cur_mid && !in_single && !in_defined) - yyerror("super called outside of method"); - $$ = NEW_ZSUPER(); - } - | primary '[' opt_args opt_nl ']' + | primary '[' call_args ']' { value_expr($1); $$ = NEW_CALL($1, AREF, $3); @@ -803,39 +835,39 @@ primary : literal { $$ = NEW_HASH($2); } - | RETURN '(' ret_args ')' + | kRETURN '(' ret_args ')' { if (!cur_mid && !in_single) yyerror("return appeared outside of method"); value_expr($3); $$ = NEW_RET($3); } - | RETURN '(' ')' + | kRETURN '(' ')' { if (!cur_mid && !in_single) yyerror("return appeared outside of method"); $$ = NEW_RET(0); } - | RETURN + | kRETURN { if (!cur_mid && !in_single) yyerror("return appeared outside of method"); $$ = NEW_RET(0); } - | YIELD '(' ret_args ')' + | kYIELD '(' ret_args ')' { value_expr($3); $$ = NEW_YIELD($3); } - | YIELD '(' ')' + | kYIELD '(' ')' { $$ = NEW_YIELD(0); } - | YIELD + | kYIELD { $$ = NEW_YIELD(0); } - | DEFINED opt_nl '(' {in_defined = 1;} expr ')' + | kDEFINED opt_nl '(' {in_defined = 1;} expr ')' { in_defined = 0; $$ = NEW_DEFINED($5); @@ -856,55 +888,61 @@ primary : literal $$ = $2; fixpos($$, $1); } - | IF expr then - compexpr + | kIF expr then + compstmt if_tail - END + kEND { value_expr($2); $$ = NEW_IF(cond($2), $4, $5); fixpos($$, $2); } - | UNLESS expr then - compexpr + | kUNLESS expr then + compstmt opt_else - END + kEND { value_expr($2); $$ = NEW_UNLESS(cond($2), $4, $5); fixpos($$, $2); } - | WHILE expr term compexpr END + | kWHILE expr do + compstmt + kEND { value_expr($2); $$ = NEW_WHILE(cond($2), $4, 1); fixpos($$, $2); } - | UNTIL expr term compexpr END + | kUNTIL expr do + compstmt + kEND { value_expr($2); $$ = NEW_UNTIL(cond($2), $4, 1); fixpos($$, $2); } - | CASE compexpr + | kCASE compstmt case_body - END + kEND { value_expr($2); $$ = NEW_CASE($2, $3); fixpos($$, $2); } - | FOR iter_var IN expr term compexpr END + | kFOR iter_var kIN expr do + compstmt + kEND { value_expr($2); $$ = NEW_FOR($2, $4, $6); fixpos($$, $2); } - | BEGIN - compexpr + | kBEGIN + compstmt rescue ensure - END + kEND { if (!$3 && !$4) $$ = NEW_BEGIN($2); @@ -915,11 +953,11 @@ primary : literal } fixpos($$, $2); } - | LPAREN compexpr ')' + | LPAREN compstmt ')' { $$ = $2; } - | CLASS cname superclass + | kCLASS cname superclass { if (cur_mid || in_single) yyerror("class definition in method body"); @@ -928,8 +966,8 @@ primary : literal cref_push(); local_push(); } - compexpr - END + compstmt + kEND { $$ = NEW_CLASS($2, $5, $3); fixpos($$, $3); @@ -937,7 +975,7 @@ primary : literal cref_pop(); class_nest--; } - | CLASS LSHFT expr term + | kCLASS LSHFT expr term { if (cur_mid || in_single) yyerror("class definition in method body"); @@ -946,8 +984,8 @@ primary : literal cref_push(); local_push(); } - compexpr - END + compstmt + kEND { $$ = NEW_SCLASS($3, $6); fixpos($$, $3); @@ -955,7 +993,7 @@ primary : literal cref_pop(); class_nest--; } - | MODULE cname + | kMODULE cname { if (cur_mid || in_single) yyerror("module definition in method body"); @@ -963,8 +1001,8 @@ primary : literal cref_push(); local_push(); } - compexpr - END + compstmt + kEND { $$ = NEW_MODULE($2, $4); fixpos($$, $4); @@ -972,7 +1010,7 @@ primary : literal cref_pop(); class_nest--; } - | DEF fname + | kDEF fname { if (cur_mid || in_single) yyerror("nested method definition"); @@ -980,15 +1018,16 @@ primary : literal local_push(); } f_arglist - compexpr - END + compstmt + kEND { + /* NOEX_PRIVATE for toplevel */ $$ = NEW_DEFN($2, $4, $5, class_nest?0:1); fixpos($$, $4); local_pop(); cur_mid = 0; } - | DEF singleton '.' {lex_state = EXPR_FNAME;} fname + | kDEF singleton '.' {lex_state = EXPR_FNAME;} fname { value_expr($2); in_single++; @@ -996,22 +1035,42 @@ primary : literal lex_state = EXPR_END; /* force for args */ } f_arglist - compexpr - END + compstmt + kEND { $$ = NEW_DEFS($2, $5, $7, $8); fixpos($$, $2); local_pop(); in_single--; } + | kBREAK + { + $$ = NEW_BREAK(); + } + | kNEXT + { + $$ = NEW_NEXT(); + } + | kREDO + { + $$ = NEW_REDO(); + } + | kRETRY + { + $$ = NEW_RETRY(); + } then : term - | THEN - | term THEN + | kTHEN + | term kTHEN + +do : term + | kDO + | term kDO if_tail : opt_else - | ELSIF expr then - compexpr + | kELSIF expr then + compstmt if_tail { value_expr($2); @@ -1023,7 +1082,7 @@ opt_else : /* none */ { $$ = 0; } - | ELSE compexpr + | kELSE compstmt { $$ = $2; } @@ -1048,13 +1107,13 @@ opt_iter_var : /* node */ $$ = $2; } -iter_do_block : DO +iter_do_block : kDO { $$ = dyna_push(); } opt_iter_var - compexpr - END + compstmt + kEND { $$ = NEW_ITER($3, 0, $4); fixpos($$, $3?$3:$4); @@ -1066,7 +1125,7 @@ iter_block : '{' $$ = dyna_push(); } opt_iter_var - compexpr '}' + compstmt '}' { $$ = NEW_ITER($3, 0, $4); fixpos($$, $3?$3:$4); @@ -1110,9 +1169,22 @@ method_call : operation '(' call_args ')' $$ = NEW_CALL($1, $3, $5); fixpos($$, $1); } + | kSUPER '(' call_args ')' + { + if (!cur_mid && !in_single && !in_defined) + yyerror("super called outside of method"); + $$ = NEW_SUPER($3); + } + | kSUPER + { + if (!cur_mid && !in_single && !in_defined) + yyerror("super called outside of method"); + $$ = NEW_ZSUPER(); + } -case_body : WHEN args then - compexpr + +case_body : kWHEN args then + compstmt cases { $$ = NEW_WHEN($2, $4, $5); @@ -1121,7 +1193,8 @@ case_body : WHEN args then cases : opt_else | case_body -rescue : RESCUE opt_args term compexpr +rescue : kRESCUE opt_list do + compstmt rescue { $$ = NEW_RESBODY($2, $4, $5); @@ -1136,15 +1209,15 @@ ensure : /* none */ { $$ = 0; } - | ENSURE compexpr + | kENSURE compstmt { $$ = $2; } literal : numeric - | SYMBEG {lex_state = EXPR_FNAME;} symbol + | SYMBEG symbol { - $$ = INT2FIX($3); + $$ = INT2FIX($2); } | REGEXP @@ -1159,14 +1232,10 @@ variable : IDENTIFIER | IVAR | GVAR | CONSTANT - | NIL - { - $$ = NIL; - } - | SELF - { - $$ = SELF; - } + | kNIL {$$ = kNIL;} + | kSELF {$$ = kSELF;} + | kTRUE {$$ = kTRUE;} + | kFALSE {$$ = kFALSE;} var_ref : variable { @@ -1329,6 +1398,13 @@ assoc : arg ASSOC arg { $$ = list_append(NEW_LIST($1), $3); } + | assoc_kw KW_ASSOC arg + { + $$ = list_append(NEW_LIST(NEW_STR(str_new2(rb_id2name($1)))), $3); + } + +assoc_kw : IDENTIFIER + | CONSTANT operation : IDENTIFIER | CONSTANT @@ -1371,6 +1447,7 @@ static NODE *str_extend(); #define LEAVE_BS 1 static VALUE lex_input; /* non-nil if File */ +static VALUE lex_lastline; /* gc protect */ static char *lex_pbeg; static char *lex_p; static char *lex_pend; @@ -1430,7 +1507,6 @@ yycompile(f) newline_seen = 0; sourcefile = strdup(f); - eval_tree = 0; rb_in_compile = 1; n = yyparse(); rb_in_compile = 0; @@ -1478,8 +1554,15 @@ nextc() if (NIL_P(v)) return -1; lex_pbeg = lex_p = RSTRING(v)->ptr; lex_pend = lex_p + RSTRING(v)->len; + if (RSTRING(v)->len == 8 && + strncmp(lex_pbeg, "__END__", 7) == 0) { + lex_lastline = 0; + return -1; + } + lex_lastline = v; } else { + lex_lastline = 0; return -1; } } @@ -1509,7 +1592,7 @@ newtok() toksiz = 60; tokenbuf = ALLOC_N(char, 60); } - if (toksiz > 1024) { + if (toksiz > 4096) { toksiz = 60; REALLOC_N(tokenbuf, char, 60); } @@ -1666,13 +1749,13 @@ parse_regx(term) case '#': list = str_extend(list, term); if (list == (NODE*)-1) return 0; - continue; + continue; case '\\': switch (c = nextc()) { case -1: sourceline = re_start; - Error("unterminated regexp meets end of file"); + Error("unterminated regexp meets end of file"); /* */ return 0; case '\n': @@ -1778,6 +1861,8 @@ parse_regx(term) return 0; } +static int parse_qstring(); + static int parse_string(func,term) int func, term; @@ -1786,11 +1871,13 @@ parse_string(func,term) NODE *list = 0; int strstart; + if (func == '\'') { + return parse_qstring(term); + } strstart = sourceline; newtok(); while ((c = nextc()) != term) { - str_retry: if (c == -1) { unterm_str: sourceline = strstart; @@ -1901,45 +1988,115 @@ parse_qstring(term) return STRING; } -#define LAST(v) ((v)-1 + sizeof(v)/sizeof(v[0])) +char *strdup(); + +static int +here_document(term) + char term; +{ + int c; + char *eos; + int len; + VALUE str, line; + char *save_beg, *save_end, *save_lexp; + NODE *list = 0; -static struct kwtable { - char *name; - int id; - enum lex_state state; -} kwtable [] = { - "__END__", 0, EXPR_BEG, - "alias", ALIAS, EXPR_FNAME, - "and", AND, EXPR_BEG, - "begin", BEGIN, EXPR_BEG, - "case", CASE, EXPR_BEG, - "class", CLASS, EXPR_BEG, - "def", DEF, EXPR_FNAME, - "defined?", DEFINED, EXPR_END, - "do", DO, EXPR_BEG, - "else", ELSE, EXPR_BEG, - "elsif", ELSIF, EXPR_BEG, - "end", END, EXPR_END, - "ensure", ENSURE, EXPR_BEG, - "for", FOR, EXPR_BEG, - "if", IF, EXPR_BEG, - "in", IN, EXPR_BEG, - "module", MODULE, EXPR_BEG, - "nil", NIL, EXPR_END, - "not", NOT, EXPR_BEG, - "or", OR, EXPR_BEG, - "rescue", RESCUE, EXPR_MID, - "return", RETURN, EXPR_MID, - "self", SELF, EXPR_END, - "super", SUPER, EXPR_END, - "then", THEN, EXPR_BEG, - "undef", UNDEF, EXPR_FNAME, - "unless", UNLESS, EXPR_BEG, - "until", UNTIL, EXPR_BEG, - "when", WHEN, EXPR_BEG, - "while", WHILE, EXPR_BEG, - "yield", YIELD, EXPR_END, -}; + newtok(); + switch (term) { + case '\'': + case '"': + case '`': + while ((c = nextc()) != term) { + tokadd(c); + } + break; + + default: + c = term; + term = '"'; + if (!is_identchar(c)) { + yyerror("illegal here document"); + return 0; + } + while (is_identchar(c)) { + tokadd(c); + c = nextc(); + } + pushback(c); + break; + } + tokfix(); + save_lexp = lex_p; + save_beg = lex_pbeg; + save_end = lex_pend; + eos = strdup(tok()); + len = strlen(eos); + + str = str_new(0,0); + for (;;) { + line = io_gets(lex_input); + if (NIL_P(line)) { + error: + Error("unterminated string meets end of file"); + free(eos); + return 0; + } + if (strncmp(eos, RSTRING(line)->ptr, len) == 0 && + (RSTRING(line)->ptr[len] == '\n' || + RSTRING(line)->ptr[len] == '\r')) { + break; + } + + lex_pbeg = lex_p = RSTRING(line)->ptr; + lex_pend = lex_p + RSTRING(line)->len; + sourceline++; + switch (parse_string(term, '\n')) { + case STRING: + case XSTRING: + str_cat(yylval.val, "\n", 1); + if (!list) { + str_cat(str, RSTRING(yylval.val)->ptr, RSTRING(yylval.val)->len); + } + else { + list_append(list, NEW_STR(yylval.val)); + } + break; + case DSTRING: + case DXSTRING: + list_append(yylval.node, NEW_STR(str_new2("\n"))); + nd_set_type(yylval.node, NODE_STR); + if (!list) list = NEW_DSTR(str); + yylval.node = NEW_LIST(yylval.node); + yylval.node->nd_next = yylval.node->nd_head->nd_next; + list_concat(list, yylval.node); + break; + + case 0: + goto error; + } + } + free(eos); + lex_p = save_lexp; + lex_pbeg = save_beg; + lex_pend = save_end; + + if (list) { + yylval.node = list; + } + switch (term) { + case '\'': + case '"': + if (list) return DSTRING; + yylval.val = str; + return STRING; + case '`': + if (list) return DXSTRING; + return XSTRING; + } + return 0; +} + +#include "lex.c" static void arg_ambiguous() @@ -1956,7 +2113,7 @@ yylex() { register int c; int space_seen = 0; - struct kwtable *low = kwtable, *mid, *high = LAST(kwtable); + struct kwtable *kw; if (newline_seen) { sourceline+=newline_seen; @@ -1981,39 +2138,20 @@ retry: while ((c = nextc()) != '\n') { if (c == -1) return 0; - if (c == '\\') { /* skip a char */ + if (c == '\\') { /* skip a char */ c = nextc(); if (c == '\n') sourceline++; } if (ismbchar(c)) { c = nextc(); - if (c == '\n') + if (c == '\n') { + sourceline++; break; + } } } /* fall through */ case '\n': - /* skip embedded rd document */ - if ((c = nextc()) == '=' && - strncmp(lex_p, "begin", 5) == 0 && - (lex_p[5] == '\n' || lex_p[5] == '\r')) { - for (;;) { - if (c == -1) return 0; - c = nextc(); - if (c != '\n') continue; - c = nextc(); - if (c != '=') continue; - if (strncmp(lex_p, "end", 3) == 0 && - (lex_p[3] == '\n' || lex_p[3] == '\r')) { - lex_p += 3; /* sizeof "end" */ - break; - } - } - } - else { - pushback(c); - } - if (lex_state == EXPR_BEG || lex_state == EXPR_FNAME) { sourceline++; goto retry; @@ -2064,18 +2202,21 @@ retry: if (lex_p == lex_pbeg + 1) { /* skip embedded rd document */ if (strncmp(lex_p, "begin", 5) == 0 && isspace(lex_p[5])) { - lex_p = lex_pend; for (;;) { - if (c == -1) return 0; - c = nextc(); - if (c != '\n') continue; + sourceline++; + lex_p = lex_pend; c = nextc(); + if (c == -1) { + Error("embedded document meets end of file"); + return 0; + } if (c != '=') continue; if (strncmp(lex_p, "end", 3) == 0 && isspace(lex_p[3])) { - lex_p = lex_pend; break; } } + sourceline++; + lex_p = lex_pend; goto retry; } } @@ -2098,8 +2239,22 @@ retry: return '='; case '<': + c = nextc(); + if (c == '<' && + lex_state != EXPR_END + && lex_state != EXPR_CLASS && + (lex_state != EXPR_ARG || space_seen)) { + int c2 = nextc(); + if (!isspace(c2) && (strchr("\"'`", c2) || is_identchar(c2))) { + if (!lex_input) { + ArgError("here document not available"); + } + return here_document(c2); + } + pushback(c2); + } lex_state = EXPR_BEG; - if ((c = nextc()) == '=') { + if (c == '=') { if ((c = nextc()) == '>') { return CMP; } @@ -2223,6 +2378,10 @@ retry: yylval.id = '-'; return OP_ASGN; } + if (c == '>') { + lex_state = EXPR_BEG; + return KW_ASSOC; + } if (lex_state == EXPR_ARG) { if (space_seen && !isspace(c)) { arg_ambiguous(); @@ -2301,7 +2460,7 @@ retry: return INTEGER; } else if (c > '7' && c <= '9') { - Error("Illegal octal digit"); + yyerror("Illegal octal digit"); } else if (c == '.') { tokadd('0'); @@ -2387,6 +2546,7 @@ retry: pushback(c); if (isspace(c)) return ':'; + lex_state = EXPR_FNAME; return SYMBEG; case '/': @@ -2533,7 +2693,7 @@ retry: return parse_regx(term); default: - Error("unknown type of string `%c'", c); + yyerror("unknown type of string `%c'", c); return 0; } } @@ -2556,8 +2716,9 @@ retry: newtok(); c = nextc(); switch (c) { - case '_': /* $_: last read line string */ case '~': /* $~: match-data */ + /* fall through */ + case '_': /* $_: last read line string */ local_cnt(c); /* fall through */ case '*': /* $*: argv */ @@ -2669,25 +2830,11 @@ retry: break; default: /* See if it is a reserved word. */ - while (low <= high) { - mid = low + (high - low)/2; - if ((c = strcmp(mid->name, tok())) == 0) { - enum lex_state state = lex_state; - lex_state = mid->state; - if (state != EXPR_BEG) { - if (mid->id == IF) return IF_MOD; - if (mid->id == UNLESS) return UNLESS_MOD; - if (mid->id == WHILE) return WHILE_MOD; - if (mid->id == UNTIL) return UNTIL_MOD; - } - return mid->id; - } - else if (c < 0) { - low = mid + 1; - } - else { - high = mid - 1; - } + kw = rb_reserved_word(tok(), toklen()); + if (kw) { + enum lex_state state = lex_state; + lex_state = kw->state; + return kw->id[state != EXPR_BEG]; } if (lex_state == EXPR_FNAME) { @@ -2725,7 +2872,7 @@ str_extend(list, term) NODE *list; char term; { - int c; + int c, brace; VALUE ss; NODE *node; int nest; @@ -2814,6 +2961,7 @@ str_extend(list, term) break; case '{': + if (c == '{') brace = '}'; nest = 0; do { loop_again: @@ -2821,14 +2969,17 @@ str_extend(list, term) switch (c) { case -1: if (nest > 0) { - Error("bad substitution in string"); + yyerror("bad substitution in string"); newtok(); return list; } return (NODE*)-1; case '}': - if (nest == 0) break; - nest--; + case ')': + if (c == brace) { + if (nest == 0) break; + nest--; + } tokadd(c); goto loop_again; case '\\': @@ -2836,7 +2987,7 @@ str_extend(list, term) tokadd(c); goto loop_again; case '{': - nest++; + if (brace == c) nest++; case '\"': case '/': case '`': @@ -2853,7 +3004,7 @@ str_extend(list, term) tokadd(c); break; } - } while (c != '}'); + } while (c != brace); } fetch_id: @@ -2875,7 +3026,7 @@ node_newnode(type, a0, a1, a2) n->flags |= T_NODE; nd_set_type(n, type); nd_set_line(n, sourceline); - n->file = sourcefile; + n->nd_file = sourcefile; n->u1.node = a0; n->u2.node = a1; @@ -2917,7 +3068,7 @@ fixpos(node, orig) { if (!node) return; if (!orig) return; - node->file = orig->file; + node->nd_file = orig->nd_file; nd_set_line(node, nd_line(orig)); } @@ -2925,7 +3076,6 @@ static NODE* block_append(head, tail) NODE *head, *tail; { - extern int verbose; NODE *end; if (tail == 0) return head; @@ -2941,11 +3091,15 @@ block_append(head, tail) end = head->nd_end; } - if (verbose) { + if (RTEST(verbose)) { NODE *nd = end->nd_head; newline: switch (nd_type(nd)) { case NODE_RETURN: + case NODE_BREAK: + case NODE_NEXT: + case NODE_REDO: + case NODE_RETRY: Warning("statement not reached"); break; @@ -3017,16 +3171,54 @@ call_op(recv, id, narg, arg1) return NEW_CALL(recv, id, narg==1?NEW_LIST(arg1):0); } +static NODE* +match_gen(node1, node2) + NODE *node1; + NODE *node2; +{ + local_cnt('~'); + + switch (nd_type(node1)) { + case NODE_DREGX: + case NODE_DREGX_ONCE: + return NEW_MATCH2(node1, node2); + + case NODE_LIT: + if (TYPE(node1->nd_lit) == T_REGEXP) { + return NEW_MATCH2(node1, node2); + } + } + + switch (nd_type(node2)) { + case NODE_DREGX: + case NODE_DREGX_ONCE: + return NEW_MATCH3(node2, node1); + + case NODE_LIT: + if (TYPE(node2->nd_lit) == T_REGEXP) { + return NEW_MATCH3(node2, node1); + } + } + + return NEW_CALL(node1, MATCH, NEW_LIST(node2)); +} + static NODE* gettable(id) ID id; { - if (id == SELF) { + if (id == kSELF) { return NEW_SELF(); } - else if (id == NIL) { + else if (id == kNIL) { return NEW_NIL(); } + else if (id == kTRUE) { + return NEW_TRUE(); + } + else if (id == kFALSE) { + return NEW_FALSE(); + } else if (is_local_id(id)) { if (local_id(id)) return NEW_LVAR(id); if (dyna_var_defined(id)) return NEW_DVAR(id); @@ -3053,12 +3245,18 @@ assignable(id, val) { NODE *lhs = 0; - if (id == SELF) { + if (id == kSELF) { yyerror("Can't change the value of self"); } - else if (id == NIL) { + else if (id == kNIL) { yyerror("Can't assign to nil"); } + else if (id == kTRUE) { + yyerror("Can't assign to true"); + } + else if (id == kFALSE) { + yyerror("Can't assign to false"); + } else if (is_local_id(id)) { if (local_id(id) || !dyna_in_block()) { lhs = NEW_LASGN(id, val); @@ -3085,13 +3283,29 @@ assignable(id, val) return lhs; } +static NODE * +arg_add(node1, node2) + NODE *node1; + NODE *node2; +{ + return call_op(node1, rb_intern("concat"), 1, node2); +} + static NODE * aryset(recv, idx, val) NODE *recv, *idx, *val; { value_expr(recv); value_expr(val); - return NEW_CALL(recv, ASET, list_append(idx, val)); + if (idx) { + if (nd_type(idx) == NODE_ARRAY) { + idx = list_append(idx, val); + } + else { + idx = arg_add(idx, val); + } + } + return NEW_CALL(recv, ASET, idx); } ID @@ -3139,6 +3353,10 @@ value_expr(node) switch (nd_type(node)) { case NODE_RETURN: + case NODE_BREAK: + case NODE_NEXT: + case NODE_REDO: + case NODE_RETRY: case NODE_WHILE: case NODE_UNTIL: case NODE_CLASS: @@ -3179,7 +3397,7 @@ cond0(node) case NODE_DREGX_ONCE: local_cnt('_'); local_cnt('~'); - return call_op(NEW_GVAR(rb_intern("$_")),MATCH,1,node); + return NEW_MATCH2(node, NEW_GVAR(rb_intern("$_"))); case NODE_DOT2: case NODE_DOT3: @@ -3195,6 +3413,11 @@ cond0(node) local_cnt('~'); return NEW_MATCH(node); } + if (TYPE(node->nd_lit) == T_STRING) { + local_cnt('_'); + local_cnt('~'); + return NEW_MATCH(reg_new(RSTRING(node)->ptr,RSTRING(node)->len,0)); + } default: return node; } @@ -3423,8 +3646,9 @@ void yyappend_print() { eval_tree = - block_append(eval_tree, NEW_FCALL(rb_intern("print"), - NEW_ARRAY(NEW_GVAR(rb_intern("$_"))))); + block_append(eval_tree, + NEW_FCALL(rb_intern("print"), + NEW_ARRAY(NEW_GVAR(rb_intern("$_"))))); } void @@ -3491,7 +3715,7 @@ static struct op_tbl rb_op_tbl[] = { char *rb_id2name(); char *rb_class2name(); -st_table *rb_symbol_tbl; +static st_table *rb_symbol_tbl; #define sym_tbl rb_symbol_tbl @@ -3501,7 +3725,8 @@ Init_sym() int strcmp(); sym_tbl = st_init_strtable(); - rb_global_variable(&cur_cref); + rb_global_variable((VALUE*)&cur_cref); + rb_global_variable((VALUE*)&lex_lastline); } ID @@ -3532,7 +3757,8 @@ rb_intern(name) id = 0; for (i=0; rb_op_tbl[i].token; i++) { - if (strcmp(rb_op_tbl[i].name, name) == 0) { + if (*rb_op_tbl[i].name == *name && + strcmp(rb_op_tbl[i].name, name) == 0) { id = rb_op_tbl[i].token; break; } diff --git a/process.c b/process.c index ac7a7465e8..9d50fea8bf 100644 --- a/process.c +++ b/process.c @@ -108,9 +108,6 @@ rb_waitpid(pid, flags, st) result = wait4(pid, st, flags, NULL); if (result < 0) { if (errno == EINTR) { -#ifdef THREAD - thread_schedule(); -#endif goto retry; } return -1; @@ -250,30 +247,36 @@ after_exec() #endif extern char *dln_find_exe(); +int env_path_tainted(); static void security(str) char *str; { - extern int env_path_tainted; extern VALUE eSecurityError; - if (rb_safe_level() > 0 && env_path_tainted) { - Raise(eSecurityError, "Insecure PATH - %s", str); + if (rb_safe_level() > 0) { + if (env_path_tainted()) { + Raise(eSecurityError, "Insecure PATH - %s", str); + } } } static int -proc_exec_v(argv) +proc_exec_v(argv, prog) char **argv; -{ char *prog; - - security(argv[0]); - prog = dln_find_exe(argv[0], 0); - if (!prog) { - errno = ENOENT; - return -1; +{ + if (prog) { + security(prog); + } + else { + security(argv[0]); + prog = dln_find_exe(argv[0], 0); + if (!prog) { + errno = ENOENT; + return -1; + } } #if (defined(MSDOS) && !defined(DJGPP)) || defined(__human68k__) { @@ -315,13 +318,19 @@ proc_exec_v(argv) } static int -proc_exec_n(argc, argv) +proc_exec_n(argc, argv, progv) int argc; VALUE *argv; + VALUE progv; { + char *prog = 0; char **args; int i; + if (progv) { + Check_SafeStr(progv); + prog = RSTRING(progv)->ptr; + } args = ALLOCA_N(char*, argc+1); for (i=0; iptr; } + Check_SafeStr(prog); args[i] = (char *) 0; if (args[0]) - return proc_exec_v(args); + return proc_spawn_v(args, RSTRING(prog)->ptr); return -1; } @@ -473,7 +490,7 @@ proc_spawn(str) *a++ = t; *a = NULL; } - return argv[0] ? proc_spawn_v(argv) : -1 ; + return argv[0] ? proc_spawn_v(argv, 0) : -1 ; } #endif /* __human68k__ */ @@ -482,12 +499,29 @@ f_exec(argc, argv) int argc; VALUE *argv; { - if (argc == 1) { + VALUE prog = 0; + + if (TYPE(argv[0]) == T_ARRAY) { + if (RARRAY(argv[0])->len != 2) { + ArgError("wrong first argument"); + } + prog = RARRAY(argv[0])->ptr[0]; + argv[0] = RARRAY(argv[0])->ptr[1]; + } + + if (TYPE(argv[0]) == T_ARRAY) { + if (RARRAY(argv[0])->len != 2) { + ArgError("wrong first argument"); + } + prog = RARRAY(argv[0])->ptr[0]; + argv[0] = RARRAY(argv[0])->ptr[1]; + } + if (argc == 1 && prog == 0) { Check_SafeStr(argv[0]); rb_proc_exec(RSTRING(argv[0])->ptr); } else { - proc_exec_n(argc, argv); + proc_exec_n(argc, argv, prog); } rb_sys_fail(RSTRING(argv[0])->ptr); } @@ -574,6 +608,12 @@ f_system(argc, argv) VALUE cmd; int state; + if (TYPE(argv[0]) == T_ARRAY) { + if (RARRAY(argv[0])->len != 2) { + ArgError("wrong first argument"); + } + argv[0] = RARRAY(argv[0])->ptr[0]; + } cmd = ary_join(ary_new4(argc, argv), str_new2(" ")); Check_SafeStr(cmd); @@ -587,6 +627,12 @@ f_system(argc, argv) VALUE cmd; int state; + if (TYPE(argv[0]) == T_ARRAY) { + if (RARRAY(argv[0])->len != 2) { + ArgError("wrong first argument"); + } + argv[0] = RARRAY(argv[0])->ptr[0]; + } cmd = ary_join(ary_new4(argc, argv), str_new2(" ")); Check_SafeStr(cmd); @@ -597,6 +643,7 @@ f_system(argc, argv) return FALSE; #else #if defined(__human68k__) + VALUE prog = 0; int i; int state; @@ -608,14 +655,25 @@ f_system(argc, argv) return INT2FIX(0); } - for (i = 0; i < argc; i++) - Check_SafeStr(argv[i]); + if (TYPE(argv[0]) == T_ARRAY) { + if (RARRAY(argv[0])->len != 2) { + ArgError("wrong first argument"); + } + prog = RARRAY(argv[0])->ptr[0]; + argv[0] = RARRAY(argv[0])->ptr[1]; + } - state = argc == 1 ? proc_spawn(RSTRING(argv[0])->ptr) : proc_spawn_n(argc, argv) ; + if (argc == 1 && prog == 0) { + state = proc_spawn(RSTRING(argv[0])->ptr); + } + else { + state = proc_spawn_n(argc, argv, prog); + } last_status = state == -1 ? INT2FIX(127) : INT2FIX(state); return state == 0 ? TRUE : FALSE ; #else + VALUE prog = 0; int i; int pid; @@ -627,18 +685,22 @@ f_system(argc, argv) return INT2FIX(0); } - for (i=0; ilen != 2) { + ArgError("wrong first argument"); + } + prog = RARRAY(argv[0])->ptr[0]; + argv[0] = RARRAY(argv[0])->ptr[1]; } retry: switch (pid = vfork()) { case 0: - if (argc == 1) { + if (argc == 1 && prog == 0) { rb_proc_exec(RSTRING(argv[0])->ptr); } else { - proc_exec_n(argc, argv); + proc_exec_n(argc, argv, prog); } _exit(127); break; /* not reached */ @@ -930,8 +992,6 @@ extern VALUE f_kill(); void Init_process() { - extern VALUE mKernel; - rb_define_virtual_variable("$$", get_pid, 0); rb_define_readonly_variable("$?", &last_status); rb_define_global_function("exec", f_exec, -1); diff --git a/random.c b/random.c index 3fc9a0003f..d0a5756b69 100644 --- a/random.c +++ b/random.c @@ -21,7 +21,8 @@ f_srand(argc, argv, obj) VALUE *argv; VALUE obj; { - int seed, old; + VALUE seed; + int old; static int saved_seed; if (rb_scan_args(argc, argv, "01", &seed) == 0) { diff --git a/range.c b/range.c index b7406a1e7a..9596e07f93 100644 --- a/range.c +++ b/range.c @@ -12,7 +12,6 @@ #include "ruby.h" -VALUE mComparable; static VALUE cRange; extern VALUE cNumeric; @@ -170,6 +169,8 @@ range_inspect(range) return str; } +VALUE enum_length(); + static VALUE range_length(rng) VALUE rng; diff --git a/re.c b/re.c index 60377f5c8e..cb0ade9aaf 100644 --- a/re.c +++ b/re.c @@ -73,19 +73,19 @@ static char casetable[] = { int str_cicmp(str1, str2) - struct RString *str1, *str2; + VALUE str1, str2; { int len, i; char *p1, *p2; - len = min(str1->len, str2->len); - p1 = str1->ptr; p2 = str2->ptr; + len = min(RSTRING(str1)->len, RSTRING(str2)->len); + p1 = RSTRING(str1)->ptr; p2 = RSTRING(str2)->ptr; for (i = 0; i < len; i++, p1++, p2++) { if (casetable[(unsigned)*p1] != casetable[(unsigned)*p2]) return casetable[(unsigned)*p1] - casetable[(unsigned)*p2]; } - return str1->len - str2->len; + return RSTRING(str1)->len - RSTRING(str2)->len; } #define REG_IGNORECASE FL_USER0 @@ -109,7 +109,7 @@ static int reg_kcode = static void kcode_euc(reg) - struct RRegexp *reg; + VALUE reg; { FL_UNSET(reg, KCODE_MASK); FL_SET(reg, KCODE_EUC); @@ -118,7 +118,7 @@ kcode_euc(reg) static void kcode_sjis(reg) - struct RRegexp *reg; + VALUE reg; { FL_UNSET(reg, KCODE_MASK); FL_SET(reg, KCODE_SJIS); @@ -127,7 +127,7 @@ kcode_sjis(reg) static void kcode_none(reg) - struct RRegexp *reg; + VALUE reg; { FL_UNSET(reg, KCODE_MASK); FL_SET(reg, KCODE_FIXED); @@ -135,7 +135,7 @@ kcode_none(reg) static void kcode_set_option(reg) - struct RRegexp *reg; + VALUE reg; { if (!FL_TEST(reg, KCODE_FIXED)) return; @@ -153,7 +153,7 @@ kcode_set_option(reg) re_set_syntax(re_syntax_options); } -static void +void kcode_reset_option() { re_syntax_options &= ~RE_MBCTYPE_MASK; @@ -172,13 +172,12 @@ kcode_reset_option() extern int rb_in_eval; -static VALUE -reg_desc(s, len, re) +static void +reg_expr_str(str, s, len) + VALUE str; char *s; int len; - VALUE re; { - VALUE str = str_new2("/"); char *p, *pend; int slash = 0; @@ -207,20 +206,52 @@ reg_desc(s, len, re) p++; } } +} + +static VALUE +reg_desc(s, len, re) + char *s; + int len; + VALUE re; +{ + VALUE str = str_new2("/"); + reg_expr_str(str, s, len); str_cat(str, "/", 1); if (re) { - if (FL_TEST(re, REG_IGNORECASE)) { + if (FL_TEST(re,REG_IGNORECASE)) str_cat(str, "i", 1); + if (FL_TEST(re,KCODE_FIXED)) { + switch ((RBASIC(re)->flags & KCODE_MASK)) { + case KCODE_NONE: + str_cat(str, "n", 1); + break; + case KCODE_EUC: + str_cat(str, "e", 1); + break; + case KCODE_SJIS: + str_cat(str, "s", 1); + break; + } } } return str; } +static VALUE +reg_source(re) + VALUE re; +{ + VALUE str = str_new(0,0); + reg_expr_str(str, RREGEXP(re)->str,RREGEXP(re)->len,re); + + return str; +} + static VALUE reg_inspect(re) - struct RRegexp *re; + VALUE re; { - return reg_desc(re->str, re->len, re); + return reg_desc(RREGEXP(re)->str, RREGEXP(re)->len, re); } static void @@ -238,6 +269,36 @@ reg_raise(s, len, err, re) Error("%s: %s", err, RSTRING(desc)->ptr); } +static VALUE +reg_casefold_p(re) + VALUE re; +{ + if (FL_TEST(re, REG_IGNORECASE)) return TRUE; + return FALSE; +} + +static VALUE +reg_kcode_method(re) + VALUE re; +{ + char *kcode = "$KCODE"; + + if (FL_TEST(re, KCODE_FIXED)) { + switch (RBASIC(re)->flags & KCODE_MASK) { + case KCODE_NONE: + kcode = "none"; break; + case KCODE_EUC: + kcode = "euc"; break; + case KCODE_SJIS: + kcode = "sjis"; break; + default: + break; + } + } + + return str_new2(kcode); +} + static Regexp* make_regexp(s, len, flag) char *s; @@ -286,50 +347,52 @@ match_alloc() return (VALUE)match; } +static VALUE +match_clone(orig) + VALUE orig; +{ + struct re_registers *rr; + + NEWOBJ(match, struct RMatch); + OBJSETUP(match, cMatch, T_MATCH); + + match->str = RMATCH(orig)->str; + + match->regs = ALLOC(struct re_registers); + match->regs->allocated = 0; + re_copy_registers(match->regs, RMATCH(orig)->regs); + + return (VALUE)match; +} + VALUE ignorecase; +static VALUE matchcache; -int -reg_search(reg, str, start, regs) - struct RRegexp *reg; - struct RString *str; - int start; - struct re_registers *regs; +void +reg_prepare_re(reg) + VALUE reg; { int result; int casefold = RTEST(ignorecase); - VALUE match = 0; - struct re_registers *regs0 = 0; int need_recompile = 0; - if (start > str->len) return -1; - /* case-flag set for the object */ if (FL_TEST(reg, REG_IGNORECASE)) { casefold = TRUE; } if (casefold) { - if (reg->ptr->translate != casetable) { - reg->ptr->translate = casetable; - reg->ptr->fastmap_accurate = 0; + if (RREGEXP(reg)->ptr->translate != casetable) { + RREGEXP(reg)->ptr->translate = casetable; + RREGEXP(reg)->ptr->fastmap_accurate = 0; need_recompile = 1; } } - else if (reg->ptr->translate) { - reg->ptr->translate = NULL; - reg->ptr->fastmap_accurate = 0; + else if (RREGEXP(reg)->ptr->translate) { + RREGEXP(reg)->ptr->translate = NULL; + RREGEXP(reg)->ptr->fastmap_accurate = 0; need_recompile = 1; } - if (regs == (struct re_registers*)-1) { - regs = 0; - } - else { - match = match_alloc(); - regs0 = RMATCH(match)->regs; - } - - if (regs && !match) regs0 = regs; - if (FL_TEST(reg, KCODE_FIXED)) { kcode_set_option(reg); } @@ -342,28 +405,61 @@ reg_search(reg, str, start, regs) if (need_recompile) { char *err; - err = re_compile_pattern(reg->str, reg->len, reg->ptr); + err = re_compile_pattern(RREGEXP(reg)->str, RREGEXP(reg)->len, RREGEXP(reg)->ptr); if (err != NULL) { kcode_reset_option(); - reg_raise(reg->str, reg->len, err, reg); + reg_raise(RREGEXP(reg)->str, RREGEXP(reg)->len, err, reg); } } +} - result = re_search(reg->ptr, str->ptr, str->len, - start, str->len - start, regs0); +int +reg_search(reg, str, start, regs) + VALUE reg, str; + int start; + struct re_registers *regs; +{ + int result; + int casefold = RTEST(ignorecase); + VALUE match = 0; + struct re_registers *regs0 = 0; + int need_recompile = 0; + + if (start > RSTRING(str)->len) return -1; + + reg_prepare_re(reg); + + if (regs == (struct re_registers*)-1) { + regs = 0; + } + else { + if (matchcache) { + match = matchcache; + matchcache = 0; + } + else { + match = match_alloc(); + } + regs0 = RMATCH(match)->regs; + } + + result = re_search(RREGEXP(reg)->ptr,RSTRING(str)->ptr,RSTRING(str)->len, + start,RSTRING(str)->len-start,regs0); kcode_reset_option(); if (start == -2) { - reg_raise(reg->str, reg->len, "Stack overfow in regexp matcher", reg); + reg_raise(RREGEXP(reg)->str, RREGEXP(reg)->len, + "Stack overfow in regexp matcher", reg); } if (result < 0) { + matchcache = match; backref_set(Qnil); } else if (match) { RMATCH(match)->str = str_new4(str); backref_set(match); } - if (regs && regs0 && regs0 != regs) re_copy_registers(regs, regs0); + if (regs && regs0) re_copy_registers(regs, regs0); return result; } @@ -371,70 +467,70 @@ reg_search(reg, str, start, regs) VALUE reg_nth_defined(nth, match) int nth; - struct RMatch *match; + VALUE match; { if (NIL_P(match)) return Qnil; - if (nth >= match->regs->num_regs) { + if (nth >= RMATCH(match)->regs->num_regs) { return FALSE; } - if (match->BEG(nth) == -1) return FALSE; + if (RMATCH(match)->BEG(nth) == -1) return FALSE; return TRUE; } VALUE reg_nth_match(nth, match) int nth; - struct RMatch *match; + VALUE match; { int start, end, len; if (NIL_P(match)) return Qnil; - if (nth >= match->regs->num_regs) { + if (nth >= RMATCH(match)->regs->num_regs) { return Qnil; } - start = match->BEG(nth); + start = RMATCH(match)->BEG(nth); if (start == -1) return Qnil; - end = match->END(nth); + end = RMATCH(match)->END(nth); len = end - start; - return str_new(RSTRING(match->str)->ptr + start, len); + return str_new(RSTRING(RMATCH(match)->str)->ptr + start, len); } VALUE reg_last_match(match) - struct RMatch *match; + VALUE match; { return reg_nth_match(0, match); } VALUE reg_match_pre(match) - struct RMatch *match; + VALUE match; { if (NIL_P(match)) return Qnil; - if (match->BEG(0) == -1) return Qnil; - return str_new(RSTRING(match->str)->ptr, match->BEG(0)); + if (RMATCH(match)->BEG(0) == -1) return Qnil; + return str_new(RSTRING(RMATCH(match)->str)->ptr, RMATCH(match)->BEG(0)); } VALUE reg_match_post(match) - struct RMatch *match; + VALUE match; { if (NIL_P(match)) return Qnil; - if (match->BEG(0) == -1) return Qnil; - return str_new(RSTRING(match->str)->ptr+match->END(0), - RSTRING(match->str)->len-match->END(0)); + if (RMATCH(match)->BEG(0) == -1) return Qnil; + return str_new(RSTRING(RMATCH(match)->str)->ptr+RMATCH(match)->END(0), + RSTRING(RMATCH(match)->str)->len-RMATCH(match)->END(0)); } VALUE reg_match_last(match) - struct RMatch *match; + VALUE match; { int i; if (NIL_P(match)) return Qnil; - if (match->BEG(0) == -1) return Qnil; + if (RMATCH(match)->BEG(0) == -1) return Qnil; - for (i=match->regs->num_regs-1; match->BEG(i) == -1 && i > 0; i--) + for (i=RMATCH(match)->regs->num_regs-1; RMATCH(match)->BEG(i) == -1 && i > 0; i--) ; if (i == 0) return Qnil; return reg_nth_match(i, match); @@ -466,11 +562,11 @@ last_paren_match_getter() static VALUE match_to_a(match) - struct RMatch *match; + VALUE match; { - struct re_registers *regs = match->regs; - VALUE ary = ary_new(regs->num_regs); - char *ptr = RSTRING(match->str)->ptr; + struct re_registers *regs = RMATCH(match)->regs; + VALUE ary = ary_new2(regs->num_regs); + char *ptr = RSTRING(RMATCH(match)->str)->ptr; int i; for (i=0; inum_regs; i++) { @@ -481,9 +577,35 @@ match_to_a(match) return ary; } +static VALUE +match_aref(argc, argv, match) + int argc; + VALUE *argv; + VALUE match; +{ + VALUE idx, rest; + struct re_registers *regs; + char *ptr; + int i; + + rb_scan_args(argc, argv, "11", &idx, &rest); + + if (!NIL_P(rest) || !FIXNUM_P(idx) || FIX2INT(idx) < 0) { + return ary_aref(argc, argv, match_to_a(match)); + } + + regs = RMATCH(match)->regs; + i = FIX2INT(idx); + + if (i>=regs->num_regs) return Qnil; + + ptr = RSTRING(RMATCH(match)->str)->ptr; + return str_new(ptr+regs->beg[i], regs->end[i]-regs->beg[i]); +} + static VALUE match_to_s(match) - struct RMatch *match; + VALUE match; { VALUE str = reg_last_match(match); @@ -557,23 +679,51 @@ static VALUE reg_cache; VALUE reg_regcomp(str) - struct RString *str; + VALUE str; { int ignc = RTEST(ignorecase); - if (reg_cache && RREGEXP(reg_cache)->len == str->len + if (reg_cache && RREGEXP(reg_cache)->len == RSTRING(str)->len && ign_cache == ignc - && memcmp(RREGEXP(reg_cache)->str, str->ptr, str->len) == 0) + && memcmp(RREGEXP(reg_cache)->str, RSTRING(str)->ptr, RSTRING(str)->len) == 0) return reg_cache; ign_cache = ignc; - return reg_cache = reg_new(str->ptr, str->len, ignc); + return reg_cache = reg_new(RSTRING(str)->ptr, RSTRING(str)->len, ignc); +} + +static int +reg_cur_kcode(re) + VALUE re; +{ + if (FL_TEST(re, KCODE_FIXED)) { + return RBASIC(re)->flags & KCODE_MASK; + } + return 0; +} + +static VALUE +reg_equal(re1, re2) + VALUE re1, re2; +{ + int min; + + if (re1 == re2) return TRUE; + if (TYPE(re2) != T_REGEXP) return FALSE; + if (RREGEXP(re1)->len != RREGEXP(re2)->len) return FALSE; + min = RREGEXP(re1)->len; + if (min > RREGEXP(re2)->len) min = RREGEXP(re2)->len; + if (memcmp(RREGEXP(re1)->str, RREGEXP(re2)->str, min) == 0 && + reg_cur_kcode(re1) == reg_cur_kcode(re2) && + !(FL_TEST(re1,REG_IGNORECASE) ^ FL_TEST(re2,REG_IGNORECASE))) { + return TRUE; + } + return FALSE; } VALUE reg_match(re, str) - struct RRegexp *re; - struct RString *str; + VALUE re, str; { int start; @@ -587,7 +737,7 @@ reg_match(re, str) VALUE reg_match2(re) - struct RRegexp *re; + VALUE re; { int start; VALUE line = lastline_get(); @@ -653,17 +803,16 @@ reg_s_new(argc, argv, self) static VALUE reg_s_quote(re, str) - VALUE re; - struct RString *str; + VALUE re, str; { char *s, *send, *t; char *tmp; Check_Type(str, T_STRING); - tmp = ALLOCA_N(char, str->len*2); + tmp = ALLOCA_N(char, RSTRING(str)->len*2); - s = str->ptr; send = s + str->len; + s = RSTRING(str)->ptr; send = s + RSTRING(str)->len; t = tmp; for (; s != send; s++) { @@ -682,30 +831,41 @@ reg_s_quote(re, str) return str_new(tmp, t - tmp); } +static int +reg_get_kcode(re) + VALUE re; +{ + int kcode = 0; + + switch (RBASIC(re)->flags & KCODE_MASK) { + case KCODE_NONE: + kcode |= 2; break; + case KCODE_EUC: + kcode |= 4; break; + case KCODE_SJIS: + kcode |= 6; break; + default: + break; + } + + return kcode; +} + static VALUE reg_clone(re) - struct RRegexp *re; + VALUE re; { - int flag = FL_TEST(re, REG_IGNORECASE); + int flag = FL_TEST(re, REG_IGNORECASE)?1:0; + if (FL_TEST(re, KCODE_FIXED)) { - switch (RBASIC(re)->flags & KCODE_MASK) { - case KCODE_NONE: - flag |= 2; break; - case KCODE_EUC: - flag |= 4; break; - case KCODE_SJIS: - flag |= 6; break; - default: - break; - } + flag |= reg_get_kcode(re); } - return reg_new_1(CLASS_OF(re), re->str, re->len, flag); + return reg_new_1(CLASS_OF(re), RREGEXP(re)->str, RREGEXP(re)->len, flag); } VALUE reg_regsub(str, src, regs) - struct RString *str; - struct RString *src; + VALUE str, src; struct re_registers *regs; { VALUE val = 0; @@ -713,8 +873,8 @@ reg_regsub(str, src, regs) char *p, *s, *e, c; int no; - p = s = str->ptr; - e = s + str->len; + p = s = RSTRING(str)->ptr; + e = s + RSTRING(str)->len; while (s < e) { char *ss = s; @@ -737,11 +897,11 @@ reg_regsub(str, src, regs) break; case '`': - str_cat(val, src->ptr, BEG(0)); + str_cat(val, RSTRING(src)->ptr, BEG(0)); continue; case '\'': - str_cat(val, src->ptr+END(0), src->len-END(0)); + str_cat(val, RSTRING(src)->ptr+END(0), RSTRING(src)->len-END(0)); continue; case '+': @@ -761,7 +921,7 @@ reg_regsub(str, src, regs) if (no >= 0) { if (BEG(no) == -1) continue; - str_cat(val, src->ptr+BEG(no), END(no)-BEG(no)); + str_cat(val, RSTRING(src)->ptr+BEG(no), END(no)-BEG(no)); } } @@ -774,6 +934,41 @@ reg_regsub(str, src, regs) return val; } +#define IS_KCODE_FIXED(re) (FL_TEST((re), KCODE_FIXED)?1:0) + +static int +reg_prepare_operation(re1, re2) + VALUE re1, re2; +{ + int flag = 0; + + Check_Type(re2, T_REGEXP); + flag = IS_KCODE_FIXED(re1)+IS_KCODE_FIXED(re2)*2; + switch (IS_KCODE_FIXED(re1)+IS_KCODE_FIXED(re2)*2) { + case 3: /* both have fixed kcode (must match) */ + if (((RBASIC(re1)->flags^RBASIC(re2)->flags)&KCODE_MASK) != 0) { + Raise(eRegxpError, "kanji code mismatch"); + } + /* fall through */ + case 2: /* re2 has fixed kcode */ + flag = reg_get_kcode(re2); + break; + case 1: /* re1 has fixed kcode */ + flag = reg_get_kcode(re1); + break; + case 0: /* neither has fixed kcode */ + flag = 0; + break; + } + + if (FL_TEST(re1, REG_IGNORECASE) ^ FL_TEST(re2, REG_IGNORECASE)) { + Raise(eRegxpError, "casefold mismatch"); + } + if (FL_TEST(re1, REG_IGNORECASE)) flag |= 0x1; + + return flag; +} + static VALUE kcode_getter() { @@ -854,7 +1049,7 @@ Init_Regexp() #ifdef DEFAULT_MBCTYPE | DEFAULT_MBCTYPE #endif -); + ); rb_define_virtual_variable("$~", match_getter, match_setter); rb_define_virtual_variable("$&", last_match_getter, 0); @@ -872,15 +1067,21 @@ Init_Regexp() rb_define_singleton_method(cRegexp, "quote", reg_s_quote, 1); rb_define_method(cRegexp, "clone", reg_clone, 0); + rb_define_method(cRegexp, "==", reg_equal, 1); rb_define_method(cRegexp, "=~", reg_match, 1); rb_define_method(cRegexp, "===", reg_match, 1); rb_define_method(cRegexp, "~", reg_match2, 0); rb_define_method(cRegexp, "inspect", reg_inspect, 0); + rb_define_method(cRegexp, "source", reg_source, 0); + rb_define_method(cRegexp, "casefold?", reg_casefold_p, 0); + rb_define_method(cRegexp, "kcode", reg_kcode_method, 0); rb_global_variable(®_cache); + rb_global_variable(&matchcache); cMatch = rb_define_class("MatchingData", cData); rb_define_method(cMatch, "to_a", match_to_a, 0); + rb_define_method(cMatch, "[]", match_aref, -1); rb_define_method(cMatch, "to_s", match_to_s, 0); rb_define_method(cMatch, "inspect", any_to_s, 0); } diff --git a/re.h b/re.h index 2be0fb7bde..8769d6ef39 100644 --- a/re.h +++ b/re.h @@ -29,6 +29,9 @@ struct RMatch { #define RMATCH(obj) (R_CAST(RMatch)(obj)) -VALUE re_regcomp(); -VALUE re_regsub(); +int str_cicmp _((VALUE, VALUE)); +VALUE reg_regcomp _((VALUE)); +int reg_search _((VALUE, VALUE, int, struct re_registers *)); +VALUE reg_regsub _((VALUE, VALUE, struct re_registers *)); +void reg_free _((Regexp *)); #endif diff --git a/regex.c b/regex.c index 686695cbe2..0fdf2c06f9 100644 --- a/regex.c +++ b/regex.c @@ -66,16 +66,21 @@ char *alloca(); #pragma alloca #endif +#ifdef HAVE_STRING_H +# include +#else +# include +#endif + #define RE_ALLOCATE alloca #define FREE_VARIABLES() alloca(0) #define FREE_AND_RETURN_VOID(stackb) return #define FREE_AND_RETURN(stackb,val) return(val) -#define DOUBLE_STACK(stackx,stackb,len) \ - (stackx = (unsigned char **) alloca(2 * len \ - * sizeof(unsigned char *)),\ +#define DOUBLE_STACK(stackx,stackb,len,type) \ + (stackx = (type*) alloca(2 * len * sizeof(type)), \ /* Only copy what is in use. */ \ - (unsigned char **) memcpy(stackx, stackb, len * sizeof (char *))) + (type*) memcpy(stackx, stackb, len * sizeof (type))) #else /* NO_ALLOCA defined */ #define RE_ALLOCATE malloc @@ -92,22 +97,34 @@ char *alloca(); #define FREE_AND_RETURN_VOID(stackb) free(stackb);return #define FREE_AND_RETURN(stackb,val) free(stackb);return(val) -#define DOUBLE_STACK(stackx,stackb,len) \ - (unsigned char **)xrealloc(stackb, 2 * len * sizeof(unsigned char *)) +#define DOUBLE_STACK(stackx,stackb,len,type) \ + (type*)xrealloc(stackb, 2 * len * sizeof(type)) #endif /* NO_ALLOCA */ #define RE_TALLOC(n,t) ((t*)RE_ALLOCATE((n)*sizeof(t))) #define TMALLOC(n,t) ((t*)xmalloc((n)*sizeof(t))) #define TREALLOC(s,n,t) (s=((t*)xrealloc(s,(n)*sizeof(t)))) +#define EXPAND_FAIL_STACK(stackx,stackb,len) \ + do {\ + /* Roughly double the size of the stack. */ \ + stackx = DOUBLE_STACK(stackx,stackb,len,unsigned char*); \ + /* Rearrange the pointers. */ \ + stackp = stackx + (stackp - stackb); \ + stackb = stackx; \ + stacke = stackb + 2 * len; \ + } while (0); \ + /* Get the interface, including the syntax bits. */ #include "regex.h" +/* Subroutines for re_compile_pattern. */ static void store_jump P((char *, int, char *)); static void insert_jump P((int, char *, char *, char *)); static void store_jump_n P((char *, int, char *, unsigned)); static void insert_jump_n P((int, char *, char *, char *, unsigned)); -static void insert_op_2 P((int, char *, char *, int, int )); +static void insert_op P((int, char *, char *)); +static void insert_op_2 P((int, char *, char *, int, int)); static int memcmp_translate P((unsigned char *, unsigned char *, int, unsigned char *)); @@ -180,6 +197,9 @@ enum regexpcode exactn=1, /* Followed by one byte giving n, then by n literal bytes. */ begline, /* Fail unless at beginning of line. */ endline, /* Fail unless at end of line. */ + begbuf, /* Succeeds if at beginning of buffer (if emacs) or at beginning + of string to be matched (if not). */ + endbuf, /* Analogously, for end of buffer/string. */ jump, /* Followed by two bytes giving relative address to jump to. */ on_failure_jump, /* Followed by two bytes giving relative address of place to resume at in case of failure. */ @@ -206,6 +226,11 @@ enum regexpcode jump_n, /* Similar to jump, but jump n times only; also the relative address following is in turn followed by yet two more bytes containing n. */ + try_next, /* Jump to next pattern for the first time, + leaving this pattern on the failure stack. */ + finalize_push, /* Finalize stack and push the beginning of the pattern + on the stack to retry (used for non-greedy match) */ + finalize_push_n, /* Similar to finalize_push, buf finalize n time only */ set_number_at, /* Set the following relative location to the subsequent number. */ anychar, /* Matches any (more or less) one character. */ @@ -226,11 +251,16 @@ enum regexpcode and store it in a memory register. Followed by one byte containing the register number. Register numbers must be in the range 0 through RE_NREGS. */ + start_nowidth, /* Save string point to the stack. */ + stop_nowidth, /* Restore string place at the point start_nowidth. */ + pop_and_fail, /* Fail after popping nowidth entry from stack. */ duplicate, /* Match a duplicate of something remembered. Followed by one byte containing the index of the memory register. */ wordchar, /* Matches any word-constituent character. */ notwordchar, /* Matches any char that is not a word-constituent. */ + wordbeg, /* Succeeds if at word beginning. */ + wordend, /* Succeeds if at word end. */ wordbound, /* Succeeds if at a word boundary. */ notwordbound,/* Succeeds if not at a word boundary. */ }; @@ -386,9 +416,6 @@ long re_syntax_options = DEFAULT_MBCTYPE; } \ } -/* Subroutines for re_compile_pattern. */ -/* static void store_jump(), insert_jump(), store_jump_n(), - insert_jump_n(), insert_op_2(); */ #define STORE_MBC(p, c) \ ((p)[0] = (unsigned char)(c >> 8), (p)[1] = (unsigned char)(c)) @@ -530,6 +557,320 @@ is_in_list(c, b) return result; } +static void +print_partial_compiled_pattern(start, end) + unsigned char *start; + unsigned char *end; +{ + int mcnt, mcnt2; + unsigned char *p = start; + unsigned char *pend = end; + + if (start == NULL) + { + printf ("(null)\n"); + return; + } + + /* Loop over pattern commands. */ + while (p < pend) + { + switch ((enum regexpcode) *p++) + { + case unused: + printf ("/unused"); + break; + + case exactn: + mcnt = *p++; + printf ("/exactn/%d", mcnt); + do + { + putchar('/'); + printf("%c", *p++); + } + while (--mcnt); + break; + + case start_memory: + mcnt = *p++; + printf ("/start_memory/%d", mcnt); + break; + + case stop_memory: + mcnt = *p++; + printf ("/stop_memory/%d", mcnt); + break; + + case start_nowidth: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + printf ("/start_nowidth//%d", mcnt); + break; + + case stop_nowidth: + printf ("/stop_nowidth//"); + p += 2; + break; + + case pop_and_fail: + printf ("/pop_and_fail"); + break; + + case duplicate: + printf ("/duplicate/%d", *p++); + break; + + case anychar: + printf ("/anychar"); + break; + + case charset: + case charset_not: + { + register int c; + + printf ("/charset%s", + (enum regexpcode) *(p - 1) == charset_not ? "_not" : ""); + + mcnt = *p; + printf("/%d", mcnt); + for (c = 0; c < mcnt; c++) + { + unsigned bit; + unsigned char map_byte = p[1 + c]; + + putchar ('/'); + + for (bit = 0; bit < BYTEWIDTH; bit++) + if (map_byte & (1 << bit)) + printf("%c", c * BYTEWIDTH + bit); + } + p += mcnt + 1; + mcnt = EXTRACT_UNSIGNED(p); + p += 2; + while (mcnt--) { + int beg = *p++; + int end = *p++; + printf("/%c%c-%c%c", beg>>BYTEWIDTH, beg&0xff, end>>BYTEWIDTH, end&0xff); + } + break; + } + + case begline: + printf ("/begline"); + break; + + case endline: + printf ("/endline"); + break; + + case on_failure_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + printf ("/on_failure_jump//%d", mcnt); + break; + + case dummy_failure_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + printf ("/dummy_failure_jump//%d", mcnt); + break; + + case finalize_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + printf ("/finalize_jump//%d", mcnt); + break; + + case maybe_finalize_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + printf ("/maybe_finalize_jump//%d", mcnt); + break; + + case jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + printf ("/jump//%d", mcnt); + break; + + case succeed_n: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + EXTRACT_NUMBER_AND_INCR (mcnt2, p); + printf ("/succeed_n//%d//%d", mcnt, mcnt2); + break; + + case jump_n: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + EXTRACT_NUMBER_AND_INCR (mcnt2, p); + printf ("/jump_n//%d//%d", mcnt, mcnt2); + break; + + case set_number_at: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + EXTRACT_NUMBER_AND_INCR (mcnt2, p); + printf ("/set_number_at//%d//%d", mcnt, mcnt2); + break; + + case try_next: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + printf ("/try_next//%d", mcnt); + break; + + case finalize_push: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + printf ("/finalize_push//%d", mcnt); + break; + + case finalize_push_n: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + EXTRACT_NUMBER_AND_INCR (mcnt2, p); + printf ("/finalize_push_n//%d//%d", mcnt, mcnt2); + break; + + case wordbound: + printf ("/wordbound"); + break; + + case notwordbound: + printf ("/notwordbound"); + break; + + case wordbeg: + printf ("/wordbeg"); + break; + + case wordend: + printf ("/wordend"); + + case wordchar: + printf ("/wordchar"); + break; + + case notwordchar: + printf ("/notwordchar"); + break; + + case begbuf: + printf ("/begbuf"); + break; + + case endbuf: + printf ("/endbuf"); + break; + + default: + printf ("?%d", *(p-1)); + } + } + printf ("/\n"); +} + + +static void +print_compiled_pattern(bufp) + struct re_pattern_buffer *bufp; +{ + unsigned char *buffer = bufp->buffer; + + print_partial_compiled_pattern (buffer, buffer + bufp->used); +} + +static char* +calculate_must_string(start, end) + unsigned char *start; + unsigned char *end; +{ + int mcnt, mcnt2; + int max = 0; + unsigned char *p = start; + unsigned char *pend = end; + unsigned char *must = 0; + + if (start == NULL) return 0; + + /* Loop over pattern commands. */ + while (p < pend) + { + switch ((enum regexpcode) *p++) + { + case unused: + break; + + case exactn: + mcnt = *p; + if (mcnt > max) { + must = p; + } + p += mcnt+1; + break; + + case start_memory: + case stop_memory: + case duplicate: + p++; + break; + + case start_nowidth: + case stop_nowidth: + case pop_and_fail: + case anychar: + case begline: + case endline: + case wordbound: + case notwordbound: + case wordbeg: + case wordend: + case wordchar: + case notwordchar: + case begbuf: + case endbuf: + break; + + case charset: + case charset_not: + mcnt = *p++; + p += mcnt; + EXTRACT_NUMBER_AND_INCR (mcnt, p); + while (mcnt--) { + EXTRACT_NUMBER_AND_INCR (mcnt2, p); + EXTRACT_NUMBER_AND_INCR (mcnt2, p); + } + break; + + case on_failure_jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + if (mcnt > 0) p += mcnt; + if ((enum regexpcode)p[-3] == jump) { + p -= 3; + EXTRACT_NUMBER_AND_INCR (mcnt, p); + if (mcnt > 0) p += mcnt; + } + break; + + case dummy_failure_jump: + case succeed_n: + case try_next: + case jump: + EXTRACT_NUMBER_AND_INCR (mcnt, p); + if (mcnt > 0) p += mcnt; + break; + + case finalize_jump: + case maybe_finalize_jump: + case finalize_push: + p += 2; + break; + + case jump_n: + case set_number_at: + case finalize_push_n: + p += 4; + break; + + default: + break; + } + } + return must; +} + + /* re_compile_pattern takes a regular-expression string and converts it into a buffer full of byte commands for matching. @@ -584,6 +925,10 @@ re_compile_pattern(pattern, size, bufp) char many_times_ok; + /* In processing a repeat, 1 means non-greedy matches. */ + + char greedy; + /* Address of beginning of regexp, or inside of last \(. */ char *begalt = b; @@ -594,18 +939,15 @@ re_compile_pattern(pattern, size, bufp) /* In processing an interval, at most this many matches can be made. */ int upper_bound; - /* Place in pattern (i.e., the {) to which to go back if the interval - is invalid. */ - char *beg_interval = 0; - /* Stack of information saved by \( and restored by \). - Four stack elements are pushed by each \(: + Five stack elements are pushed by each \(: First, the value of b. Second, the value of fixup_jump. - Third, the value of regnum. - Fourth, the value of begalt. */ + Third, the value of begalt. + Fourth, the value of regnum. + Fifth, the type of the paren. */ - int stackb[40]; + int *stackb = RE_TALLOC(40, int); int *stackp = stackb; int *stacke = stackb + 40; int *stackt; @@ -672,11 +1014,6 @@ re_compile_pattern(pattern, size, bufp) /* $ means succeed if at end of line, but only in special contexts. If validly in the middle of a pattern, it is a normal character. */ -#if 0 - /* not needed for perl4 compatible */ - if ((re_syntax_options & RE_CONTEXTUAL_INVALID_OPS) && p1 != pend) - goto invalid_pattern; -#endif if (p1 == pend || *p1 == '\n' || (re_syntax_options & RE_CONTEXT_INDEP_OPS) || (re_syntax_options & RE_NO_BK_PARENS @@ -716,55 +1053,37 @@ re_compile_pattern(pattern, size, bufp) case '+': case '?': - if ((re_syntax_options & RE_BK_PLUS_QM) - || (re_syntax_options & RE_LIMITED_OPS)) + if (re_syntax_options & RE_LIMITED_OPS) goto normal_char; - handle_plus: case '*': /* If there is no previous pattern, char not special. */ - if (!laststart) - { - if (re_syntax_options & RE_CONTEXTUAL_INVALID_OPS) - goto invalid_pattern; - else if (! (re_syntax_options & RE_CONTEXT_INDEP_OPS)) - goto normal_char; - } + if (!laststart) { + if (re_syntax_options & RE_CONTEXTUAL_INVALID_OPS) + goto invalid_pattern; + else if (! (re_syntax_options & RE_CONTEXT_INDEP_OPS)) + goto normal_char; + } /* If there is a sequence of repetition chars, collapse it down to just one. */ - zero_times_ok = 0; - many_times_ok = 0; - while (1) - { - zero_times_ok |= c != '+'; - many_times_ok |= c != '?'; - if (p == pend) + zero_times_ok = c != '+'; + many_times_ok = c != '?'; + greedy = 1; + if (p != pend) { + PATFETCH(c); + switch (c) { + case '?': + greedy = 0; + break; + case '*': + case '+': + goto nested_meta; + default: + PATUNFETCH; break; - PATFETCH(c); - if (c == '*') - ; - else if (!(re_syntax_options & RE_BK_PLUS_QM) - && (c == '+' || c == '?')) - ; - else if ((re_syntax_options & RE_BK_PLUS_QM) - && c == '\\') - { - /* int c1; */ - PATFETCH(c1); - if (!(c1 == '+' || c1 == '?')) - { - PATUNFETCH; - PATUNFETCH; - break; - } - c = c1; - } - else - { - PATUNFETCH; - break; - } } + } + repeat: /* Star, etc. applied to an empty pattern is equivalent to an empty pattern. */ if (!laststart) @@ -772,32 +1091,39 @@ re_compile_pattern(pattern, size, bufp) /* Now we know whether or not zero matches is allowed and also whether or not two or more matches is allowed. */ - if (many_times_ok) - { - /* If more than one repetition is allowed, put in at the - end a backward relative jump from b to before the next - jump we're going to put in below (which jumps from - laststart to after this jump). */ - GET_BUFFER_SPACE(3); - store_jump(b, maybe_finalize_jump, laststart - 3); - b += 3; /* Because store_jump put stuff here. */ - } - /* On failure, jump from laststart to b + 3, which will be the - end of the buffer after this jump is inserted. */ - GET_BUFFER_SPACE(3); + if (many_times_ok) { + /* If more than one repetition is allowed, put in at the + end a backward relative jump from b to before the next + jump we're going to put in below (which jumps from + laststart to after this jump). */ + GET_BUFFER_SPACE(3); + store_jump(b,greedy?maybe_finalize_jump:finalize_push,laststart-3); + b += 3; /* Because store_jump put stuff here. */ + } + + /* On failure, jump from laststart to next pattern, which will be the + end of the buffer after this jump is inserted. */ + GET_BUFFER_SPACE(3); insert_jump(on_failure_jump, laststart, b + 3, b); - pending_exact = 0; b += 3; - if (!zero_times_ok) - { - /* At least one repetition is required, so insert a - dummy-failure before the initial on-failure-jump - instruction of the loop. This effects a skip over that - instruction the first time we hit that loop. */ - GET_BUFFER_SPACE(6); - insert_jump(dummy_failure_jump, laststart, laststart + 6, b); + + if (zero_times_ok) { + if (greedy == 0) { + GET_BUFFER_SPACE(3); + insert_jump(try_next, laststart, b + 3, b); b += 3; } + } + else { + /* At least one repetition is required, so insert a + `dummy_failure_jump' before the initial + `on_failure_jump' instruction of the loop. This + effects a skip over that instruction the first time + we hit that loop. */ + GET_BUFFER_SPACE(3); + insert_jump(dummy_failure_jump, laststart, laststart + 6, b); + b += 3; + } break; case '.': @@ -831,7 +1157,7 @@ re_compile_pattern(pattern, size, bufp) /* Read in characters and ranges, setting map bits. */ - while (1) + for (;;) { int size; unsigned last = (unsigned)-1; @@ -984,310 +1310,342 @@ re_compile_pattern(pattern, size, bufp) break; case '(': - if (! (re_syntax_options & RE_NO_BK_PARENS)) - goto normal_char; - else - goto handle_open; - - case ')': - if (! (re_syntax_options & RE_NO_BK_PARENS)) - goto normal_char; - else - goto handle_close; - - case '\n': - if (! (re_syntax_options & RE_NEWLINE_OR)) - goto normal_char; - else - goto handle_bar; + PATFETCH(c); + if (c == '?') { + PATFETCH(c); + switch (c) { + case '#': + case 'i': + case 'm': + case 's': + case 'x': + for (;;) { + PATFETCH(c); + if (c == ')') break; + } + c = '#'; + break; - case '|': -#if 0 - /* not needed for perl4 compatible */ - if ((re_syntax_options & RE_CONTEXTUAL_INVALID_OPS) - && (! laststart || p == pend)) - goto invalid_pattern; - else - if (! (re_syntax_options & RE_NO_BK_VBAR)) - goto normal_char; - else -#endif - goto handle_bar; + case ':': + case '=': + case '!': + break; - case '{': - if (! ((re_syntax_options & RE_NO_BK_CURLY_BRACES) - && (re_syntax_options & RE_INTERVALS))) - goto normal_char; - else - goto handle_interval; + default: + FREE_AND_RETURN(stackb, "undefined (?...) sequence"); + } + } + else { + PATUNFETCH; + c = '('; + } + if (c == '#') break; + if (stackp+6 >= stacke) { + int *stackx; + unsigned int len = stacke - stackb; + + stackx = DOUBLE_STACK(stackx,stackb,len,int); + /* Rearrange the pointers. */ + stackp = stackx + (stackp - stackb); + stackb = stackx; + stacke = stackb + 2 * len; + } - case '\\': - if (p == pend) goto invalid_pattern; - /* Do not translate the character after the \, so that we can - distinguish, e.g., \B from \b, even if we normally would - translate, e.g., B to b. */ - PATFETCH_RAW(c); - switch (c) - { + /* Laststart should point to the start_memory that we are about + to push (unless the pattern has RE_NREGS or more ('s). */ + /* obsolete: now RE_NREGS is just a default register size. */ + *stackp++ = b - bufp->buffer; + *stackp++ = fixup_jump ? fixup_jump - bufp->buffer + 1 : 0; + *stackp++ = begalt - bufp->buffer; + switch (c) { case '(': - if (re_syntax_options & RE_NO_BK_PARENS) - goto normal_backsl; - handle_open: - if (stackp == stacke) goto nesting_too_deep; - - /* Laststart should point to the start_memory that we are about - to push (unless the pattern has RE_NREGS or more ('s). */ - /* obsolete: now RE_NREGS is just a default register size. */ - *stackp++ = b - bufp->buffer; BUFPUSH(start_memory); BUFPUSH(regnum); - *stackp++ = fixup_jump ? fixup_jump - bufp->buffer + 1 : 0; *stackp++ = regnum++; - *stackp++ = begalt - bufp->buffer; - fixup_jump = 0; - laststart = 0; - begalt = b; - /* too many ()'s to fit in a byte. */ - if (regnum >= (1<= RE_REG_MAX) goto too_big; break; - case ')': - if (re_syntax_options & RE_NO_BK_PARENS) - goto normal_backsl; - handle_close: - if (stackp == stackb) goto unmatched_close; - begalt = *--stackp + bufp->buffer; + case '=': + case '!': + BUFPUSH(start_nowidth); + *stackp++ = b - bufp->buffer; + BUFPUSH(0); /* temporary value */ + BUFPUSH(0); + if (c == '=') break; + + BUFPUSH(on_failure_jump); + *stackp++ = b - bufp->buffer; + BUFPUSH(0); /* temporary value */ + BUFPUSH(0); + break; + + case ':': + default: + break; + } + *stackp++ = c; + fixup_jump = 0; + laststart = 0; + begalt = b; + break; + + case ')': + if (stackp == stackb) goto unmatched_close; + switch (c = *--stackp) { + case '(': if (fixup_jump) store_jump(fixup_jump, jump, b); BUFPUSH(stop_memory); BUFPUSH(stackp[-1]); - stackp -= 2; - fixup_jump = *stackp ? *stackp + bufp->buffer - 1 : 0; - laststart = *--stackp + bufp->buffer; break; - case '|': - if ((re_syntax_options & RE_LIMITED_OPS) - || (re_syntax_options & RE_NO_BK_VBAR)) + case '!': + BUFPUSH(pop_and_fail); + /* back patch */ + STORE_NUMBER(bufp->buffer+stackp[-1], b - bufp->buffer - stackp[-1] - 2); + stackp--; + /* fall through */ + case '=': + BUFPUSH(stop_nowidth); + /* tell stack-pos place to start_nowidth */ + STORE_NUMBER(bufp->buffer+stackp[-1], b - bufp->buffer - stackp[-1] - 2); + BUFPUSH(0); /* space to hold stack pos */ + BUFPUSH(0); + break; + + case ':': + default: + break; + } + stackp--; + begalt = *--stackp + bufp->buffer; + stackp--; + fixup_jump = *stackp ? *stackp + bufp->buffer - 1 : 0; + laststart = *--stackp + bufp->buffer; + if (c == '!' || c == '=') laststart = b; + break; + + case '|': + /* Insert before the previous alternative a jump which + jumps to this alternative if the former fails. */ + GET_BUFFER_SPACE(6); + insert_jump(on_failure_jump, begalt, b + 6, b); + pending_exact = 0; + b += 3; + /* The alternative before the previous alternative has a + jump after it which gets executed if it gets matched. + Adjust that jump so it will jump to the previous + alternative's analogous jump (put in below, which in + turn will jump to the next (if any) alternative's such + jump, etc.). The last such jump jumps to the correct + final destination. */ + if (fixup_jump) + store_jump(fixup_jump, jump, b); + + /* Leave space for a jump after previous alternative---to be + filled in later. */ + fixup_jump = b; + b += 3; + + laststart = 0; + begalt = b; + break; + + case '{': + /* If there is no previous pattern, this isn't an interval. */ + if (!laststart) + { + if (re_syntax_options & RE_CONTEXTUAL_INVALID_OPS) + goto invalid_pattern; + else goto normal_backsl; - handle_bar: - if (re_syntax_options & RE_LIMITED_OPS) - goto normal_char; - /* Insert before the previous alternative a jump which - jumps to this alternative if the former fails. */ - GET_BUFFER_SPACE(6); - insert_jump(on_failure_jump, begalt, b + 6, b); - pending_exact = 0; - b += 3; - /* The alternative before the previous alternative has a - jump after it which gets executed if it gets matched. - Adjust that jump so it will jump to the previous - alternative's analogous jump (put in below, which in - turn will jump to the next (if any) alternative's such - jump, etc.). The last such jump jumps to the correct - final destination. */ - if (fixup_jump) - store_jump(fixup_jump, jump, b); + } + /* It also isn't an interval if not preceded by an re + matching a single character or subexpression, or if + the current type of intervals can't handle back + references and the previous thing is a back reference. */ + if (! (*laststart == anychar + || *laststart == charset + || *laststart == charset_not + || *laststart == wordchar + || *laststart == notwordchar + || *laststart == start_memory + || (*laststart == exactn + && (laststart[1] == 1 + || laststart[1] == 2 && ismbchar(laststart[2]))) + || (! (re_syntax_options & RE_NO_BK_REFS) + && *laststart == duplicate))) + { + /* Posix extended syntax is handled in previous + statement; this is for Posix basic syntax. */ + if (re_syntax_options & RE_INTERVALS) + goto invalid_pattern; - /* Leave space for a jump after previous alternative---to be - filled in later. */ - fixup_jump = b; - b += 3; + goto normal_backsl; + } + lower_bound = -1; /* So can see if are set. */ + upper_bound = -1; + GET_UNSIGNED_NUMBER(lower_bound); + if (c == ',') { + GET_UNSIGNED_NUMBER(upper_bound); + if (upper_bound < 0) + upper_bound = RE_DUP_MAX; + } + if (upper_bound < 0) + upper_bound = lower_bound; + if (c != '}' || lower_bound < 0 || upper_bound > RE_DUP_MAX + || lower_bound > upper_bound + || (p != pend && *p == '{')) { + goto invalid_pattern; + } + greedy = 1; + if (p != pend) { + PATFETCH(c); + if (c == '?') greedy = 0; + else PATUNFETCH; + } - laststart = 0; - begalt = b; - break; + /* If upper_bound is zero, don't want to succeed at all; + jump from laststart to b + 3, which will be the end of + the buffer after this jump is inserted. */ - case '{': - if (! (re_syntax_options & RE_INTERVALS) - /* Let \{ be a literal. */ - || ((re_syntax_options & RE_INTERVALS) - && (re_syntax_options & RE_NO_BK_CURLY_BRACES)) - /* If it's the string "\{". */ - || (p - 2 == pattern && p == pend)) - goto normal_backsl; - handle_interval: - beg_interval = p - 1; /* The {. */ - /* If there is no previous pattern, this isn't an interval. */ - if (!laststart) - { - if (re_syntax_options & RE_CONTEXTUAL_INVALID_OPS) - goto invalid_pattern; - else - goto normal_backsl; - } - /* It also isn't an interval if not preceded by an re - matching a single character or subexpression, or if - the current type of intervals can't handle back - references and the previous thing is a back reference. */ - if (! (*laststart == anychar - || *laststart == charset - || *laststart == charset_not - || *laststart == wordchar - || *laststart == notwordchar - || *laststart == start_memory - || (*laststart == exactn - && (laststart[1] == 1 - || laststart[1] == 2 && ismbchar(laststart[2]))) - || (! (re_syntax_options & RE_NO_BK_REFS) - && *laststart == duplicate))) - { - if (re_syntax_options & RE_NO_BK_CURLY_BRACES) - goto normal_char; + if (upper_bound == 0) { + GET_BUFFER_SPACE(3); + insert_jump(jump, laststart, b + 3, b); + b += 3; + break; + } - /* Posix extended syntax is handled in previous - statement; this is for Posix basic syntax. */ - if (re_syntax_options & RE_INTERVALS) - goto invalid_pattern; + if (lower_bound == 0) { + zero_times_ok = 1; + if (upper_bound == RE_DUP_MAX) { + many_times_ok = 1; + goto repeat; + } + if (upper_bound == 1) { + many_times_ok = 0; + goto repeat; + } + } + if (lower_bound == 1 && upper_bound == RE_DUP_MAX) { + many_times_ok = 1; + zero_times_ok = 0; + goto repeat; + } - goto normal_backsl; - } - lower_bound = -1; /* So can see if are set. */ - upper_bound = -1; - GET_UNSIGNED_NUMBER(lower_bound); - if (c == ',') - { - GET_UNSIGNED_NUMBER(upper_bound); - if (upper_bound < 0) - upper_bound = RE_DUP_MAX; - } - if (upper_bound < 0) - upper_bound = lower_bound; - if (! (re_syntax_options & RE_NO_BK_CURLY_BRACES)) - { - if (c != '\\') - goto invalid_pattern; - PATFETCH(c); - } - if (c != '}' || lower_bound < 0 || upper_bound > RE_DUP_MAX - || lower_bound > upper_bound - || ((re_syntax_options & RE_NO_BK_CURLY_BRACES) - && p != pend && *p == '{')) - { - if (re_syntax_options & RE_NO_BK_CURLY_BRACES) - goto unfetch_interval; - else - goto invalid_pattern; - } + /* Star, etc. applied to an empty pattern is equivalent + to an empty pattern. */ + if (!laststart) + break; - /* If upper_bound is zero, don't want to succeed at all; - jump from laststart to b + 3, which will be the end of - the buffer after this jump is inserted. */ - - if (upper_bound == 0) - { - GET_BUFFER_SPACE(3); - insert_jump(jump, laststart, b + 3, b); - b += 3; - } - - /* Otherwise, after lower_bound number of succeeds, jump - to after the jump_n which will be inserted at the end - of the buffer, and insert that jump_n. */ - else - { /* Set to 5 if only one repetition is allowed and - hence no jump_n is inserted at the current end of - the buffer; then only space for the succeed_n is - needed. Otherwise, need space for both the - succeed_n and the jump_n. */ - - unsigned slots_needed = upper_bound == 1 ? 5 : 10; - - GET_BUFFER_SPACE(slots_needed); - /* Initialize the succeed_n to n, even though it will - be set by its attendant set_number_at, because - re_compile_fastmap will need to know it. Jump to - what the end of buffer will be after inserting - this succeed_n and possibly appending a jump_n. */ - insert_jump_n(succeed_n, laststart, b + slots_needed, - b, lower_bound); - b += 5; /* Just increment for the succeed_n here. */ - - /* When hit this when matching, set the succeed_n's n. */ - GET_BUFFER_SPACE(5); - insert_op_2(set_number_at, laststart, b, 5, lower_bound); - b += 5; - - /* More than one repetition is allowed, so put in at - the end of the buffer a backward jump from b to the - succeed_n we put in above. By the time we've gotten - to this jump when matching, we'll have matched once - already, so jump back only upper_bound - 1 times. */ - - if (upper_bound > 1) - { - GET_BUFFER_SPACE(15); - store_jump_n(b, jump_n, laststart+5, upper_bound - 1); - b += 5; - /* When hit this when matching, reset the - preceding jump_n's n to upper_bound - 1. */ - insert_op_2(set_number_at, laststart, b, b - laststart, upper_bound - 1); - b += 5; - - BUFPUSH(set_number_at); - STORE_NUMBER_AND_INCR(b, -5); - STORE_NUMBER_AND_INCR(b, upper_bound - 1); - } - } - pending_exact = 0; - beg_interval = 0; - break; - - - unfetch_interval: - /* If an invalid interval, match the characters as literals. */ - if (beg_interval) - p = beg_interval; - else - { - fprintf(stderr, - "regex: no interval beginning to which to backtrack.\n"); - exit (1); - } - - beg_interval = 0; - PATFETCH(c); /* normal_char expects char in `c'. */ - goto normal_char; - break; + { /* If the upper bound is > 1, we need to insert + more at the end of the loop. */ + unsigned slots_needed = upper_bound == 1 ? 5 : 10; + + GET_BUFFER_SPACE(5); + /* Initialize lower bound of the `succeed_n', even + though it will be set during matching by its + attendant `set_number_at' (inserted next), + because `re_compile_fastmap' needs to know. + Jump to the `jump_n' we might insert below. */ + insert_jump_n(succeed_n, laststart, b + slots_needed, + b, lower_bound); + b += 5; /* Just increment for the succeed_n here. */ + + /* Code to initialize the lower bound. Insert + before the `succeed_n'. The `5' is the last two + bytes of this `set_number_at', plus 3 bytes of + the following `succeed_n'. */ + GET_BUFFER_SPACE(5); + insert_op_2(set_number_at, laststart, b, 5, lower_bound); + b += 5; + + if (upper_bound > 1) + { /* More than one repetition is allowed, so + append a backward jump to the `succeed_n' + that starts this interval. + + When we've reached this during matching, + we'll have matched the interval once, so + jump back only `upper_bound - 1' times. */ + GET_BUFFER_SPACE(5); + store_jump_n(b, greedy?jump_n:finalize_push_n, laststart + 5, upper_bound - 1); + b += 5; + + /* The location we want to set is the second + parameter of the `jump_n'; that is `b-2' as + an absolute address. `laststart' will be + the `set_number_at' we're about to insert; + `laststart+3' the number to set, the source + for the relative address. But we are + inserting into the middle of the pattern -- + so everything is getting moved up by 5. + Conclusion: (b - 2) - (laststart + 3) + 5, + i.e., b - laststart. + + We insert this at the beginning of the loop + so that if we fail during matching, we'll + reinitialize the bounds. */ + GET_BUFFER_SPACE(5); + insert_op_2(set_number_at, laststart, b, b - laststart, upper_bound - 1); + b += 5; + + GET_BUFFER_SPACE(5); + BUFPUSH(set_number_at); + STORE_NUMBER_AND_INCR(b, -5); + STORE_NUMBER_AND_INCR(b, upper_bound - 1); + } + pending_exact = 0; + } + break; + case '\\': + if (p == pend) goto invalid_pattern; + /* Do not translate the character after the \, so that we can + distinguish, e.g., \B from \b, even if we normally would + translate, e.g., B to b. */ + PATFETCH_RAW(c); + switch (c) + { case 's': case 'S': case 'd': case 'D': while (b - bufp->buffer > bufp->allocated - 9 - (1 << BYTEWIDTH) / BYTEWIDTH) - EXTEND_BUFFER; + EXTEND_BUFFER; laststart = b; if (c == 's' || c == 'd') { - BUFPUSH(charset); + BUFPUSH(charset); } else { - BUFPUSH(charset_not); + BUFPUSH(charset_not); } BUFPUSH((1 << BYTEWIDTH) / BYTEWIDTH); memset(b, 0, (1 << BYTEWIDTH) / BYTEWIDTH + 2); if (c == 's' || c == 'S') { - SET_LIST_BIT(' '); - SET_LIST_BIT('\t'); - SET_LIST_BIT('\n'); - SET_LIST_BIT('\r'); - SET_LIST_BIT('\f'); + SET_LIST_BIT(' '); + SET_LIST_BIT('\t'); + SET_LIST_BIT('\n'); + SET_LIST_BIT('\r'); + SET_LIST_BIT('\f'); } else { - char cc; + char cc; - for (cc = '0'; cc <= '9'; cc++) { - SET_LIST_BIT(cc); - } + for (cc = '0'; cc <= '9'; cc++) { + SET_LIST_BIT(cc); + } } while ((int) b[-1] > 0 && b[b[-1] - 1] == 0) - b[-1]--; + b[-1]--; if (b[-1] != (1 << BYTEWIDTH) / BYTEWIDTH) - memmove(&b[b[-1]], &b[(1 << BYTEWIDTH) / BYTEWIDTH], - 2 + EXTRACT_UNSIGNED(&b[(1 << BYTEWIDTH) / BYTEWIDTH])*4); + memmove(&b[b[-1]], &b[(1 << BYTEWIDTH) / BYTEWIDTH], + 2 + EXTRACT_UNSIGNED(&b[(1 << BYTEWIDTH) / BYTEWIDTH])*4); b += b[-1] + 2 + EXTRACT_UNSIGNED(&b[b[-1]])*4; break; @@ -1301,6 +1659,14 @@ re_compile_pattern(pattern, size, bufp) BUFPUSH(notwordchar); break; + case '<': + BUFPUSH(wordbeg); + break; + + case '>': + BUFPUSH(wordend); + break; + case 'b': BUFPUSH(wordbound); break; @@ -1309,6 +1675,14 @@ re_compile_pattern(pattern, size, bufp) BUFPUSH(notwordbound); break; + case 'A': + BUFPUSH(begbuf); + break; + + case 'Z': + BUFPUSH(endbuf); + break; + /* hex */ case 'x': c1 = 0; @@ -1354,7 +1728,7 @@ re_compile_pattern(pattern, size, bufp) } /* Can't back reference to a subexpression if inside of it. */ - for (stackt = stackp - 2; stackt > stackb; stackt -= 4) + for (stackt = stackp - 2; stackt > stackb; stackt -= 5) if (*stackt == c1) goto normal_char; laststart = b; @@ -1362,14 +1736,6 @@ re_compile_pattern(pattern, size, bufp) BUFPUSH(c1); break; - case '+': - case '?': - if (re_syntax_options & RE_BK_PLUS_QM) - goto handle_plus; - else - goto normal_backsl; - break; - default: normal_backsl: goto normal_char; @@ -1384,19 +1750,14 @@ re_compile_pattern(pattern, size, bufp) PATFETCH(c); } else if (c > 0x7f) { - c1 = 0xff; + c1 = 0xff; } numeric_char: if (!pending_exact || pending_exact + *pending_exact + 1 != b || *pending_exact >= (c1 ? 0176 : 0177) + || *p == '+' || *p == '?' || *p == '*' || *p == '^' - || ((re_syntax_options & RE_BK_PLUS_QM) - ? *p == '\\' && (p[1] == '+' || p[1] == '?') - : (*p == '+' || *p == '?')) - || ((re_syntax_options & RE_INTERVALS) - && ((re_syntax_options & RE_NO_BK_CURLY_BRACES) - ? *p == '{' - : (p[0] == '\\' && p[1] == '{')))) + || *p == '{') { laststart = b; BUFPUSH(exactn); @@ -1419,31 +1780,32 @@ re_compile_pattern(pattern, size, bufp) bufp->used = b - bufp->buffer; bufp->re_nsub = regnum; - return 0; + bufp->must = calculate_must_string(bufp->buffer, b); + FREE_AND_RETURN(stackb, 0); invalid_char: - return "Invalid character in regular expression"; + FREE_AND_RETURN(stackb, "invalid character in regular expression"); invalid_pattern: - return "Invalid regular expression"; + FREE_AND_RETURN(stackb, "invalid regular expression"); unmatched_open: - return "Unmatched ("; + FREE_AND_RETURN(stackb, "unmatched ("); unmatched_close: - return "Unmatched )"; + FREE_AND_RETURN(stackb, "unmatched )"); end_of_pattern: - return "Premature end of regular expression"; - - nesting_too_deep: - return "Nesting too deep"; + FREE_AND_RETURN(stackb, "premature end of regular expression"); too_big: - return "Regular expression too big"; + FREE_AND_RETURN(stackb, "regular expression too big"); memory_exhausted: - return "Memory exhausted"; + FREE_AND_RETURN(stackb, "memory exhausted"); + + nested_meta: + FREE_AND_RETURN(stackb, "nested *?+ in regexp"); } @@ -1524,6 +1886,27 @@ insert_jump_n(op, from, to, current_end, n) } +/* Open up space at location THERE, and insert operation OP. + CURRENT_END gives the end of the storage in use, so + we know how much data to copy up. + + If you call this function, you must zero out pending_exact. */ + +static void +insert_op(op, there, current_end) + int op; + char *there, *current_end; +{ + register char *pfrom = current_end; /* Copy from here... */ + register char *pto = current_end + 1; /* ...to here. */ + + while (pfrom != there) + *--pto = *--pfrom; + + there[0] = (char)op; +} + + /* Open up space at location THERE, and insert operation OP followed by NUM_1 and NUM_2. CURRENT_END gives the end of the storage in use, so we know how much data to copy up. @@ -1547,6 +1930,83 @@ insert_op_2(op, there, current_end, num_1, num_2) STORE_NUMBER(there + 3, num_2); } + +#define trans_eq(c1, c2, translate) (translate?(translate[c1]==translate[c2]):((c1)==(c2))) +static int +must_match(little, lend, big, bend, translate) + unsigned char *little, *lend; + unsigned char *big, *bend; + unsigned char *translate; +{ + int c; + + while (little < lend && big < bend) { + c = *little++; + if (c == 0xff) { + if (!trans_eq(*big++, *little++, translate)) break; + continue; + } + if (!trans_eq(*big++, c, translate)) break; + } + if (little == lend) return 1; + return 0; +} + +static int +must_instr(little, llen, big, blen, translate) + unsigned char *little; + int llen; + unsigned char *big; + int blen; + char *translate; +{ + unsigned char *bend = big + blen; + register int c; + int fescape = 0; + + if (blen < llen) + return 0; + + c = *little; + if (c == 0xff) { + c = *++little; + fescape = 1; + } + else if (translate && !ismbchar(c)) { + c = translate[c]; + } + + while (big < bend) { + /* look for first character */ + if (fescape) { + while (big < bend) { + if (*big == c) break; + big++; + } + } + else if (translate && !ismbchar(c)) { + while (big < bend) { + if (ismbchar(*big)) big++; + else if (translate[*big] == c) break; + big++; + } + } + else { + while (big < bend) { + if (*big == c) break; + if (ismbchar(*big)) big++; + big++; + } + } + + if (must_match(little, little+llen, big, bend, translate)) + return 1; + + if (ismbchar(*big)) big++; + big++; + } + return 0; +} /* Given a pattern, compute a fastmap from it. The fastmap records @@ -1557,7 +2017,6 @@ insert_op_2(op, there, current_end, num_1, num_2) The caller must supply the address of a (1 << BYTEWIDTH)-byte data area as bufp->fastmap. The other components of bufp describe the pattern to be used. */ - void re_compile_fastmap(bufp) struct re_pattern_buffer *bufp; @@ -1571,10 +2030,9 @@ re_compile_fastmap(bufp) unsigned char *translate = (unsigned char *)bufp->translate; unsigned is_a_succeed_n; - unsigned char **stackb; - unsigned char **stackp; - stackb = RE_TALLOC(NFAILURES, unsigned char*); - stackp = stackb; + unsigned char **stackb = RE_TALLOC(NFAILURES, unsigned char*); + unsigned char **stackp = stackb; + unsigned char **stacke = stackb + NFAILURES; memset(fastmap, 0, (1 << BYTEWIDTH)); bufp->fastmap_accurate = 1; @@ -1608,9 +2066,14 @@ re_compile_fastmap(bufp) break; case begline: + case begbuf: + case endbuf: case wordbound: case notwordbound: - continue; + case wordbeg: + case wordend: + case pop_and_fail: + continue; case endline: if (translate) @@ -1639,19 +2102,43 @@ re_compile_fastmap(bufp) If so, discard that as redundant. */ if ((enum regexpcode) *p != on_failure_jump - && (enum regexpcode) *p != succeed_n) + && (enum regexpcode) *p != try_next + && (enum regexpcode) *p != finalize_push + && (enum regexpcode) *p != finalize_push_n) continue; p++; EXTRACT_NUMBER_AND_INCR(j, p); p += j; if (stackp != stackb && *stackp == p) - stackp--; + stackp--; /* pop */ continue; + case start_nowidth: + case stop_nowidth: + case finalize_push: + p += 2; + continue; + + case finalize_push_n: + p += 4; + continue; + + case try_next: case on_failure_jump: handle_on_failure_jump: EXTRACT_NUMBER_AND_INCR(j, p); - *++stackp = p + j; + if (p + j < pend) { + if (stackp == stacke) { + unsigned char **stackx; + unsigned int len = stacke - stackb; + + EXPAND_FAIL_STACK(stackx, stackb, len); + } + *++stackp = p + j; /* push */ + } + else { + bufp->can_be_null = 1; + } if (is_a_succeed_n) EXTRACT_NUMBER_AND_INCR(k, p); /* Skip the n. */ continue; @@ -1659,14 +2146,14 @@ re_compile_fastmap(bufp) case succeed_n: is_a_succeed_n = 1; /* Get to the number of times to succeed. */ - p += 2; + EXTRACT_NUMBER(k, p + 2); /* Increment p past the n for when k != 0. */ - EXTRACT_NUMBER_AND_INCR(k, p); - if (k == 0) - { - p -= 4; - goto handle_on_failure_jump; - } + if (k == 0) { + p += 4; + } + else { + goto handle_on_failure_jump; + } continue; case set_number_at: @@ -1805,14 +2292,12 @@ re_compile_fastmap(bufp) path any farther. Instead, look at the next alternative remembered in the stack. */ if (stackp != stackb) - p = *stackp--; + p = *stackp--; /* pop */ else break; } FREE_AND_RETURN_VOID(stackb); } - - /* Using the compiled pattern in BUFP->buffer, first tries to match @@ -1842,14 +2327,45 @@ re_search(bufp, string, size, startpos, range, regs) if (startpos < 0 || startpos > size) return -1; + /* If the search isn't to be a backwards one, don't waste time in a + search for a pattern that must be anchored. */ + if (bufp->used>0) { + switch ((enum regexpcode)bufp->buffer[0]) { + case begbuf: + if (range > 0) { + if (startpos > 0) + return -1; + else + return re_match(bufp, string, size, 0, regs); + } + break; + + case begline: + if (startpos == 0) { + val = re_match(bufp, string, size, 0, regs); + if (val >= 0) return 0; + } + anchor = 1; + break; + + default: + break; + } + } +#if 1 + if (range > 0 + && bufp->must + && !must_instr(bufp->must+1, bufp->must[0], + string+startpos, size-startpos, + translate)) { + return -1; + } +#endif /* Update the fastmap now if not correct already. */ if (fastmap && !bufp->fastmap_accurate) { - re_compile_fastmap (bufp); + re_compile_fastmap(bufp); } - if (bufp->used > 0 && (enum regexpcode)bufp->buffer[0] == begline) - anchor = 1; - for (;;) { /* If a fastmap is supplied, skip quickly over characters that @@ -1863,14 +2379,12 @@ re_search(bufp, string, size, startpos, range, regs) { if (range > 0) /* Searching forwards. */ { - register int lim = 0; register unsigned char *p, c; int irange = range; - lim = range - (size - startpos); - p = (unsigned char *)&(string[startpos]); + p = (unsigned char *)string+startpos; - while (range > lim) { + while (range > 0) { c = *p++; if (ismbchar(c)) { if (fastmap[c]) @@ -1917,8 +2431,8 @@ re_search(bufp, string, size, startpos, range, regs) #ifdef cALLOCA alloca(0); #endif /* cALLOCA */ - #endif /* NO_ALLOCA */ + advance: if (!range) break; @@ -2021,11 +2535,7 @@ struct register_info } \ \ /* Roughly double the size of the stack. */ \ - stackx = DOUBLE_STACK(stackx,stackb,len); \ - /* Rearrange the pointers. */ \ - stackp = stackx + (stackp - stackb); \ - stackb = stackx; \ - stacke = stackb + 2 * len; \ + EXPAND_FAIL_STACK(stackx, stackb, len); \ } \ \ /* Now push the info for each of those registers. */ \ @@ -2041,6 +2551,7 @@ struct register_info \ *stackp++ = pattern_place; \ *stackp++ = string_place; \ + *stackp++ = (unsigned char *)0; /* non-greedy flag */ \ } @@ -2049,7 +2560,7 @@ struct register_info #define POP_FAILURE_POINT() \ { \ int temp; \ - stackp -= 2; /* Remove failure points. */ \ + stackp -= 3; /* Remove failure points (and flag). */ \ temp = (int) *--stackp; /* How many regs pushed. */ \ temp *= NUM_REG_ITEMS; /* How much to take off the stack. */ \ stackp -= temp; /* Remove the register info. */ \ @@ -2071,11 +2582,11 @@ struct register_info } \ } -#define AT_STRINGS_BEG (d == string) -#define AT_STRINGS_END (d == dend) +#define AT_STRINGS_BEG(d) (d == string) +#define AT_STRINGS_END(d) (d == dend) -#define AT_WORD_BOUNDARY \ - (AT_STRINGS_BEG || AT_STRINGS_END || IS_A_LETTER (d - 1) != IS_A_LETTER (d)) +#define AT_WORD_BOUNDARY(d) \ + (AT_STRINGS_BEG(d) || AT_STRINGS_END(d) || IS_A_LETTER(d - 1) != IS_A_LETTER(d)) /* We have two special cases to check for: 1) if we're past the end of string1, we have to look at the first @@ -2191,10 +2702,9 @@ re_match(bufp, string_arg, size, pos, regs) unsigned char **best_regend = RE_TALLOC(num_regs, unsigned char*); if (regs) { - init_regs(regs, num_regs); + init_regs(regs, num_regs); } - /* Initialize the stack. */ stackb = RE_TALLOC(MAX_NUM_FAILURE_ITEMS * NFAILURES, unsigned char*); stackp = stackb; @@ -2232,7 +2742,7 @@ re_match(bufp, string_arg, size, pos, regs) function if match is complete, or it drops through if match fails at this starting point in the input data. */ - while (1) + for (;;) { #ifdef DEBUG_REGEX fprintf(stderr, @@ -2319,7 +2829,7 @@ re_match(bufp, string_arg, size, pos, regs) IS_ACTIVE(reg_info[*p]) = 1; MATCHED_SOMETHING(reg_info[*p]) = 0; p++; - break; + continue; case stop_memory: regend[*p] = d; @@ -2360,7 +2870,7 @@ re_match(bufp, string_arg, size, pos, regs) } } p++; - break; + continue; /* \ has been turned into a `duplicate' command which is followed by the numeric value of as the register number. */ @@ -2378,7 +2888,7 @@ re_match(bufp, string_arg, size, pos, regs) the end of the first string. */ dend2 = regend[regno]; - while (1) + for (;;) { /* At end of register contents => success */ if (d2 == dend2) break; @@ -2405,6 +2915,25 @@ re_match(bufp, string_arg, size, pos, regs) } break; + case start_nowidth: + PUSH_FAILURE_POINT(0, d); + EXTRACT_NUMBER_AND_INCR(mcnt, p); + STORE_NUMBER(p+mcnt, stackp - stackb); + continue; + + case stop_nowidth: + EXTRACT_NUMBER_AND_INCR(mcnt, p); + stackp = stackb + mcnt; + d = stackp[-2]; + POP_FAILURE_POINT(); + continue; + + case pop_and_fail: + EXTRACT_NUMBER(mcnt, p+1); + stackp = stackb + mcnt; + POP_FAILURE_POINT(); + goto fail; + case anychar: PREFETCH; /* Match anything but a newline, maybe even a null. */ @@ -2470,6 +2999,18 @@ re_match(bufp, string_arg, size, pos, regs) break; goto fail; + /* Match at the very beginning of the string. */ + case begbuf: + if (AT_STRINGS_BEG(d)) + break; + goto fail; + + /* Match at the very end of the data. */ + case endbuf: + if (AT_STRINGS_END(d)) + break; + goto fail; + /* `or' constructs are handled by starting each alternative with an on_failure_jump that points to the start of the next alternative. Each alternative except the last ends with a @@ -2490,7 +3031,7 @@ re_match(bufp, string_arg, size, pos, regs) on_failure: EXTRACT_NUMBER_AND_INCR(mcnt, p); PUSH_FAILURE_POINT(p + mcnt, d); - break; + continue; /* The end of a smart repeat has a maybe_finalize_jump back. Change it either to a finalize_jump or an ordinary jump. */ @@ -2555,7 +3096,7 @@ re_match(bufp, string_arg, size, pos, regs) nofinalize: EXTRACT_NUMBER_AND_INCR(mcnt, p); p += mcnt; - break; + continue; case dummy_failure_jump: /* Normally, the on_failure_jump pushes a failure point, which @@ -2566,17 +3107,17 @@ re_match(bufp, string_arg, size, pos, regs) PUSH_FAILURE_POINT(0, 0); goto nofinalize; - /* Have to succeed matching what follows at least n times. Then just handle like an on_failure_jump. */ case succeed_n: EXTRACT_NUMBER(mcnt, p + 2); /* Originally, this is how many times we HAVE to succeed. */ - if (mcnt) + if (mcnt > 0) { mcnt--; p += 2; STORE_NUMBER_AND_INCR(p, mcnt); + PUSH_FAILURE_POINT(0, 0); } else if (mcnt == 0) { @@ -2584,14 +3125,9 @@ re_match(bufp, string_arg, size, pos, regs) p[3] = unused; goto on_failure; } - else - { - fprintf(stderr, "regex: the succeed_n's n is not set.\n"); - exit(1); - } - break; + continue; - case jump_n: + case jump_n: EXTRACT_NUMBER(mcnt, p + 2); /* Originally, this is how many times we CAN jump. */ if (mcnt) @@ -2604,7 +3140,7 @@ re_match(bufp, string_arg, size, pos, regs) /* If don't have to jump any more, skip over the rest of command. */ else p += 4; - break; + continue; case set_number_at: { @@ -2614,24 +3150,68 @@ re_match(bufp, string_arg, size, pos, regs) p1 = p + mcnt; EXTRACT_NUMBER_AND_INCR(mcnt, p); STORE_NUMBER(p1, mcnt); - break; + continue; } + case try_next: + EXTRACT_NUMBER_AND_INCR(mcnt, p); + if (p + mcnt < pend) { + PUSH_FAILURE_POINT(p, d); + stackp[-1] = (unsigned char*)1; + } + p += mcnt; + continue; + + case finalize_push: + POP_FAILURE_POINT(); + EXTRACT_NUMBER_AND_INCR(mcnt, p); + PUSH_FAILURE_POINT(p + mcnt, d); + stackp[-1] = (unsigned char*)1; + continue; + + case finalize_push_n: + EXTRACT_NUMBER(mcnt, p + 2); + /* Originally, this is how many times we CAN jump. */ + if (mcnt) { + mcnt--; + STORE_NUMBER(p + 2, mcnt); + POP_FAILURE_POINT(); + EXTRACT_NUMBER_AND_INCR(mcnt, p); + PUSH_FAILURE_POINT(p + mcnt, d); + stackp[-1] = (unsigned char*)1; + p += 7; /* skip n and set_number_at after destination */ + } + /* If don't have to push any more, skip over the rest of command. */ + else + p += 4; + continue; + /* Ignore these. Used to ignore the n of succeed_n's which currently have n == 0. */ case unused: - break; + continue; case wordbound: - if (AT_WORD_BOUNDARY) + if (AT_WORD_BOUNDARY(d)) break; goto fail; case notwordbound: - if (AT_WORD_BOUNDARY) + if (AT_WORD_BOUNDARY(d)) goto fail; break; + case wordbeg: + if (IS_A_LETTER(d) && (AT_STRINGS_BEG(d) || !IS_A_LETTER(d - 1))) + break; + goto fail; + + case wordend: + if (!AT_STRINGS_BEG(d) && IS_A_LETTER(d - 1) + && (!IS_A_LETTER(d) || AT_STRINGS_END(d))) + break; + goto fail; + case wordchar: PREFETCH; if (!IS_A_LETTER(d)) @@ -2672,7 +3252,7 @@ re_match(bufp, string_arg, size, pos, regs) goto fail; continue; } - else if (ismbchar(c)) { + if (ismbchar(c)) { if (c != (unsigned char)*p++ || !--mcnt /* redundant check if pattern was compiled properly. */ @@ -2701,6 +3281,8 @@ re_match(bufp, string_arg, size, pos, regs) SET_REGS_MATCHED; break; } + if (stackp != stackb && (int)stackp[-1] == 1) + POP_FAILURE_POINT(); continue; /* Successfully executed one pattern command; keep going. */ /* Jump here if any matching operation fails. */ @@ -2712,12 +3294,11 @@ re_match(bufp, string_arg, size, pos, regs) /* If this failure point is from a dummy_failure_point, just skip it. */ - if (!stackp[-2]) - { - POP_FAILURE_POINT(); - goto fail; - } - + if (stackp[-3] == 0) { + POP_FAILURE_POINT(); + goto fail; + } + stackp--; /* discard flag */ d = *--stackp; p = *--stackp; /* Restore register info. */ diff --git a/regex.h b/regex.h index 32b4cf10d4..91442a8b2b 100644 --- a/regex.h +++ b/regex.h @@ -30,6 +30,7 @@ #define BYTEWIDTH 8 +#define RE_REG_MAX ((1< +#endif #include "ruby.h" #include "re.h" #include "dln.h" @@ -18,9 +21,10 @@ #include #include -#ifdef HAVE_STRING_H -# include -#else +#ifdef HAVE_UNISTD_H +#include +#endif +#ifndef HAVE_STRING_H char *strchr(); char *strrchr(); char *strstr(); @@ -30,8 +34,8 @@ char *getenv(); static int version, copyright; -int debug = FALSE; -int verbose = FALSE; +VALUE debug = FALSE; +VALUE verbose = FALSE; int tainting = FALSE; static int sflag = FALSE; @@ -49,12 +53,18 @@ static void load_stdin(); static void load_file _((char *, int)); static void forbid_setid _((char *)); -static int do_loop = FALSE, do_print = FALSE; -static int do_check = FALSE, do_line = FALSE; -static int do_split = FALSE; +static VALUE do_loop = FALSE, do_print = FALSE; +static VALUE do_check = FALSE, do_line = FALSE; +static VALUE do_split = FALSE; static char *script; +static int origargc; +static char **origargv; + +extern int sourceline; +extern char *sourcefile; + #ifndef RUBY_LIB #define RUBY_LIB "/usr/local/lib/ruby" #endif @@ -118,18 +128,14 @@ rb_require_modules() { struct req_list *list = req_list; struct req_list *tmp; - extern void *eval_tree; /* hack to save syntax tree */ - void *save; req_list = 0; - save = eval_tree; while (list) { f_require(Qnil, str_new2(list->name)); tmp = list->next; free(list); list = tmp; } - eval_tree = save; } static void @@ -331,6 +337,11 @@ proc_options(argcp, argvp) } break; + case '*': + case ' ': + if (s[1] == '-') s+=2; + break; + default: Fatal("Unrecognized switch: -%s",s); @@ -366,11 +377,12 @@ proc_options(argcp, argvp) if (do_search) { char *path = getenv("RUBYPATH"); + script = 0; if (path) { - script = dln_find_file(script, path); + script = dln_find_file(argv[0], path); } if (!script) { - script = dln_find_file(script, getenv("PATH")); + script = dln_find_file(argv[0], getenv("PATH")); } if (!script) script = argv[0]; } @@ -457,14 +469,45 @@ load_file(fname, script) char *p; + if ((p = strstr(RSTRING(line)->ptr, "ruby")) == 0) { + /* not ruby script, kick the program */ + char **argv; + char *path; + char *pend = RSTRING(line)->ptr + RSTRING(line)->len; + + p = RSTRING(line)->ptr + 2; /* skip `#!' */ + if (pend[-1] == '\n') pend--; /* chomp line */ + if (pend[-1] == '\r') pend--; + *pend = '\0'; + while (p < pend && isspace(*p)) + p++; + path = p; /* interpreter path */ + while (p < pend && !isspace(*p)) + p++; + *p++ = '\0'; + if (p < pend) { + argv = ALLOCA_N(char*, origargc+3); + argv[1] = p; + MEMCPY(argv+2, origargv+1, char*, origargc); + } + else { + argv = origargv; + } + argv[0] = path; + execv(path, argv); + sourcefile = fname; + sourceline = 1; + Fatal("Can't exec %s", path); + } + start_read: if (p = strstr(RSTRING(line)->ptr, "ruby -")) { int argc; char *argv[2]; char **argvp = argv; UCHAR *s; s = RSTRING(line)->ptr; - while (isspace(*s++)) - ; + while (isspace(*s)) + s++; *s = '\0'; RSTRING(line)->ptr[RSTRING(line)->len-1] = '\0'; if (RSTRING(line)->ptr[RSTRING(line)->len-2] == '\r') @@ -497,11 +540,9 @@ load_stdin() load_file("-", 1); } -VALUE Progname; -VALUE Argv; - -static int origargc; -static char **origargv; +VALUE rb_progname; +VALUE rb_argv; +VALUE rb_argv0; static void set_arg0(val, id) @@ -537,7 +578,7 @@ set_arg0(val, id) while (++i < len) *s++ = ' '; } - Progname = str_taint(str_new2(origargv[0])); + rb_progname = str_taint(str_new2(origargv[0])); } void @@ -545,7 +586,7 @@ ruby_script(name) char *name; { if (name) { - Progname = str_taint(str_new2(name)); + rb_progname = str_taint(str_new2(name)); sourcefile = name; } } @@ -578,6 +619,40 @@ forbid_setid(s) Fatal("No %s allowed while running setgid", s); } +#if defined(_WIN32) || defined(DJGPP) +static char * +ruby_libpath() +{ + static char libpath[FILENAME_MAX+1]; + char *p; +#if defined(_WIN32) + GetModuleFileName(NULL, libpath, sizeof libpath); +#elif defined(DJGPP) + extern char *__dos_argv0; + strcpy(libpath, __dos_argv0); +#endif + p = strrchr(libpath, '\\'); + if (p) + *p = 0; + if (!strcasecmp(p-4, "\\bin")) + p -= 4; + strcpy(p, "\\lib"); +#if defined(__CYGWIN32__) + p = (char *)malloc(strlen(libpath)+10); + if (!p) + return 0; + cygwin32_conv_to_posix_path(libpath, p); + strcpy(libpath, p); + free(p); +#else + for (p = libpath; *p; p++) + if (*p == '\\') + *p = '/'; +#endif + return libpath; +} +#endif + void ruby_prog_init() { @@ -591,6 +666,10 @@ ruby_prog_init() rb_define_readonly_variable("$-p", &do_print); rb_define_readonly_variable("$-l", &do_line); +#if defined(_WIN32) || defined(DJGPP) + addpath(ruby_libpath()); +#endif + if (rb_safe_level() == 0) { addpath(getenv("RUBYLIB")); } @@ -607,12 +686,13 @@ ruby_prog_init() addpath("."); } - rb_define_hooked_variable("$0", &Progname, 0, set_arg0); + rb_define_hooked_variable("$0", &rb_progname, 0, set_arg0); - Argv = ary_new(); - rb_define_readonly_variable("$*", &Argv); - rb_define_global_const("ARGV", Argv); + rb_argv = ary_new(); + rb_define_readonly_variable("$*", &rb_argv); + rb_define_global_const("ARGV", rb_argv); rb_define_readonly_variable("$-a", &do_split); + rb_global_variable(&rb_argv0); #ifdef MSDOS /* @@ -636,7 +716,7 @@ ruby_set_argv(argc, argv) else dln_argv0 = argv[0]; #endif for (i=0; i < argc; i++) { - ary_push(Argv, str_taint(str_new2(argv[i]))); + ary_push(rb_argv, str_taint(str_new2(argv[i]))); } } @@ -650,6 +730,7 @@ ruby_process_options(argc, argv) origargc = argc; origargv = argv; ruby_script(argv[0]); /* for the time being */ + rb_argv0 = str_taint(str_new2(argv[0])); #if defined(USE_DLN_A_OUT) dln_argv0 = argv[0]; #endif diff --git a/ruby.h b/ruby.h index b477c9e775..ac53f620a9 100644 --- a/ruby.h +++ b/ruby.h @@ -21,6 +21,12 @@ # include #endif +#ifdef HAVE_STRING_H +# include +#else +# include +#endif + #ifndef __STDC__ # define volatile # ifdef __GNUC__ @@ -41,11 +47,19 @@ #pragma alloca #endif -typedef unsigned int UINT; +typedef unsigned short USHORT; +typedef unsigned long UINT; + +#if SIZEOF_INT == SIZEOF_VOIDP +typedef int INT; +#elif SIZEOF_LONG == SIZEOF_VOIDP +typedef long INT; +#else +---->> ruby requires sizeof(void*) == sizeof(int/long) to be compiled. <<---- +#endif typedef UINT VALUE; -typedef UINT ID; +typedef unsigned int ID; -typedef unsigned short USHORT; typedef unsigned char UCHAR; #ifdef __STDC__ @@ -71,11 +85,11 @@ typedef unsigned char UCHAR; #endif #define FIXNUM_MAX (LONG_MAX>>1) -#define FIXNUM_MIN RSHIFT((long)LONG_MIN,1) +#define FIXNUM_MIN RSHIFT((INT)LONG_MIN,1) #define FIXNUM_FLAG 0x01 -#define INT2FIX(i) (VALUE)(((int)(i))<<1 | FIXNUM_FLAG) -VALUE int2inum _((int)); +#define INT2FIX(i) (VALUE)(((INT)(i))<<1 | FIXNUM_FLAG) +VALUE int2inum _((INT)); #define INT2NUM(v) int2inum(v) #if (-1==(((-1)<<1)&FIXNUM_FLAG)>>1) @@ -83,22 +97,24 @@ VALUE int2inum _((int)); #else # define RSHIFT(x,y) (((x)<0) ? ~((~(x))>>y) : (x)>>y) #endif -#define FIX2INT(x) RSHIFT((int)x,1) +#define FIX2INT(x) RSHIFT((INT)x,1) -#define FIX2UINT(f) ((UINT)(f)>>1) -#define FIXNUM_P(f) (((int)(f))&FIXNUM_FLAG) +#define FIX2UINT(f) (((UINT)(f))>>1) +#define FIXNUM_P(f) (((long)(f))&FIXNUM_FLAG) #define POSFIXABLE(f) ((f) <= FIXNUM_MAX) #define NEGFIXABLE(f) ((f) >= FIXNUM_MIN) #define FIXABLE(f) (POSFIXABLE(f) && NEGFIXABLE(f)) /* special contants - i.e. non-zero and non-fixnum constants */ #undef FALSE -#define FALSE 0 #undef TRUE -#define TRUE 2 -#define Qnil 4 +#define FALSE 0 +#define TRUE 2 +#define NIL 4 +#define Qfalse 0 +#define Qtrue 2 +#define Qnil 4 -int rb_test_false_or_nil _((VALUE)); # define RTEST(v) rb_test_false_or_nil((VALUE)(v)) #define NIL_P(v) ((VALUE)(v) == Qnil) @@ -135,7 +151,6 @@ VALUE rb_class_of _((VALUE)); #define BUILTIN_TYPE(x) (((struct RBasic*)(x))->flags & T_MASK) -int rb_type _((VALUE)); #define TYPE(x) rb_type((VALUE)(x)) void rb_check_type _((VALUE,int)); @@ -144,17 +159,22 @@ void rb_check_safe_str _((VALUE)); #define Check_SafeStr(v) rb_check_safe_str((VALUE)(v)) void rb_secure _((int)); -#define NUM2INT(x) (FIXNUM_P(x)?FIX2INT(x):num2int(x)) -VALUE num2fix _((VALUE)); int num2int _((VALUE)); +#define NUM2INT(x) (FIXNUM_P(x)?FIX2INT(x):num2int(x)) + +double num2dbl _((VALUE)); +#define NUM2DBL(x) num2dbl((VALUE)(x)) +VALUE rb_newobj _((void)); #define NEWOBJ(obj,type) type *obj = (type*)rb_newobj() #define OBJSETUP(obj,c,t) {\ RBASIC(obj)->class = (c);\ RBASIC(obj)->flags = (t);\ } -#define CLONESETUP(obj1,obj2) \ - OBJSETUP(obj1,RBASIC(obj2)->class,RBASIC(obj2)->flags); +#define CLONESETUP(clone,obj) {\ + OBJSETUP(clone,singleton_class_clone(RBASIC(obj)->class),RBASIC(obj)->flags);\ + singleton_class_attached(RBASIC(clone)->class, (VALUE)clone);\ +} struct RBasic { UINT flags; @@ -170,7 +190,7 @@ struct RClass { struct RBasic basic; struct st_table *iv_tbl; struct st_table *m_tbl; - struct RClass *super; + VALUE super; }; struct RFloat { @@ -182,7 +202,7 @@ struct RString { struct RBasic basic; UINT len; UCHAR *ptr; - struct RString *orig; + VALUE orig; }; struct RArray { @@ -278,13 +298,44 @@ struct RBignum { #define FL_UMASK (0x7f<flags&(f)):0) #define FL_SET(x,f) if (FL_ABLE(x)) {RBASIC(x)->flags |= (f);} #define FL_UNSET(x,f) if(FL_ABLE(x)){RBASIC(x)->flags &= ~(f);} #define FL_REVERSE(x,f) if(FL_ABLE(x)){RBASIC(x)->flags ^= f;} +#if defined(__GNUC__) && __GNUC__ >= 2 && !defined(RUBY_NO_INLINE) +extern __inline__ int +rb_type(VALUE obj) +{ + if (FIXNUM_P(obj)) return T_FIXNUM; + if (obj == Qnil) return T_NIL; + if (obj == FALSE) return T_FALSE; + if (obj == TRUE) return T_TRUE; + + return BUILTIN_TYPE(obj); +} + +extern __inline__ int +rb_special_const_p(VALUE obj) +{ + return (FIXNUM_P(obj)||obj == Qnil||obj == FALSE||obj == TRUE)?TRUE:FALSE; +} + +extern __inline__ int +rb_test_false_or_nil(VALUE v) +{ + return (v != Qnil) && (v != FALSE); +} +#else +int rb_type _((VALUE)); +int rb_special_const_p _((VALUE)); +int rb_test_false_or_nil _((VALUE)); +#endif + +void *xmalloc _((unsigned long)); +void *xcalloc _((unsigned long,unsigned long)); +void *xrealloc _((void*,unsigned long)); #define ALLOC_N(type,n) (type*)xmalloc(sizeof(type)*(n)) #define ALLOC(type) (type*)xmalloc(sizeof(type)) #define REALLOC_N(var,type,n) (var)=(type*)xrealloc((char*)(var),sizeof(type)*(n)) @@ -295,51 +346,53 @@ int rb_special_const_p _((VALUE)); #define MEMCPY(p1,p2,type,n) memcpy((p1), (p2), sizeof(type)*(n)) #define MEMMOVE(p1,p2,type,n) memmove((p1), (p2), sizeof(type)*(n)) -void *xmalloc _((unsigned long)); -void *xcalloc _((unsigned long,unsigned long)); -void *xrealloc _((void*,unsigned long)); - VALUE rb_define_class _((char*,VALUE)); VALUE rb_define_module _((char*)); +VALUE rb_define_class_under _((VALUE, char *, VALUE)); +VALUE rb_define_module_under _((VALUE, char *)); + void rb_include_module _((VALUE,VALUE)); void rb_extend_object _((VALUE,VALUE)); void rb_define_variable _((char*,VALUE*)); void rb_define_virtual_variable _((char*,VALUE(*)(),void(*)())); void rb_define_hooked_variable _((char*,VALUE*,VALUE(*)(),void(*)())); +void rb_define_readonly_variable _((char*,VALUE*)); void rb_define_const _((VALUE,char*,VALUE)); void rb_define_global_const _((char*,VALUE)); void rb_define_method _((VALUE,char*,VALUE(*)(),int)); -void rb_define_singleton_method _((VALUE,char*,VALUE(*)(),int)); +void rb_define_function _((VALUE,char*,VALUE(*)(),int)); +void rb_define_module_function _((VALUE,char*,VALUE(*)(),int)); +void rb_define_global_function _((char *, VALUE (*)(), int)); + void rb_undef_method _((VALUE,char*)); void rb_define_alias _((VALUE,char*,char*)); -void rb_define_attr _((VALUE,ID,int)); +void rb_define_attr _((VALUE,ID,int,int)); ID rb_intern _((char*)); char *rb_id2name _((ID)); ID rb_to_id _((VALUE)); char *rb_class2name _((VALUE)); -int rb_method_boundp _((VALUE,ID,int)); + +void rb_p _((VALUE)); VALUE rb_eval_string _((char*)); VALUE rb_funcall(); int rb_scan_args(); -VALUE rb_iv_get(); -VALUE rb_iv_set(); -void rb_const_set(); -VALUE rb_const_get(); - -VALUE rb_yield(); -int iterator_p(); +VALUE rb_iv_get _((VALUE, char *)); +VALUE rb_iv_set _((VALUE, char *, VALUE)); +VALUE rb_const_get _((VALUE, ID)); +VALUE rb_const_get_at _((VALUE, ID)); +void rb_const_set _((VALUE, ID, VALUE)); VALUE rb_equal _((VALUE,VALUE)); -extern int verbose, debug; +extern VALUE verbose, debug; -int rb_safe_level(); +int rb_safe_level _((void)); void rb_set_safe_level _((int)); #ifdef __GNUC__ @@ -350,7 +403,7 @@ volatile voidfn Fatal; volatile voidfn Bug; volatile voidfn WrongType; volatile voidfn rb_sys_fail; -volatile voidfn rb_break; +volatile voidfn rb_iter_break; volatile voidfn rb_exit; volatile voidfn rb_fatal; volatile voidfn rb_raise; @@ -361,17 +414,26 @@ void Fail(); void Fatal(); void Bug(); void WrongType(); -void rb_sys_fail(); -void rb_break(); -void rb_exit(); -void rb_fatal(); -void rb_raise(); -void rb_notimplement(); +void rb_sys_fail _((char *)); +void rb_iter_break _((void)); +void rb_exit _((int)); +void rb_raise _((VALUE)); +void rb_fatal _((VALUE)); +void rb_notimplement _((void)); #endif void Error(); void Warning(); +VALUE rb_each _((VALUE)); +VALUE rb_yield _((VALUE)); +int iterator_p _((void)); +VALUE rb_iterate(); +VALUE rb_rescue(); +VALUE rb_ensure(); + +#include "intern.h" + #if defined(EXTLIB) && defined(USE_DLN_A_OUT) /* hook for external modules */ static char *libs_to_be_linked[] = { EXTLIB, 0 }; diff --git a/sample/exyacc.rb b/sample/exyacc.rb index dbe0dee710..908ba6c501 100644 --- a/sample/exyacc.rb +++ b/sample/exyacc.rb @@ -9,7 +9,7 @@ while gets() send = $_.rindex("\n%%") + 1 $_ = $_[sbeg, send-sbeg] sub!(/.*\n/, "") - gsub!(/'{'/, "'\001'") + gsub!(/'\{'/, "'\001'") gsub!(/'}'/, "'\002'") gsub!('\*/', "\003\003") gsub!("/\\*[^\003]*\003\003", '') diff --git a/sample/fact.rb b/sample/fact.rb index 49678bc9d0..1462a6923a 100644 --- a/sample/fact.rb +++ b/sample/fact.rb @@ -1,8 +1,10 @@ def fact(n) - if n == 0 - 1 - else - n * fact(n-1) + return 1 if n == 0 + f = 1 + while n>0 + f *= n + n -= 1 end + return f end print fact(ARGV[0].to_i), "\n" diff --git a/sample/mkproto.rb b/sample/mkproto.rb index 1d9c9faccb..97006f9f54 100644 --- a/sample/mkproto.rb +++ b/sample/mkproto.rb @@ -1,6 +1,6 @@ $/ = nil while gets() - if /^((void|VALUE|int|char *\*|ID|struct [\w_]+ *\*|st_table *\*) *)?\n([\w\d_]+)\(.*\)\n\s*((.+;\n)*){/ + if /^((void|VALUE|int|char *\*|ID|struct [\w_]+ *\*|st_table *\*) *)?\n([\w\d_]+)\(.*\)\n\s*((.+;\n)*)\{/ $_ = $' printf "%s %s(", $2, $3 args = [] diff --git a/sample/ruby-mode.el b/sample/ruby-mode.el index d8165bd23a..0f56477ea0 100644 --- a/sample/ruby-mode.el +++ b/sample/ruby-mode.el @@ -131,7 +131,7 @@ The variable ruby-indent-level controls the amount of indentation. (make-variable-buffer-local 'comment-column) (setq comment-column 32) (make-variable-buffer-local 'comment-start-skip) - (setq comment-start-skip "#+ *") + (setq comment-start-skip "\\(^\\|\\s-\\);?#+ *") (make-local-variable 'parse-sexp-ignore-comments) (setq parse-sexp-ignore-comments t) (run-hooks 'ruby-mode-hook)) @@ -385,6 +385,8 @@ The variable ruby-indent-level controls the amount of indentation. )) ((and (nth 2 state)(> (nth 2 state) 0)) ; in nest + (if (null (cdr (nth 1 state))) + (error "invalid nest")) (goto-char (cdr (nth 1 state))) (forward-word -1) ; skip back a keyword (cond @@ -440,7 +442,10 @@ The variable ruby-indent-level controls the amount of indentation. (and (or (and (looking-at ruby-symbol-chars) (skip-chars-backward ruby-symbol-chars) - (looking-at ruby-block-op-re)) + (looking-at ruby-block-op-re) + (save-excursion + (goto-char (match-end 0)) + (not (looking-at "[a-z_]")))) (and (looking-at ruby-operator-chars) (or (not (or (eq ?/ (char-after (point))))) (null (nth 0 (ruby-parse-region parse-start (point))))) @@ -627,7 +632,7 @@ An end of a defun is found by moving forward from the beginning of one." '("\\(^\\|[^_]\\)\\b\\([A-Z]+[a-zA-Z0-9_]*\\)" 2 font-lock-type-face) ;; functions - '("\\bdef[ \t]+\\([a-zA-Z_]+[a-zA-Z0-9_]*[?!=]?\\|\\[\\]=?\\)" + '("^\\s *def[ \t]+.*$" 0 font-lock-function-name-face)) "*Additional expressions to highlight in ruby mode.") (if (and (>= (string-to-int emacs-version) 20) diff --git a/sample/test.rb b/sample/test.rb index 382ca9428a..0a9d41c2ed 100644 --- a/sample/test.rb +++ b/sample/test.rb @@ -28,59 +28,59 @@ check "condition" $x = '0'; -$x == $x && ok(TRUE) -$x != $x && ok(FALSE) -$x == $x || ok(FALSE) -$x != $x || ok(TRUE) +$x == $x && ok(true) +$x != $x && ok(false) +$x == $x || ok(false) +$x != $x || ok(true) # first test to see if we can run the tests. check "if/unless"; $x = 'test'; -ok(if $x == $x then TRUE else FALSE end) -$bad = FALSE +ok(if $x == $x then true else false end) +$bad = false unless $x == $x - $bad = TRUE + $bad = true end ok(!$bad) -ok(unless $x != $x then TRUE else FALSE end) +ok(unless $x != $x then true else false end) check "case" case 5 when 1, 2, 3, 4, 6, 7, 8 - ok(FALSE) + ok(false) when 5 - ok(TRUE) + ok(true) end case 5 when 5 - ok(TRUE) + ok(true) when 1..10 - ok(FALSE) + ok(false) end case 5 when 1..10 - ok(TRUE) + ok(true) else - ok(FALSE) + ok(false) end case 5 when 5 - ok(TRUE) + ok(true) else - ok(FALSE) + ok(false) end case "foobar" when /^f.*r$/ - ok(TRUE) + ok(true) else - ok(FALSE) + ok(false) end check "while/until"; @@ -106,7 +106,7 @@ ok(!tmp.eof? && /vt100/) tmp.close # test next -$bad = FALSE +$bad = false tmp = open("while_tmp", "r") while tmp.gets() next if /vt100/; @@ -116,7 +116,7 @@ ok(!(!tmp.eof? || /vt100/ || $bad)) tmp.close # test redo -$bad = FALSE +$bad = false tmp = open("while_tmp", "r") while tmp.gets() if gsub!('vt100', 'VT100') @@ -140,12 +140,12 @@ end ok(sum == 220) # test interval -$bad = FALSE +$bad = false tmp = open("while_tmp", "r") while tmp.gets() break unless 1..2 if /vt100/ || /Amiga/ || /paper/ - $bad = TRUE + $bad = true break end end @@ -166,22 +166,22 @@ check "exception"; begin fail "this must be handled" - ok(FALSE) + ok(false) rescue - ok(TRUE) + ok(true) end -$bad = TRUE +$bad = true begin fail "this must be handled no.2" rescue if $bad - $bad = FALSE + $bad = false retry - ok(FALSE) + ok(false) end end -ok(TRUE) +ok(true) # exception in rescue clause $string = "this must be handled no.3" @@ -191,9 +191,9 @@ begin rescue fail $string end - ok(FALSE) + ok(false) rescue - ok(TRUE) if $! == $string + ok(true) if $! == $string end # exception in ensure clause @@ -203,39 +203,39 @@ begin ensure fail "exception in ensure clause" end - ok(FALSE) + ok(false) rescue - ok(TRUE) + ok(true) end -$bad = TRUE +$bad = true begin begin fail "this must be handled no.5" ensure - $bad = FALSE + $bad = false end rescue end ok(!$bad) -$bad = TRUE +$bad = true begin begin fail "this must be handled no.6" ensure - $bad = FALSE + $bad = false end rescue end ok(!$bad) -$bad = TRUE -while TRUE +$bad = true +while true begin break ensure - $bad = FALSE + $bad = false end end ok(!$bad) @@ -292,6 +292,11 @@ ok("1 byte string".split(//).reverse.join(":") == "g:n:i:r:t:s: :e:t:y:b: :1") $x = "a b c d" ok($x.split == ['a', 'b', 'c', 'd']) ok($x.split(' ') == ['a', 'b', 'c', 'd']) +ok(defined? "a".chomp) +ok("abc".scan(/./) == ["a", "b", "c"]) +ok("1a2b3c".scan(/(\d.)/) == [["1a"], ["2b"], ["3c"]]) +# non-greedy match +ok("a=12;b=22".scan(/(.*?)=(\d*?);?/) == [["a", "12"], ["b", "22"]]) $x = [1] ok(($x * 5).join(":") == '1:1:1:1:1') @@ -312,16 +317,16 @@ ok(begin for k,v in $y fail if k*2 != v end - TRUE + true rescue - FALSE + false end) ok($x.length == 3) ok($x.has_key?(1)) ok($x.has_value?(4)) ok($x.indexes(2,3) == [4,6]) -ok($x == (1=>2, 2=>4, 3=>6)) +ok($x == {1=>2, 2=>4, 3=>6}) $z = $y.keys.join(":") ok($z == "1:2:3") @@ -371,39 +376,39 @@ ok(i == 5) # iterator break/redo/next/retry unless defined? loop def loop - while TRUE + while true yield end end - ok(FALSE) + ok(false) else - ok(TRUE) + ok(true) end -done = TRUE +done = true loop{ break - done = FALSE + done = false } ok(done) -done = FALSE -$bad = FALSE +done = false +$bad = false loop { break if done - done = TRUE + done = true next - $bad = TRUE + $bad = true } ok(!$bad) -done = FALSE -$bad = FALSE +done = false +$bad = false loop { break if done - done = TRUE + done = true redo - $bad = TRUE + $bad = true } ok(!$bad) @@ -414,11 +419,11 @@ end ok($x.size == 7) ok($x == [1, 2, 3, 4, 5, 6, 7]) -$done = FALSE +$done = false $x = [] for i in 1 .. 7 # see how retry works in iterator loop if i == 4 and not $done - $done = TRUE + $done = true retry end $x.push(i) @@ -451,33 +456,33 @@ ok($x == -815915283247897734345611269596115894272000000000) ok(2-(2**32) == -(2**32-2)) ok(2**32 - 5 == (2**32-3)-2) -$good = TRUE; -for i in 1000..1024 - $good = FALSE if ((1<> 1 - $good = FALSE if (n1 != n2) + $good = false if (n1 != n2) end ok($good) -$good = TRUE; -for i in 4000..4192 +$good = true; +for i in 4000..4096 n1 = 1 << i; - $good = FALSE if ((n1**2-1) / (n1+1) != (n1-1)) + $good = false if ((n1**2-1) / (n1+1) != (n1-1)) end ok($good) @@ -486,13 +491,21 @@ check "string & char" ok("abcd" == "abcd") ok("abcd" =~ "abcd") ok("abcd" === "abcd") -ok(("abc" =~ /^$/) == FALSE) -ok(("abc\n" =~ /^$/) == FALSE) -ok(("abc" =~ /^d*$/) == FALSE) +ok(("abc" =~ /^$/) == false) +ok(("abc\n" =~ /^$/) == false) +ok(("abc" =~ /^d*$/) == false) ok(("abc" =~ /d*$/) == 3) ok("" =~ /^$/) ok("\n" =~ /^$/) ok("a\n\n" =~ /^$/) +"abcabc" =~ /.*a/ +ok($& == "abca") +"abcabc" =~ /.*c/ +ok($& == "abcabc") +"abcabc" =~ /.*?a/ +ok($& == "a") +"abcabc" =~ /.*?c/ +ok($& == "abc") $foo = "abc" ok("#$foo = abc" == "abc = abc") @@ -523,13 +536,18 @@ ok(?a == ?a) ok(?\C-a == 1) ok(?\M-a == 225) ok(?\M-\C-a == 129) +ok("a".upcase![0] == ?A) +ok("A".downcase![0] == ?a) +ok("abc".tr!("a-z", "A-Z") == "ABC") +ok("abcc".squeeze!("a-z") == "abc") +ok("abcd".delete!("bc") == "ad") $x = "abcdef" $y = [ ?a, ?b, ?c, ?d, ?e, ?f ] -$bad = FALSE +$bad = false $x.each_byte {|i| if i != $y.shift - $bad = TRUE + $bad = true break end } @@ -556,6 +574,9 @@ ok(a == 1 && b == [2, 3]) *a = 1, 2, 3 ok(a == [1, 2, 3]) +*a = 1..3 +ok(a == [1, 2, 3]) + check "call" def aaa(a, b=100, *rest) res = [a, b] @@ -566,38 +587,20 @@ end # not enough argument begin aaa() # need at least 1 arg - ok(FALSE) + ok(false) rescue - ok(TRUE) + ok(true) end begin aaa # no arg given (exception raised) - ok(FALSE) -rescue - ok(TRUE) -end - -begin - if aaa(1) == [1, 100] - ok(TRUE) - else - fail - end -rescue - ok(FALSE) -end - -begin - if aaa(1, 2) == [1, 2] - ok(TRUE) - else - fail - end + ok(false) rescue - ok(FALSE) + ok(true) end +ok(aaa(1) == [1, 100]) +ok(aaa(1, 2) == [1, 2]) ok(aaa(1, 2, 3, 4) == [1, 2, 3, 4]) ok(aaa(1, *[2, 3, 4]) == [1, 2, 3, 4]) @@ -639,7 +642,7 @@ if defined? Process.kill trap "SIGINT", proc{fail "Interrupt"} - x = FALSE + x = false begin Process.kill "SIGINT", $$ sleep 0.1 @@ -648,26 +651,31 @@ if defined? Process.kill end ok(x && x =~ /Interrupt/) else - ok(FALSE) + ok(false) end check "eval" ok(eval("") == nil) -$bad=FALSE -eval 'while FALSE; $bad = TRUE; print "foo\n" end' +$bad=false +eval 'while false; $bad = true; print "foo\n" end' ok(!$bad) ok(eval('TRUE')) +ok(eval('true')) +ok(!eval('NIL')) +ok(!eval('nil')) +ok(!eval('FALSE')) +ok(!eval('false')) -$foo = 'ok(TRUE)' +$foo = 'ok(true)' begin eval $foo rescue - ok(FALSE) + ok(false) end -ok(eval("$foo") == 'ok(TRUE)') -ok(eval("TRUE") == TRUE) +ok(eval("$foo") == 'ok(true)') +ok(eval("true") == true) i = 5 ok(eval("i == 5")) ok(eval("i") == 5) @@ -685,11 +693,11 @@ end $x = test_ev ok(eval("local1", $x) == "local1") # static local var ok(eval("local2", $x) == "local2") # dynamic local var -$bad = TRUE +$bad = true begin p eval("local1") rescue NameError # must raise error - $bad = FALSE + $bad = false end ok(!$bad) @@ -700,11 +708,11 @@ module EvTest end ok(eval("EVTEST1", $x) == 25) # constant in module ok(eval("evtest2", $x) == 125) # local var in module -$bad = TRUE +$bad = true begin eval("EVTEST1") rescue NameError # must raise error - $bad = FALSE + $bad = false end ok(!$bad) @@ -716,7 +724,7 @@ tmp = open("script_tmp", "w") tmp.print "print $zzz\n"; tmp.close -ok(`./ruby -s script_tmp -zzz` == 'TRUE') +ok(`./ruby -s script_tmp -zzz` == 'true') ok(`./ruby -s script_tmp -zzz=555` == '555') tmp = open("script_tmp", "w") @@ -744,11 +752,11 @@ end tmp.close `./ruby -i.bak -pe 'sub(/^[0-9]+$/){$&.to_i * 5}' script_tmp` -done = TRUE +done = true tmp = open("script_tmp", "r") while tmp.gets if $_.to_i % 5 != 0 - done = FALSE + done = false break end end @@ -796,9 +804,9 @@ ok(foo.test == "test") begin foo.test2 - ok FALSE + ok false rescue - ok TRUE + ok true end check "pack" @@ -843,9 +851,9 @@ ok($$.instance_of?(Fixnum)) # read-only variable begin $$ = 5 - ok FALSE + ok false rescue - ok TRUE + ok true end foobar = "foobar" @@ -931,9 +939,9 @@ begin tmp = [0,1,2,3,4,5,6,7,8,9] } tmp = nil - ok TRUE + ok true rescue - ok FALSE + ok false end if $failed > 0 diff --git a/sample/tkhello.rb b/sample/tkhello.rb index 1ff1403e71..5188fe1c8c 100644 --- a/sample/tkhello.rb +++ b/sample/tkhello.rb @@ -1,13 +1,10 @@ require "tk" -TkButton.new { - text 'hello' - command proc{print "hello\n"} - pack('fill'=>'x') -} -TkButton.new { - text 'quit' - command 'exit' - pack('fill'=>'x') -} +TkButton.new(nil, + 'text' => 'hello', + 'command' => proc{print "hello\n"}).pack('fill'=>'x') +TkButton.new(nil, + 'text' => 'quit', + 'command' => 'exit').pack('fill'=>'x') + Tk.mainloop diff --git a/sample/uumerge.rb b/sample/uumerge.rb index 297b08f26a..26f28923d5 100644 --- a/sample/uumerge.rb +++ b/sample/uumerge.rb @@ -1,37 +1,43 @@ #!/usr/local/bin/ruby if ARGV[0] == "-c" - out_stdout = 1; + out_stdout = 1 ARGV.shift end +$sawbegin = 0 +$sawend = 0 + while gets() if /^begin\s*(\d*)\s*(\S*)/ $mode, $file = $1, $2 $sawbegin+=1 - break + if out_stdout + out = STDOUT + else + out = open($file, "w") if $file != "" + end + out.binmode + next end end -fail "missing begin" if ! $sawbegin; - -if out_stdout - out = STDOUT -else - out = open($file, "w") if $file != ""; -end +raise "missing begin" unless $sawbegin +out.binmode while gets() if /^end/ $sawend+=1 - break + out.close unless out_stdout + File.chmod $mode.oct, $file unless out_stdout + next end - sub(/[a-z]+$/, ""); # handle stupid trailing lowercase letters + sub(/[a-z]+$/, "") # handle stupid trailing lowercase letters next if /[a-z]/ next if !(((($_[0] - 32) & 077) + 2) / 3 == $_.length / 4) - out << $_.unpack("u"); + out << $_.unpack("u") if $sawbegin > $sawend end -fail "missing end" if !$sawend; -File.chmod $mode.oct, $file if ! out_stdout -exit 0; +raise "missing end" if $sawbegin > $sawend +raise "missing begin" if ! $sawbegin +exit 0 diff --git a/sprintf.c b/sprintf.c index 0dd998b5a5..7862a469e8 100644 --- a/sprintf.c +++ b/sprintf.c @@ -109,7 +109,7 @@ f_sprintf(argc, argv) int argc; VALUE *argv; { - struct RString *fmt; + VALUE fmt; char *buf, *p, *end; int blen, bsiz; VALUE result; @@ -122,7 +122,7 @@ f_sprintf(argc, argv) #define FWIDTH 16 #define FPREC 32 - int width, prec, flags = FNONE; + int width = 0, prec = 0, flags = FNONE; VALUE str; @@ -142,15 +142,15 @@ f_sprintf(argc, argv) #define GETARG() \ ((argc == 0)?(ArgError("too few argument."),0):(argc--,((argv++)[0]))) - fmt = (struct RString*)GETARG(); + fmt = GETARG(); Check_Type(fmt, T_STRING); blen = 0; bsiz = 120; buf = ALLOC_N(char, bsiz); - end = fmt->ptr + fmt->len; + end = RSTRING(fmt)->ptr + RSTRING(fmt)->len; - for (p = fmt->ptr; p < end; p++) { + for (p = RSTRING(fmt)->ptr; p < end; p++) { char *t; for (t = p; t < end && *t != '%'; t++) ; @@ -597,7 +597,7 @@ f_sprintf(argc, argv) } sprint_exit: - if (verbose && argc > 1) { + if (RTEST(verbose) && argc > 1) { ArgError("too many argument for format string"); } result = str_new(buf, blen); diff --git a/string.c b/string.c index 64b5347833..3c3d24f3cf 100644 --- a/string.c +++ b/string.c @@ -18,6 +18,9 @@ #include #include +#ifdef HAVE_UNISTD_H +#include +#endif VALUE cString; @@ -25,8 +28,8 @@ VALUE cString; #define STR_FREEZE FL_USER1 #define STR_TAINT FL_USER2 -VALUE str_taint(); -VALUE str_tainted(); +void reg_prepare_re _((VALUE)); +void kcode_reset_option _((void)); VALUE str_new(ptr, len) @@ -58,13 +61,13 @@ str_new2(ptr) VALUE str_new3(str) - struct RString *str; + VALUE str; { NEWOBJ(str2, struct RString); OBJSETUP(str2, cString, T_STRING); - str2->len = str->len; - str2->ptr = str->ptr; + str2->len = RSTRING(str)->len; + str2->ptr = RSTRING(str)->ptr; str2->orig = str; if (rb_safe_level() >= 3) { @@ -76,18 +79,18 @@ str_new3(str) VALUE str_new4(orig) - struct RString *orig; + VALUE orig; { NEWOBJ(str, struct RString); OBJSETUP(str, cString, T_STRING); - str->len = orig->len; - str->ptr = orig->ptr; - if (orig->orig) { - str->orig = orig->orig; + str->len = RSTRING(orig)->len; + str->ptr = RSTRING(orig)->ptr; + if (RSTRING(orig)->orig) { + str->orig = RSTRING(orig)->orig; } else { - orig->orig = str; + RSTRING(orig)->orig = (VALUE)str; str->orig = 0; } if (rb_safe_level() >= 3) { @@ -97,8 +100,6 @@ str_new4(orig) return (VALUE)str; } -#define as_str(str) (struct RString*)obj_as_string(str) - static ID pr_str; VALUE @@ -118,23 +119,23 @@ obj_as_string(obj) static VALUE str_clone(orig) - struct RString *orig; + VALUE orig; { VALUE str; - if (orig->orig) - str = str_new3(orig->orig); + if (RSTRING(orig)->orig) + str = str_new3(RSTRING(orig)->orig); else - str = str_new(orig->ptr, orig->len); + str = str_new(RSTRING(orig)->ptr, RSTRING(orig)->len); CLONESETUP(str, orig); return str; } VALUE str_dup(str) - struct RString *str; + VALUE str; { - VALUE s = str_new(str->ptr, str->len); + VALUE s = str_new(RSTRING(str)->ptr, RSTRING(str)->len); if (str_tainted(str)) s = str_taint(s); return s; } @@ -142,18 +143,18 @@ str_dup(str) static VALUE str_s_new(class, orig) VALUE class; - struct RString *orig; + VALUE orig; { NEWOBJ(str, struct RString); OBJSETUP(str, class, T_STRING); - orig = as_str(orig); - str->len = orig->len; - str->ptr = ALLOC_N(char, orig->len+1); + orig = obj_as_string(orig); + str->len = RSTRING(orig)->len; + str->ptr = ALLOC_N(char, RSTRING(orig)->len+1); if (str->ptr) { - memcpy(str->ptr, orig->ptr, orig->len); + memcpy(str->ptr, RSTRING(orig)->ptr, RSTRING(orig)->len); } - str->ptr[orig->len] = '\0'; + str->ptr[RSTRING(orig)->len] = '\0'; str->orig = 0; if (rb_safe_level() >= 3) { @@ -165,22 +166,22 @@ str_s_new(class, orig) static VALUE str_length(str) - struct RString *str; + VALUE str; { - return INT2FIX(str->len); + return INT2FIX(RSTRING(str)->len); } VALUE str_plus(str1, str2) - struct RString *str1, *str2; + VALUE str1, str2; { - struct RString *str3; + VALUE str3; - str2 = as_str(str2); - str3 = (struct RString*)str_new(0, str1->len+str2->len); - memcpy(str3->ptr, str1->ptr, str1->len); - memcpy(str3->ptr+str1->len, str2->ptr, str2->len); - str3->ptr[str3->len] = '\0'; + str2 = obj_as_string(str2); + str3 = str_new(0, RSTRING(str1)->len+RSTRING(str2)->len); + memcpy(RSTRING(str3)->ptr, RSTRING(str1)->ptr, RSTRING(str1)->len); + memcpy(RSTRING(str3)->ptr+RSTRING(str1)->len, RSTRING(str2)->ptr, RSTRING(str2)->len); + RSTRING(str3)->ptr[RSTRING(str3)->len] = '\0'; if (str_tainted(str1) || str_tainted(str2)) return str_taint(str3); @@ -189,10 +190,10 @@ str_plus(str1, str2) VALUE str_times(str, times) - struct RString *str; + VALUE str; VALUE times; { - struct RString *str2; + VALUE str2; int i, len; len = NUM2INT(times); @@ -200,43 +201,61 @@ str_times(str, times) ArgError("negative argument"); } - str2 = (struct RString*)str_new(0, str->len*len); + str2 = str_new(0, RSTRING(str)->len*len); for (i=0; iptr+(i*str->len), str->ptr, str->len); + memcpy(RSTRING(str2)->ptr+(i*RSTRING(str)->len), RSTRING(str)->ptr, RSTRING(str)->len); + } + RSTRING(str2)->ptr[RSTRING(str2)->len] = '\0'; + + if (str_tainted(str)) { + return str_taint((VALUE)str2); } - str2->ptr[str2->len] = '\0'; - if (str_tainted(str)) - return str_taint(str2); + return str2; +} - return (VALUE)str2; +VALUE +str_format(str, arg) + VALUE str, arg; +{ + VALUE *argv; + + if (TYPE(arg) == T_ARRAY) { + argv = ALLOCA_N(VALUE, RARRAY(arg)->len + 1); + argv[0] = str; + MEMCPY(argv+1, RARRAY(arg)->ptr, VALUE, RARRAY(arg)->len); + return f_sprintf(RARRAY(arg)->len+1, argv); + } + + argv = ALLOCA_N(VALUE, 2); + argv[0] = str; + argv[1] = arg; + return f_sprintf(2, argv); } VALUE str_substr(str, start, len) - struct RString *str; + VALUE str; int start, len; { struct RString *str2; if (start < 0) { - start = str->len + start; + start = RSTRING(str)->len + start; } - if (str->len <= start || len < 0) { + if (RSTRING(str)->len <= start || len < 0) { return str_new(0,0); } - if (str->len < start + len) { - len = str->len - start; + if (RSTRING(str)->len < start + len) { + len = RSTRING(str)->len - start; } - str2 = (struct RString*)str_new(str->ptr+start, len); - - return (VALUE)str2; + return str_new(RSTRING(str)->ptr+start, len); } static VALUE str_subseq(str, beg, end) - struct RString *str; + VALUE str; int beg, end; { int len; @@ -246,18 +265,18 @@ str_subseq(str, beg, end) } if (beg < 0) { - beg = str->len + beg; + beg = RSTRING(str)->len + beg; if (beg < 0) beg = 0; } if (end < 0) { - end = str->len + end; + end = RSTRING(str)->len + end; if (end < 0) end = -1; - else if (str->len < end) { - end = str->len; + else if (RSTRING(str)->len < end) { + end = RSTRING(str)->len; } } - if (beg >= str->len) { + if (beg >= RSTRING(str)->len) { return str_new(0, 0); } @@ -273,7 +292,7 @@ extern VALUE ignorecase; void str_modify(str) - struct RString *str; + VALUE str; { UCHAR *ptr; @@ -283,14 +302,14 @@ str_modify(str) } if (FL_TEST(str, STR_FREEZE)) TypeError("can't modify frozen string"); - if (!str->orig) return; - ptr = str->ptr; - str->ptr = ALLOC_N(char, str->len+1); - if (str->ptr) { - memcpy(str->ptr, ptr, str->len); - str->ptr[str->len] = 0; + if (!RSTRING(str)->orig) return; + ptr = RSTRING(str)->ptr; + RSTRING(str)->ptr = ALLOC_N(char, RSTRING(str)->len+1); + if (RSTRING(str)->ptr) { + memcpy(RSTRING(str)->ptr, ptr, RSTRING(str)->len); + RSTRING(str)->ptr[RSTRING(str)->len] = 0; } - str->orig = 0; + RSTRING(str)->orig = 0; } VALUE @@ -340,56 +359,56 @@ str_tainted(str) VALUE str_resize(str, len) - struct RString *str; + VALUE str; int len; { str_modify(str); if (len >= 0) { - if (str->len < len || str->len - len > 1024) { - REALLOC_N(str->ptr, char, len + 1); + if (RSTRING(str)->len < len || RSTRING(str)->len - len > 1024) { + REALLOC_N(RSTRING(str)->ptr, char, len + 1); } - str->len = len; - str->ptr[len] = '\0'; /* sentinel */ + RSTRING(str)->len = len; + RSTRING(str)->ptr[len] = '\0'; /* sentinel */ } return (VALUE)str; } VALUE str_cat(str, ptr, len) - struct RString *str; + VALUE str; UCHAR *ptr; UINT len; { if (len > 0) { str_modify(str); - REALLOC_N(str->ptr, char, str->len + len + 1); + REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len + len + 1); if (ptr) - memcpy(str->ptr + str->len, ptr, len); - str->len += len; - str->ptr[str->len] = '\0'; /* sentinel */ + memcpy(RSTRING(str)->ptr + RSTRING(str)->len, ptr, len); + RSTRING(str)->len += len; + RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; /* sentinel */ } - return (VALUE)str; + return str; } static VALUE str_concat(str1, str2) - struct RString *str1, *str2; + VALUE str1, str2; { - str2 = as_str(str2); - str_cat(str1, str2->ptr, str2->len); - return (VALUE)str1; + str2 = obj_as_string(str2); + str_cat(str1, RSTRING(str2)->ptr, RSTRING(str2)->len); + return str1; } int str_hash(str) - struct RString *str; + VALUE str; { - int len = str->len; - UCHAR *p = str->ptr; - int key = 0; + register int len = RSTRING(str)->len; + register UCHAR *p = RSTRING(str)->ptr; + register int key = 0; - if (ignorecase) { + if (RTEST(ignorecase)) { while (len--) { key = key*65599 + toupper(*p); p++; @@ -416,31 +435,31 @@ str_hash_method(str) int str_cmp(str1, str2) - struct RString *str1, *str2; + VALUE str1, str2; { UINT len; int retval; - if (ignorecase != FALSE) { + if (RTEST(ignorecase)) { return str_cicmp(str1, str2); } - len = min(str1->len, str2->len); - retval = memcmp(str1->ptr, str2->ptr, len); + len = min(RSTRING(str1)->len, RSTRING(str2)->len); + retval = memcmp(RSTRING(str1)->ptr, RSTRING(str2)->ptr, len); if (retval == 0) { - return str1->ptr[len] - str2->ptr[len]; + return RSTRING(str1)->ptr[len] - RSTRING(str2)->ptr[len]; } return retval; } static VALUE str_equal(str1, str2) - struct RString *str1, *str2; + VALUE str1, str2; { if (TYPE(str2) != T_STRING) return FALSE; - if (str1->len == str2->len + if (RSTRING(str1)->len == RSTRING(str2)->len && str_cmp(str1, str2) == 0) { return TRUE; } @@ -458,11 +477,9 @@ str_cmp_method(str1, str2) return INT2FIX(result); } -VALUE Freg_match(); - static VALUE str_match(x, y) - struct RString *x, *y; + VALUE x, y; { VALUE reg; int start; @@ -480,34 +497,33 @@ str_match(x, y) return INT2FIX(start); default: - TypeError("type mismatch"); - break; + return rb_funcall(y, rb_intern("=~"), 1, x); } } static VALUE str_match2(str) - struct RString *str; + VALUE str; { return reg_match2(reg_regcomp(str)); } static int str_index(str, sub, offset) - struct RString *str, *sub; + VALUE str, sub; int offset; { UCHAR *s, *e, *p; int len; - if (str->len - offset < sub->len) return -1; - s = str->ptr+offset; - p = sub->ptr; - len = sub->len; - e = s + str->len - len + 1; + if (RSTRING(str)->len - offset < RSTRING(sub)->len) return -1; + s = RSTRING(str)->ptr+offset; + p = RSTRING(sub)->ptr; + len = RSTRING(sub)->len; + e = s + RSTRING(str)->len - len + 1; while (s < e) { - if (*s == *(sub->ptr) && memcmp(s, p, len) == 0) { - return (s-(str->ptr)); + if (*s == *(RSTRING(sub)->ptr) && memcmp(s, p, len) == 0) { + return (s-(RSTRING(str)->ptr)); } s++; } @@ -518,9 +534,9 @@ static VALUE str_index_method(argc, argv, str) int argc; VALUE *argv; - struct RString *str; + VALUE str; { - struct RString *sub; + VALUE sub; VALUE initpos; int pos; @@ -540,6 +556,18 @@ str_index_method(argc, argv, str) pos = str_index(str, sub, pos); break; + case T_FIXNUM: + { + int c = FIX2INT(sub); + int len = RSTRING(str)->len; + char *p = RSTRING(str)->ptr; + + for (;pos= str->len) pos = str->len; + if (pos >= RSTRING(str)->len) pos = RSTRING(str)->len; } else { - pos = str->len; + pos = RSTRING(str)->len; } - Check_Type(sub, T_STRING); - if (pos > str->len) return Qnil; /* substring longer than string */ - sbeg = str->ptr; s = sbeg + pos - sub->len; - t = sub->ptr; - len = sub->len; - while (sbeg <= s) { - if (*s == *t && memcmp(s, t, len) == 0) { - return INT2FIX(s - sbeg); + switch (TYPE(sub)) { + case T_REGEXP: + reg_prepare_re(sub); + pos = re_search(RREGEXP(sub)->ptr, + RSTRING(str)->ptr, RSTRING(str)->len, + pos, -pos, 0); + kcode_reset_option(); + if (pos >= 0) return INT2FIX(pos); + break; + + case T_STRING: + /* substring longer than string */ + if (pos > RSTRING(str)->len) return Qnil; + sbeg = RSTRING(str)->ptr; s = sbeg + pos - RSTRING(sub)->len; + t = RSTRING(sub)->ptr; + len = RSTRING(sub)->len; + while (sbeg <= s) { + if (*s == *t && memcmp(s, t, len) == 0) { + return INT2FIX(s - sbeg); + } + s--; } - s--; + break; + + case T_FIXNUM: + { + int c = FIX2INT(sub); + char *p = RSTRING(str)->ptr; + + for (;pos>=0;pos--) { + if (p[pos] == c) return INT2FIX(pos); + } + return Qnil; + } + + default: + TypeError("Type mismatch: %s given", rb_class2name(CLASS_OF(sub))); } return Qnil; } @@ -608,36 +663,37 @@ succ_char(s) static VALUE str_succ(orig) - struct RString *orig; + VALUE orig; { - struct RString *str, *str2; + VALUE str, str2; UCHAR *sbeg, *s; char c = -1; - str = (struct RString*)str_new(orig->ptr, orig->len); + str = str_new(RSTRING(orig)->ptr, RSTRING(orig)->len); - sbeg = str->ptr; s = sbeg + str->len - 1; + sbeg = RSTRING(str)->ptr; s = sbeg + RSTRING(str)->len - 1; while (sbeg <= s) { if (isalnum(*s) && (c = succ_char(s)) == 0) break; s--; } if (s < sbeg) { - if (c == -1 && str->len > 0) { - str->ptr[str->len-1] += 1; + if (c == -1 && RSTRING(str)->len > 0) { + RSTRING(str)->ptr[RSTRING(str)->len-1] += 1; } else { - str2 = (struct RString*)str_new(0, str->len+1); - str2->ptr[0] = c; - memcpy(str2->ptr+1, str->ptr, str->len); + str2 = str_new(0, RSTRING(str)->len+1); + RSTRING(str2)->ptr[0] = c; + memcpy(RSTRING(str2)->ptr+1, RSTRING(str)->ptr, RSTRING(str)->len); str = str2; } } - if (str_tainted(orig)) + if (str_tainted(orig)) { return str_taint(str); + } - return (VALUE)str; + return str; } VALUE @@ -664,7 +720,7 @@ str_upto(beg, end) static VALUE str_aref(str, indx) - struct RString *str; + VALUE str; VALUE indx; { int idx; @@ -674,12 +730,12 @@ str_aref(str, indx) idx = FIX2INT(indx); if (idx < 0) { - idx = str->len + idx; + idx = RSTRING(str)->len + idx; } - if (idx < 0 || str->len <= idx) { + if (idx < 0 || RSTRING(str)->len <= idx) { return Qnil; } - return (VALUE)INT2FIX(str->ptr[idx] & 0xff); + return (VALUE)INT2FIX(RSTRING(str)->ptr[idx] & 0xff); case T_REGEXP: if (str_match(str, indx)) @@ -706,7 +762,7 @@ static VALUE str_aref_method(argc, argv, str) int argc; VALUE *argv; - struct RString *str; + VALUE str; { VALUE arg1, arg2; @@ -718,26 +774,28 @@ str_aref_method(argc, argv, str) static void str_replace(str, beg, len, val) - struct RString *str, *val; + VALUE str, val; int beg, len; { - if (len < val->len) { + if (len < RSTRING(val)->len) { /* expand string */ - REALLOC_N(str->ptr, char, str->len+val->len-len+1); + REALLOC_N(RSTRING(str)->ptr, char, RSTRING(str)->len+RSTRING(val)->len-len+1); } - if (len != val->len) { - memmove(str->ptr+beg+val->len, str->ptr+beg+len, str->len-(beg+len)); + if (len != RSTRING(val)->len) { + memmove(RSTRING(str)->ptr+beg+RSTRING(val)->len, + RSTRING(str)->ptr+beg+len, + RSTRING(str)->len-(beg+len)); } - memcpy(str->ptr+beg, val->ptr, val->len); - str->len += val->len - len; - str->ptr[str->len] = '\0'; + memcpy(RSTRING(str)->ptr+beg, RSTRING(val)->ptr, RSTRING(val)->len); + RSTRING(str)->len += RSTRING(val)->len - len; + RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; } /* str_replace2() understands negatice offset */ static void str_replace2(str, beg, end, val) - struct RString *str, *val; + VALUE str, *val; int beg, end; { int len; @@ -747,22 +805,22 @@ str_replace2(str, beg, end, val) } if (beg < 0) { - beg = str->len + beg; + beg = RSTRING(str)->len + beg; if (beg < 0) { beg = 0; } } - if (str->len <= beg) { - beg = str->len; + if (RSTRING(str)->len <= beg) { + beg = RSTRING(str)->len; } if (end < 0) { - end = str->len + end; + end = RSTRING(str)->len + end; if (end < 0) { end = 0; } } - if (str->len <= end) { - end = str->len - 1; + if (RSTRING(str)->len <= end) { + end = RSTRING(str)->len - 1; } len = end - beg + 1; /* length of substring */ if (len < 0) { @@ -774,9 +832,7 @@ str_replace2(str, beg, end, val) static VALUE str_sub_s(str, pat, val, once) - struct RString *str; - struct RRegexp *pat; - VALUE val; + VALUE str, pat, val; int once; { VALUE result, repl; @@ -788,7 +844,7 @@ str_sub_s(str, pat, val, once) break; case T_STRING: - pat = (struct RRegexp*)reg_regcomp(pat); + pat = reg_regcomp(pat); break; default: @@ -803,7 +859,7 @@ str_sub_s(str, pat, val, once) n++; regs = RMATCH(backref_get())->regs; - str_cat(result, str->ptr+offset, beg-offset); + str_cat(result, RSTRING(str)->ptr+offset, beg-offset); repl = reg_regsub(val, str, regs); str_cat(result, RSTRING(repl)->ptr, RSTRING(repl)->len); @@ -812,7 +868,9 @@ str_sub_s(str, pat, val, once) * Always consume at least one character of the input string * in order to prevent infinite loops. */ - if (str->len) str_cat(result, str->ptr+END(0), 1); + if (RSTRING(str)->len > 0) { + str_cat(result, RSTRING(str)->ptr+END(0), 1); + } offset = END(0)+1; } else { @@ -823,8 +881,8 @@ str_sub_s(str, pat, val, once) if (offset >= STRLEN(str)) break; } if (n == 0) return Qnil; - if (str->len > offset) { - str_cat(result, str->ptr+offset, str->len-offset); + if (RSTRING(str)->len > offset) { + str_cat(result, RSTRING(str)->ptr+offset, RSTRING(str)->len-offset); } if (str_tainted(val)) str_taint(result); @@ -833,7 +891,7 @@ str_sub_s(str, pat, val, once) static VALUE str_sub_f(str, pat, val, once) - struct RString *str; + VALUE str; VALUE pat; VALUE val; int once; @@ -845,7 +903,7 @@ str_sub_f(str, pat, val, once) if (NIL_P(result)) return Qnil; str_resize(str, RSTRING(result)->len); - memcpy(str->ptr, RSTRING(result)->ptr, RSTRING(result)->len); + memcpy(RSTRING(str)->ptr, RSTRING(result)->ptr, RSTRING(result)->len); if (str_tainted(result)) str_taint(str); return (VALUE)str; @@ -853,7 +911,7 @@ str_sub_f(str, pat, val, once) static VALUE str_sub_iter_s(str, pat, once) - struct RString *str; + VALUE str; VALUE pat; int once; { @@ -884,9 +942,9 @@ str_sub_iter_s(str, pat, once) n++; null = 0; - regs = RMATCH(backref_get())->regs; - str_cat(result, str->ptr+offset, beg-offset); + str_cat(result, RSTRING(str)->ptr+offset, beg-offset); + regs = RMATCH(backref_get())->regs; if (END(0) == offset) { null = 1; offset = END(0)+1; @@ -898,16 +956,16 @@ str_sub_iter_s(str, pat, once) val = rb_yield(reg_nth_match(0, backref_get())); val = obj_as_string(val); str_cat(result, RSTRING(val)->ptr, RSTRING(val)->len); - if (null && str->len) { - str_cat(result, str->ptr+offset-1, 1); + if (null && RSTRING(str)->len) { + str_cat(result, RSTRING(str)->ptr+offset-1, 1); } if (once) break; if (offset >= STRLEN(str)) break; } if (n == 0) return Qnil; - if (str->len > offset) { - str_cat(result, str->ptr+offset, str->len-offset); + if (RSTRING(str)->len > offset) { + str_cat(result, RSTRING(str)->ptr+offset, RSTRING(str)->len-offset); } return result; @@ -915,7 +973,7 @@ str_sub_iter_s(str, pat, once) static VALUE str_sub_iter_f(str, pat, once) - struct RString *str; + VALUE str; VALUE pat; int once; { @@ -926,14 +984,14 @@ str_sub_iter_f(str, pat, once) if (NIL_P(result)) return Qnil; str_resize(str, RSTRING(result)->len); - memcpy(str->ptr, RSTRING(result)->ptr, RSTRING(result)->len); + memcpy(RSTRING(str)->ptr, RSTRING(result)->ptr, RSTRING(result)->len); return (VALUE)str; } static VALUE str_aset(str, indx, val) - struct RString *str; + VALUE str; VALUE indx, val; { int idx, beg, end, offset; @@ -942,12 +1000,12 @@ str_aset(str, indx, val) case T_FIXNUM: idx = NUM2INT(indx); if (idx < 0) { - idx = str->len + idx; + idx = RSTRING(str)->len + idx; } - if (idx < 0 || str->len <= idx) { - IndexError("index %d out of range [0..%d]", idx, str->len-1); + if (idx < 0 || RSTRING(str)->len <= idx) { + IndexError("index %d out of range [0..%d]", idx, RSTRING(str)->len-1); } - str->ptr[idx] = FIX2INT(val) & 0xff; + RSTRING(str)->ptr[idx] = FIX2INT(val) & 0xff; return val; case T_REGEXP: @@ -981,7 +1039,7 @@ static VALUE str_aset_method(argc, argv, str) int argc; VALUE *argv; - struct RString *str; + VALUE str; { VALUE arg1, arg2, arg3; @@ -994,13 +1052,13 @@ str_aset_method(argc, argv, str) beg = NUM2INT(arg1); if (beg < 0) { - beg = str->len + beg; + beg = RSTRING(str)->len + beg; if (beg < 0) beg = 0; } len = NUM2INT(arg2); if (len < 0) IndexError("negative length %d", len); - if (beg + len > str->len) { - len = str->len - beg; + if (beg + len > RSTRING(str)->len) { + len = RSTRING(str)->len - beg; } str_replace(str, beg, len, arg3); return arg3; @@ -1036,7 +1094,7 @@ str_sub(argc, argv, str) else { v = str_sub_s(str, pat, val, 1); } - if (NIL_P(v)) return str; + if (NIL_P(v)) return str_dup(str); return v; } @@ -1068,7 +1126,7 @@ str_gsub(argc, argv, str) else { v = str_sub_s(str, pat, val, 0); } - if (NIL_P(v)) return str; + if (NIL_P(v)) return str_dup(str); return v; } @@ -1079,7 +1137,8 @@ uscore_get() line = lastline_get(); if (TYPE(line) != T_STRING) { - TypeError("$_ value need to be String"); + TypeError("$_ value need to be String (%s given)", + rb_class2name(CLASS_OF(line))); } return line; } @@ -1147,39 +1206,38 @@ f_gsub(argc, argv) else { v = str_sub_s(line, pat, val, 0); } - if (!NIL_P(v)) { - lastline_set(v); - return v; - } - return line; + if (NIL_P(v)) v = str_dup(line); + lastline_set(v); + + return v; } static VALUE str_reverse_bang(str) - struct RString *str; + VALUE str; { UCHAR *s, *e, *p; - s = str->ptr; - e = s + str->len - 1; - p = ALLOCA_N(char, str->len); + s = RSTRING(str)->ptr; + e = s + RSTRING(str)->len - 1; + p = ALLOCA_N(char, RSTRING(str)->len); while (e >= s) { *p++ = *e--; } - MEMCPY(str->ptr, p, char, str->len); + MEMCPY(RSTRING(str)->ptr, p, char, RSTRING(str)->len); return (VALUE)str; } static VALUE str_reverse(str) - struct RString *str; + VALUE str; { - VALUE obj = str_new(0, str->len); + VALUE obj = str_new(0, RSTRING(str)->len); UCHAR *s, *e, *p; - s = str->ptr; e = s + str->len - 1; + s = RSTRING(str)->ptr; e = s + RSTRING(str)->len - 1; p = RSTRING(obj)->ptr; while (e >= s) { @@ -1189,11 +1247,37 @@ str_reverse(str) return obj; } +static VALUE +str_include(str, arg) + VALUE str, arg; +{ + int i; + + if (FIXNUM_P(arg)) { + int c = FIX2INT(arg); + int len = RSTRING(str)->len; + char *p = RSTRING(str)->ptr; + + for (i=0; iptr, 10); + return str2inum(RSTRING(str)->ptr, 10); } #ifndef atof @@ -1202,9 +1286,9 @@ double atof(); static VALUE str_to_f(str) - struct RString *str; + VALUE str; { - double f = atof(str->ptr); + double f = atof(RSTRING(str)->ptr); return float_new(f); } @@ -1218,14 +1302,14 @@ str_to_s(str) VALUE str_inspect(str) - struct RString *str; + VALUE str; { #define STRMAX 80 UCHAR buf[STRMAX]; UCHAR *p, *pend; UCHAR *b; - p = str->ptr; pend = p + str->len; + p = RSTRING(str)->ptr; pend = p + RSTRING(str)->len; b = buf; *b++ = '"'; @@ -1306,12 +1390,12 @@ str_inspect(str) static VALUE str_upcase_bang(str) - struct RString *str; + VALUE str; { UCHAR *s, *send; str_modify(str); - s = str->ptr; send = s + str->len; + s = RSTRING(str)->ptr; send = s + RSTRING(str)->len; while (s < send) { if (islower(*s)) { *s = toupper(*s); @@ -1324,19 +1408,19 @@ str_upcase_bang(str) static VALUE str_upcase(str) - struct RString *str; + VALUE str; { return str_upcase_bang(str_dup(str)); } static VALUE str_downcase_bang(str) - struct RString *str; + VALUE str; { UCHAR *s, *send; str_modify(str); - s = str->ptr; send = s + str->len; + s = RSTRING(str)->ptr; send = s + RSTRING(str)->len; while (s < send) { if (isupper(*s)) { *s = tolower(*s); @@ -1349,19 +1433,19 @@ str_downcase_bang(str) static VALUE str_downcase(str) - struct RString *str; + VALUE str; { return str_downcase_bang(str_dup(str)); } static VALUE str_capitalize_bang(str) - struct RString *str; + VALUE str; { UCHAR *s, *send; str_modify(str); - s = str->ptr; send = s + str->len; + s = RSTRING(str)->ptr; send = s + RSTRING(str)->len; if (islower(*s)) *s = toupper(*s); while (++s < send) { @@ -1374,19 +1458,19 @@ str_capitalize_bang(str) static VALUE str_capitalize(str) - struct RString *str; + VALUE str; { return str_capitalize_bang(str_dup(str)); } static VALUE str_swapcase_bang(str) - struct RString *str; + VALUE str; { UCHAR *s, *send; str_modify(str); - s = str->ptr; send = s + str->len; + s = RSTRING(str)->ptr; send = s + RSTRING(str)->len; while (s < send) { if (isupper(*s)) { *s = tolower(*s); @@ -1402,7 +1486,7 @@ str_swapcase_bang(str) static VALUE str_swapcase(str) - struct RString *str; + VALUE str; { return str_swapcase_bang(str_dup(str)); } @@ -1449,7 +1533,7 @@ static VALUE str_delete_bang(); static VALUE tr_trans(str, src, repl, sflag) - struct RString *str, *src, *repl; + VALUE str, src, repl; int sflag; { struct tr trsrc, trrepl; @@ -1459,14 +1543,14 @@ tr_trans(str, src, repl, sflag) UCHAR *s, *send, *t; Check_Type(src, T_STRING); - trsrc.p = src->ptr; trsrc.pend = trsrc.p + src->len; - if (src->len > 2 && src->ptr[0] == '^') { + trsrc.p = RSTRING(src)->ptr; trsrc.pend = trsrc.p + RSTRING(src)->len; + if (RSTRING(src)->len > 2 && RSTRING(src)->ptr[0] == '^') { cflag++; trsrc.p++; } Check_Type(repl, T_STRING); - if (repl->len == 0) return str_delete_bang(str, src); - trrepl.p = repl->ptr; trrepl.pend = trrepl.p + repl->len; + if (RSTRING(repl)->len == 0) return str_delete_bang(str, src); + trrepl.p = RSTRING(repl)->ptr; trrepl.pend = trrepl.p + RSTRING(repl)->len; trsrc.gen = trrepl.gen = 0; trsrc.now = trrepl.now = 0; trsrc.max = trrepl.max = 0; @@ -1507,7 +1591,7 @@ tr_trans(str, src, repl, sflag) } str_modify(str); - t = s = str->ptr; send = s + str->len; + t = s = RSTRING(str)->ptr; send = s + RSTRING(str)->len; c0 = -1; if (sflag) { while (s < send) { @@ -1525,7 +1609,7 @@ tr_trans(str, src, repl, sflag) } } *t = '\0'; - if (sflag) str->len = (t - str->ptr); + if (sflag) RSTRING(str)->len = (t - RSTRING(str)->ptr); return (VALUE)str; } @@ -1546,16 +1630,16 @@ str_tr(str, src, repl) static void tr_setup_table(str, table) - struct RString *str; + VALUE str; UCHAR table[256]; { struct tr tr; int i, cflag = 0; int c; - tr.p = str->ptr; tr.pend = tr.p + str->len; + tr.p = RSTRING(str)->ptr; tr.pend = tr.p + RSTRING(str)->len; tr.gen = tr.now = tr.max = 0; - if (str->len > 1 && str->ptr[0] == '^') { + if (RSTRING(str)->len > 1 && RSTRING(str)->ptr[0] == '^') { cflag++; tr.p++; } @@ -1570,7 +1654,7 @@ tr_setup_table(str, table) static VALUE str_delete_bang(str1, str2) - struct RString *str1, *str2; + VALUE str1, *str2; { UCHAR *s, *send, *t; UCHAR squeez[256]; @@ -1580,8 +1664,8 @@ str_delete_bang(str1, str2) str_modify(str1); - s = t = str1->ptr; - send = s + str1->len; + s = t = RSTRING(str1)->ptr; + send = s + RSTRING(str1)->len; while (s < send) { if (!squeez[*s & 0xff]) { *t++ = *s; @@ -1589,21 +1673,21 @@ str_delete_bang(str1, str2) s++; } *t = '\0'; - str1->len = t - str1->ptr; + RSTRING(str1)->len = t - RSTRING(str1)->ptr; return (VALUE)str1; } static VALUE str_delete(str1, str2) - struct RString *str1, *str2; + VALUE str1, *str2; { return str_delete_bang(str_dup(str1), str2); } static VALUE tr_squeeze(str1, str2) - struct RString *str1, *str2; + VALUE str1, str2; { UCHAR squeez[256]; UCHAR *s, *send, *t; @@ -1622,8 +1706,8 @@ tr_squeeze(str1, str2) str_modify(str1); - s = t = str1->ptr; - send = s + str1->len; + s = t = RSTRING(str1)->ptr; + send = s + RSTRING(str1)->len; save = -1; while (s < send) { c = *s++ & 0xff; @@ -1632,7 +1716,7 @@ tr_squeeze(str1, str2) } } *t = '\0'; - str1->len = t - str1->ptr; + RSTRING(str1)->len = t - RSTRING(str1)->ptr; return (VALUE)str1; } @@ -1645,8 +1729,7 @@ str_squeeze_bang(argc, argv, str1) { VALUE str2; - rb_scan_args(argc, argv, "01", &str2); - if (!NIL_P(str2)) { + if (rb_scan_args(argc, argv, "01", &str2) == 1) { Check_Type(str2, T_STRING); } return tr_squeeze(str1, str2); @@ -1682,10 +1765,10 @@ static VALUE str_split_method(argc, argv, str) int argc; VALUE *argv; - struct RString *str; + VALUE str; { extern VALUE FS; - struct RRegexp *spat; + VALUE spat; VALUE limit; char char_sep = 0; int beg, end, lim, i; @@ -1701,7 +1784,7 @@ str_split_method(argc, argv, str) if (NIL_P(spat)) { if (!NIL_P(FS)) { - spat = (struct RRegexp*)FS; + spat = FS; goto fs_set; } char_sep = ' '; @@ -1714,7 +1797,7 @@ str_split_method(argc, argv, str) char_sep = RSTRING(spat)->ptr[0]; } else { - spat = (struct RRegexp*)reg_regcomp(spat); + spat = reg_regcomp(spat); } break; case T_REGEXP: @@ -1727,8 +1810,8 @@ str_split_method(argc, argv, str) result = ary_new(); beg = 0; if (char_sep != 0) { - UCHAR *ptr = str->ptr; - int len = str->len; + UCHAR *ptr = RSTRING(str)->ptr; + int len = RSTRING(str)->len; UCHAR *eptr = ptr + len; if (char_sep == ' ') { /* AWK emulation */ @@ -1778,14 +1861,14 @@ str_split_method(argc, argv, str) regs = RMATCH(backref_get())->regs; if (start == end && BEG(0) == END(0)) { if (last_null == 1) { - if (ismbchar(str->ptr[beg])) + if (ismbchar(RSTRING(str)->ptr[beg])) ary_push(result, str_substr(str, beg, 2)); else ary_push(result, str_substr(str, beg, 1)); beg = start; } else { - start += ismbchar(str->ptr[start])?2:1; + start += ismbchar(RSTRING(str)->ptr[start])?2:1; last_null = 1; continue; } @@ -1807,7 +1890,7 @@ str_split_method(argc, argv, str) if (!NIL_P(limit) && lim <= ++i) break; } } - if (str->len > beg) { + if (RSTRING(str)->len > beg) { ary_push(result, str_subseq(str, beg, -1)); } @@ -1816,7 +1899,7 @@ str_split_method(argc, argv, str) VALUE str_split(str, sep0) - struct RString* str; + VALUE str; char *sep0; { VALUE sep; @@ -1838,15 +1921,15 @@ static VALUE str_each_line(argc, argv, str) int argc; VALUE *argv; - struct RString* str; + VALUE str; { extern VALUE RS; VALUE rs; int newline; int rslen; - UCHAR *p = str->ptr, *pend = p + str->len, *s; + UCHAR *p = RSTRING(str)->ptr, *pend = p + RSTRING(str)->len, *s; UCHAR *ptr = p; - int len = str->len; + int len = RSTRING(str)->len; VALUE line; if (rb_scan_args(argc, argv, "01", &rs) == 1) { @@ -1881,7 +1964,7 @@ str_each_line(argc, argv, str) line = str_new(s, p - s + 1); lastline_set(line); rb_yield(line); - if (str->ptr != ptr || str->len != len) + if (RSTRING(str)->ptr != ptr || RSTRING(str)->len != len) Fail("string modified"); s = p + 1; } @@ -1902,41 +1985,42 @@ str_each_byte(str) { int i; - for (i=0; ilen; i++) { - rb_yield(INT2FIX(str->ptr[i] & 0xff)); + for (i=0; ilen; i++) { + rb_yield(INT2FIX(RSTRING(str)->ptr[i] & 0xff)); } return Qnil; } static VALUE str_chop_bang(str) - struct RString *str; + VALUE str; { str_modify(str); - if (str->len > 0) { - str->len--; - if (str->ptr[str->len] == '\n') { - if (str->len > 0 && str->ptr[str->len-1] == '\r') { - str->len--; + if (RSTRING(str)->len > 0) { + RSTRING(str)->len--; + if (RSTRING(str)->ptr[RSTRING(str)->len] == '\n') { + if (RSTRING(str)->len > 0 && + RSTRING(str)->ptr[RSTRING(str)->len-1] == '\r') { + RSTRING(str)->len--; } } - str->ptr[str->len] = '\0'; + RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; } - return (VALUE)str; + return str; } static VALUE str_chop(str) - struct RString *str; + VALUE str; { return str_chop_bang(str_dup(str)); } static VALUE f_chop_bang(str) - struct RString *str; + VALUE str; { return str_chop_bang(uscore_get()); } @@ -1947,16 +2031,54 @@ f_chop() return str_chop_bang(str_dup(uscore_get())); } +static VALUE +str_chomp_bang(str) + VALUE str; +{ + str_modify(str); + + if (RSTRING(str)->len > 0 && + RSTRING(str)->ptr[RSTRING(str)->len-1] == '\n') { + RSTRING(str)->len--; + if (RSTRING(str)->len > 0 && + RSTRING(str)->ptr[RSTRING(str)->len] == '\r') { + RSTRING(str)->len--; + } + RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; + } + return str; +} + +static VALUE +str_chomp(str) + VALUE str; +{ + return str_chomp_bang(str_dup(str)); +} + +static VALUE +f_chomp_bang(str) + VALUE str; +{ + return str_chomp_bang(uscore_get()); +} + +static VALUE +f_chomp() +{ + return str_chomp_bang(str_dup(uscore_get())); +} + static VALUE str_strip_bang(str) - struct RString *str; + VALUE str; { UCHAR *s, *t, *e; str_modify(str); - s = str->ptr; - e = t = s + str->len; + s = RSTRING(str)->ptr; + e = t = s + RSTRING(str)->len; /* remove spaces at head */ while (s < t && isspace(*s)) s++; @@ -1965,17 +2087,17 @@ str_strip_bang(str) while (s <= t && isspace(*t)) t--; t++; - str->len = t-s; - if (s > str->ptr) { - UCHAR *p = str->ptr; + RSTRING(str)->len = t-s; + if (s > RSTRING(str)->ptr) { + UCHAR *p = RSTRING(str)->ptr; - str->ptr = ALLOC_N(char, str->len+1); - memcpy(str->ptr, s, str->len); - str->ptr[str->len] = '\0'; + RSTRING(str)->ptr = ALLOC_N(char, RSTRING(str)->len+1); + memcpy(RSTRING(str)->ptr, s, RSTRING(str)->len); + RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; free(p); } else if (t < e) { - str->ptr[str->len] = '\0'; + RSTRING(str)->ptr[RSTRING(str)->len] = '\0'; } return (VALUE)str; @@ -1983,34 +2105,33 @@ str_strip_bang(str) static VALUE scan_once(str, pat, start) - struct RString *str; - struct RRegexp *pat; + VALUE str, pat; int *start; { VALUE result; struct re_registers *regs; - int idx; + int i; if (reg_search(pat, str, *start, 0) >= 0) { regs = RMATCH(backref_get())->regs; - result = ary_new2(regs->num_regs); - for (idx=1; idx < regs->num_regs; idx++) { - if (BEG(idx) == -1) { - ary_push(result, Qnil); - } - else if (BEG(idx) == END(idx)) { - ary_push(result, str_new(0, 0)); - } - else { - ary_push(result, str_subseq(str, BEG(idx), END(idx)-1)); - } - } if (END(0) == *start) { *start = END(0)+1; } else { *start = END(0); } + if (regs->num_regs == 1) { + return str_substr(str, BEG(0), END(0)-BEG(0)); + } + result = ary_new2(regs->num_regs); + for (i=1; i < regs->num_regs; i++) { + if (BEG(i) == -1) { + ary_push(result, Qnil); + } + else { + ary_push(result, str_substr(str, BEG(i), END(i)-BEG(i))); + } + } return result; } @@ -2019,15 +2140,14 @@ scan_once(str, pat, start) static VALUE str_scan(str, pat) - struct RString *str; - struct RRegexp *pat; + VALUE str, pat; { VALUE result; int start = 0; switch (TYPE(pat)) { case T_STRING: - pat = (struct RRegexp*)reg_regcomp(pat); + pat = reg_regcomp(pat); break; case T_REGEXP: break; @@ -2036,7 +2156,12 @@ str_scan(str, pat) } if (!iterator_p()) { - return scan_once(str, pat, &start); + VALUE ary = ary_new(); + + while (!NIL_P(result = scan_once(str, pat, &start))) { + ary_push(ary, result); + } + return ary; } while (!NIL_P(result = scan_once(str, pat, &start))) { @@ -2047,44 +2172,45 @@ str_scan(str, pat) static VALUE str_strip(str) - struct RString *str; + VALUE str; { return str_strip_bang(str_dup(str)); } static VALUE str_hex(str) - struct RString *str; + VALUE str; { - return str2inum(str->ptr, 16); + return str2inum(RSTRING(str)->ptr, 16); } static VALUE str_oct(str) - struct RString *str; + VALUE str; { - return str2inum(str->ptr, 8); + return str2inum(RSTRING(str)->ptr, 8); } static VALUE str_crypt(str, salt) - struct RString *str, *salt; + VALUE str, salt; { - salt = as_str(salt); - if (salt->len < 2) + extern char *crypt(); + salt = obj_as_string(salt); + if (RSTRING(salt)->len < 2) ArgError("salt too short(need >2 bytes)"); - return str_new2(crypt(str->ptr, salt->ptr)); + return str_new2(crypt(RSTRING(str)->ptr, RSTRING(salt)->ptr)); } static VALUE str_intern(str) - struct RString *str; + VALUE str; { ID id; - if (strlen(str->ptr) != str->len) + if (strlen(RSTRING(str)->ptr) != RSTRING(str)->len) ArgError("string contains `\0'"); - id = rb_intern(str->ptr); + id = rb_intern(RSTRING(str)->ptr); return INT2FIX(id); } @@ -2092,7 +2218,7 @@ static VALUE str_sum(argc, argv, str) int argc; VALUE *argv; - struct RString *str; + VALUE str; { VALUE vbits; int bits; @@ -2102,7 +2228,7 @@ str_sum(argc, argv, str) if (NIL_P(vbits)) bits = 16; else bits = NUM2INT(vbits); - p = str->ptr; pend = p + str->len; + p = RSTRING(str)->ptr; pend = p + RSTRING(str)->len; if (bits > 32) { VALUE res = INT2FIX(0); VALUE mod; @@ -2132,70 +2258,71 @@ str_sum(argc, argv, str) static VALUE str_ljust(str, w) - struct RString *str; + VALUE str; VALUE w; { int width = NUM2INT(w); - struct RString *res; + VALUE res; UCHAR *p, *pend; - if (str->len >= width) return (VALUE)str; - res = (struct RString*)str_new(0, width); - memcpy(res->ptr, str->ptr, str->len); - p = res->ptr + str->len; pend = res->ptr + width; + if (RSTRING(str)->len >= width) return (VALUE)str; + res = str_new(0, width); + memcpy(RSTRING(res)->ptr, RSTRING(str)->ptr, RSTRING(str)->len); + p = RSTRING(res)->ptr + RSTRING(str)->len; pend = RSTRING(res)->ptr + width; while (p < pend) { *p++ = ' '; } - return (VALUE)res; + return res; } static VALUE str_rjust(str, w) - struct RString *str; + VALUE str; VALUE w; { int width = NUM2INT(w); - struct RString *res; + VALUE res; UCHAR *p, *pend; - if (str->len >= width) return (VALUE)str; - res = (struct RString*)str_new(0, width); - p = res->ptr; pend = p + width - str->len; + if (RSTRING(str)->len >= width) return (VALUE)str; + res = str_new(0, width); + p = RSTRING(res)->ptr; pend = p + width - RSTRING(str)->len; while (p < pend) { *p++ = ' '; } - memcpy(pend, str->ptr, str->len); - return (VALUE)res; + memcpy(pend, RSTRING(str)->ptr, RSTRING(str)->len); + return res; } static VALUE str_center(str, w) - struct RString *str; + VALUE str; VALUE w; { int width = NUM2INT(w); - struct RString *res; + VALUE res; UCHAR *p, *pend; int n; - if (str->len >= width) return (VALUE)str; - res = (struct RString*)str_new(0, width); - n = (width - str->len)/2; - p = res->ptr; pend = p + n; + if (RSTRING(str)->len >= width) return (VALUE)str; + res = str_new(0, width); + n = (width - RSTRING(str)->len)/2; + p = RSTRING(res)->ptr; pend = p + n; while (p < pend) { *p++ = ' '; } - memcpy(pend, str->ptr, str->len); - p = pend + str->len; pend = res->ptr + width; + memcpy(pend, RSTRING(str)->ptr, RSTRING(str)->len); + p = pend + RSTRING(str)->len; pend = RSTRING(res)->ptr + width; while (p < pend) { *p++ = ' '; } - return (VALUE)res; + return res; } extern VALUE mKernel; extern VALUE mComparable; extern VALUE mEnumerable; +extern VALUE eGlobalExit; void Init_String() @@ -2213,6 +2340,7 @@ Init_String() rb_define_method(cString, "hash", str_hash_method, 0); rb_define_method(cString, "+", str_plus, 1); rb_define_method(cString, "*", str_times, 1); + rb_define_method(cString, "%", str_format, 1); rb_define_method(cString, "[]", str_aref_method, -1); rb_define_method(cString, "[]=", str_aset_method, -1); rb_define_method(cString, "length", str_length, 0); @@ -2255,6 +2383,8 @@ Init_String() rb_define_method(cString, "crypt", str_crypt, 1); rb_define_method(cString, "intern", str_intern, 0); + rb_define_method(cString, "include?", str_include, 1); + rb_define_method(cString, "scan", str_scan, 1); rb_define_method(cString, "ljust", str_ljust, 1); @@ -2264,12 +2394,14 @@ Init_String() rb_define_method(cString, "sub", str_sub, -1); rb_define_method(cString, "gsub", str_gsub, -1); rb_define_method(cString, "chop", str_chop, 0); + rb_define_method(cString, "chomp", str_chomp, 0); rb_define_method(cString, "strip", str_strip, 0); rb_define_method(cString, "sub!", str_sub_bang, -1); rb_define_method(cString, "gsub!", str_gsub_bang, -1); rb_define_method(cString, "strip!", str_strip_bang, 0); rb_define_method(cString, "chop!", str_chop_bang, 0); + rb_define_method(cString, "chomp!", str_chomp_bang, 0); rb_define_method(cString, "tr", str_tr, 2); rb_define_method(cString, "tr_s", str_tr_s, 2); @@ -2296,7 +2428,13 @@ Init_String() rb_define_global_function("chop", f_chop, 0); rb_define_global_function("chop!", f_chop_bang, 0); + rb_define_global_function("chomp", f_chomp, 0); + rb_define_global_function("chomp!", f_chomp_bang, 0); + rb_define_global_function("split", f_split, -1); pr_str = rb_intern("to_s"); + + /* Fix-up initialize ordering */ + RCLASS(eGlobalExit)->super = cString; } diff --git a/struct.c b/struct.c index 52822d9c55..7234d1e5d2 100644 --- a/struct.c +++ b/struct.c @@ -44,7 +44,7 @@ struct_members(obj) VALUE struct_getmember(obj, id) - struct RStruct *obj; + VALUE obj; ID id; { VALUE nstr, member, slot; @@ -58,7 +58,7 @@ struct_getmember(obj, id) slot = INT2FIX(id); for (i=0; ilen; i++) { if (RARRAY(member)->ptr[i] == slot) { - return obj->ptr[i]; + return RSTRUCT(obj)->ptr[i]; } } NameError("%s is not struct member", rb_id2name(id)); @@ -72,16 +72,16 @@ struct_ref(obj) return struct_getmember(obj, rb_frame_last_func()); } -static VALUE struct_ref0(obj) struct RStruct *obj; {return obj->ptr[0];} -static VALUE struct_ref1(obj) struct RStruct *obj; {return obj->ptr[1];} -static VALUE struct_ref2(obj) struct RStruct *obj; {return obj->ptr[2];} -static VALUE struct_ref3(obj) struct RStruct *obj; {return obj->ptr[3];} -static VALUE struct_ref4(obj) struct RStruct *obj; {return obj->ptr[4];} -static VALUE struct_ref5(obj) struct RStruct *obj; {return obj->ptr[5];} -static VALUE struct_ref6(obj) struct RStruct *obj; {return obj->ptr[6];} -static VALUE struct_ref7(obj) struct RStruct *obj; {return obj->ptr[7];} -static VALUE struct_ref8(obj) struct RStruct *obj; {return obj->ptr[8];} -static VALUE struct_ref9(obj) struct RStruct *obj; {return obj->ptr[9];} +static VALUE struct_ref0(obj) VALUE obj; {return RSTRUCT(obj)->ptr[0];} +static VALUE struct_ref1(obj) VALUE obj; {return RSTRUCT(obj)->ptr[1];} +static VALUE struct_ref2(obj) VALUE obj; {return RSTRUCT(obj)->ptr[2];} +static VALUE struct_ref3(obj) VALUE obj; {return RSTRUCT(obj)->ptr[3];} +static VALUE struct_ref4(obj) VALUE obj; {return RSTRUCT(obj)->ptr[4];} +static VALUE struct_ref5(obj) VALUE obj; {return RSTRUCT(obj)->ptr[5];} +static VALUE struct_ref6(obj) VALUE obj; {return RSTRUCT(obj)->ptr[6];} +static VALUE struct_ref7(obj) VALUE obj; {return RSTRUCT(obj)->ptr[7];} +static VALUE struct_ref8(obj) VALUE obj; {return RSTRUCT(obj)->ptr[8];} +static VALUE struct_ref9(obj) VALUE obj; {return RSTRUCT(obj)->ptr[9];} VALUE (*ref_func[10])() = { struct_ref0, @@ -98,8 +98,7 @@ VALUE (*ref_func[10])() = { static VALUE struct_set(obj, val) - struct RStruct *obj; - VALUE val; + VALUE obj, val; { VALUE nstr, member, slot; int i; @@ -112,7 +111,7 @@ struct_set(obj, val) for (i=0; ilen; i++) { slot = RARRAY(member)->ptr[i]; if (id_attrset(FIX2INT(slot)) == rb_frame_last_func()) { - return obj->ptr[i] = val; + return RSTRUCT(obj)->ptr[i] = val; } } NameError("not struct member"); @@ -123,26 +122,25 @@ VALUE struct_alloc(); static VALUE make_struct(name, member) - struct RString *name; - struct RArray *member; + VALUE name, member; { VALUE nstr; ID id; int i; - id = rb_intern(name->ptr); + id = rb_intern(RSTRING(name)->ptr); if (!rb_is_const_id(id)) { - NameError("identifier %s needs to be constant", name->ptr); + NameError("identifier %s needs to be constant", RSTRING(name)->ptr); } - nstr = rb_define_class_under(cStruct, name->ptr, cStruct); - rb_iv_set(nstr, "__size__", INT2FIX(member->len)); + nstr = rb_define_class_under(cStruct, RSTRING(name)->ptr, cStruct); + rb_iv_set(nstr, "__size__", INT2FIX(RARRAY(member)->len)); rb_iv_set(nstr, "__member__", member); rb_define_singleton_method(nstr, "new", struct_alloc, -2); rb_define_singleton_method(nstr, "[]", struct_alloc, -2); rb_define_singleton_method(nstr, "members", struct_s_members, 0); - for (i=0; i< member->len; i++) { - ID id = FIX2INT(member->ptr[i]); + for (i=0; i< RARRAY(member)->len; i++) { + ID id = FIX2INT(RARRAY(member)->ptr[i]); if (i<10) { rb_define_method_id(nstr, id, ref_func[i], 0); } @@ -199,15 +197,14 @@ struct_s_def(argc, argv) VALUE struct_alloc(class, values) - VALUE class; - struct RArray *values; + VALUE class, values; { VALUE size; int n; size = rb_iv_get(class, "__size__"); n = FIX2INT(size); - if (n < values->len) { + if (n < RARRAY(values)->len) { ArgError("struct size differs"); } else { @@ -216,8 +213,8 @@ struct_alloc(class, values) st->len = n; st->ptr = 0; /* avoid GC crashing */ st->ptr = ALLOC_N(VALUE, n); - MEMCPY(st->ptr, values->ptr, VALUE, values->len); - memclear(st->ptr+values->len, n - values->len); + MEMCPY(st->ptr, RARRAY(values)->ptr, VALUE, RARRAY(values)->len); + memclear(st->ptr+RARRAY(values)->len, n - RARRAY(values)->len); return (VALUE)st; } @@ -248,12 +245,12 @@ struct_new(class, va_alist) static VALUE struct_each(s) - struct RStruct *s; + VALUE s; { int i; - for (i=0; ilen; i++) { - rb_yield(s->ptr[i]); + for (i=0; ilen; i++) { + rb_yield(RSTRUCT(s)->ptr[i]); } return Qnil; } @@ -262,7 +259,7 @@ char *rb_class2name(); static VALUE struct_to_s(s) - struct RStruct *s; + VALUE s; { char *name, *buf; @@ -274,7 +271,7 @@ struct_to_s(s) static VALUE struct_inspect(s) - struct RStruct *s; + VALUE s; { char *name = rb_class2name(CLASS_OF(s)); VALUE str, member; @@ -288,7 +285,7 @@ struct_inspect(s) sprintf(buf, "#<%s ", name); str = str_new2(buf); - for (i=0; ilen; i++) { + for (i=0; ilen; i++) { VALUE str2, slot; char *p; @@ -299,7 +296,7 @@ struct_inspect(s) p = rb_id2name(FIX2INT(slot)); str_cat(str, p, strlen(p)); str_cat(str, "=", 1); - str2 = rb_inspect(s->ptr[i]); + str2 = rb_inspect(RSTRUCT(s)->ptr[i]); str2 = obj_as_string(str2); str_cat(str, RSTRING(str2)->ptr, RSTRING(str2)->len); } @@ -310,102 +307,100 @@ struct_inspect(s) static VALUE struct_to_a(s) - struct RStruct *s; + VALUE s; { - return ary_new4(s->len, s->ptr); + return ary_new4(RSTRUCT(s)->len, RSTRUCT(s)->ptr); } static VALUE struct_clone(s) - struct RStruct *s; + VALUE s; { NEWOBJ(st, struct RStruct); CLONESETUP(st, s); - st->len = s->len; + st->len = RSTRUCT(s)->len; st->ptr = 0; /* avoid GC crashing */ - st->ptr = ALLOC_N(VALUE, s->len); - MEMCPY(st->ptr, s->ptr, VALUE, st->len); + st->ptr = ALLOC_N(VALUE, RSTRUCT(s)->len); + MEMCPY(st->ptr, RSTRUCT(s)->ptr, VALUE, st->len); return (VALUE)st; } VALUE struct_aref(s, idx) - struct RStruct *s; - VALUE idx; + VALUE s, idx; { int i; i = NUM2INT(idx); - if (i < 0) i = s->len - i; + if (i < 0) i = RSTRUCT(s)->len - i; if (i < 0) - IndexError("offset %d too small for struct(size:%d)", i, s->len); - if (s->len <= i) - IndexError("offset %d too large for struct(size:%d)", i, s->len); - return s->ptr[i]; + IndexError("offset %d too small for struct(size:%d)", i, RSTRUCT(s)->len); + if (RSTRUCT(s)->len <= i) + IndexError("offset %d too large for struct(size:%d)", i, RSTRUCT(s)->len); + return RSTRUCT(s)->ptr[i]; } VALUE struct_aset(s, idx, val) - struct RStruct *s; - VALUE idx, val; + VALUE s, idx, val; { int i; i = NUM2INT(idx); - if (i < 0) i = s->len - i; + if (i < 0) i = RSTRUCT(s)->len - i; if (i < 0) - IndexError("offset %d too small for struct(size:%d)", i, s->len); - if (s->len <= i) - IndexError("offset %d too large for struct(size:%d)", i, s->len); - return s->ptr[i] = val; + IndexError("offset %d too small for struct(size:%d)", i, RSTRUCT(s)->len); + if (RSTRUCT(s)->len <= i) + IndexError("offset %d too large for struct(size:%d)", i, RSTRUCT(s)->len); + return RSTRUCT(s)->ptr[i] = val; } static VALUE struct_equal(s, s2) - struct RStruct *s, *s2; + VALUE s, s2; { int i; if (TYPE(s2) != T_STRUCT) return FALSE; if (CLASS_OF(s) != CLASS_OF(s2)) return FALSE; - if (s->len != s2->len) { + if (RSTRUCT(s)->len != RSTRUCT(s2)->len) { Bug("inconsistent struct"); /* should never happen */ } - for (i=0; ilen; i++) { - if (!rb_equal(s->ptr[i], s2->ptr[i])) return FALSE; + for (i=0; ilen; i++) { + if (!rb_equal(RSTRUCT(s)->ptr[i], RSTRUCT(s2)->ptr[i])) return FALSE; } return TRUE; } static VALUE struct_eql(s, s2) - struct RStruct *s, *s2; + VALUE s, s2; { int i; if (TYPE(s2) != T_STRUCT) return FALSE; if (CLASS_OF(s) != CLASS_OF(s2)) return FALSE; - if (s->len != s2->len) { + if (RSTRUCT(s)->len != RSTRUCT(s2)->len) { Bug("inconsistent struct"); /* should never happen */ } - for (i=0; ilen; i++) { - if (!rb_eql(s->ptr[i], s2->ptr[i])) return FALSE; + for (i=0; ilen; i++) { + if (!rb_eql(RSTRUCT(s)->ptr[i], RSTRUCT(s2)->ptr[i])) return FALSE; } return TRUE; } static VALUE struct_hash(s) - struct RStruct *s; + VALUE s; { int i, h; h = CLASS_OF(s); - for (i=0; ilen; i++) { - h ^= rb_hash(s->ptr[i]); + for (i=0; ilen; i++) { + h ^= rb_hash(RSTRUCT(s)->ptr[i]); } return INT2FIX(h); } diff --git a/time.c b/time.c index b1184fbe98..1749c32319 100644 --- a/time.c +++ b/time.c @@ -13,10 +13,6 @@ #include "ruby.h" #include -#ifdef HAVE_STRING_H -# include -#endif - #include #ifndef NT #ifdef HAVE_SYS_TIME_H @@ -437,20 +433,6 @@ time_asctime(time) return str_new(buf, len); } -static VALUE -time_coerce(time1, time2) - VALUE time1, time2; -{ - if (TYPE(time2) == T_FLOAT) { - double d = RFLOAT(time2)->value; - unsigned int i = (unsigned int) d; - - return assoc_new(time_new(i, (int)((d - (double)i)*1e6)),time1); - } - - return assoc_new(time_new(NUM2INT(time2), 0), time1); -} - static VALUE time_plus(time1, time2) VALUE time1, time2; @@ -673,13 +655,40 @@ time_to_a(time) return ary; } +#define SMALLBUF 100 +static int +rb_strftime(buf, format, time) + char ** volatile buf; + char * volatile format; + struct tm * volatile time; +{ + volatile int i; + int len; + + len = strftime(*buf, SMALLBUF, format, time); + if (len != 0) return len; + for (i=1024; i<8192; i+=1024) { + *buf = xmalloc(i); + len = strftime(*buf, i-1, format, time); + if (len == 0) { + free(*buf); + continue; + } + return len; + } + + ArgError("bad strftime format or result too long"); +} + static VALUE time_strftime(time, format) VALUE time, format; { struct time_object *tobj; - char buf[100]; + char buffer[SMALLBUF]; + char *buf = buffer; int len; + VALUE str; Check_Type(format, T_STRING); GetTimeval(time, tobj); @@ -687,22 +696,23 @@ time_strftime(time, format) time_localtime(time); } if (strlen(RSTRING(format)->ptr) < RSTRING(format)->len) { - /* Ruby string contains \0. */ - VALUE str; + /* Ruby string may contain \0's. */ int l; char *p = RSTRING(format)->ptr, *pe = p + RSTRING(format)->len; str = str_new(0, 0); while (p < pe) { - len = strftime(buf, 100, p, &(tobj->tm)); + len = rb_strftime(&buf, p, &(tobj->tm)); str_cat(str, buf, len); - l = strlen(p); - p += l + 1; + p += strlen(p) + 1; + if (len > SMALLBUF) free(buf); } return str; } - len = strftime(buf, 100, RSTRING(format)->ptr, &(tobj->tm)); - return str_new(buf, len); + len = rb_strftime(&buf, RSTRING(format)->ptr, &(tobj->tm)); + str = str_new(buf, len); + if (len > SMALLBUF) free(buf); + return str; } static VALUE @@ -767,7 +777,6 @@ Init_Time() rb_define_method(cTime, "to_s", time_asctime, 0); rb_define_method(cTime, "inspect", time_asctime, 0); rb_define_method(cTime, "to_a", time_to_a, 0); - rb_define_method(cTime, "coerce", time_coerce, 1); rb_define_method(cTime, "+", time_plus, 1); rb_define_method(cTime, "-", time_minus, 1); @@ -776,7 +785,9 @@ Init_Time() rb_define_method(cTime, "min", time_min, 0); rb_define_method(cTime, "hour", time_hour, 0); rb_define_method(cTime, "mday", time_mday, 0); + rb_define_method(cTime, "day", time_mday, 0); rb_define_method(cTime, "mon", time_mon, 0); + rb_define_method(cTime, "month", time_mon, 0); rb_define_method(cTime, "year", time_year, 0); rb_define_method(cTime, "wday", time_wday, 0); rb_define_method(cTime, "yday", time_yday, 0); diff --git a/top.sed b/top.sed index d91a80eb0a..934f60142d 100644 --- a/top.sed +++ b/top.sed @@ -1,6 +1,6 @@ /^SHELL/s,/bin/sh,$(COMPSEC), -/^VPATH/s/:/;/g s/@srcdir@/./g +s/@top_srcdir@/../ s/@CC@/gcc/ s/@CPP@/gcc -E/ s/@CPPFLAGS@// @@ -11,7 +11,7 @@ s/@INSTALL@/ginstall -c/ s/@INSTALL_PROGRAM@/${INSTALL}/ s/@INSTALL_DATA@/${INSTALL} -m 644/ s/@SET_MAKE@// -s/@CFLAGS@/-g -O -I./ +s/@CFLAGS@/-g -O2 -I./ s/@STATIC@// s/@LDFLAGS@// s/@LIBS@// @@ -40,7 +40,7 @@ s/y\.tab\.c/y_tab.c/ #/`rm -f ruby`/s//`rm -f ruby.exe`/ #/`cp miniruby ruby`/s//`cp miniruby.exe ruby.exe`/ /^all:.*miniruby/ { - n;N;N;N;c\ + n;c\ cd ext\ ../miniruby ./extmk.rb\ cd .. diff --git a/util.c b/util.c index 8e822631ed..21e0a55639 100644 --- a/util.c +++ b/util.c @@ -10,11 +10,42 @@ ************************************************/ +#define RUBY_NO_INLINE #include "ruby.h" + +int +rb_type(obj) + VALUE obj; +{ + if (FIXNUM_P(obj)) return T_FIXNUM; + if (obj == Qnil) return T_NIL; + if (obj == FALSE) return T_FALSE; + if (obj == TRUE) return T_TRUE; + + return BUILTIN_TYPE(obj); +} + +int +rb_special_const_p(obj) + VALUE obj; +{ + if (FIXNUM_P(obj)) return TRUE; + if (obj == Qnil) return TRUE; + if (obj == FALSE) return TRUE; + if (obj == TRUE) return TRUE; + + return FALSE; +} + +int +rb_test_false_or_nil(v) + VALUE v; +{ + return (v != Qnil) && (v != FALSE); +} + #include "util.h" -#ifdef HAVE_STRING_H -# include -#else +#ifndef HAVE_STRING_H char *strchr(); #endif @@ -136,7 +167,7 @@ static char suffix2[] = ".~~~"; #define strEQ(s1,s2) (strcmp(s1,s2) == 0) void -add_suffix(struct RString *str, char *suffix) +add_suffix(VALUE str, char *suffix) { int baselen; int extlen = strlen(suffix); @@ -144,25 +175,25 @@ add_suffix(struct RString *str, char *suffix) int slen; char buf[1024]; - if (str->len > 1000) - Fatal("Cannot do inplace edit on long filename (%d characters)", str->len); + if (RSTRING(str)->len > 1000) + Fatal("Cannot do inplace edit on long filename (%d characters)", RSTRING(str)->len); #if defined(DJGPP) || defined(__CYGWIN32__) || defined(NT) /* Style 0 */ - slen = str->len; + slen = RSTRING(str)->len; str_cat(str, suffix, extlen); #if defined(DJGPP) if (_USE_LFN) return; #else - if (valid_filename(str->ptr)) return; + if (valid_filename(RSTRING(str)->ptr)) return; #endif /* Fooey, style 0 failed. Fix str before continuing. */ - str->ptr[str->len = slen] = '\0'; + RSTRING(str)->ptr[RSTRING(str)->len = slen] = '\0'; #endif slen = extlen; - t = buf; baselen = 0; s = str->ptr; + t = buf; baselen = 0; s = RSTRING(str)->ptr; while ( (*t = *s) && *s != '.') { baselen++; if (*s == '\\' || *s == '/') baselen = 0; @@ -194,7 +225,7 @@ fallback: (void)memcpy(p, strEQ(ext, suffix1) ? suffix2 : suffix1, 5); } str_resize(str, strlen(buf)); - memcpy(str->ptr, buf, str->len); + memcpy(RSTRING(str)->ptr, buf, RSTRING(str)->len); } #if defined(__CYGWIN32__) || defined(NT) @@ -232,7 +263,6 @@ valid_filename(char *s) #include /* For FILENAME_MAX */ #include /* For errno */ #include /* For tolower */ -#include /* For strlen() */ #include /* For LFN stuff */ #include #include /* For dpmisim */ diff --git a/variable.c b/variable.c index fc514f902a..0115b87d68 100644 --- a/variable.c +++ b/variable.c @@ -13,10 +13,6 @@ #include "node.h" #include "st.h" -#ifdef HAVE_STRING_H -# include -#endif - static st_table *rb_global_tbl; st_table *rb_class_tbl; #define global_tbl rb_global_tbl @@ -39,7 +35,7 @@ Init_var_tables() struct fc_result { ID name; - VALUE class; + VALUE klass; VALUE path; VALUE track; struct fc_result *prev; @@ -67,7 +63,7 @@ fc_i(key, value, res) else { path = str_new2(name); } - if (value == res->class) { + if (value == res->klass) { res->name = key; res->path = path; return ST_STOP; @@ -87,7 +83,7 @@ fc_i(key, value, res) arg.name = 0; arg.path = path; - arg.class = res->class; + arg.klass = res->klass; arg.track = value; arg.prev = res; st_foreach(RCLASS(value)->iv_tbl, fc_i, &arg); @@ -101,15 +97,14 @@ fc_i(key, value, res) } static VALUE -find_class_path(class) - VALUE class; +find_class_path(cls) + VALUE cls; { - VALUE c; struct fc_result arg; arg.name = 0; arg.path = 0; - arg.class = class; + arg.klass = cls; arg.track = cObject; arg.prev = 0; if (RCLASS(cObject)->iv_tbl) { @@ -119,30 +114,30 @@ find_class_path(class) st_foreach(class_tbl, fc_i, &arg); } if (arg.name) { - rb_iv_set(class, "__classpath__", arg.path); + rb_iv_set(cls, "__classpath__", arg.path); return arg.path; } return Qnil; } static VALUE -classname(class) - VALUE class; +classname(cls) + VALUE cls; { VALUE path; - while (TYPE(class) == T_ICLASS || FL_TEST(class, FL_SINGLETON)) { - class = (VALUE)RCLASS(class)->super; + while (TYPE(cls) == T_ICLASS || FL_TEST(cls, FL_SINGLETON)) { + cls = (VALUE)RCLASS(cls)->super; } - path = rb_iv_get(class, "__classpath__"); + path = rb_iv_get(cls, "__classpath__"); if (NIL_P(path)) { - path = rb_iv_get(class, "__classid__"); + path = rb_iv_get(cls, "__classid__"); if (!NIL_P(path)) { path = str_new2(rb_id2name(FIX2INT(path))); } } if (NIL_P(path)) { - path = find_class_path(class); + path = find_class_path(cls); if (NIL_P(path)) { return 0; } @@ -153,29 +148,38 @@ classname(class) } VALUE -rb_class_path(class) - VALUE class; +mod_name(mod) + VALUE mod; +{ + VALUE path = classname(mod); + + if (path) return path; + return str_new(0,0); +} + +VALUE +rb_class_path(cls) + VALUE cls; { - VALUE path = classname(class); + VALUE path = classname(cls); if (path) return path; else { char buf[256]; char *s = "Class"; - if (TYPE(class) == T_MODULE) s = "Module"; - sprintf(buf, "#<%s 0x%x>", s, class); + if (TYPE(cls) == T_MODULE) s = "Module"; + sprintf(buf, "#<%s 0x%x>", s, cls); return str_new2(buf); } } void -rb_set_class_path(class, under, name) - VALUE class, under; +rb_set_class_path(cls, under, name) + VALUE cls, under; char *name; { VALUE str; - char *s; if (under == cObject) { str = str_new2(name); @@ -185,7 +189,7 @@ rb_set_class_path(class, under, name) str_cat(str, "::", 2); str_cat(str, name, strlen(name)); } - rb_iv_set(class, "__classpath__", str); + rb_iv_set(cls, "__classpath__", str); } VALUE @@ -199,17 +203,17 @@ rb_path2class(path) } void -rb_name_class(class, id) - VALUE class; +rb_name_class(cls, id) + VALUE cls; ID id; { extern VALUE cString; if (cString) { - rb_iv_set(class, "__classpath__", str_new2(rb_id2name(id))); + rb_iv_set(cls, "__classpath__", str_new2(rb_id2name(id))); } else { - rb_iv_set(class, "__classid__", INT2FIX(id)); + rb_iv_set(cls, "__classid__", INT2FIX(id)); } } @@ -231,39 +235,37 @@ rb_autoload_id(id, filename) } void -rb_autoload(class, filename) - char *class, *filename; +rb_autoload(cls, filename) + char *cls, *filename; { - rb_autoload_id(rb_intern(class), filename); + rb_autoload_id(rb_intern(cls), filename); } VALUE -f_autoload(obj, class, file) - VALUE obj, class; - struct RString *file; +f_autoload(obj, cls, file) + VALUE obj, cls, file; { - ID id = rb_to_id(class); + ID id = rb_to_id(cls); Check_Type(file, T_STRING); - rb_autoload_id(id, file->ptr); + rb_autoload_id(id, RSTRING(file)->ptr); return Qnil; } char * -rb_class2name(class) - VALUE class; +rb_class2name(cls) + VALUE cls; { - return RSTRING(rb_class_path(class))->ptr; + return RSTRING(rb_class_path(cls))->ptr; } struct trace_var { + int removed; void (*func)(); void *data; struct trace_var *next; }; -VALUE f_untrace_var(); - struct global_entry { ID id; void *data; @@ -496,7 +498,7 @@ f_trace_var(argc, argv) cmd = f_lambda(); } if (NIL_P(cmd)) { - return f_untrace_var(argc, argv, Qnil); + return f_untrace_var(argc, argv); } id = rb_to_id(var); if (!st_lookup(global_tbl, id, &entry)) { @@ -506,11 +508,33 @@ f_trace_var(argc, argv) trace->next = entry->trace; trace->func = rb_trace_eval; trace->data = (void*)cmd; + trace->removed = 0; entry->trace = trace; return Qnil; } +static void +remove_trace(entry) + struct global_entry *entry; +{ + struct trace_var *trace = entry->trace; + struct trace_var t; + struct trace_var *next; + + t.next = trace; + trace = &t; + while (trace->next) { + next = trace->next; + if (next->removed) { + trace->next = next->next; + free(next); + } + trace = next; + } + entry->trace = t.next; +} + VALUE f_untrace_var(argc, argv) int argc; @@ -532,34 +556,27 @@ f_untrace_var(argc, argv) trace = entry->trace; while (trace) { struct trace_var *next = trace->next; - ary_push(ary, trace->data); - free(trace); + ary_push(ary, (VALUE)trace->data); + trace->removed = 1; trace = next; } entry->trace = 0; + if (!entry->block_trace) remove_trace(entry); return ary; } else { - struct trace_var t; - struct trace_var *next; - - t.next = entry->trace; - trace = &t; - while (trace->next) { - next = trace->next; - if (next->data == (void*)cmd) { - trace->next = next->next; - free(next); - entry->trace = t.next; + while (trace) { + if (trace->data == (void*)cmd) { + trace->removed = 1; + if (!entry->block_trace) remove_trace(entry); return ary_new3(1, cmd); } - trace = next; + trace = trace->next; } } return Qnil; } - VALUE rb_gvar_get(entry) struct global_entry *entry; @@ -589,6 +606,7 @@ trace_en(entry) struct global_entry *entry; { entry->block_trace = 0; + remove_trace(entry); } VALUE @@ -604,7 +622,7 @@ rb_gvar_set(entry, val) } (*entry->setter)(val, entry->id, entry->data, entry); - if (!entry->block_trace) { + if (entry->trace && !entry->block_trace) { entry->block_trace = 1; trace.trace = entry->trace; trace.val = val; @@ -632,6 +650,31 @@ rb_gvar_defined(entry) return TRUE; } +static int +gvar_i(key, entry, ary) + ID key; + struct global_entry *entry; + VALUE ary; +{ + ary_push(ary, str_new2(rb_id2name(entry->id))); + return ST_CONTINUE; +} + +VALUE +f_global_variables() +{ + VALUE ary = ary_new(); + char buf[3]; + char *s = "^&`'+123456789"; + + st_foreach(global_tbl, gvar_i, ary); + while (*s) { + sprintf(buf, "$%c", *s++); + ary_push(ary, str_new2(buf)); + } + return ary; +} + void rb_alias_variable(name1, name2) ID name1; @@ -650,7 +693,7 @@ rb_alias_variable(name1, name2) VALUE rb_ivar_get(obj, id) - struct RObject *obj; + VALUE obj; ID id; { VALUE val; @@ -659,7 +702,7 @@ rb_ivar_get(obj, id) case T_OBJECT: case T_CLASS: case T_MODULE: - if (obj->iv_tbl && st_lookup(obj->iv_tbl, id, &val)) + if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, &val)) return val; return Qnil; default: @@ -673,7 +716,7 @@ rb_ivar_get(obj, id) VALUE rb_ivar_set(obj, id, val) - struct RObject *obj; + VALUE obj; ID id; VALUE val; { @@ -685,8 +728,8 @@ rb_ivar_set(obj, id, val) case T_OBJECT: case T_CLASS: case T_MODULE: - if (!obj->iv_tbl) obj->iv_tbl = new_idhash(); - st_insert(obj->iv_tbl, id, val); + if (!ROBJECT(obj)->iv_tbl) ROBJECT(obj)->iv_tbl = new_idhash(); + st_insert(ROBJECT(obj)->iv_tbl, id, val); break; default: TypeError("class %s can not have instance variables", @@ -698,55 +741,117 @@ rb_ivar_set(obj, id, val) VALUE rb_ivar_defined(obj, id) - struct RObject *obj; + VALUE obj; ID id; { + if (!rb_is_instance_id(id)) return FALSE; + switch (TYPE(obj)) { case T_OBJECT: case T_CLASS: case T_MODULE: - if (obj->iv_tbl && st_lookup(obj->iv_tbl, id, 0)) + if (ROBJECT(obj)->iv_tbl && st_lookup(ROBJECT(obj)->iv_tbl, id, 0)) return TRUE; break; } return FALSE; } +static int +ivar_i(key, value, hash) + ID key; + VALUE value; + VALUE hash; +{ + if (rb_is_instance_id(key)) { + hash_aset(hash, str_new2(rb_id2name(key)), value); + } + return ST_CONTINUE; +} + +VALUE +obj_instance_variables(obj) + VALUE obj; +{ + VALUE hash = hash_new(); + + switch (TYPE(obj)) { + case T_OBJECT: + case T_CLASS: + case T_MODULE: + if (ROBJECT(obj)->iv_tbl) { + st_foreach(ROBJECT(obj)->iv_tbl, ivar_i, hash); + } + break; + default: + break; + } + return hash; +} + +VALUE +obj_remove_instance_variable(obj, name) + VALUE obj, name; +{ + VALUE val; + ID id = rb_to_id(name); + + if (rb_ivar_defined(obj, id)) { + NameError("`%s' is not an instance variable", rb_id2name(id)); + } + + switch (TYPE(obj)) { + case T_OBJECT: + case T_CLASS: + case T_MODULE: + if (ROBJECT(obj)->iv_tbl) { + st_delete(ROBJECT(obj)->iv_tbl, &id, &val); + } + break; + default: + TypeError("object %s can not have instance variables", + rb_class2name(CLASS_OF(obj))); + break; + } + return obj; +} + VALUE -rb_const_get_at(class, id) - struct RClass *class; +rb_const_get_at(cls, id) + VALUE cls; ID id; { VALUE value; - if (class->iv_tbl && st_lookup(class->iv_tbl, id, &value)) { + if (RCLASS(cls)->iv_tbl && st_lookup(RCLASS(cls)->iv_tbl, id, &value)) { return value; } - if ((VALUE)class == cObject) { - return rb_const_get(class, id); + if (cls == cObject) { + return rb_const_get(cls, id); } NameError("Uninitialized constant %s::%s", - RSTRING(rb_class_path(class))->ptr, + RSTRING(rb_class_path(cls))->ptr, rb_id2name(id)); /* not reached */ } + VALUE -rb_const_get(class, id) - struct RClass *class; +rb_const_get(cls, id) + VALUE cls; ID id; { VALUE value; - struct RClass *tmp; + VALUE tmp; - tmp = class; + tmp = cls; while (tmp) { - if (tmp->iv_tbl && st_lookup(tmp->iv_tbl, id, &value)) { + if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) { return value; } - tmp = tmp->super; + tmp = RCLASS(tmp)->super; } - if (BUILTIN_TYPE(class) == T_MODULE) { + if (BUILTIN_TYPE(cls) == T_MODULE) { return rb_const_get(cObject, id); } @@ -762,13 +867,13 @@ rb_const_get(class, id) module = str_new2(modname); free(modname); f_require(0, module); - return rb_const_get(class, id); + return rb_const_get(cls, id); } /* Uninitialized constant */ - if (class && (VALUE)class != cObject) + if (cls && cls != cObject) NameError("Uninitialized constant %s::%s", - RSTRING(rb_class_path(class))->ptr, + RSTRING(rb_class_path(cls))->ptr, rb_id2name(id)); else { NameError("Uninitialized constant %s",rb_id2name(id)); @@ -776,61 +881,81 @@ rb_const_get(class, id) /* not reached */ } -int -const_i(key, value, hash) +static int +const_i(key, value, ary) ID key; VALUE value; - VALUE hash; + VALUE ary; { if (rb_is_const_id(key)) { - hash_aset(hash, str_new2(rb_id2name(key)), value); + VALUE kval = str_new2(rb_id2name(key)); + if (!ary_includes(ary, kval)) { + ary_push(ary, kval); + } } return ST_CONTINUE; } -VALUE -mod_constants(argc, argv, mod) - int argc; - VALUE *argv; - struct RClass *mod; +static int +autoload_i(key, name, ary) + ID key; + char *name; + VALUE ary; { - VALUE option; - VALUE hash; + VALUE kval = str_new2(rb_id2name(key)); + if (!ary_includes(ary, kval)) { + ary_push(ary, kval); + } + return ST_CONTINUE; +} - rb_scan_args(argc, argv, "01", &option); - hash = hash_new(); - st_foreach(mod->iv_tbl, const_i, hash); - if (!FL_TEST(mod, FL_SINGLETON)) { - mod = mod->super; - if (!mod) { - Bug("no superclass for singleton class"); - } - st_foreach(mod->iv_tbl, const_i, hash); +VALUE +mod_const_at(mod, ary) + VALUE mod, ary; +{ + if (RCLASS(mod)->iv_tbl) { + st_foreach(RCLASS(mod)->iv_tbl, const_i, ary); } - if (RTEST(option)) { - for (;;) { - mod = mod->super; - if (!mod) break; - st_foreach(mod->iv_tbl, const_i, hash); - } - st_foreach(class_tbl, const_i, hash); + if ((VALUE)mod == cObject) { + st_foreach(class_tbl, const_i, ary); if (autoload_tbl) { - st_foreach(autoload_tbl, const_i, hash); + st_foreach(autoload_tbl, autoload_i, ary); } } - return hash; + return ary; +} + +VALUE +mod_constants(mod) + VALUE mod; +{ + return mod_const_at(mod, ary_new()); +} + +VALUE +mod_const_of(mod, ary) + VALUE mod; + VALUE ary; +{ + mod_const_at(mod, ary); + for (;;) { + mod = RCLASS(mod)->super; + if (!mod) break; + mod_const_at(mod, ary); + } + return ary; } int -rb_const_defined_at(class, id) - struct RClass *class; +rb_const_defined_at(cls, id) + VALUE cls; ID id; { - if (class->iv_tbl && st_lookup(class->iv_tbl, id, 0)) { + if (RCLASS(cls)->iv_tbl && st_lookup(RCLASS(cls)->iv_tbl, id, 0)) { return TRUE; } - if ((VALUE)class == cObject) { - return rb_const_defined(class, id); + if (cls == cObject) { + return rb_const_defined(cls, id); } return FALSE; } @@ -845,15 +970,15 @@ rb_autoload_defined(id) } int -rb_const_defined(class, id) - struct RClass *class; +rb_const_defined(cls, id) + VALUE cls; ID id; { - while (class) { - if (class->iv_tbl && st_lookup(class->iv_tbl, id, 0)) { + while (cls) { + if (RCLASS(cls)->iv_tbl && st_lookup(RCLASS(cls)->iv_tbl, id, 0)) { return TRUE; } - class = class->super; + cls = RCLASS(cls)->super; } if (st_lookup(class_tbl, id, 0)) return TRUE; @@ -861,24 +986,24 @@ rb_const_defined(class, id) } void -rb_const_set(class, id, val) - struct RClass *class; +rb_const_set(cls, id, val) + VALUE cls; ID id; VALUE val; { - if (!class->iv_tbl) { - class->iv_tbl = new_idhash(); + if (!RCLASS(cls)->iv_tbl) { + RCLASS(cls)->iv_tbl = new_idhash(); } - else if (st_lookup(class->iv_tbl, id, 0)) { + else if (st_lookup(RCLASS(cls)->iv_tbl, id, 0)) { NameError("already initialized constant %s", rb_id2name(id)); } - st_insert(class->iv_tbl, id, val); + st_insert(RCLASS(cls)->iv_tbl, id, val); } void -rb_define_const(class, name, val) - VALUE class; +rb_define_const(cls, name, val) + VALUE cls; char *name; VALUE val; { @@ -886,17 +1011,15 @@ rb_define_const(class, name, val) if (!rb_is_const_id(id)) { NameError("wrong constant name %s", name); } - rb_const_set(class, id, val); + rb_const_set(cls, id, val); } -extern VALUE mKernel; - void rb_define_global_const(name, val) char *name; VALUE val; { - rb_define_const(mKernel, name, val); + rb_define_const(cObject, name, val); } VALUE diff --git a/version.c b/version.c index 49bdc7e33e..71f531c963 100644 --- a/version.c +++ b/version.c @@ -25,7 +25,7 @@ Init_version() void show_version() { - fprintf(stderr, "ruby - version %s (%s)\n", RUBY_VERSION, RUBY_PLATFORM); + fprintf(stderr, "ruby %s(%s) [%s]\n", RUBY_VERSION, VERSION_DATE, RUBY_PLATFORM); } void diff --git a/version.h b/version.h index a4aaff6e93..b737876434 100644 --- a/version.h +++ b/version.h @@ -1,2 +1,2 @@ -#define RUBY_VERSION "1.0-971225" -#define VERSION_DATE "97/12/25" +#define RUBY_VERSION "1.1b5" +#define VERSION_DATE "98/01/16" diff --git a/win32/Makefile b/win32/Makefile index 29d2101479..c7e8b8dbec 100644 --- a/win32/Makefile +++ b/win32/Makefile @@ -15,10 +15,10 @@ INSTALL_DATA = $(INSTALL) -m 644 PURIFY = -#CFLAGS = -nologo -DNT=1 -Ox -#LDFLAGS = $(CFLAGS) -Fm -CFLAGS = -nologo -DNT=1 -Zi -MD -LDFLAGS = $(CFLAGS) -Fm -MD +CFLAGS = -nologo -DNT=1 -Ox +LDFLAGS = $(CFLAGS) -Fm +#CFLAGS = -nologo -DNT=1 -Zi -MD +#LDFLAGS = $(CFLAGS) -Fm -MD LIBS = $(EXTLIBS) advapi32.lib wsock32.lib MISSING = crypt.obj setenv.obj alloca.obj nt.obj @@ -29,6 +29,8 @@ bindir = libdir = STACK = 0x200000 +ORGLIBPATH = $(LIB) +#MISCLIBS = win32\sdbm.lib #### End of system configuration section. #### @@ -56,6 +58,7 @@ OBJS = array.obj \ inits.obj \ io.obj \ math.obj \ + marshal.obj \ numeric.obj \ object.obj \ pack.obj \ @@ -77,31 +80,29 @@ OBJS = array.obj \ version.obj \ $(MISSING) -all: miniruby.exe ext/Setup +all: miniruby.exe ext/Setup $(MISCLIBS) cd ext + set LIB=..\..\win32;$(ORGLIBPATH) ..\miniruby .\extmk.rb static +# ..\miniruby .\extmk.rb cd .. miniruby.exe: $(OBJS) $(MAINOBJ) $(EXTOBJS) @echo $(EXTOBJS) @echo $(LIBS) @rm -f miniruby.exe -# $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(LIBS) -o miniruby.exe - $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(LIBS) -o miniruby.exe -link /NOD:LIBC + $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(LIBS) -o miniruby.exe -ruby.exe: $(LIBRUBY) $(MAINOBJ) $(EXTOBJS) ruby.dll - @echo $(EXTOBJS) - @echo $(LIBS) +ruby.exe: $(LIBRUBY) $(MAINOBJ) $(EXTOBJS) rubymw.dll @rm -f ruby.exe # $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBY) $(LIBS) -o ruby.exe -# $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBY) $(LIBS) -o ruby.exe -link /DEF:rubyexe.def /NOD:LIBC - $(CC) $(LDFLAGS) $(MAINOBJ) -o ruby.exe ruby.lib -link /NOD:LIBC /STACK:$(STACK) + $(CC) $(LDFLAGS) $(MAINOBJ) -o ruby.exe rubymw.lib -link /STACK:$(STACK) -ruby.dll: $(LIBRUBY) $(EXTOBJS) - @echo $(EXTOBJS) - @echo $(LIBS) - @rm -f ruby.dll - $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBY) $(LIBS) -o ruby.dll -link /DLL /DEF:ruby.def /NOD:LIBC +rubymw.dll: $(LIBRUBY) $(EXTOBJS) + set LIB=.\win32;$(ORGLIBPATH) + @rm -f rubymw.dll + $(PURIFY) $(CC) $(LDFLAGS) $(MAINOBJ) $(EXTOBJS) $(LIBRUBY) $(LIBS) -o rubymw.dll -link /DLL /DEF:ruby.def + @mv rubymw.map rubydll.map $(LIBRUBY): $(OBJS) lib /OUT:$(LIBRUBY) $(OBJS) @@ -188,6 +189,13 @@ parse.c: parse.y sed -e "s!^extern char \*getenv();!/* & */!" y.tab.c > parse.c @rm y.tab.c +win32\sdbm.lib : win32\sdbm.c win32\sdbm.h + cd win32 + $(CC) $(CFLAGS) $(CPPFLAGS) -DMSDOS -c sdbm.c + lib /OUT:sdbm.lib sdbm.obj + copy sdbm.h ndbm.h + cd .. + # Prevent GNU make v3 from overflowing arg limit on SysV. .NOEXPORT: ### diff --git a/win32/ruby.def b/win32/ruby.def index 44372d2e76..e8ece2ae50 100644 --- a/win32/ruby.def +++ b/win32/ruby.def @@ -1,55 +1,424 @@ -LIBRARY ruby.dll +LIBRARY rubymw.dll CODE LOADONCALL DATA LOADONCALL -DESCRIPTION 'win32 ruby.dll' +DESCRIPTION 'win32 rubymw.dll' EXPORTS +;global objects +;array.c: + cArray +;bignum.c: + cBignum +;eval.c: + cProc +;file.c: + cFile +;hash.c: + cHash +;io.c: + cIO +;numeric.c: + cNumeric + cFloat + cInteger + cFixnum +;object.c + cObject + cModule + cClass + cFixnum + cData +;re.c: + cRegexp +;string.c: + cString + cStruct +; procedures/methods ;missing/nt.c NtInitialize -;eval.c - ruby_init - ruby_options - ruby_run + myfdopen + myaccept + mybind + myconnect + mygetpeername + mygetsockname + mygetsockopt + myioctlsocket + mylisten + myrecv + myrecvfrom + mysend + mysendto + mysetsockopt + myshutdown + mysocket + mygethostbyaddr + mygethostbyname + mygethostname + mygetprotobyname + mygetprotobynumber + mygetservbyname + mygetservbyport +;array.c + memclear + ary_freeze + ary_new2 + ary_new + ary_new3 + ary_new4 + assoc_new + ary_store + ary_push + ary_pop + ary_shift + ary_unshift + ary_entry + ary_each + ary_join + ary_to_s + ary_reverse + ary_sort_bang + ary_sort + ary_delete + ary_delete_at + ary_plus + ary_concat + ary_assoc + ary_rassoc + ary_includes +;bignum.c + big_clone + big_2comp + big_norm + uint2big + int2big + uint2inum + int2inum + str2inum + big2str + big2int + big_to_i + dbl2big + big2dbl + big_to_f + big_plus + big_minus + big_mul + big_pow + big_and + big_or + big_xor + big_lshift + big_rand ;class.c - ;;rb_define_module_function - ;;rb_define_const - ;;rb_define_singleton_method - ;;rb_define_alias - rb_define_alias - rb_define_attr - rb_define_class + class_new + singleton_class_new + singleton_class_clone rb_define_class_id + rb_define_class rb_define_class_under - rb_define_global_function - rb_define_method - rb_define_method_id - rb_define_module - rb_define_module_function + module_new rb_define_module_id + rb_define_module rb_define_module_under + rb_include_module + rb_define_method_id + rb_define_method + rb_undef_method rb_define_private_method + rb_singleton_class rb_define_singleton_method + rb_define_module_function + rb_define_global_function + rb_define_alias + rb_define_attr rb_scan_args -;variable.c - rb_define_const - rb_define_hooked_variable - rb_define_global_const - rb_define_readonly_variable - rb_define_variable - rb_define_virtual_variable -;string.c +; dln.c + dln_load + dln_find_exe + dln_find_file +; enum.c + rb_each + enum_length +; error.c + Error + Error_Append + Warning + Bug + rb_check_type + exc_new + exc_new2 + exc_new3 + Raise + TypeError + ArgError + NameError + IndexError + Fail + rb_notimplement + LoadError + Fatal + rb_sys_fail +;eval.c + rb_clear_cache + rb_add_method + rb_alias + rb_method_boundp + dyna_var_defined + dyna_var_ref + dyna_var_asgn + rb_safe_level + rb_set_safe_level + rb_check_safe_str + rb_secure + ruby_init + ruby_options + ruby_run + rb_eval_string + rb_eval_cmd + rb_trap_eval + rb_test_false_or_nil + rb_respond_to + rb_exit + rb_raise + rb_fatal + rb_interrupt + iterator_p + rb_yield_0 + rb_yield + rb_iterate + rb_rescue + rb_ensure + rb_apply + rb_funcall + rb_funcall2 + rb_backtrace + rb_frame_last_func + f_load + rb_provide + f_require + class_new_instance + rb_extend_object + f_lambda + gc_mark_threads + thread_schedule + thread_wait_fd + thread_fd_writable + thread_wait_for + thread_alone + thread_select + thread_sleep + thread_sleep_forever + thread_create + thread_interrupt +; file.c + file_open + eaccess + file_s_expand_path +; gc.c + xmalloc + xcalloc + xrealloc + gc_s_enable + gc_s_disable + rb_global_variable + rb_newobj + data_object_alloc + gc_mark_locations + gc_mark_maybe + gc_mark + gc_force_recycle + gc_mark_frame + gc_gc +; hash.c + rb_hash + hash_new + hash_aref + hash_aset +; inits.c + rb_call_inits +; io.c + eof_error + io_writable + io_readable + io_write + io_gets_method + io_gets + io_getc + io_ungetc + io_fptr_finalize + io_close + io_binmode + io_mode_flags + rb_fopen + rb_fdopen + io_unbuffered + io_reopen + f_gets + rb_str_setter +; numeric.c + num_zerodiv + num_coerce_bin + float_new + flo_pow + num2int + num2fix + fix2str + fix_to_s + num_upto + fix_upto +; object.c + rb_equal + rb_eql + obj_equal + any_to_s + rb_inspect + obj_is_instance_of + obj_is_kind_of + obj_alloc + rb_to_id + rb_class_of + rb_type + rb_special_const_p + rb_Integer + rb_Float + rb_String + rb_Array +; parse.c + ;;compile_string + ;;compile_file + ;;node_newnode + nodetype + nodeline + id_attrset + rb_intern + rb_id2name + rb_is_const_id + rb_is_instance_id + local_var_append + backref_get + backref_set + lastline_get + lastline_set +; process.c + rb_proc_exec + rb_syswait +; range.c + range_new + range_beg_end +; re.c + str_cicmp + reg_search + reg_nth_defined + reg_nth_match + reg_last_match + reg_match_pre + reg_match_post + reg_match_last + reg_free + reg_new + reg_regcomp + reg_match + reg_match2 + reg_regsub + rb_set_kcode +; ruby.c + rb_require_modules + rb_load_file + ruby_script + ruby_prog_init + ruby_set_argv + ruby_process_options +; signal.c + gc_mark_trap_list + rb_trap_exit + rb_trap_exec +; st.c + st_init_table_with_size + st_init_table + st_init_numtable + st_init_strtable + st_free_table + st_lookup + st_insert + st_add_direct + st_find_or_add + st_copy + st_delete + st_delete_safe + st_foreach +; string.c str_new str_new2 str_new3 str_new4 -;numeric.c - num2int - -;error.c - rb_check_type - Fatal + obj_as_string + str_dup + str_plus + str_times + str_substr + str_modify + str_freeze + str_dup_freezed + str_taint + str_tainted + str_resize + str_cat + str_hash + str_cmp + str_upto + str_inspect + str_split +; struct.c + struct_getmember + struct_define + struct_alloc + struct_new + struct_aref + struct_aset +; time.c + time_new + time_timeval +; util.c + scan_oct + scan_hex + add_suffix +;variable.c + new_idhash + rb_class_path + rb_set_class_path + rb_path2class + rb_name_class + rb_autoload + f_autoload + rb_class2name + rb_global_entry + gc_mark_global_tbl + rb_define_hooked_variable + rb_define_variable + rb_define_readonly_variable + rb_define_virtual_variable + rb_gvar_get + rb_gvar_set + rb_gvar_set2 + rb_gvar_defined + rb_alias_variable + rb_ivar_get + rb_ivar_set + rb_ivar_defined + rb_const_get_at + rb_const_get + mod_constants + rb_const_defined_at + rb_autoload_defined + rb_const_defined + rb_const_set + rb_define_const + rb_define_global_const + rb_iv_get + rb_iv_set +; version.c + show_version + show_copyright -;gc.c - xmalloc - xcalloc -- cgit v1.2.3