From d6c60dbf6d42f411a31a1c2e768a5a986a270a8c Mon Sep 17 00:00:00 2001 From: matz Date: Tue, 5 Jun 2001 07:19:39 +0000 Subject: * variable.c (rb_mod_const_at): use hash table as internal data. [new] * variable.c (rb_mod_const_of): ditto. * variable.c (rb_const_list): new function to convert internal data (hash table) to array of strings. * eval.c (rb_mod_s_constants): data handling scheme has changed. * eval.c (rb_add_method): should not call rb_secure(), for last_func may not be set. * io.c (rb_io_ctl): ioctl should accept any integer within C long range. * marshal.c (r_object): wrong type check for modules. * marshal.c (w_object): should not dump anonymous classes/modules. * io.c (rb_open_file): use rb_file_sysopen_internal() if the 3rd argument (permission flags) is given. [new, should be backported?] * io.c (rb_io_mode_binmode): mode string (e.g. "r+") to flags to open(2). * eval.c (rb_eval): NODE_REXPAND expand an array of 1 element as the element itself. [new, should be backported?] * parse.y (ret_args): should treat "*[a]" in rhs expression as "a", not "[a]". * regex.c (re_compile_pattern): should push option modifier at the right place. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1504 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 47 +++++++++++ eval.c | 53 +++++++++--- intern.h | 5 +- io.c | 126 ++++++++++++++++----------- marshal.c | 12 ++- node.h | 2 + parse.y | 7 +- regex.c | 281 +++++++++++++++++++++++++++++++++---------------------------- variable.c | 90 +++++++++++++------- version.h | 4 +- 10 files changed, 399 insertions(+), 228 deletions(-) diff --git a/ChangeLog b/ChangeLog index b14fc8db7e..0cefc72ce1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,11 +1,58 @@ +Tue Jun 5 16:15:58 2001 Yukihiro Matsumoto + + * variable.c (rb_mod_const_at): use hash table as internal + data. [new] + + * variable.c (rb_mod_const_of): ditto. + + * variable.c (rb_const_list): new function to convert internal + data (hash table) to array of strings. + + * eval.c (rb_mod_s_constants): data handling scheme has changed. + +Tue Jun 5 15:16:06 2001 Yukihiro Matsumoto + + * eval.c (rb_add_method): should not call rb_secure(), for + last_func may not be set. + + * io.c (rb_io_ctl): ioctl should accept any integer within C long + range. + Tue Jun 5 13:41:13 2001 WATANABE Hirofumi * ext/etc/extconf.rb: use egrep_cpp. +Tue Jun 5 12:44:59 2001 Yukihiro Matsumoto + + * marshal.c (r_object): wrong type check for modules. + + * marshal.c (w_object): should not dump anonymous classes/modules. + +Tue Jun 5 01:19:34 2001 Yukihiro Matsumoto + + * io.c (rb_open_file): use rb_file_sysopen_internal() if the 3rd + argument (permission flags) is given. [new, should be backported?] + + * io.c (rb_io_mode_binmode): mode string (e.g. "r+") to flags to + open(2). + +Mon Jun 4 23:55:54 2001 Yukihiro Matsumoto + + * eval.c (rb_eval): NODE_REXPAND expand an array of 1 element as + the element itself. [new, should be backported?] + + * parse.y (ret_args): should treat "*[a]" in rhs expression as + "a", not "[a]". + Mon Jun 4 04:14:53 2001 Wakou Aoyama * lib/shellwords.rb: don't destroy argument. +Sat Jun 2 23:23:05 2001 Yukihiro Matsumoto + + * regex.c (re_compile_pattern): should push option modifier at the + right place. + Sat Jun 2 23:05:20 2001 Shugo Maeda * lib/cgi/session.rb: don't use module_function for Class. diff --git a/eval.c b/eval.c index 1dbd43b2d1..c4d298421c 100644 --- a/eval.c +++ b/eval.c @@ -228,10 +228,7 @@ rb_add_method(klass, mid, node, noex) NODE *body; if (NIL_P(klass)) klass = rb_cObject; - if (klass == rb_cObject) { - rb_secure(4); - } - if (rb_safe_level() >= 4 && !OBJ_TAINTED(klass)) { + if (rb_safe_level() >= 4 && (klass == rb_cObject || !OBJ_TAINTED(klass))) { rb_raise(rb_eSecurityError, "Insecure: can't define method"); } if (OBJ_FROZEN(klass)) rb_error_frozen("class/module"); @@ -1474,15 +1471,19 @@ static VALUE rb_mod_s_constants() { NODE *cbase = RNODE(ruby_frame->cbase); - VALUE ary = rb_ary_new(); + void *data = 0; while (cbase) { - if (!NIL_P(cbase->nd_clss)) rb_mod_const_at(cbase->nd_clss, ary); + if (!NIL_P(cbase->nd_clss)) { + data = rb_mod_const_at(cbase->nd_clss, data); + } cbase = cbase->nd_next; } - if (!NIL_P(ruby_cbase)) rb_mod_const_of(ruby_cbase, ary); - return ary; + if (!NIL_P(ruby_cbase)) { + data = rb_mod_const_of(ruby_cbase, data); + } + return rb_const_list(data); } void @@ -2349,12 +2350,19 @@ rb_eval(self, n) } break; + case NODE_REXPAND: + result = rb_eval(self, node->nd_head); + if (TYPE(result) != T_ARRAY) { + result = rb_Array(result); + } + if (RARRAY(result)->len == 1) { + result = RARRAY(result)->ptr[0]; + } + break; + case NODE_YIELD: if (node->nd_stts) { result = rb_eval(self, node->nd_stts); - if (nd_type(node->nd_stts) == NODE_RESTARGS && RARRAY(result)->len == 1) { - result = RARRAY(result)->ptr[0]; - } } else { result = Qnil; @@ -8602,6 +8610,28 @@ rb_thread_key_p(thread, id) return Qfalse; } +static int +thread_keys_i(key, value, ary) + ID key; + VALUE value, ary; +{ + rb_ary_push(ary, ID2SYM(key)); + return ST_CONTINUE; +} + +static VALUE +rb_thread_keys(thread) + VALUE thread; +{ + rb_thread_t th = rb_thread_check(thread); + VALUE ary = rb_ary_new(); + + if (th->locals) { + st_foreach(th->locals, thread_keys_i, ary); + } + return ary; +} + static VALUE rb_thread_inspect(thread) VALUE thread; @@ -8823,6 +8853,7 @@ Init_Thread() rb_define_method(rb_cThread, "[]", rb_thread_aref, 1); rb_define_method(rb_cThread, "[]=", rb_thread_aset, 2); rb_define_method(rb_cThread, "key?", rb_thread_key_p, 1); + rb_define_method(rb_cThread, "keys", rb_thread_keys, 0); rb_define_method(rb_cThread, "inspect", rb_thread_inspect, 0); diff --git a/intern.h b/intern.h index cf7df058b8..866df5845d 100644 --- a/intern.h +++ b/intern.h @@ -367,9 +367,10 @@ VALUE rb_ivar_set _((VALUE, ID, VALUE)); VALUE rb_ivar_defined _((VALUE, ID)); VALUE rb_obj_instance_variables _((VALUE)); VALUE rb_obj_remove_instance_variable _((VALUE, VALUE)); -VALUE rb_mod_const_at _((VALUE, VALUE)); +void *rb_mod_const_at _((VALUE, void*)); +void *rb_mod_const_of _((VALUE, void*)); +VALUE rb_const_list _((void*)); VALUE rb_mod_constants _((VALUE)); -VALUE rb_mod_const_of _((VALUE, VALUE)); VALUE rb_mod_remove_const _((VALUE, VALUE)); int rb_const_defined_at _((VALUE, ID)); int rb_autoload_defined _((ID)); diff --git a/io.c b/io.c index 3d6dac5c60..3bcf663aad 100644 --- a/io.c +++ b/io.c @@ -1253,8 +1253,9 @@ rb_io_mode_flags(mode) const char *mode; { int flags = 0; + const char *m = mode; - switch (mode[0]) { + switch (*m++) { case 'r': flags |= FMODE_READABLE; break; @@ -1269,22 +1270,22 @@ rb_io_mode_flags(mode) rb_raise(rb_eArgError, "illegal access mode %s", mode); } - if (mode[1] == 'b') { + if (*m == 'b') { flags |= FMODE_BINMODE; - mode++; + m++; } - if (mode[1] == '+') { + if (*m == '+') { flags |= FMODE_READWRITE; - if (mode[2] != 0) goto error; + if (m[1] != 0) goto error; } - else if (mode[1] != 0) goto error; + else if (*m != 0) goto error; return flags; } static int -rb_io_mode_flags2(mode) +rb_io_binmode_flags(mode) int mode; { int flags; @@ -1310,8 +1311,46 @@ rb_io_mode_flags2(mode) return flags; } +int +rb_io_mode_binmode(mode) + const char *mode; +{ + int flags = 0; + const char *m = mode; + + switch (*m++) { + case 'r': + flags |= O_RDONLY; + break; + case 'w': + flags |= O_WRONLY | O_CREAT | O_TRUNC; + break; + case 'a': + flags |= O_WRONLY | O_CREAT | O_APPEND; + break; + default: + error: + rb_raise(rb_eArgError, "illegal access mode %s", mode); + } + + if (*m == 'b') { +#ifdef O_BINARY + flags |= O_BINARY; +#endif + m++; + } + + if (*m == '+') { + flags |= O_RDWR; + if (m[1] != 0) goto error; + } + else if (*m != 0) goto error; + + return flags; +} + static char* -rb_io_flags_mode(flags) +rb_io_modestr(flags) int flags; { static char mode[4]; @@ -1454,8 +1493,8 @@ rb_file_sysopen_internal(io, fname, flags, mode) MakeOpenFile(io, fptr); fd = rb_sysopen(fname, flags, mode); - m = rb_io_flags_mode(flags); - fptr->mode = rb_io_mode_flags2(flags); + m = rb_io_modestr(flags); + fptr->mode = rb_io_binmode_flags(flags); fptr->f = rb_fdopen(fd, m); fptr->path = strdup(fname); @@ -1734,37 +1773,48 @@ rb_io_s_popen(argc, argv, klass) } static VALUE -rb_file_s_open(argc, argv, klass) +rb_open_file(argc, argv, io) int argc; VALUE *argv; - VALUE klass; + VALUE io; { VALUE fname, vmode, file, perm; char *path, *mode; + int flags, fmode; - NEWOBJ(io, struct RFile); - OBJSETUP(io, klass, T_FILE); rb_scan_args(argc, argv, "12", &fname, &vmode, &perm); SafeStringValue(fname); path = RSTRING(fname)->ptr; - RFILE(io)->fptr = 0; - if (FIXNUM_P(vmode)) { - int flags = NUM2INT(vmode); - int fmode = NIL_P(perm) ? 0666 : NUM2INT(perm); - - file = rb_file_sysopen_internal((VALUE)io, path, flags, fmode); + if (FIXNUM_P(vmode) || !NIL_P(perm)) { + flags = FIXNUM_P(vmode) ? NUM2INT(vmode) : rb_io_mode_binmode(StringValuePtr(vmode)); + fmode = NIL_P(perm) ? 0666 : NUM2INT(perm); + + file = rb_file_sysopen_internal(io, path, flags, fmode); } else { mode = NIL_P(vmode) ? "r" : StringValuePtr(vmode); - file = rb_file_open_internal((VALUE)io, RSTRING(fname)->ptr, mode); + file = rb_file_open_internal(io, RSTRING(fname)->ptr, mode); } + return io; +} +static VALUE +rb_file_s_open(argc, argv, klass) + int argc; + VALUE *argv; + VALUE klass; +{ + NEWOBJ(io, struct RFile); + OBJSETUP(io, klass, T_FILE); + RFILE(io)->fptr = 0; + + rb_open_file(argc, argv, (VALUE)io); if (rb_block_given_p()) { - return rb_ensure(rb_yield, file, rb_io_close, file); + return rb_ensure(rb_yield, (VALUE)io, rb_io_close, (VALUE)io); } - return file; + return (VALUE)io; } static VALUE @@ -2395,38 +2445,17 @@ rb_file_initialize(argc, argv, io) VALUE *argv; VALUE io; { - VALUE fname, vmode, file, perm; - char *path, *mode; - - rb_scan_args(argc, argv, "12", &fname, &vmode, &perm); - SafeStringValue(fname); - path = RSTRING(fname)->ptr; - if (RFILE(io)->fptr) { rb_io_close_m(io); free(RFILE(io)->fptr); RFILE(io)->fptr = 0; } - if (FIXNUM_P(vmode)) { - int flags = NUM2INT(vmode); - int fmode = NIL_P(perm) ? 0666 : NUM2INT(perm); - - file = rb_file_sysopen_internal(io, path, flags, fmode); - } - else { - if (NIL_P(vmode)) { - mode = "r"; - } - else { - mode = StringValuePtr(vmode); - } - file = rb_file_open_internal(io, RSTRING(fname)->ptr, mode); - } + rb_open_file(argc, argv, io); if (rb_block_given_p()) { rb_warn("File::new() does not take block; use File::open() instead"); } - return file; + return io; } static VALUE @@ -2852,7 +2881,7 @@ rb_f_select(argc, argv, obj) #if !defined(MSDOS) && !defined(__human68k__) static int -io_cntl(fd,cmd,narg,io_p) +io_cntl(fd, cmd, narg, io_p) int fd, cmd, io_p; long narg; { @@ -2902,6 +2931,9 @@ rb_io_ctl(io, req, arg, io_p) else if (arg == Qtrue) { narg = 1; } + else if (rb_obj_is_kind_of(arg, rb_cInteger)) { + narg = NUM2LONG(arg); + } else { StringValue(arg); diff --git a/marshal.c b/marshal.c index 8bb8d2c984..29620125dd 100644 --- a/marshal.c +++ b/marshal.c @@ -52,7 +52,7 @@ shortlen(len, ds) #endif #define MARSHAL_MAJOR 4 -#define MARSHAL_MINOR 5 +#define MARSHAL_MINOR 6 #define TYPE_NIL '0' #define TYPE_TRUE 'T' @@ -348,6 +348,10 @@ w_object(obj, arg, limit) w_byte(TYPE_CLASS, arg); { VALUE path = rb_class_path(obj); + if (RSTRING(path)->ptr[0] == '#') { + rb_raise(rb_eArgError, "can't dump anonymous class %s", + RSTRING(path)->ptr); + } w_bytes(RSTRING(path)->ptr, RSTRING(path)->len, arg); } break; @@ -356,6 +360,10 @@ w_object(obj, arg, limit) w_byte(TYPE_MODULE, arg); { VALUE path = rb_class_path(obj); + if (RSTRING(path)->ptr[0] == '#') { + rb_raise(rb_eArgError, "can't dump anonymous module %s", + RSTRING(path)->ptr); + } w_bytes(RSTRING(path)->ptr, RSTRING(path)->len, arg); } break; @@ -991,7 +999,7 @@ r_object(arg) char *buf; r_bytes(buf, arg); m = rb_path2class(buf); - if (TYPE(m) != T_CLASS) { + if (TYPE(m) != T_MODULE) { rb_raise(rb_eTypeError, "%s is not a module", buf); } return r_regist(m, arg); diff --git a/node.h b/node.h index 671dbeb520..98f4f0659d 100644 --- a/node.h +++ b/node.h @@ -89,6 +89,7 @@ enum node_type { NODE_ARGSCAT, NODE_ARGSPUSH, NODE_RESTARGS, + NODE_REXPAND, NODE_BLOCK_ARG, NODE_BLOCK_PASS, NODE_DEFN, @@ -304,6 +305,7 @@ typedef struct RNode { #define NEW_ARGSCAT(a,b) rb_node_newnode(NODE_ARGSCAT,a,b,0) #define NEW_ARGSPUSH(a,b) rb_node_newnode(NODE_ARGSPUSH,a,b,0) #define NEW_RESTARGS(a) rb_node_newnode(NODE_RESTARGS,a,0,0) +#define NEW_REXPAND(a) rb_node_newnode(NODE_REXPAND,a,0,0) #define NEW_BLOCK_ARG(v) rb_node_newnode(NODE_BLOCK_ARG,v,0,local_cnt(v)) #define NEW_BLOCK_PASS(b) rb_node_newnode(NODE_BLOCK_PASS,0,b,0) #define NEW_ALIAS(n,o) rb_node_newnode(NODE_ALIAS,o,n,0) diff --git a/parse.y b/parse.y index e436153945..ed97518650 100644 --- a/parse.y +++ b/parse.y @@ -425,7 +425,7 @@ stmt : kALIAS fitem {lex_state = EXPR_FNAME;} fitem } | lhs '=' mrhs_basic { - $$ = node_assign($1, $3); + $$ = node_assign($1, ret_args($3)); } | mlhs '=' mrhs { @@ -1146,7 +1146,7 @@ mrhs_basic : args ',' arg | tSTAR arg { value_expr($2); - $$ = $2; + $$ = NEW_RESTARGS($2); } primary : literal @@ -4671,6 +4671,9 @@ ret_args(node) rb_compile_error("block argument should not be given"); } } + if (nd_type(node) == NODE_RESTARGS) { + nd_set_type(node, NODE_REXPAND); + } return node; } diff --git a/regex.c b/regex.c index bd2d613e03..2ebaa4c1ff 100644 --- a/regex.c +++ b/regex.c @@ -543,7 +543,7 @@ print_mbc(c) reset the pointers that pointed into the old allocation to point to the correct places in the new allocation. If extending the buffer results in it being larger than 1 << 16, then flag memory exhausted. */ -#define EXTEND_BUFFER \ +#define EXTEND_BUFFER \ do { char *old_buffer = bufp->buffer; \ if (bufp->allocated == (1L<<16)) goto too_big; \ bufp->allocated *= 2; \ @@ -1260,7 +1260,6 @@ re_compile_pattern(pattern, size, bufp) int had_char_class = 0; int options = bufp->options; - int old_options = 0; bufp->fastmap_accurate = 0; bufp->must = 0; @@ -1683,167 +1682,182 @@ re_compile_pattern(pattern, size, bufp) break; case '(': - old_options = options; - PATFETCH(c); - if (c == '?') { - int negative = 0; + { + int old_options = options; int push_option = 0; - PATFETCH_RAW(c); - switch (c) { - case 'x': case 'p': case 'm': case 'i': case '-': - for (;;) { - switch (c) { - case '-': - negative = 1; - break; - - case ':': - case ')': - break; + int casefold = 0; - case 'x': - if (negative) - options &= ~RE_OPTION_EXTENDED; - else - options |= RE_OPTION_EXTENDED; - break; + PATFETCH(c); + if (c == '?') { + int negative = 0; - case 'p': - if (negative) { - if ((options&RE_OPTION_POSIXLINE) == RE_OPTION_POSIXLINE) { - options &= ~RE_OPTION_POSIXLINE; + PATFETCH_RAW(c); + switch (c) { + case 'x': case 'p': case 'm': case 'i': case '-': + for (;;) { + switch (c) { + case '-': + negative = 1; + break; + + case ':': + case ')': + break; + + case 'x': + if (negative) + options &= ~RE_OPTION_EXTENDED; + else + options |= RE_OPTION_EXTENDED; + break; + + case 'p': + if (negative) { + if ((options&RE_OPTION_POSIXLINE) == RE_OPTION_POSIXLINE) { + options &= ~RE_OPTION_POSIXLINE; + } } - } - else if ((options&RE_OPTION_POSIXLINE) != RE_OPTION_POSIXLINE) { - options |= RE_OPTION_POSIXLINE; - } - push_option = 1; - break; - - case 'm': - if (negative) { - if (options&RE_OPTION_MULTILINE) { - options &= ~RE_OPTION_MULTILINE; + else if ((options&RE_OPTION_POSIXLINE) != RE_OPTION_POSIXLINE) { + options |= RE_OPTION_POSIXLINE; } - } - else if (!(options&RE_OPTION_MULTILINE)) { - options |= RE_OPTION_MULTILINE; - } - push_option = 1; - break; - - case 'i': - if (negative) { - if (options&RE_OPTION_IGNORECASE) { - options &= ~RE_OPTION_IGNORECASE; - BUFPUSH(casefold_off); + push_option = 1; + break; + + case 'm': + if (negative) { + if (options&RE_OPTION_MULTILINE) { + options &= ~RE_OPTION_MULTILINE; + } + } + else if (!(options&RE_OPTION_MULTILINE)) { + options |= RE_OPTION_MULTILINE; + } + push_option = 1; + break; + + case 'i': + if (negative) { + if (options&RE_OPTION_IGNORECASE) { + options &= ~RE_OPTION_IGNORECASE; + } } + else if (!(options&RE_OPTION_IGNORECASE)) { + options |= RE_OPTION_IGNORECASE; + } + casefold = 1; + break; + + default: + FREE_AND_RETURN(stackb, "undefined (?...) inline option"); } - else if (!(options&RE_OPTION_IGNORECASE)) { - options |= RE_OPTION_IGNORECASE; - BUFPUSH(casefold_on); + if (c == ')') { + c = '#'; /* read whole in-line options */ + break; } - break; - - default: - FREE_AND_RETURN(stackb, "undefined (?...) inline option"); + if (c == ':') break; + PATFETCH_RAW(c); } - if (c == ')') { - c = '#'; /* read whole in-line options */ - break; + break; + + case '#': + for (;;) { + PATFETCH(c); + if (c == ')') break; } - if (c == ':') break; - PATFETCH_RAW(c); + c = '#'; + break; + + case ':': + case '=': + case '!': + case '>': + break; + + default: + FREE_AND_RETURN(stackb, "undefined (?...) sequence"); + } + } + else { + PATUNFETCH; + c = '('; + } + if (c == '#') { + if (push_option) { + BUFPUSH(option_set); + BUFPUSH(options); + } + if (casefold) { + if (options & RE_OPTION_IGNORECASE) + BUFPUSH(casefold_on); + else + BUFPUSH(casefold_off); } break; + } + if (stackp+8 >= stacke) { + DOUBLE_STACK(int); + } - case '#': - for (;;) { - PATFETCH(c); - if (c == ')') break; - } - 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_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0; + *stackp++ = begalt - bufp->buffer; + switch (c) { + case '(': + BUFPUSH(start_memory); + BUFPUSH(regnum); + *stackp++ = regnum++; + *stackp++ = b - bufp->buffer; + BUFPUSH(0); + /* too many ()'s to fit in a byte. (max 254) */ + if (regnum >= RE_REG_MAX) goto too_big; break; - case ':': case '=': 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 ':': + BUFPUSH(start_paren); + pending_exact = 0; default: - FREE_AND_RETURN(stackb, "undefined (?...) sequence"); + break; } if (push_option) { BUFPUSH(option_set); BUFPUSH(options); } + if (casefold) { + if (options & RE_OPTION_IGNORECASE) + BUFPUSH(casefold_on); + else + BUFPUSH(casefold_off); + } + *stackp++ = c; + *stackp++ = old_options; + fixup_alt_jump = 0; + laststart = 0; + begalt = b; } - else { - PATUNFETCH; - c = '('; - } - if (c == '#') break; - if (stackp+8 >= stacke) { - DOUBLE_STACK(int); - } - - /* 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_alt_jump ? fixup_alt_jump - bufp->buffer + 1 : 0; - *stackp++ = begalt - bufp->buffer; - switch (c) { - case '(': - BUFPUSH(start_memory); - BUFPUSH(regnum); - *stackp++ = regnum++; - *stackp++ = b - bufp->buffer; - BUFPUSH(0); - /* too many ()'s to fit in a byte. (max 254) */ - if (regnum >= RE_REG_MAX) goto too_big; - break; - - case '=': - 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 ':': - BUFPUSH(start_paren); - pending_exact = 0; - default: - break; - } - *stackp++ = c; - *stackp++ = old_options; - fixup_alt_jump = 0; - laststart = 0; - begalt = b; break; case ')': if (stackp == stackb) FREE_AND_RETURN(stackb, "unmatched )"); - if (options != stackp[-1]) { - if ((options ^ stackp[-1]) & RE_OPTION_IGNORECASE) { - BUFPUSH((options&RE_OPTION_IGNORECASE)?casefold_off:casefold_on); - } - BUFPUSH(option_set); - BUFPUSH(stackp[-1]); - } pending_exact = 0; if (fixup_alt_jump) { /* Push a dummy failure point at the end of the @@ -1856,6 +1870,13 @@ re_compile_pattern(pattern, size, bufp) to `fixup_alt_jump', in the `handle_alt' case below. */ store_jump(fixup_alt_jump, jump, b); } + if (options != stackp[-1]) { + if ((options ^ stackp[-1]) & RE_OPTION_IGNORECASE) { + BUFPUSH((options&RE_OPTION_IGNORECASE)?casefold_off:casefold_on); + } + BUFPUSH(option_set); + BUFPUSH(stackp[-1]); + } p0 = b; options = *--stackp; switch (c = *--stackp) { diff --git a/variable.c b/variable.c index fe0272d21e..f0ae3bfe22 100644 --- a/variable.c +++ b/variable.c @@ -1092,21 +1092,6 @@ rb_const_get(klass, id) return Qnil; /* not reached */ } -static int -sv_i(key, value, ary) - ID key; - VALUE value; - VALUE ary; -{ - if (rb_is_const_id(key)) { - VALUE kval = rb_str_new2(rb_id2name(key)); - if (!rb_ary_includes(ary, kval)) { - rb_ary_push(ary, kval); - } - } - return ST_CONTINUE; -} - VALUE rb_mod_remove_const(mod, name) VALUE mod, name; @@ -1134,44 +1119,85 @@ rb_mod_remove_const(mod, name) } static int -autoload_i(key, name, ary) +sv_i(key, value, tbl) + ID key; + VALUE value; + st_table *tbl; +{ + if (rb_is_const_id(key)) { + if (!st_lookup(tbl, key, 0)) { + st_insert(tbl, key, key); + } + } + return ST_CONTINUE; +} + +static int +autoload_i(key, name, tbl) ID key; const char *name; - VALUE ary; + st_table *tbl; { - VALUE kval = rb_str_new2(rb_id2name(key)); - if (!rb_ary_includes(ary, kval)) { - rb_ary_push(ary, kval); + if (!st_lookup(tbl, key, 0)) { + st_insert(tbl, key, key); } return ST_CONTINUE; } -VALUE -rb_mod_const_at(mod, ary) - VALUE mod, ary; +void* +rb_mod_const_at(mod, data) + VALUE mod; + void *data; { + st_table *tbl = data; + if (!tbl) { + tbl = st_init_numtable(); + } if (RCLASS(mod)->iv_tbl) { - st_foreach(RCLASS(mod)->iv_tbl, sv_i, ary); + st_foreach(RCLASS(mod)->iv_tbl, sv_i, tbl); } if ((VALUE)mod == rb_cObject) { - st_foreach(rb_class_tbl, sv_i, ary); + st_foreach(rb_class_tbl, sv_i, tbl); if (autoload_tbl) { - st_foreach(autoload_tbl, autoload_i, ary); + st_foreach(autoload_tbl, autoload_i, tbl); } } - return ary; + return tbl; } -VALUE -rb_mod_const_of(mod, ary) +void* +rb_mod_const_of(mod, data) VALUE mod; - VALUE ary; + void *data; { for (;;) { - rb_mod_const_at(mod, ary); + data = rb_mod_const_at(mod, data); mod = RCLASS(mod)->super; if (!mod) break; } + return data; +} + +static int +list_i(key, value, ary) + ID key, value; + VALUE ary; +{ + rb_ary_push(ary, rb_str_new2(rb_id2name(key))); + return ST_CONTINUE; +} + +VALUE +rb_const_list(data) + void *data; +{ + st_table *tbl = data; + VALUE ary; + + if (!tbl) return rb_ary_new2(0); + ary = rb_ary_new2(tbl->num_entries); + st_foreach(tbl, list_i, ary); + return ary; } @@ -1179,7 +1205,7 @@ VALUE rb_mod_constants(mod) VALUE mod; { - return rb_mod_const_of(mod, rb_ary_new()); + return rb_const_list(rb_mod_const_of(mod, 0)); } int diff --git a/version.h b/version.h index d9aa8ed816..1a0d374dd0 100644 --- a/version.h +++ b/version.h @@ -1,4 +1,4 @@ #define RUBY_VERSION "1.7.1" -#define RUBY_RELEASE_DATE "2001-06-01" +#define RUBY_RELEASE_DATE "2001-06-05" #define RUBY_VERSION_CODE 171 -#define RUBY_RELEASE_CODE 20010601 +#define RUBY_RELEASE_CODE 20010605 -- cgit v1.2.3