#include "ruby/ruby.h"
#include "ruby/st.h"
#include "ruby/util.h"
#include "ruby/encoding.h"
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <math.h>
#include <float.h>
#include "constant.h"
#include "internal.h"
#include "probes.h"
VALUE rb_cBasicObject;
VALUE rb_mKernel;
VALUE rb_cObject;
VALUE rb_cModule;
VALUE rb_cClass;
VALUE rb_cData;
VALUE rb_cNilClass;
VALUE rb_cTrueClass;
VALUE rb_cFalseClass;
static ID id_eq, id_eql, id_match, id_inspect;
static ID id_init_copy, id_init_clone, id_init_dup;
static ID id_const_missing;
#define CLASS_OR_MODULE_P(obj) \
(!SPECIAL_CONST_P(obj) && \
(BUILTIN_TYPE(obj) == T_CLASS || BUILTIN_TYPE(obj) == T_MODULE))
VALUE
rb_equal(VALUE obj1, VALUE obj2)
{
VALUE result;
if (obj1 == obj2) return Qtrue;
result = rb_funcall(obj1, id_eq, 1, obj2);
if (RTEST(result)) return Qtrue;
return Qfalse;
}
int
rb_eql(VALUE obj1, VALUE obj2)
{
return RTEST(rb_funcall(obj1, id_eql, 1, obj2));
}
VALUE
rb_obj_equal(VALUE obj1, VALUE obj2)
{
if (obj1 == obj2) return Qtrue;
return Qfalse;
}
VALUE
rb_obj_hash(VALUE obj)
{
VALUE oid = rb_obj_id(obj);
#if SIZEOF_LONG == SIZEOF_VOIDP
st_index_t index = NUM2LONG(oid);
#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP
st_index_t index = NUM2LL(oid);
#else
# error not supported
#endif
st_index_t h = rb_hash_end(rb_hash_start(index));
return LONG2FIX(h);
}
VALUE
rb_obj_not(VALUE obj)
{
return RTEST(obj) ? Qfalse : Qtrue;
}
VALUE
rb_obj_not_equal(VALUE obj1, VALUE obj2)
{
VALUE result = rb_funcall(obj1, id_eq, 1, obj2);
return RTEST(result) ? Qfalse : Qtrue;
}
VALUE
rb_class_real(VALUE cl)
{
if (cl == 0)
return 0;
while ((RBASIC(cl)->flags & FL_SINGLETON) || BUILTIN_TYPE(cl) == T_ICLASS) {
cl = RCLASS_SUPER(cl);
}
return cl;
}
VALUE
rb_obj_class(VALUE obj)
{
return rb_class_real(CLASS_OF(obj));
}
static VALUE
rb_obj_singleton_class(VALUE obj)
{
return rb_singleton_class(obj);
}
void
rb_obj_copy_ivar(VALUE dest, VALUE obj)
{
if (!(RBASIC(dest)->flags & ROBJECT_EMBED) && ROBJECT_IVPTR(dest)) {
xfree(ROBJECT_IVPTR(dest));
ROBJECT(dest)->as.heap.ivptr = 0;
ROBJECT(dest)->as.heap.numiv = 0;
ROBJECT(dest)->as.heap.iv_index_tbl = 0;
}
if (RBASIC(obj)->flags & ROBJECT_EMBED) {
MEMCPY(ROBJECT(dest)->as.ary, ROBJECT(obj)->as.ary, VALUE, ROBJECT_EMBED_LEN_MAX);
RBASIC(dest)->flags |= ROBJECT_EMBED;
}
else {
long len = ROBJECT(obj)->as.heap.numiv;
VALUE *ptr = 0;
if (len > 0) {
ptr = ALLOC_N(VALUE, len);
MEMCPY(ptr, ROBJECT(obj)->as.heap.ivptr, VALUE, len);
}
ROBJECT(dest)->as.heap.ivptr = ptr;
ROBJECT(dest)->as.heap.numiv = len;
ROBJECT(dest)->as.heap.iv_index_tbl = ROBJECT(obj)->as.heap.iv_index_tbl;
RBASIC(dest)->flags &= ~ROBJECT_EMBED;
}
}
static void
init_copy(VALUE dest, VALUE obj)
{
if (OBJ_FROZEN(dest)) {
rb_raise(rb_eTypeError, "[bug] frozen object (%s) allocated", rb_obj_classname(dest));
}
RBASIC(dest)->flags &= ~(T_MASK|FL_EXIVAR);
RBASIC(dest)->flags |= RBASIC(obj)->flags & (T_MASK|FL_EXIVAR|FL_TAINT|FL_UNTRUSTED);
rb_copy_generic_ivar(dest, obj);
rb_gc_copy_finalizer(dest, obj);
switch (TYPE(obj)) {
case T_OBJECT:
rb_obj_copy_ivar(dest, obj);
break;
case T_CLASS:
case T_MODULE:
if (RCLASS_IV_TBL(dest)) {
st_free_table(RCLASS_IV_TBL(dest));
RCLASS_IV_TBL(dest) = 0;
}
if (RCLASS_CONST_TBL(dest)) {
rb_free_const_table(RCLASS_CONST_TBL(dest));
RCLASS_CONST_TBL(dest) = 0;
}
if (RCLASS_IV_TBL(obj)) {
RCLASS_IV_TBL(dest) = st_copy(RCLASS_IV_TBL(obj));
}
break;
}
}
VALUE
rb_obj_clone(VALUE obj)
{
VALUE clone;
VALUE singleton;
if (rb_special_const_p(obj)) {
rb_raise(rb_eTypeError, "can't clone %s", rb_obj_classname(obj));
}
clone = rb_obj_alloc(rb_obj_class(obj));
singleton = rb_singleton_class_clone_and_attach(obj, clone);
RBASIC(clone)->klass = singleton;
if (FL_TEST(singleton, FL_SINGLETON)) {
rb_singleton_class_attached(singleton, clone);
}
RBASIC(clone)->flags &= (FL_TAINT|FL_UNTRUSTED);
RBASIC(clone)->flags |= RBASIC(obj)->flags & ~(FL_FREEZE|FL_FINALIZE);
init_copy(clone, obj);
rb_funcall(clone, id_init_clone, 1, obj);
RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
return clone;
}
VALUE
rb_obj_dup(VALUE obj)
{
VALUE dup;
if (rb_special_const_p(obj)) {
rb_raise(rb_eTypeError, "can't dup %s", rb_obj_classname(obj));
}
dup = rb_obj_alloc(rb_obj_class(obj));
init_copy(dup, obj);
rb_funcall(dup, id_init_dup, 1, obj);
return dup;
}
VALUE
rb_obj_init_copy(VALUE obj, VALUE orig)
{
if (obj == orig) return obj;
rb_check_frozen(obj);
rb_check_trusted(obj);
if (TYPE(obj) != TYPE(orig) || rb_obj_class(obj) != rb_obj_class(orig)) {
rb_raise(rb_eTypeError, "initialize_copy should take same class object");
}
return obj;
}
VALUE
rb_obj_init_dup_clone(VALUE obj, VALUE orig)
{
rb_funcall(obj, id_init_copy, 1, orig);
return obj;
}
VALUE
rb_any_to_s(VALUE obj)
{
VALUE str;
VALUE cname = rb_class_name(CLASS_OF(obj));
str = rb_sprintf("#<%"PRIsVALUE":%p>", cname, (void*)obj);
OBJ_INFECT(str, obj);
return str;
}
VALUE
rb_inspect(VALUE obj)
{
VALUE str = rb_obj_as_string(rb_funcall(obj, id_inspect, 0, 0));
rb_encoding *ext = rb_default_external_encoding();
if (!rb_enc_asciicompat(ext)) {
if (!rb_enc_str_asciionly_p(str))
rb_raise(rb_eEncCompatError, "inspected result must be ASCII only if default external encoding is ASCII incompatible");
return str;
}
if (rb_enc_get(str) != ext && !rb_enc_str_asciionly_p(str))
rb_raise(rb_eEncCompatError, "inspected result must be ASCII only or use the same encoding with default external");
return str;
}
static int
inspect_i(st_data_t k, st_data_t v, st_data_t a)
{
ID id = (ID)k;
VALUE value = (VALUE)v;
VALUE str = (VALUE)a;
VALUE str2;
const char *ivname;
if (CLASS_OF(value) == 0) return ST_CONTINUE;
if (!rb_is_instance_id(id)) return ST_CONTINUE;
if (RSTRING_PTR(str)[0] == '-') {
RSTRING_PTR(str)[0] = '#';
rb_str_cat2(str, " ");
}
else {
rb_str_cat2(str, ", ");
}
ivname = rb_id2name(id);
rb_str_cat2(str, ivname);
rb_str_cat2(str, "=");
str2 = rb_inspect(value);
rb_str_append(str, str2);
OBJ_INFECT(str, str2);
return ST_CONTINUE;
}
static VALUE
inspect_obj(VALUE obj, VALUE str, int recur)
{
if (recur) {
rb_str_cat2(str, " ...");
}
else {
rb_ivar_foreach(obj, inspect_i, str);
}
rb_str_cat2(str, ">");
RSTRING_PTR(str)[0] = '#';
OBJ_INFECT(str, obj);
return str;
}
static VALUE
rb_obj_inspect(VALUE obj)
{
if (rb_ivar_count(obj) > 0) {
VALUE str;
VALUE c = rb_class_name(CLASS_OF(obj));
str = rb_sprintf("-<%"PRIsVALUE":%p", c, (void*)obj);
return rb_exec_recursive(inspect_obj, obj, str);
}
else {
return rb_any_to_s(obj);
}
}
static VALUE
class_or_module_required(VALUE c)
{
if (SPECIAL_CONST_P(c)) goto not_class;
switch (BUILTIN_TYPE(c)) {
case T_MODULE:
case T_CLASS:
case T_ICLASS:
break;
default:
not_class:
rb_raise(rb_eTypeError, "class or module required");
}
return c;
}
static VALUE class_search_ancestor(VALUE cl, VALUE c);
VALUE
rb_obj_is_instance_of(VALUE obj, VALUE c)
{
c = class_or_module_required(c);
if (rb_obj_class(obj) == c) return Qtrue;
return Qfalse;
}
VALUE
rb_obj_is_kind_of(VALUE obj, VALUE c)
{
VALUE cl = CLASS_OF(obj);
c = class_or_module_required(c);
return class_search_ancestor(cl, RCLASS_ORIGIN(c)) ? Qtrue : Qfalse;
}
static VALUE
class_search_ancestor(VALUE cl, VALUE c)
{
while (cl) {
if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c))
return cl;
cl = RCLASS_SUPER(cl);
}
return 0;
}
VALUE
rb_class_search_ancestor(VALUE cl, VALUE c)
{
cl = class_or_module_required(cl);
c = class_or_module_required(c);
return class_search_ancestor(cl, RCLASS_ORIGIN(c));
}
VALUE
rb_obj_tap(VALUE obj)
{
rb_yield(obj);
return obj;
}
static VALUE
rb_obj_dummy(void)
{
return Qnil;
}
VALUE
rb_obj_tainted(VALUE obj)
{
if (OBJ_TAINTED(obj))
return Qtrue;
return Qfalse;
}
VALUE
rb_obj_taint(VALUE obj)
{
rb_secure(4);
if (!OBJ_TAINTED(obj)) {
rb_check_frozen(obj);
OBJ_TAINT(obj);
}
return obj;
}
VALUE
rb_obj_untaint(VALUE obj)
{
rb_secure(3);
if (OBJ_TAINTED(obj)) {
rb_check_frozen(obj);
FL_UNSET(obj, FL_TAINT);
}
return obj;
}
VALUE
rb_obj_untrusted(VALUE obj)
{
if (OBJ_UNTRUSTED(obj))
return Qtrue;
return Qfalse;
}
VALUE
rb_obj_untrust(VALUE obj)
{
rb_secure(4);
if (!OBJ_UNTRUSTED(obj)) {
rb_check_frozen(obj);
OBJ_UNTRUST(obj);
}
return obj;
}
VALUE
rb_obj_trust(VALUE obj)
{
rb_secure(3);
if (OBJ_UNTRUSTED(obj)) {
rb_check_frozen(obj);
FL_UNSET(obj, FL_UNTRUSTED);
}
return obj;
}
void
rb_obj_infect(VALUE obj1, VALUE obj2)
{
OBJ_INFECT(obj1, obj2);
}
static st_table *immediate_frozen_tbl = 0;
VALUE
rb_obj_freeze(VALUE obj)
{
if (!OBJ_FROZEN(obj)) {
if (rb_safe_level() >= 4 && !OBJ_UNTRUSTED(obj)) {
rb_raise(rb_eSecurityError, "Insecure: can't freeze object");
}
OBJ_FREEZE(obj);
if (SPECIAL_CONST_P(obj)) {
if (!immediate_frozen_tbl) {
immediate_frozen_tbl = st_init_numtable();
}
st_insert(immediate_frozen_tbl, obj, (st_data_t)Qtrue);
}
}
return obj;
}
VALUE
rb_obj_frozen_p(VALUE obj)
{
if (OBJ_FROZEN(obj)) return Qtrue;
if (SPECIAL_CONST_P(obj)) {
if (!immediate_frozen_tbl) return Qfalse;
if (st_lookup(immediate_frozen_tbl, obj, 0)) return Qtrue;
}
return Qfalse;
}
static VALUE
nil_to_i(VALUE obj)
{
return INT2FIX(0);
}
static VALUE
nil_to_f(VALUE obj)
{
return DBL2NUM(0.0);
}
static VALUE
nil_to_s(VALUE obj)
{
return rb_usascii_str_new(0, 0);
}
static VALUE
nil_to_a(VALUE obj)
{
return rb_ary_new2(0);
}
static VALUE
nil_to_h(VALUE obj)
{
return rb_hash_new();
}
static VALUE
nil_inspect(VALUE obj)
{
return rb_usascii_str_new2("nil");
}
static VALUE
true_to_s(VALUE obj)
{
return rb_usascii_str_new2("true");
}
static VALUE
true_and(VALUE obj, VALUE obj2)
{
return RTEST(obj2)?Qtrue:Qfalse;
}
static VALUE
true_or(VALUE obj, VALUE obj2)
{
return Qtrue;
}
static VALUE
true_xor(VALUE obj, VALUE obj2)
{
return RTEST(obj2)?Qfalse:Qtrue;
}
static VALUE
false_to_s(VALUE obj)
{
return rb_usascii_str_new2("false");
}
static VALUE
false_and(VALUE obj, VALUE obj2)
{
return Qfalse;
}
static VALUE
false_or(VALUE obj, VALUE obj2)
{
return RTEST(obj2)?Qtrue:Qfalse;
}
static VALUE
false_xor(VALUE obj, VALUE obj2)
{
return RTEST(obj2)?Qtrue:Qfalse;
}
static VALUE
rb_true(VALUE obj)
{
return Qtrue;
}
static VALUE
rb_false(VALUE obj)
{
return Qfalse;
}
static VALUE
rb_obj_match(VALUE obj1, VALUE obj2)
{
return Qnil;
}
static VALUE
rb_obj_not_match(VALUE obj1, VALUE obj2)
{
VALUE result = rb_funcall(obj1, id_match, 1, obj2);
return RTEST(result) ? Qfalse : Qtrue;
}
static VALUE
rb_obj_cmp(VALUE obj1, VALUE obj2)
{
if (obj1 == obj2 || rb_equal(obj1, obj2))
return INT2FIX(0);
return Qnil;
}
static VALUE
rb_mod_to_s(VALUE klass)
{
ID id_defined_at;
VALUE refined_class, defined_at;
if (FL_TEST(klass, FL_SINGLETON)) {
VALUE s = rb_usascii_str_new2("#<Class:");
VALUE v = rb_iv_get(klass, "__attached__");
if (CLASS_OR_MODULE_P(v)) {
rb_str_append(s, rb_inspect(v));
}
else {
rb_str_append(s, rb_any_to_s(v));
}
rb_str_cat2(s, ">");
return s;
}
refined_class = rb_refinement_module_get_refined_class(klass);
if (!NIL_P(refined_class)) {
VALUE s = rb_usascii_str_new2("#<refinement:");
rb_str_concat(s, rb_inspect(refined_class));
rb_str_cat2(s, "@");
CONST_ID(id_defined_at, "__defined_at__");
defined_at = rb_attr_get(klass, id_defined_at);
rb_str_concat(s, rb_inspect(defined_at));
rb_str_cat2(s, ">");
return s;
}
return rb_str_dup(rb_class_name(klass));
}
static VALUE
rb_mod_freeze(VALUE mod)
{
rb_class_name(mod);
return rb_obj_freeze(mod);
}
static VALUE
rb_mod_eqq(VALUE mod, VALUE arg)
{
return rb_obj_is_kind_of(arg, mod);
}
VALUE
rb_class_inherited_p(VALUE mod, VALUE arg)
{
VALUE start = mod;
if (mod == arg) return Qtrue;
if (!CLASS_OR_MODULE_P(arg) && !RB_TYPE_P(arg, T_ICLASS)) {
rb_raise(rb_eTypeError, "compared with non class/module");
}
arg = RCLASS_ORIGIN(arg);
if (class_search_ancestor(mod, arg)) {
return Qtrue;
}
if (class_search_ancestor(arg, start)) {
return Qfalse;
}
return Qnil;
}
static VALUE
rb_mod_lt(VALUE mod, VALUE arg)
{
if (mod == arg) return Qfalse;
return rb_class_inherited_p(mod, arg);
}
static VALUE
rb_mod_ge(VALUE mod, VALUE arg)
{
if (!CLASS_OR_MODULE_P(arg)) {
rb_raise(rb_eTypeError, "compared with non class/module");
}
return rb_class_inherited_p(arg, mod);
}
static VALUE
rb_mod_gt(VALUE mod, VALUE arg)
{
if (mod == arg) return Qfalse;
return rb_mod_ge(mod, arg);
}
static VALUE
rb_mod_cmp(VALUE mod, VALUE arg)
{
VALUE cmp;
if (mod == arg) return INT2FIX(0);
if (!CLASS_OR_MODULE_P(arg)) {
return Qnil;
}
cmp = rb_class_inherited_p(mod, arg);
if (NIL_P(cmp)) return Qnil;
if (cmp) {
return INT2FIX(-1);
}
return INT2FIX(1);
}
static VALUE
rb_module_s_alloc(VALUE klass)
{
VALUE mod = rb_module_new();
RBASIC(mod)->klass = klass;
return mod;
}
static VALUE
rb_class_s_alloc(VALUE klass)
{
return rb_class_boot(0);
}
static VALUE
rb_mod_initialize(VALUE module)
{
if (rb_block_given_p()) {
rb_mod_module_exec(1, &module, module);
}
return Qnil;
}
static VALUE
rb_class_initialize(int argc, VALUE *argv, VALUE klass)
{
VALUE super;
if (RCLASS_SUPER(klass) != 0 || klass == rb_cBasicObject) {
rb_raise(rb_eTypeError, "already initialized class");
}
if (argc == 0) {
super = rb_cObject;
}
else {
rb_scan_args(argc, argv, "01", &super);
rb_check_inheritable(super);
if (super != rb_cBasicObject && !RCLASS_SUPER(super)) {
rb_raise(rb_eTypeError, "can't inherit uninitialized class");
}
}
RCLASS_SUPER(klass) = super;
rb_make_metaclass(klass, RBASIC(super)->klass);
rb_class_inherited(super, klass);
rb_mod_initialize(klass);
return klass;
}
VALUE
rb_obj_alloc(VALUE klass)
{
VALUE obj;
rb_alloc_func_t allocator;
if (RCLASS_SUPER(klass) == 0 && klass != rb_cBasicObject) {
rb_raise(rb_eTypeError, "can't instantiate uninitialized class");
}
if (FL_TEST(klass, FL_SINGLETON)) {
rb_raise(rb_eTypeError, "can't create instance of singleton class");
}
allocator = rb_get_alloc_func(klass);
if (!allocator) {
rb_raise(rb_eTypeError, "allocator undefined for %"PRIsVALUE,
klass);
}
#if !defined(DTRACE_PROBES_DISABLED) || !DTRACE_PROBES_DISABLED
if (RUBY_DTRACE_OBJECT_CREATE_ENABLED()) {
const char * file = rb_sourcefile();
RUBY_DTRACE_OBJECT_CREATE(rb_class2name(klass),
file ? file : "",
rb_sourceline());
}
#endif
obj = (*allocator)(klass);
if (rb_obj_class(obj) != rb_class_real(klass)) {
rb_raise(rb_eTypeError, "wrong instance allocation");
}
return obj;
}
static VALUE
rb_class_allocate_instance(VALUE klass)
{
NEWOBJ_OF(obj, struct RObject, klass, T_OBJECT);
return (VALUE)obj;
}
VALUE
rb_class_new_instance(int argc, VALUE *argv, VALUE klass)
{
VALUE obj;
obj = rb_obj_alloc(klass);
rb_obj_call_init(obj, argc, argv);
return obj;
}
VALUE
rb_class_superclass(VALUE klass)
{
VALUE super = RCLASS_SUPER(klass);
if (!super) {
if (klass == rb_cBasicObject) return Qnil;
rb_raise(rb_eTypeError, "uninitialized class");
}
while (RB_TYPE_P(super, T_ICLASS)) {
super = RCLASS_SUPER(super);
}
if (!super) {
return Qnil;
}
return super;
}
VALUE
rb_class_get_superclass(VALUE klass)
{
return RCLASS_SUPER(klass);
}
static VALUE
rb_mod_attr_reader(int argc, VALUE *argv, VALUE klass)
{
int i;
for (i=0; i<argc; i++) {
rb_attr(klass, rb_to_id(argv[i]), TRUE, FALSE, TRUE);
}
return Qnil;
}
VALUE
rb_mod_attr(int argc, VALUE *argv, VALUE klass)
{
if (argc == 2 && (argv[1] == Qtrue || argv[1] == Qfalse)) {
rb_warning("optional boolean argument is obsoleted");
rb_attr(klass, rb_to_id(argv[0]), 1, RTEST(argv[1]), TRUE);
return Qnil;
}
return rb_mod_attr_reader(argc, argv, klass);
}
static VALUE
rb_mod_attr_writer(int argc, VALUE *argv, VALUE klass)
{
int i;
for (i=0; i<argc; i++) {
rb_attr(klass, rb_to_id(argv[i]), FALSE, TRUE, TRUE);
}
return Qnil;
}
static VALUE
rb_mod_attr_accessor(int argc, VALUE *argv, VALUE klass)
{
int i;
for (i=0; i<argc; i++) {
rb_attr(klass, rb_to_id(argv[i]), TRUE, TRUE, TRUE);
}
return Qnil;
}
static VALUE
rb_mod_const_get(int argc, VALUE *argv, VALUE mod)
{
VALUE name, recur;
rb_encoding *enc;
const char *pbeg, *p, *path, *pend;
ID id;
int nestable = 1;
if (argc == 1) {
name = argv[0];
recur = Qtrue;
}
else {
rb_scan_args(argc, argv, "11", &name, &recur);
}
if (SYMBOL_P(name)) {
name = rb_sym_to_s(name);
nestable = 0;
}
name = rb_check_string_type(name);
Check_Type(name, T_STRING);
enc = rb_enc_get(name);
path = RSTRING_PTR(name);
if (!rb_enc_asciicompat(enc)) {
rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)");
}
pbeg = p = path;
pend = path + RSTRING_LEN(name);
if (p >= pend || !*p) {
wrong_name:
rb_raise(rb_eNameError, "wrong constant name %"PRIsVALUE,
QUOTE(name));
}
if (p + 2 < pend && p[0] == ':' && p[1] == ':') {
if (!nestable) goto wrong_name;
mod = rb_cObject;
p += 2;
pbeg = p;
}
while (p < pend) {
VALUE part;
long len, beglen;
while (p < pend && *p != ':') p++;
if (pbeg == p) goto wrong_name;
id = rb_check_id_cstr(pbeg, len = p-pbeg, enc);
beglen = pbeg-path;
if (p < pend && p[0] == ':') {
if (!nestable) goto wrong_name;
if (p + 2 >= pend || p[1] != ':') goto wrong_name;
p += 2;
pbeg = p;
}
if (!RB_TYPE_P(mod, T_MODULE) && !RB_TYPE_P(mod, T_CLASS)) {
rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module",
QUOTE(name));
}
if (!id) {
if (!ISUPPER(*pbeg) || !rb_enc_symname2_p(pbeg, len, enc)) {
part = rb_str_subseq(name, beglen, len);
rb_name_error_str(part, "wrong constant name %"PRIsVALUE,
QUOTE(part));
}
else if (!rb_method_basic_definition_p(CLASS_OF(mod), id_const_missing)) {
id = rb_intern3(pbeg, len, enc);
}
else {
part = rb_str_subseq(name, beglen, len);
rb_name_error_str(part, "uninitialized constant %"PRIsVALUE"%"PRIsVALUE,
rb_str_subseq(name, 0, beglen),
QUOTE(part));
}
}
if (!rb_is_const_id(id)) {
rb_name_error(id, "wrong constant name %"PRIsVALUE,
QUOTE_ID(id));
}
mod = RTEST(recur) ? rb_const_get(mod, id) : rb_const_get_at(mod, id);
}
return mod;
}
static VALUE
rb_mod_const_set(VALUE mod, VALUE name, VALUE value)
{
ID id = rb_to_id(name);
if (!rb_is_const_id(id)) {
rb_name_error(id, "wrong constant name %"PRIsVALUE,
QUOTE_ID(id));
}
rb_const_set(mod, id, value);
return value;
}
static VALUE
rb_mod_const_defined(int argc, VALUE *argv, VALUE mod)
{
VALUE name, recur;
ID id;
if (argc == 1) {
name = argv[0];
recur = Qtrue;
}
else {
rb_scan_args(argc, argv, "11", &name, &recur);
}
if (!(id = rb_check_id(&name))) {
if (rb_is_const_name(name)) {
return Qfalse;
}
else {
rb_name_error_str(name, "wrong constant name %"PRIsVALUE,
QUOTE(name));
}
}
if (!rb_is_const_id(id)) {
rb_name_error(id, "wrong constant name %"PRIsVALUE,
QUOTE_ID(id));
}
return RTEST(recur) ? rb_const_defined(mod, id) : rb_const_defined_at(mod, id);
}
static VALUE
rb_obj_ivar_get(VALUE obj, VALUE iv)
{
ID id = rb_check_id(&iv);
if (!id) {
if (rb_is_instance_name(iv)) {
return Qnil;
}
else {
rb_name_error_str(iv, "`%"PRIsVALUE"' is not allowed as an instance variable name",
QUOTE(iv));
}
}
if (!rb_is_instance_id(id)) {
rb_name_error(id, "`%"PRIsVALUE"' is not allowed as an instance variable name",
QUOTE_ID(id));
}
return rb_ivar_get(obj, id);
}
static VALUE
rb_obj_ivar_set(VALUE obj, VALUE iv, VALUE val)
{
ID id = rb_to_id(iv);
if (!rb_is_instance_id(id)) {
rb_name_error(id, "`%"PRIsVALUE"' is not allowed as an instance variable name",
QUOTE_ID(id));
}
return rb_ivar_set(obj, id, val);
}
static VALUE
rb_obj_ivar_defined(VALUE obj, VALUE iv)
{
ID id = rb_check_id(&iv);
if (!id) {
if (rb_is_instance_name(iv)) {
return Qfalse;
}
else {
rb_name_error_str(iv, "`%"PRIsVALUE"' is not allowed as an instance variable name",
QUOTE(iv));
}
}
if (!rb_is_instance_id(id)) {
rb_name_error(id, "`%"PRIsVALUE"' is not allowed as an instance variable name",
QUOTE_ID(id));
}
return rb_ivar_defined(obj, id);
}
static VALUE
rb_mod_cvar_get(VALUE obj, VALUE iv)
{
ID id = rb_check_id(&iv);
if (!id) {
if (rb_is_class_name(iv)) {
rb_name_error_str(iv, "uninitialized class variable %"PRIsVALUE" in %"PRIsVALUE"",
iv, rb_class_name(obj));
}
else {
rb_name_error_str(iv, "`%"PRIsVALUE"' is not allowed as a class variable name",
QUOTE(iv));
}
}
if (!rb_is_class_id(id)) {
rb_name_error(id, "`%"PRIsVALUE"' is not allowed as a class variable name",
QUOTE_ID(id));
}
return rb_cvar_get(obj, id);
}
static VALUE
rb_mod_cvar_set(VALUE obj, VALUE iv, VALUE val)
{
ID id = rb_to_id(iv);
if (!rb_is_class_id(id)) {
rb_name_error(id, "`%"PRIsVALUE"' is not allowed as a class variable name",
QUOTE_ID(id));
}
rb_cvar_set(obj, id, val);
return val;
}
static VALUE
rb_mod_cvar_defined(VALUE obj, VALUE iv)
{
ID id = rb_check_id(&iv);
if (!id) {
if (rb_is_class_name(iv)) {
return Qfalse;
}
else {
rb_name_error_str(iv, "`%"PRIsVALUE"' is not allowed as a class variable name",
QUOTE(iv));
}
}
if (!rb_is_class_id(id)) {
rb_name_error(id, "`%"PRIsVALUE"' is not allowed as a class variable name",
QUOTE_ID(id));
}
return rb_cvar_defined(obj, id);
}
static struct conv_method_tbl {
const char *method;
ID id;
} conv_method_names[] = {
{"to_int", 0},
{"to_ary", 0},
{"to_str", 0},
{"to_sym", 0},
{"to_hash", 0},
{"to_proc", 0},
{"to_io", 0},
{"to_a", 0},
{"to_s", 0},
{NULL, 0}
};
#define IMPLICIT_CONVERSIONS 7
static VALUE
convert_type(VALUE val, const char *tname, const char *method, int raise)
{
ID m = 0;
int i;
VALUE r;
for (i=0; conv_method_names[i].method; i++) {
if (conv_method_names[i].method[0] == method[0] &&
strcmp(conv_method_names[i].method, method) == 0) {
m = conv_method_names[i].id;
break;
}
}
if (!m) m = rb_intern(method);
r = rb_check_funcall(val, m, 0, 0);
if (r == Qundef) {
if (raise) {
const char *msg = i < IMPLICIT_CONVERSIONS ?
"no implicit conversion of" : "can't convert";
const char *cname = NIL_P(val) ? "nil" :
val == Qtrue ? "true" :
val == Qfalse ? "false" :
NULL;
if (cname)
rb_raise(rb_eTypeError, "%s %s into %s", msg, cname, tname);
rb_raise(rb_eTypeError, "%s %"PRIsVALUE" into %s", msg,
rb_obj_class(val),
tname);
}
return Qnil;
}
return r;
}
NORETURN(static void conversion_mismatch(VALUE, const char *, const char *, VALUE));
static void
conversion_mismatch(VALUE val, const char *tname, const char *method, VALUE result)
{
VALUE cname = rb_obj_class(val);
rb_raise(rb_eTypeError,
"can't convert %"PRIsVALUE" to %s (%"PRIsVALUE"#%s gives %"PRIsVALUE")",
cname, tname, cname, method, rb_obj_class(result));
}
VALUE
rb_convert_type(VALUE val, int type, const char *tname, const char *method)
{
VALUE v;
if (TYPE(val) == type) return val;
v = convert_type(val, tname, method, TRUE);
if (TYPE(v) != type) {
conversion_mismatch(val, tname, method, v);
}
return v;
}
VALUE
rb_check_convert_type(VALUE val, int type, const char *tname, const char *method)
{
VALUE v;
if (TYPE(val) == type && type != T_DATA) return val;
v = convert_type(val, tname, method, FALSE);
if (NIL_P(v)) return Qnil;
if (TYPE(v) != type) {
conversion_mismatch(val, tname, method, v);
}
return v;
}
static VALUE
rb_to_integer(VALUE val, const char *method)
{
VALUE v;
if (FIXNUM_P(val)) return val;
if (RB_TYPE_P(val, T_BIGNUM)) return val;
v = convert_type(val, "Integer", method, TRUE);
if (!rb_obj_is_kind_of(v, rb_cInteger)) {
conversion_mismatch(val, "Integer", method, v);
}
return v;
}
VALUE
rb_check_to_integer(VALUE val, const char *method)
{
VALUE v;
if (FIXNUM_P(val)) return val;
if (RB_TYPE_P(val, T_BIGNUM)) return val;
v = convert_type(val, "Integer", method, FALSE);
if (!rb_obj_is_kind_of(v, rb_cInteger)) {
return Qnil;
}
return v;
}
VALUE
rb_to_int(VALUE val)
{
return rb_to_integer(val, "to_int");
}
VALUE
rb_check_to_int(VALUE val)
{
return rb_check_to_integer(val, "to_int");
}
static VALUE
rb_convert_to_integer(VALUE val, int base)
{
VALUE tmp;
switch (TYPE(val)) {
case T_FLOAT:
if (base != 0) goto arg_error;
if (RFLOAT_VALUE(val) <= (double)FIXNUM_MAX
&& RFLOAT_VALUE(val) >= (double)FIXNUM_MIN) {
break;
}
return rb_dbl2big(RFLOAT_VALUE(val));
case T_FIXNUM:
case T_BIGNUM:
if (base != 0) goto arg_error;
return val;
case T_STRING:
string_conv:
return rb_str_to_inum(val, base, TRUE);
case T_NIL:
if (base != 0) goto arg_error;
rb_raise(rb_eTypeError, "can't convert nil into Integer");
break;
default:
break;
}
if (base != 0) {
tmp = rb_check_string_type(val);
if (!NIL_P(tmp)) goto string_conv;
arg_error:
rb_raise(rb_eArgError, "base specified for non string value");
}
tmp = convert_type(val, "Integer", "to_int", FALSE);
if (NIL_P(tmp)) {
return rb_to_integer(val, "to_i");
}
return tmp;
}
VALUE
rb_Integer(VALUE val)
{
return rb_convert_to_integer(val, 0);
}
static VALUE
rb_f_integer(int argc, VALUE *argv, VALUE obj)
{
VALUE arg = Qnil;
int base = 0;
switch (argc) {
case 2:
base = NUM2INT(argv[1]);
case 1:
arg = argv[0];
break;
default:
rb_scan_args(argc, argv, "11", NULL, NULL);
}
return rb_convert_to_integer(arg, base);
}
double
rb_cstr_to_dbl(const char *p, int badcheck)
{
const char *q;
char *end;
double d;
const char *ellipsis = "";
int w;
enum {max_width = 20};
#define OutOfRange() ((end - p > max_width) ? \
(w = max_width, ellipsis = "...") : \
(w = (int)(end - p), ellipsis = ""))
if (!p) return 0.0;
q = p;
while (ISSPACE(*p)) p++;
if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
return 0.0;
}
d = strtod(p, &end);
if (errno == ERANGE) {
OutOfRange();
rb_warning("Float %.*s%s out of range", w, p, ellipsis);
errno = 0;
}
if (p == end) {
if (badcheck) {
bad:
rb_invalid_str(q, "Float()");
}
return d;
}
if (*end) {
char buf[DBL_DIG * 4 + 10];
char *n = buf;
char *e = buf + sizeof(buf) - 1;
char prev = 0;
while (p < end && n < e) prev = *n++ = *p++;
while (*p) {
if (*p == '_') {
if (badcheck) {
if (n == buf || !ISDIGIT(prev)) goto bad;
++p;
if (!ISDIGIT(*p)) goto bad;
}
else {
while (*++p == '_');
continue;
}
}
prev = *p++;
if (n < e) *n++ = prev;
}
*n = '\0';
p = buf;
if (!badcheck && p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
return 0.0;
}
d = strtod(p, &end);
if (errno == ERANGE) {
OutOfRange();
rb_warning("Float %.*s%s out of range", w, p, ellipsis);
errno = 0;
}
if (badcheck) {
if (!end || p == end) goto bad;
while (*end && ISSPACE(*end)) end++;
if (*end) goto bad;
}
}
if (errno == ERANGE) {
errno = 0;
OutOfRange();
rb_raise(rb_eArgError, "Float %.*s%s out of range", w, q, ellipsis);
}
return d;
}
double
rb_str_to_dbl(VALUE str, int badcheck)
{
char *s;
long len;
double ret;
VALUE v = 0;
StringValue(str);
s = RSTRING_PTR(str);
len = RSTRING_LEN(str);
if (s) {
if (badcheck && memchr(s, '\0', len)) {
rb_raise(rb_eArgError, "string for Float contains null byte");
}
if (s[len]) {
char *p = ALLOCV(v, len);
MEMCPY(p, s, char, len);
p[len] = '\0';
s = p;
}
}
ret = rb_cstr_to_dbl(s, badcheck);
if (v)
ALLOCV_END(v);
return ret;
}
VALUE
rb_Float(VALUE val)
{
switch (TYPE(val)) {
case T_FIXNUM:
return DBL2NUM((double)FIX2LONG(val));
case T_FLOAT:
return val;
case T_BIGNUM:
return DBL2NUM(rb_big2dbl(val));
case T_STRING:
return DBL2NUM(rb_str_to_dbl(val, TRUE));
case T_NIL:
rb_raise(rb_eTypeError, "can't convert nil into Float");
break;
default:
return rb_convert_type(val, T_FLOAT, "Float", "to_f");
}
UNREACHABLE;
}
static VALUE
rb_f_float(VALUE obj, VALUE arg)
{
return rb_Float(arg);
}
VALUE
rb_to_float(VALUE val)
{
if (RB_TYPE_P(val, T_FLOAT)) return val;
if (!rb_obj_is_kind_of(val, rb_cNumeric)) {
rb_raise(rb_eTypeError, "can't convert %s into Float",
NIL_P(val) ? "nil" :
val == Qtrue ? "true" :
val == Qfalse ? "false" :
rb_obj_classname(val));
}
return rb_convert_type(val, T_FLOAT, "Float", "to_f");
}
VALUE
rb_check_to_float(VALUE val)
{
if (RB_TYPE_P(val, T_FLOAT)) return val;
if (!rb_obj_is_kind_of(val, rb_cNumeric)) {
return Qnil;
}
return rb_check_convert_type(val, T_FLOAT, "Float", "to_f");
}
double
rb_num2dbl(VALUE val)
{
switch (TYPE(val)) {
case T_FLOAT:
return RFLOAT_VALUE(val);
case T_STRING:
rb_raise(rb_eTypeError, "no implicit conversion to float from string");
break;
case T_NIL:
rb_raise(rb_eTypeError, "no implicit conversion to float from nil");
break;
default:
break;
}
return RFLOAT_VALUE(rb_Float(val));
}
VALUE
rb_String(VALUE val)
{
VALUE tmp = rb_check_string_type(val);
if (NIL_P(tmp))
tmp = rb_convert_type(val, T_STRING, "String", "to_s");
return tmp;
}
static VALUE
rb_f_string(VALUE obj, VALUE arg)
{
return rb_String(arg);
}
VALUE
rb_Array(VALUE val)
{
VALUE tmp = rb_check_array_type(val);
if (NIL_P(tmp)) {
tmp = rb_check_convert_type(val, T_ARRAY, "Array", "to_a");
if (NIL_P(tmp)) {
return rb_ary_new3(1, val);
}
}
return tmp;
}
static VALUE
rb_f_array(VALUE obj, VALUE arg)
{
return rb_Array(arg);
}
VALUE
rb_Hash(VALUE val)
{
VALUE tmp;
if (NIL_P(val)) return rb_hash_new();
tmp = rb_check_hash_type(val);
if (NIL_P(tmp)) {
if (RB_TYPE_P(val, T_ARRAY) && RARRAY_LEN(val) == 0)
return rb_hash_new();
rb_raise(rb_eTypeError, "can't convert %s into Hash", rb_obj_classname(val));
}
return tmp;
}
static VALUE
rb_f_hash(VALUE obj, VALUE arg)
{
return rb_Hash(arg);
}
void
Init_Object(void)
{
int i;
Init_class_hierarchy();
#if 0
rb_cBasicObject = rb_define_class("BasicObject", Qnil);
rb_cObject = rb_define_class("Object", rb_cBasicObject);
rb_cModule = rb_define_class("Module", rb_cObject);
rb_cClass = rb_define_class("Class", rb_cModule);
#endif
#undef rb_intern
#define rb_intern(str) rb_intern_const(str)
rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, 0);
rb_define_alloc_func(rb_cBasicObject, rb_class_allocate_instance);
rb_define_method(rb_cBasicObject, "==", rb_obj_equal, 1);
rb_define_method(rb_cBasicObject, "equal?", rb_obj_equal, 1);
rb_define_method(rb_cBasicObject, "!", rb_obj_not, 0);
rb_define_method(rb_cBasicObject, "!=", rb_obj_not_equal, 1);
rb_define_private_method(rb_cBasicObject, "singleton_method_added", rb_obj_dummy, 1);
rb_define_private_method(rb_cBasicObject, "singleton_method_removed", rb_obj_dummy, 1);
rb_define_private_method(rb_cBasicObject, "singleton_method_undefined", rb_obj_dummy, 1);
rb_mKernel = rb_define_module("Kernel");
rb_include_module(rb_cObject, rb_mKernel);
rb_define_private_method(rb_cClass, "inherited", rb_obj_dummy, 1);
rb_define_private_method(rb_cModule, "included", rb_obj_dummy, 1);
rb_define_private_method(rb_cModule, "extended", rb_obj_dummy, 1);
rb_define_private_method(rb_cModule, "prepended", rb_obj_dummy, 1);
rb_define_private_method(rb_cModule, "method_added", rb_obj_dummy, 1);
rb_define_private_method(rb_cModule, "method_removed", rb_obj_dummy, 1);
rb_define_private_method(rb_cModule, "method_undefined", rb_obj_dummy, 1);
rb_define_method(rb_mKernel, "nil?", rb_false, 0);
rb_define_method(rb_mKernel, "===", rb_equal, 1);
rb_define_method(rb_mKernel, "=~", rb_obj_match, 1);
rb_define_method(rb_mKernel, "!~", rb_obj_not_match, 1);
rb_define_method(rb_mKernel, "eql?", rb_obj_equal, 1);
rb_define_method(rb_mKernel, "hash", rb_obj_hash, 0);
rb_define_method(rb_mKernel, "<=>", rb_obj_cmp, 1);
rb_define_method(rb_mKernel, "class", rb_obj_class, 0);
rb_define_method(rb_mKernel, "singleton_class", rb_obj_singleton_class, 0);
rb_define_method(rb_mKernel, "clone", rb_obj_clone, 0);
rb_define_method(rb_mKernel, "dup", rb_obj_dup, 0);
rb_define_method(rb_mKernel, "initialize_copy", rb_obj_init_copy, 1);
rb_define_method(rb_mKernel, "initialize_dup", rb_obj_init_dup_clone, 1);
rb_define_method(rb_mKernel, "initialize_clone", rb_obj_init_dup_clone, 1);
rb_define_method(rb_mKernel, "taint", rb_obj_taint, 0);
rb_define_method(rb_mKernel, "tainted?", rb_obj_tainted, 0);
rb_define_method(rb_mKernel, "untaint", rb_obj_untaint, 0);
rb_define_method(rb_mKernel, "untrust", rb_obj_untrust, 0);
rb_define_method(rb_mKernel, "untrusted?", rb_obj_untrusted, 0);
rb_define_method(rb_mKernel, "trust", rb_obj_trust, 0);
rb_define_method(rb_mKernel, "freeze", rb_obj_freeze, 0);
rb_define_method(rb_mKernel, "frozen?", rb_obj_frozen_p, 0);
rb_define_method(rb_mKernel, "to_s", rb_any_to_s, 0);
rb_define_method(rb_mKernel, "inspect", rb_obj_inspect, 0);
rb_define_method(rb_mKernel, "methods", rb_obj_methods, -1);
rb_define_method(rb_mKernel, "singleton_methods", rb_obj_singleton_methods, -1);
rb_define_method(rb_mKernel, "protected_methods", rb_obj_protected_methods, -1);
rb_define_method(rb_mKernel, "private_methods", rb_obj_private_methods, -1);
rb_define_method(rb_mKernel, "public_methods", rb_obj_public_methods, -1);
rb_define_method(rb_mKernel, "instance_variables", rb_obj_instance_variables, 0);
rb_define_method(rb_mKernel, "instance_variable_get", rb_obj_ivar_get, 1);
rb_define_method(rb_mKernel, "instance_variable_set", rb_obj_ivar_set, 2);
rb_define_method(rb_mKernel, "instance_variable_defined?", rb_obj_ivar_defined, 1);
rb_define_method(rb_mKernel, "remove_instance_variable",
rb_obj_remove_instance_variable, 1);
rb_define_method(rb_mKernel, "instance_of?", rb_obj_is_instance_of, 1);
rb_define_method(rb_mKernel, "kind_of?", rb_obj_is_kind_of, 1);
rb_define_method(rb_mKernel, "is_a?", rb_obj_is_kind_of, 1);
rb_define_method(rb_mKernel, "tap", rb_obj_tap, 0);
rb_define_global_function("sprintf", rb_f_sprintf, -1);
rb_define_global_function("format", rb_f_sprintf, -1);
rb_define_global_function("Integer", rb_f_integer, -1);
rb_define_global_function("Float", rb_f_float, 1);
rb_define_global_function("String", rb_f_string, 1);
rb_define_global_function("Array", rb_f_array, 1);
rb_define_global_function("Hash", rb_f_hash, 1);
rb_cNilClass = rb_define_class("NilClass", rb_cObject);
rb_define_method(rb_cNilClass, "to_i", nil_to_i, 0);
rb_define_method(rb_cNilClass, "to_f", nil_to_f, 0);
rb_define_method(rb_cNilClass, "to_s", nil_to_s, 0);
rb_define_method(rb_cNilClass, "to_a", nil_to_a, 0);
rb_define_method(rb_cNilClass, "to_h", nil_to_h, 0);
rb_define_method(rb_cNilClass, "inspect", nil_inspect, 0);
rb_define_method(rb_cNilClass, "&", false_and, 1);
rb_define_method(rb_cNilClass, "|", false_or, 1);
rb_define_method(rb_cNilClass, "^", false_xor, 1);
rb_define_method(rb_cNilClass, "nil?", rb_true, 0);
rb_undef_alloc_func(rb_cNilClass);
rb_undef_method(CLASS_OF(rb_cNilClass), "new");
rb_define_global_const("NIL", Qnil);
rb_define_method(rb_cModule, "freeze", rb_mod_freeze, 0);
rb_define_method(rb_cModule, "===", rb_mod_eqq, 1);
rb_define_method(rb_cModule, "==", rb_obj_equal, 1);
rb_define_method(rb_cModule, "<=>", rb_mod_cmp, 1);
rb_define_method(rb_cModule, "<", rb_mod_lt, 1);
rb_define_method(rb_cModule, "<=", rb_class_inherited_p, 1);
rb_define_method(rb_cModule, ">", rb_mod_gt, 1);
rb_define_method(rb_cModule, ">=", rb_mod_ge, 1);
rb_define_method(rb_cModule, "initialize_copy", rb_mod_init_copy, 1);
rb_define_method(rb_cModule, "to_s", rb_mod_to_s, 0);
rb_define_alias(rb_cModule, "inspect", "to_s");
rb_define_method(rb_cModule, "included_modules", rb_mod_included_modules, 0);
rb_define_method(rb_cModule, "include?", rb_mod_include_p, 1);
rb_define_method(rb_cModule, "name", rb_mod_name, 0);
rb_define_method(rb_cModule, "ancestors", rb_mod_ancestors, 0);
rb_define_private_method(rb_cModule, "attr", rb_mod_attr, -1);
rb_define_private_method(rb_cModule, "attr_reader", rb_mod_attr_reader, -1);
rb_define_private_method(rb_cModule, "attr_writer", rb_mod_attr_writer, -1);
rb_define_private_method(rb_cModule, "attr_accessor", rb_mod_attr_accessor, -1);
rb_define_alloc_func(rb_cModule, rb_module_s_alloc);
rb_define_method(rb_cModule, "initialize", rb_mod_initialize, 0);
rb_define_method(rb_cModule, "instance_methods", rb_class_instance_methods, -1);
rb_define_method(rb_cModule, "public_instance_methods",
rb_class_public_instance_methods, -1);
rb_define_method(rb_cModule, "protected_instance_methods",
rb_class_protected_instance_methods, -1);
rb_define_method(rb_cModule, "private_instance_methods",
rb_class_private_instance_methods, -1);
rb_define_method(rb_cModule, "constants", rb_mod_constants, -1);
rb_define_method(rb_cModule, "const_get", rb_mod_const_get, -1);
rb_define_method(rb_cModule, "const_set", rb_mod_const_set, 2);
rb_define_method(rb_cModule, "const_defined?", rb_mod_const_defined, -1);
rb_define_private_method(rb_cModule, "remove_const",
rb_mod_remove_const, 1);
rb_define_method(rb_cModule, "const_missing",
rb_mod_const_missing, 1);
rb_define_method(rb_cModule, "class_variables",
rb_mod_class_variables, -1);
rb_define_method(rb_cModule, "remove_class_variable",
rb_mod_remove_cvar, 1);
rb_define_method(rb_cModule, "class_variable_get", rb_mod_cvar_get, 1);
rb_define_method(rb_cModule, "class_variable_set", rb_mod_cvar_set, 2);
rb_define_method(rb_cModule, "class_variable_defined?", rb_mod_cvar_defined, 1);
rb_define_method(rb_cModule, "public_constant", rb_mod_public_constant, -1);
rb_define_method(rb_cModule, "private_constant", rb_mod_private_constant, -1);
rb_define_method(rb_cClass, "allocate", rb_obj_alloc, 0);
rb_define_method(rb_cClass, "new", rb_class_new_instance, -1);
rb_define_method(rb_cClass, "initialize", rb_class_initialize, -1);
rb_define_method(rb_cClass, "superclass", rb_class_superclass, 0);
rb_define_alloc_func(rb_cClass, rb_class_s_alloc);
rb_undef_method(rb_cClass, "extend_object");
rb_undef_method(rb_cClass, "append_features");
rb_undef_method(rb_cClass, "prepend_features");
rb_cData = rb_define_class("Data", rb_cObject);
rb_undef_alloc_func(rb_cData);
rb_cTrueClass = rb_define_class("TrueClass", rb_cObject);
rb_define_method(rb_cTrueClass, "to_s", true_to_s, 0);
rb_define_alias(rb_cTrueClass, "inspect", "to_s");
rb_define_method(rb_cTrueClass, "&", true_and, 1);
rb_define_method(rb_cTrueClass, "|", true_or, 1);
rb_define_method(rb_cTrueClass, "^", true_xor, 1);
rb_undef_alloc_func(rb_cTrueClass);
rb_undef_method(CLASS_OF(rb_cTrueClass), "new");
rb_define_global_const("TRUE", Qtrue);
rb_cFalseClass = rb_define_class("FalseClass", rb_cObject);
rb_define_method(rb_cFalseClass, "to_s", false_to_s, 0);
rb_define_alias(rb_cFalseClass, "inspect", "to_s");
rb_define_method(rb_cFalseClass, "&", false_and, 1);
rb_define_method(rb_cFalseClass, "|", false_or, 1);
rb_define_method(rb_cFalseClass, "^", false_xor, 1);
rb_undef_alloc_func(rb_cFalseClass);
rb_undef_method(CLASS_OF(rb_cFalseClass), "new");
rb_define_global_const("FALSE", Qfalse);
id_eq = rb_intern("==");
id_eql = rb_intern("eql?");
id_match = rb_intern("=~");
id_inspect = rb_intern("inspect");
id_init_copy = rb_intern("initialize_copy");
id_init_clone = rb_intern("initialize_clone");
id_init_dup = rb_intern("initialize_dup");
id_const_missing = rb_intern("const_missing");
for (i=0; conv_method_names[i].method; i++) {
conv_method_names[i].id = rb_intern(conv_method_names[i].method);
}
}