summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog47
-rw-r--r--eval.c53
-rw-r--r--intern.h5
-rw-r--r--io.c126
-rw-r--r--marshal.c12
-rw-r--r--node.h2
-rw-r--r--parse.y7
-rw-r--r--regex.c281
-rw-r--r--variable.c90
-rw-r--r--version.h4
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 <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * 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 <eban@ruby-lang.org>
* ext/etc/extconf.rb: use egrep_cpp.
+Tue Jun 5 12:44:59 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * 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 <matz@ruby-lang.org>
+
+ * 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 <wakou@fsinet.or.jp>
* lib/shellwords.rb: don't destroy argument.
+Sat Jun 2 23:23:05 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * regex.c (re_compile_pattern): should push option modifier at the
+ right place.
+
Sat Jun 2 23:05:20 2001 Shugo Maeda <shugo@ruby-lang.org>
* 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