* intern.h: prototypes; rb_const_search, rb_const_search_at,
  rb_const_search_from.

* class.c (rb_define_class, rb_define_module): use
  rb_const_search().

* class.c (rb_define_class_under, rb_define_module_under): use
  rb_const_search_at().

* eval.c (rb_eval): ditto.

* parse.y (yycompile): ditto.

* variable.c (Init_var_tables): default table size is too small.

* variable.c (autoload_load): internal function, load autoloaded
  symbol but no exception.

* variable.c (rb_const_search_at, rb_const_search_from,
  rb_const_search): search a constant at the class/class-tree.

* eval.c (is_defined): return "constant" for NODE_COLON3.


Index: class.c
===================================================================
RCS file: /src/ruby/class.c,v
retrieving revision 1.76
diff -u -2 -p -r1.76 class.c
--- class.c	6 Aug 2003 21:50:05 -0000	1.76
+++ class.c	19 Aug 2003 15:31:37 -0000
@@ -197,6 +197,5 @@ rb_define_class(name, super)
 
     id = rb_intern(name);
-    if (rb_const_defined(rb_cObject, id)) {
-	klass = rb_const_get(rb_cObject, id);
+    if (rb_const_search(rb_cObject, id, &klass)) {
 	if (TYPE(klass) != T_CLASS) {
 	    rb_raise(rb_eTypeError, "%s is not a class", name);
@@ -228,6 +227,5 @@ rb_define_class_under(outer, name, super
 
     id = rb_intern(name);
-    if (rb_const_defined_at(outer, id)) {
-	klass = rb_const_get_at(outer, id);
+    if (rb_const_search_at(outer, id, &klass)) {
 	if (TYPE(klass) != T_CLASS) {
 	    rb_raise(rb_eTypeError, "%s is not a class", name);
@@ -284,6 +282,5 @@ rb_define_module(name)
 
     id = rb_intern(name);
-    if (rb_const_defined(rb_cObject, id)) {
-	module = rb_const_get(rb_cObject, id);
+    if (rb_const_search(rb_cObject, id, &module)) {
 	if (TYPE(module) == T_MODULE)
 	    return module;
@@ -306,6 +303,5 @@ rb_define_module_under(outer, name)
 
     id = rb_intern(name);
-    if (rb_const_defined_at(outer, id)) {
-	module = rb_const_get_at(outer, id);
+    if (rb_const_search_at(outer, id, &module)) {
 	if (TYPE(module) == T_MODULE)
 	    return module;
Index: eval.c
===================================================================
RCS file: /src/ruby/eval.c,v
retrieving revision 1.515
diff -u -2 -p -r1.515 eval.c
--- eval.c	14 Aug 2003 17:19:23 -0000	1.515
+++ eval.c	19 Aug 2003 20:15:09 -0000
@@ -2164,4 +2164,10 @@ is_defined(self, node, buf)
 	break;
 
+      case NODE_COLON3:
+	if (!(val = ruby_wrapper)) val = rb_cObject;
+	if (rb_const_defined_at(val, node->nd_mid))
+	    return "constant";
+	break;
+
       case NODE_NTH_REF:
 	if (RTEST(rb_reg_nth_defined(node->nd_nth, MATCH_DATA))) {
@@ -3533,6 +3539,6 @@ rb_eval(self, n)
 	    cbase = class_prefix(self, node->nd_cpath);
 	    cname = node->nd_cpath->nd_mid;
-	    if (rb_const_defined_at(cbase, cname)) {
-		klass = rb_const_get_at(cbase, cname);
+	    if ((*(node->nd_cpath->nd_cval ? rb_const_search_from
+		   : rb_const_search_at))(cbase, cname, &klass)) {
 		if (TYPE(klass) != T_CLASS) {
 		    rb_raise(rb_eTypeError, "%s is not a class",
@@ -3576,6 +3582,6 @@ rb_eval(self, n)
 	    cbase = class_prefix(self, node->nd_cpath);
 	    cname = node->nd_cpath->nd_mid;
-	    if (rb_const_defined_at(cbase, cname)) {
-		module = rb_const_get_at(cbase, cname);
+	    if ((*(node->nd_cpath->nd_cval ? rb_const_search_from
+		   : rb_const_search_at))(cbase, cname, &module)) {
 		if (TYPE(module) != T_MODULE) {
 		    rb_raise(rb_eTypeError, "%s is not a module",
Index: intern.h
===================================================================
RCS file: /src/ruby/intern.h,v
retrieving revision 1.132
diff -u -2 -p -r1.132 intern.h
--- intern.h	6 Aug 2003 21:50:06 -0000	1.132
+++ intern.h	19 Aug 2003 15:31:38 -0000
@@ -457,4 +457,7 @@ VALUE rb_const_list _((void*));
 VALUE rb_mod_constants _((VALUE));
 VALUE rb_mod_remove_const _((VALUE, VALUE));
+VALUE rb_const_search _((VALUE, ID, VALUE*));
+VALUE rb_const_search_at _((VALUE, ID, VALUE*));
+VALUE rb_const_search_from _((VALUE, ID, VALUE*));
 int rb_const_defined _((VALUE, ID));
 int rb_const_defined_at _((VALUE, ID));
Index: parse.y
===================================================================
RCS file: /src/ruby/parse.y,v
retrieving revision 1.284
diff -u -2 -p -r1.284 parse.y
--- parse.y	14 Aug 2003 17:19:23 -0000	1.284
+++ parse.y	19 Aug 2003 19:29:15 -0000
@@ -876,4 +873,5 @@ cpath		: tCOLON3 cname
 		    {
 			$$ = NEW_COLON2(0, $$);
+			$$->nd_cval = 1;
 		    }
 		| primary_value tCOLON2 cname
@@ -2451,5 +2449,5 @@ static char *lex_pend;
 static int
 yyerror(msg)
-    char *msg;
+    const char *msg;
 {
     char *p, *pe, *buf;
@@ -2508,11 +2506,11 @@ yycompile(f, line)
     NODE *node = 0;
     struct RVarmap *vp, *vars = ruby_dyna_vars;
+    VALUE hash;
 
     ruby_in_compile = 1;
     if (!compile_for_eval && rb_safe_level() == 0 &&
-	rb_const_defined(rb_cObject, rb_intern("SCRIPT_LINES__"))) {
-	VALUE hash, fname;
+	rb_const_search(rb_cObject, rb_intern("SCRIPT_LINES__"), &hash)) {
+	VALUE fname;
 
-	hash = rb_const_get(rb_cObject, rb_intern("SCRIPT_LINES__"));
 	if (TYPE(hash) == T_HASH) {
 	    fname = rb_str_new2(f);
Index: variable.c
===================================================================
RCS file: /src/ruby/variable.c,v
retrieving revision 1.100
diff -u -2 -p -r1.100 variable.c
--- variable.c	2 Aug 2003 05:02:43 -0000	1.100
+++ variable.c	19 Aug 2003 19:29:15 -0000
@@ -1097,19 +1097,4 @@ rb_obj_remove_instance_variable(obj, nam
 }
 
-NORETURN(static void uninitialized_constant _((VALUE, ID)));
-static void
-uninitialized_constant(klass, id)
-    VALUE klass;
-    ID id;
-{
-    if (klass && klass != rb_cObject)
-	rb_name_error(id, "uninitialized constant %s::%s",
-		      RSTRING(rb_class_path(klass))->ptr,
-		      rb_id2name(id));
-    else {
-	rb_name_error(id, "uninitialized constant %s", rb_id2name(id));
-    }
-}
-
 static VALUE
 const_missing(klass, id)
@@ -1124,6 +1109,14 @@ rb_mod_const_missing(klass, name)
     VALUE klass, name;
 {
+    ID id = rb_to_id(name);
+    char *n = rb_id2name(id);
+
     ruby_frame = ruby_frame->prev; /* pop frame for "const_missing" */
-    uninitialized_constant(klass, rb_to_id(name));
+    if (klass && klass != rb_cObject)
+	rb_name_error(id, "uninitialized constant %s::%s",
+		      RSTRING(rb_class_path(klass))->ptr, n);
+    else {
+	rb_name_error(id, "uninitialized constant %s", n);
+    }
     return Qnil;		/* not reached */
 }
@@ -1200,6 +1193,6 @@ autoload_delete(mod, id)
 }
 
-void
-rb_autoload_load(klass, id)
+static int
+autoload_load(klass, id)
     VALUE klass;
     ID id;
@@ -1208,12 +1201,19 @@ rb_autoload_load(klass, id)
 
     file = autoload_delete(klass, id);
-    if (NIL_P(file)) {
-	uninitialized_constant(klass, id);
-    }
-    if (rb_provided(RSTRING(file)->ptr)) {
-	uninitialized_constant(klass, id);
-    }
+    if (NIL_P(file)) return Qfalse;
+    if (rb_provided(RSTRING(file)->ptr)) return Qfalse;
     FL_UNSET(file, FL_TAINT);
     rb_f_require(Qnil, file);
+    return Qtrue;
+}
+
+void
+rb_autoload_load(klass, id)
+    VALUE klass;
+    ID id;
+{
+    if (!autoload_load(klass, id)) {
+	const_missing(klass, id);
+    }
 }
 
@@ -1266,7 +1266,8 @@ rb_autoload_p(mod, id)
 
 VALUE
-rb_const_get_at(klass, id)
+rb_const_search_at(klass, id, valuep)
     VALUE klass;
     ID id;
+    VALUE *valuep;
 {
     VALUE value;
@@ -1274,44 +1275,70 @@ rb_const_get_at(klass, id)
     while (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &value)) {
 	if (value == Qundef) {
-	    rb_autoload_load(klass, id);
+	    if (!autoload_load(klass, id)) break;
 	    continue;
 	}
-	return value;
+	if (valuep) *valuep = value;
+	return klass;
     }
-    return const_missing(klass, id);
+    return 0;
 }
 
-static VALUE
-rb_const_get_0(klass, id, exclude)
+VALUE
+rb_const_search_from(klass, id, valuep)
     VALUE klass;
     ID id;
-    int exclude;
+    VALUE *valuep;
 {
-    VALUE value, tmp;
-    int mod_retry = 0;
+    VALUE tmp = klass;
 
-    tmp = klass;
-  retry:
     while (tmp) {
-	while (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl,id,&value)) {
-	    if (value == Qundef) {
-		rb_autoload_load(tmp, id);
-		continue;
-	    }
-	    if (exclude && tmp == rb_cObject && klass != rb_cObject) {
+	if (rb_const_search_at(tmp, id, valuep)) {
+	  found:
+	    if (tmp == rb_cObject && klass != rb_cObject) {
+		char *name = rb_id2name(id);
 		rb_warn("toplevel constant %s referenced by %s::%s",
-			rb_id2name(id), rb_class2name(klass), rb_id2name(id));
+			name, rb_class2name(klass), name);
 	    }
-	    return value;
+	    return tmp;
 	}
 	tmp = RCLASS(tmp)->super;
     }
-    if (!mod_retry && BUILTIN_TYPE(klass) == T_MODULE) {
-	mod_retry = 1;
-	tmp = rb_cObject;
-	goto retry;
+    if (BUILTIN_TYPE(klass) == T_MODULE) {
+	for (tmp = rb_cObject; tmp; tmp = RCLASS(tmp)->super) {
+	    if (rb_const_search_at(tmp, id, valuep)) goto found;
+	}
+    }
+    return 0;
+}
+
+VALUE
+rb_const_search(klass, id, valuep)
+    VALUE klass;
+    ID id;
+    VALUE *valuep;
+{
+    VALUE tmp;
+
+    for (tmp = klass; tmp; tmp = RCLASS(tmp)->super) {
+	if (rb_const_search_at(tmp, id, valuep)) return tmp;
+    }
+    if (BUILTIN_TYPE(klass) == T_MODULE) {
+	for (tmp = rb_cObject; tmp; tmp = RCLASS(tmp)->super) {
+	    if (rb_const_search_at(tmp, id, valuep)) return tmp;
+	}
     }
+    return 0;
+}
 
-    return const_missing(klass, id);
+VALUE
+rb_const_get_at(klass, id)
+    VALUE klass;
+    ID id;
+{
+    VALUE value;
+
+    if (!rb_const_search_at(klass, id, &value))
+	return const_missing(klass, id);
+    return value;
 }
 
@@ -1321,5 +1348,10 @@ rb_const_get_from(klass, id)
     ID id;
 {
-    return rb_const_get_0(klass, id, Qtrue);
+    VALUE value;
+
+    if (!rb_const_search_from(klass, id, &value)) {
+	return const_missing(klass, id);
+    }
+    return value;
 }
 
@@ -1329,5 +1361,10 @@ rb_const_get(klass, id)
     ID id;
 {
-    return rb_const_get_0(klass, id, Qfalse);
+    VALUE value;
+
+    if (!rb_const_search(klass, id, &value)) {
+	return const_missing(klass, id);
+    }
+    return value;
 }
 
@@ -1444,13 +1481,7 @@ rb_const_defined_at(klass, id)
     VALUE value;
 
-    if (RCLASS(klass)->iv_tbl && st_lookup(RCLASS(klass)->iv_tbl, id, &value)) {
-	if (value == Qundef && NIL_P(autoload_file(klass, id)))
-	    return Qfalse;
-	return Qtrue;
-    }
-    if (klass == rb_cObject) {
-	return rb_const_defined(klass, id);
-    }
-    return Qfalse;
+    if (!rb_const_search_at(klass, id, &value))
+	return Qfalse;
+    return Qtrue;
 }
 
@@ -1460,18 +1491,10 @@ rb_const_defined_from(klass, id)
     ID id;
 {
-    VALUE tmp = klass, value;
+    VALUE value;
 
-    while (tmp) {
-	if (tmp == rb_cObject && klass != rb_cObject) {
-	    break;
-	}
-	if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl, id, &value)) {
-	    if (value == Qundef && NIL_P(autoload_file(klass, id)))
-		return Qfalse;
-	    return Qtrue;
-	}
-	tmp = RCLASS(tmp)->super;
+    if (!rb_const_search(klass, id, &value)) {
+	return Qfalse;
     }
-    return Qfalse;
+    return Qtrue;
 }
 
@@ -1481,18 +1504,10 @@ rb_const_defined(klass, id)
     ID id;
 {
-    VALUE tmp = klass, value;
+    VALUE value;
 
-    while (tmp) {
-	if (RCLASS(tmp)->iv_tbl && st_lookup(RCLASS(tmp)->iv_tbl, id, &value)) {
-	    if (value == Qundef && NIL_P(autoload_file(klass, id)))
-		return Qfalse;
-	    return Qtrue;
-	}
-	tmp = RCLASS(tmp)->super;
-    }
-    if (BUILTIN_TYPE(klass) == T_MODULE) {
-	return rb_const_defined(rb_cObject, id);
+    if (!rb_const_search(klass, id, &value)) {
+	return Qfalse;
     }
-    return Qfalse;
+    return Qtrue;
 }
 
