Example #1
0
static VALUE
method_missing(VALUE obj, SEL sel, rb_vm_block_t *block, int argc,
	const VALUE *argv, rb_vm_method_missing_reason_t call_status)
{
    if (sel == selAlloc) {
        rb_raise(rb_eTypeError, "allocator undefined for %s",
		RSTRING_PTR(rb_inspect(obj)));
    }

    GET_VM()->set_method_missing_reason(call_status);

    VALUE *new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE) * (argc + 1));

    char buf[100];
    int n = snprintf(buf, sizeof buf, "%s", sel_getName(sel));
    if (buf[n - 1] == ':') {
	// Let's see if there are more colons making this a real selector.
	bool multiple_colons = false;
	for (int i = 0; i < (n - 1); i++) {
	    if (buf[i] == ':') {
		multiple_colons = true;
		break;
	    }
	}
	if (!multiple_colons) {
	    // Not a typical multiple argument selector. So as this is
	    // probably a typical ruby method name, chop off the colon.
	    buf[n - 1] = '\0';
	}
    }
    new_argv[0] = ID2SYM(rb_intern(buf));
    MEMCPY(&new_argv[1], argv, VALUE, argc);

    // In case the missing selector _is_ method_missing: OR the object does
    // not respond to method_missing: (this can happen for NSProxy-based
    // objects), directly trigger the exception.
    Class k = (Class)CLASS_OF(obj);
    if (sel == selMethodMissing
	    || class_getInstanceMethod(k, selMethodMissing) == NULL) {
	rb_vm_method_missing(obj, argc + 1, new_argv);
	return Qnil; // never reached
    }
    else {
	return rb_vm_call2(block, obj, (VALUE)k, selMethodMissing, argc + 1,
		new_argv);
    }
}
Example #2
0
static VALUE
rb_method_missing(VALUE obj, SEL sel, int argc, const VALUE *argv)
{
    return rb_vm_method_missing(obj, argc, argv);
}