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); } }
static VALUE rb_method_missing(VALUE obj, SEL sel, int argc, const VALUE *argv) { return rb_vm_method_missing(obj, argc, argv); }