Beispiel #1
0
static VALUE
yield_block(int argc, VALUE *argv, VALUE self)
{
    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    return rb_block_call(self, rb_to_id(argv[0]), argc-1, argv+1, rb_yield_block, 0);
}
Beispiel #2
0
static VALUE
rb_mod_public_method_defined(VALUE mod, SEL sel, VALUE mid)
{
    ID id = rb_to_id(mid);
    return check_method_visibility(mod, id, NOEX_PUBLIC);
}
static VALUE
rb_mod_private_method_defined(VALUE mod, VALUE mid)
{
    return check_definition(mod, rb_to_id(mid), NOEX_PRIVATE);
}
Beispiel #4
0
static VALUE
rb_thread_aset(VALUE self, SEL sel, VALUE key, VALUE val)
{
    key = ID2SYM(rb_to_id(key));
    return rb_hash_aset(rb_vm_thread_locals(self, true), key, val);
}
Beispiel #5
0
static inline VALUE
vm_call_method(rb_thread_t *th, rb_control_frame_t *cfp,
	       int num, const rb_block_t *blockptr, VALUE flag,
	       ID id, const rb_method_entry_t *me, VALUE recv)
{
    VALUE val;

  start_method_dispatch:

    if (me != 0) {
	if ((me->flag == 0)) {
	  normal_method_dispatch:
	    switch (me->def->type) {
	      case VM_METHOD_TYPE_ISEQ:{
		vm_setup_method(th, cfp, recv, num, blockptr, flag, me);
		return Qundef;
	      }
	      case VM_METHOD_TYPE_NOTIMPLEMENTED:
	      case VM_METHOD_TYPE_CFUNC:{
		val = vm_call_cfunc(th, cfp, num, recv, blockptr, me);
		break;
	      }
	      case VM_METHOD_TYPE_ATTRSET:{
		if (num != 1) {
		    rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", num);
		}
		val = rb_ivar_set(recv, me->def->body.attr.id, *(cfp->sp - 1));
		cfp->sp -= 2;
		break;
	      }
	      case VM_METHOD_TYPE_IVAR:{
		if (num != 0) {
		    rb_raise(rb_eArgError, "wrong number of arguments (%d for 0)", num);
		}
		val = rb_attr_get(recv, me->def->body.attr.id);
		cfp->sp -= 1;
		break;
	      }
	      case VM_METHOD_TYPE_MISSING:{
		VALUE *argv = ALLOCA_N(VALUE, num+1);
		argv[0] = ID2SYM(me->def->original_id);
		MEMCPY(argv+1, cfp->sp - num, VALUE, num);
		cfp->sp += - num - 1;
		val = rb_funcall2(recv, rb_intern("method_missing"), num+1, argv);
		break;
	      }
	      case VM_METHOD_TYPE_BMETHOD:{
		VALUE *argv = ALLOCA_N(VALUE, num);
		MEMCPY(argv, cfp->sp - num, VALUE, num);
		cfp->sp += - num - 1;
		val = vm_call_bmethod(th, recv, num, argv, blockptr, me);
		break;
	      }
	      case VM_METHOD_TYPE_ZSUPER:{
		VALUE klass = RCLASS_SUPER(me->klass);
		me = rb_method_entry(klass, id);

		if (me != 0) {
		    goto normal_method_dispatch;
		}
		else {
		    goto start_method_dispatch;
		}
	      }
	      case VM_METHOD_TYPE_OPTIMIZED:{
		switch (me->def->body.optimize_type) {
		  case OPTIMIZED_METHOD_TYPE_SEND: {
		    rb_control_frame_t *reg_cfp = cfp;
		    rb_num_t i = num - 1;
		    VALUE sym;

		    if (num == 0) {
			rb_raise(rb_eArgError, "no method name given");
		    }

		    sym = TOPN(i);
		    id = SYMBOL_P(sym) ? SYM2ID(sym) : rb_to_id(sym);
		    /* shift arguments */
		    if (i > 0) {
			MEMMOVE(&TOPN(i), &TOPN(i-1), VALUE, i);
		    }
		    me = rb_method_entry(CLASS_OF(recv), id);
		    num -= 1;
		    DEC_SP(1);
		    flag |= VM_CALL_FCALL_BIT | VM_CALL_OPT_SEND_BIT;

		    goto start_method_dispatch;
		  }
		  case OPTIMIZED_METHOD_TYPE_CALL: {
		    rb_proc_t *proc;
		    int argc = num;
		    VALUE *argv = ALLOCA_N(VALUE, num);
		    GetProcPtr(recv, proc);
		    MEMCPY(argv, cfp->sp - num, VALUE, num);
		    cfp->sp -= num + 1;

		    val = rb_vm_invoke_proc(th, proc, proc->block.self, argc, argv, blockptr);
		    break;
		  }
		  default:
		    rb_bug("eval_invoke_method: unsupported optimized method type (%d)",
			   me->def->body.optimize_type);
		}
		break;
	      }
	      default:{
		rb_bug("eval_invoke_method: unsupported method type (%d)", me->def->type);
		break;
	      }
	    }
	}
	else {
	    int noex_safe;

	    if (!(flag & VM_CALL_FCALL_BIT) &&
		(me->flag & NOEX_MASK) & NOEX_PRIVATE) {
		int stat = NOEX_PRIVATE;

		if (flag & VM_CALL_VCALL_BIT) {
		    stat |= NOEX_VCALL;
		}
		val = vm_method_missing(th, id, recv, num, blockptr, stat);
	    }
	    else if (!(flag & VM_CALL_OPT_SEND_BIT) && (me->flag & NOEX_MASK) & NOEX_PROTECTED) {
		VALUE defined_class = me->klass;

		if (TYPE(defined_class) == T_ICLASS) {
		    defined_class = RBASIC(defined_class)->klass;
		}

		if (!rb_obj_is_kind_of(cfp->self, defined_class)) {
		    val = vm_method_missing(th, id, recv, num, blockptr, NOEX_PROTECTED);
		}
		else {
		    goto normal_method_dispatch;
		}
	    }
	    else if ((noex_safe = NOEX_SAFE(me->flag)) > th->safe_level &&
		     (noex_safe > 2)) {
		rb_raise(rb_eSecurityError, "calling insecure method: %s", rb_id2name(id));
	    }
	    else {
		goto normal_method_dispatch;
	    }
	}
    }
    else {
	/* method missing */
	int stat = 0;
	if (flag & VM_CALL_VCALL_BIT) {
	    stat |= NOEX_VCALL;
	}
	if (flag & VM_CALL_SUPER_BIT) {
	    stat |= NOEX_SUPER;
	}
	if (id == idMethodMissing) {
	    VALUE *argv = ALLOCA_N(VALUE, num);
	    vm_method_missing_args(th, argv, num - 1, 0, stat);
	    rb_raise_method_missing(th, num, argv, recv, stat);
	}
	else {
	    val = vm_method_missing(th, id, recv, num, blockptr, stat);
	}
    }

    RUBY_VM_CHECK_INTS();
    return val;
}
Beispiel #6
0
VALUE
rb_obj_public_method(VALUE obj, VALUE vid)
{
    return mnew(CLASS_OF(obj), obj, rb_to_id(vid), rb_cMethod, Qtrue);
}
Beispiel #7
0
static VALUE
rb_mod_define_method(int argc, VALUE *argv, VALUE mod)
{
    ID id;
    VALUE body;
    NODE *node;
    int noex = NOEX_PUBLIC;

    if (argc == 1) {
	id = rb_to_id(argv[0]);
	body = rb_block_lambda();
    }
    else if (argc == 2) {
	id = rb_to_id(argv[0]);
	body = argv[1];
	if (!rb_obj_is_method(body) && !rb_obj_is_proc(body)) {
	    rb_raise(rb_eTypeError,
		     "wrong argument type %s (expected Proc/Method)",
		     rb_obj_classname(body));
	}
    }
    else {
	rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
    }

    if (RDATA(body)->dmark == (RUBY_DATA_FUNC) bm_mark) {
	struct METHOD *method = (struct METHOD *)DATA_PTR(body);
	VALUE rclass = method->rclass;
	if (rclass != mod) {
	    if (RCLASS_SINGLETON(rclass)) {
		rb_raise(rb_eTypeError,
			 "can't bind singleton method to a different class");
	    }
	    if (!RTEST(rb_class_inherited_p(mod, rclass))) {
		rb_raise(rb_eTypeError,
			 "bind argument must be a subclass of %s",
			 rb_class2name(rclass));
	    }
	}
	node = method->body;
    }
    else if (rb_obj_is_proc(body)) {
	rb_proc_t *proc;
	body = proc_dup(body);
	GetProcPtr(body, proc);
	if (BUILTIN_TYPE(proc->block.iseq) != T_NODE) {
	    proc->block.iseq->defined_method_id = id;
	    proc->block.iseq->klass = mod;
	    proc->is_lambda = Qtrue;
	    proc->is_from_method = Qtrue;
	}
	node = NEW_BMETHOD(body);
    }
    else {
	/* type error */
	rb_raise(rb_eTypeError, "wrong argument type (expected Proc/Method)");
    }

    /* TODO: visibility */

    rb_add_method(mod, id, node, noex);
    return body;
}
Beispiel #8
0
static VALUE
rb_mod_method_defined(VALUE mod, VALUE mid)
{
    return rb_method_boundp(mod, rb_to_id(mid), 1);
}
Beispiel #9
0
static VALUE
rb_mod_instance_method(VALUE mod, SEL sel, VALUE vid)
{
    return mnew(mod, Qundef, rb_to_id(vid), rb_cUnboundMethod, Qfalse);
}
Beispiel #10
0
VALUE
rb_vm_dispatch(void *_vm, struct mcache *cache, VALUE top, VALUE self,
	Class klass, SEL sel, rb_vm_block_t *block, unsigned char opt,
	int argc, const VALUE *argv)
{
    RoxorVM *vm = (RoxorVM *)_vm;

#if ROXOR_VM_DEBUG
    bool cached = true;
#endif
    bool cache_method = true;

    Class current_super_class = vm->get_current_super_class();
    SEL current_super_sel = vm->get_current_super_sel();

    if (opt & DISPATCH_SUPER) {
	// TODO
	goto recache;
    }

    if (cache->sel != sel || cache->klass != klass || cache->flag == 0) {
recache:
#if ROXOR_VM_DEBUG
	cached = false;
#endif

	Method method;
	if (opt & DISPATCH_SUPER) {
	    if (!sel_equal(klass, current_super_sel, sel)) {
		current_super_sel = sel;
		current_super_class = klass;
	    }
	    else {
		// Let's make sure the current_super_class is valid before
		// using it; we check this by verifying that it's a real
		// super class of the current class, as we may be calling
		// a super method of the same name but on a totally different
		// class hierarchy.
		Class k = klass;
		bool current_super_class_ok = false;
		while (k != NULL) {
		    if (k == current_super_class) {
			current_super_class_ok = true;
			break;
		    }
		    k = class_getSuperclass(k);
		}
		if (!current_super_class_ok) {
		    current_super_class = klass;
		}
	    }
	    method = rb_vm_super_lookup(current_super_class, sel,
		    &current_super_class);
	}
	else {
	    current_super_sel = 0;
	    method = class_getInstanceMethod(klass, sel);
	}

	if (method != NULL) {
recache2:
	    IMP imp = method_getImplementation(method);

	    if (UNAVAILABLE_IMP(imp)) {
		// Method was undefined.
		goto call_method_missing;
	    }

	    rb_vm_method_node_t *node = GET_CORE()->method_node_get(method);

	    if (node != NULL) {
		// ruby call
		fill_rcache(cache, klass, sel, node);
	    }
	    else {
		// objc call
		fill_ocache(cache, self, klass, imp, sel, method, argc);
	    }

	    if (opt & DISPATCH_SUPER) {
		cache->flag |= MCACHE_SUPER;
	    }
	}
	else {
	    // Method is not found...

#if !defined(MACRUBY_STATIC)
	    // Force a method resolving, because the objc cache might be
	    // wrong.
	    if (rb_vm_resolve_method(klass, sel)) {
		goto recache;
	    }
#endif

	    // Does the receiver implements -forwardInvocation:?
	    if ((opt & DISPATCH_SUPER) == 0
		    && rb_objc_supports_forwarding(self, sel)) {

//#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070
		// In earlier versions of the Objective-C runtime, there seems
		// to be a bug where class_getInstanceMethod isn't atomic,
		// and might return NULL while at the exact same time another
		// thread registers the related method.
		// As a work-around, we double-check if the method still does
		// not exist here. If he does, we can dispatch it properly.

		// note: OS X 10.7 also, this workaround is required. see #1476
		method = class_getInstanceMethod(klass, sel);
		if (method != NULL) {
		    goto recache2;
		}
//#endif
		fill_ocache(cache, self, klass, (IMP)objc_msgSend, sel, NULL,
			argc);
		goto dispatch;
	    }

	    // Let's see if are not trying to call a Ruby method that accepts
	    // a regular argument then an optional Hash argument, to be
	    // compatible with the Ruby specification.
	    const char *selname = (const char *)sel;
	    size_t selname_len = strlen(selname);
	    if (argc > 1) {
		const char *p = strchr(selname, ':');
		if (p != NULL && p + 1 != '\0') {
		    char *tmp = (char *)malloc(selname_len + 1);
		    assert(tmp != NULL);
		    strncpy(tmp, selname, p - selname + 1);
		    tmp[p - selname + 1] = '\0';
		    sel = sel_registerName(tmp);
		    VALUE h = rb_hash_new();
		    bool ok = true;
		    p += 1;
		    for (int i = 1; i < argc; i++) {
			const char *p2 = strchr(p, ':');
			if (p2 == NULL) {
			    ok = false;
			    break;
			}
			strlcpy(tmp, p, selname_len);
			tmp[p2 - p] = '\0';
			p = p2 + 1; 
			rb_hash_aset(h, ID2SYM(rb_intern(tmp)), argv[i]);
		    }
		    free(tmp);
		    tmp = NULL;
		    if (ok) {
			argc = 2;
			((VALUE *)argv)[1] = h; // bad, I know...
			Method m = class_getInstanceMethod(klass, sel);
			if (m != NULL) {	
			    method = m;
			    cache_method = false;
			    goto recache2;
			}
		    }
		}
	    }

	    // Enable helpers for classes which are not RubyObject based.
	    if ((RCLASS_VERSION(klass) & RCLASS_IS_OBJECT_SUBCLASS)
		    != RCLASS_IS_OBJECT_SUBCLASS) {
		// Let's try to see if we are not given a helper selector.
		SEL new_sel = helper_sel(selname, selname_len);
		if (new_sel != NULL) {
		    Method m = class_getInstanceMethod(klass, new_sel);
		    if (m != NULL) {
		    	sel = new_sel;
		    	method = m;
		    	// We need to invert arguments because
		    	// #[]= and setObject:forKey: take arguments
		    	// in a reverse order
		    	if (new_sel == selSetObjectForKey && argc == 2) {
		    	    VALUE swap = argv[0];
		    	    ((VALUE *)argv)[0] = argv[1];
		    	    ((VALUE *)argv)[1] = swap;
		    	    cache_method = false;
		    	}
		    	goto recache2;
		    }
		}
	    }

	    // Let's see if we are not trying to call a BridgeSupport function.
	    if (selname[selname_len - 1] == ':') {
		selname_len--;
	    }
	    std::string name(selname, selname_len);
	    bs_element_function_t *bs_func = GET_CORE()->find_bs_function(name);
	    if (bs_func != NULL) {
		if ((unsigned)argc < bs_func->args_count
			|| ((unsigned)argc > bs_func->args_count
				&& bs_func->variadic == false)) {
		    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
			argc, bs_func->args_count);
		}
		std::string types;
		vm_gen_bs_func_types(argc, argv, bs_func, types);

		cache->flag = MCACHE_FCALL;
		cache->sel = sel;
		cache->klass = klass;
		cache->as.fcall.bs_function = bs_func;
		cache->as.fcall.imp = (IMP)dlsym(RTLD_DEFAULT, bs_func->name);
		assert(cache->as.fcall.imp != NULL);
		cache->as.fcall.stub = (rb_vm_c_stub_t *)GET_CORE()->gen_stub(
			types, bs_func->variadic, bs_func->args_count, false);
	    }
	    else {
		// Still nothing, then let's call #method_missing.
		goto call_method_missing;
	    }
	}
    }

dispatch:
    if (cache->flag & MCACHE_RCALL) {
	if (!cache_method) {
	    cache->flag = 0;
	}

#if ROXOR_VM_DEBUG
	printf("ruby dispatch %c[<%s %p> %s] (imp %p block %p argc %d opt %d cache %p cached %s)\n",
		class_isMetaClass(klass) ? '+' : '-',
		class_getName(klass),
		(void *)self,
		sel_getName(sel),
		cache->as.rcall.node->ruby_imp,
		block,
		argc,
		opt,
		cache,
		cached ? "true" : "false");
#endif

	bool block_already_current = vm->is_block_current(block);
	Class current_klass = vm->get_current_class();
	if (!block_already_current) {
	    vm->add_current_block(block);
	}
	vm->set_current_class(NULL);

	Class old_current_super_class = vm->get_current_super_class();
	vm->set_current_super_class(current_super_class);
	SEL old_current_super_sel = vm->get_current_super_sel();
	vm->set_current_super_sel(current_super_sel);

	const bool should_pop_broken_with =
	    sel != selInitialize && sel != selInitialize2;

	struct Finally {
	    bool block_already_current;
	    Class current_class;
	    Class current_super_class;
	    SEL current_super_sel;
	    bool should_pop_broken_with;
	    RoxorVM *vm;
	    Finally(bool _block_already_current, Class _current_class,
		    Class _current_super_class, SEL _current_super_sel,
		    bool _should_pop_broken_with, RoxorVM *_vm) {
		block_already_current = _block_already_current;
		current_class = _current_class;
		current_super_class = _current_super_class;
		current_super_sel = _current_super_sel;
		should_pop_broken_with = _should_pop_broken_with;
		vm = _vm;
	    }
	    ~Finally() {
		if (!block_already_current) {
		    vm->pop_current_block();
		}
		vm->set_current_class(current_class);
		if (should_pop_broken_with) {
		    vm->pop_broken_with();
		}
		vm->set_current_super_class(current_super_class);
		vm->set_current_super_sel(current_super_sel);
		vm->pop_current_binding();
	    }
	} finalizer(block_already_current, current_klass,
		old_current_super_class, old_current_super_sel,
		should_pop_broken_with, vm);

	// DTrace probe: method__entry
	if (MACRUBY_METHOD_ENTRY_ENABLED()) {
	    char *class_name = (char *)rb_class2name((VALUE)klass);
	    char *method_name = (char *)sel_getName(sel);
	    char file[PATH_MAX];
	    unsigned long line = 0;
	    GET_CORE()->symbolize_backtrace_entry(1, file, sizeof file, &line,
		    NULL, 0);
	    MACRUBY_METHOD_ENTRY(class_name, method_name, file, line);
	}

	VALUE v = ruby_dispatch(top, self, sel, cache->as.rcall.node,
		opt, argc, argv);

	// DTrace probe: method__return
	if (MACRUBY_METHOD_RETURN_ENABLED()) {
	    char *class_name = (char *)rb_class2name((VALUE)klass);
	    char *method_name = (char *)sel_getName(sel);
	    char file[PATH_MAX];
	    unsigned long line = 0;
	    GET_CORE()->symbolize_backtrace_entry(1, file, sizeof file, &line,
		    NULL, 0);
	    MACRUBY_METHOD_RETURN(class_name, method_name, file, line);
	}

	return v;
    }
    else if (cache->flag & MCACHE_OCALL) {
	if (cache->as.ocall.argc != argc) {
	    goto recache;
	}
	if (!cache_method) {
	    cache->flag = 0;
	}

	if (block != NULL) {
	    rb_warn("passing a block to an Objective-C method - " \
		    "will be ignored");
	}
	else if (sel == selNew) {
	    if (self == rb_cNSMutableArray) {
		self = rb_cRubyArray;
	    }
	}
	else if (sel == selClass) {
	    // Because +[NSObject class] returns self.
	    if (RCLASS_META(klass)) {
		return RCLASS_MODULE(self) ? rb_cModule : rb_cClass;
	    }
	    // Because the CF classes should be hidden, for Ruby compat.
	    if (self == Qnil) {
		return rb_cNilClass;
	    }
	    if (self == Qtrue) {
		return rb_cTrueClass;
	    }
	    if (self == Qfalse) {
		return rb_cFalseClass;
	    }
	    return rb_class_real((VALUE)klass, true);
	}

#if ROXOR_VM_DEBUG
	printf("objc dispatch %c[<%s %p> %s] imp=%p cache=%p argc=%d (cached=%s)\n",
		class_isMetaClass(klass) ? '+' : '-',
		class_getName(klass),
		(void *)self,
		sel_getName(sel),
		cache->as.ocall.imp,
		cache,
		argc,
		cached ? "true" : "false");
#endif

	id ocrcv = RB2OC(self);

 	if (cache->as.ocall.bs_method != NULL) {
	    Class ocklass = object_getClass(ocrcv);
	    for (int i = 0; i < (int)cache->as.ocall.bs_method->args_count;
		    i++) {
		bs_element_arg_t *arg = &cache->as.ocall.bs_method->args[i];
		if (arg->sel_of_type != NULL) {
		    // BridgeSupport tells us that this argument contains a
		    // selector of the given type, but we don't have any
		    // information regarding the target. RubyCocoa and the
		    // other ObjC bridges do not really require it since they
		    // use the NSObject message forwarding mechanism, but
		    // MacRuby registers all methods in the runtime.
		    //
		    // Therefore, we apply here a naive heuristic by assuming
		    // that either the receiver or one of the arguments of this
		    // call is the future target.
		    const int arg_i = arg->index;
		    assert(arg_i >= 0 && arg_i < argc);
		    if (argv[arg_i] != Qnil) {
			ID arg_selid = rb_to_id(argv[arg_i]);
			SEL arg_sel = sel_registerName(rb_id2name(arg_selid));

			if (reinstall_method_maybe(ocklass, arg_sel,
				    arg->sel_of_type)) {
			    goto sel_target_found;
			}
			for (int j = 0; j < argc; j++) {
			    if (j != arg_i && !SPECIAL_CONST_P(argv[j])) {
				if (reinstall_method_maybe(*(Class *)argv[j],
					    arg_sel, arg->sel_of_type)) {
				    goto sel_target_found;
				}
			    }
			}
		    }

sel_target_found:
		    // There can only be one sel_of_type argument.
		    break; 
		}
	    }
	}

	return __rb_vm_objc_dispatch(cache->as.ocall.stub, cache->as.ocall.imp,
		ocrcv, sel, argc, argv);
    }
    else if (cache->flag & MCACHE_FCALL) {
#if ROXOR_VM_DEBUG
	printf("C dispatch %s() imp=%p argc=%d (cached=%s)\n",
		cache->as.fcall.bs_function->name,
		cache->as.fcall.imp,
		argc,
		cached ? "true" : "false");
#endif
	return (*cache->as.fcall.stub)(cache->as.fcall.imp, argc, argv);
    }

    printf("method dispatch is b0rked\n");
    abort();

call_method_missing:
    // Before calling method_missing, let's check if we are not in the following
    // cases:
    //
    //    def foo; end; foo(42)
    //    def foo(x); end; foo
    //
    // If yes, we need to raise an ArgumentError exception instead.
    const char *selname = sel_getName(sel);
    const size_t selname_len = strlen(selname);
    SEL new_sel = 0;

    if (argc > 0 && selname[selname_len - 1] == ':') {
	char buf[100];
	assert(sizeof buf > selname_len - 1);
	strlcpy(buf, selname, sizeof buf);
	buf[selname_len - 1] = '\0';
	new_sel = sel_registerName(buf);
    }
    else if (argc == 0) {
	char buf[100];
	snprintf(buf, sizeof buf, "%s:", selname);
	new_sel = sel_registerName(buf);
    }
    if (new_sel != 0) {
	Method m = class_getInstanceMethod(klass, new_sel);
	if (m != NULL) {
	    IMP mimp = method_getImplementation(m);
	    if (!UNAVAILABLE_IMP(mimp)) {
		unsigned expected_argc;
		rb_vm_method_node_t *node = GET_CORE()->method_node_get(m);
		if (node != NULL) {
		    expected_argc = node->arity.min;
		}
		else {
		    expected_argc = rb_method_getNumberOfArguments(m);
		    expected_argc -= 2; // removing receiver and selector
		}
		rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
			argc, expected_argc);
	    }
	}
    }

    rb_vm_method_missing_reason_t status;
    if (opt & DISPATCH_VCALL) {
	status = METHOD_MISSING_VCALL;
    }
    else if (opt & DISPATCH_SUPER) {
	status = METHOD_MISSING_SUPER;
    }
    else {
	status = METHOD_MISSING_DEFAULT;
    }
    return method_missing((VALUE)self, sel, block, argc, argv, status);
}
Beispiel #11
0
/*
 * Interprets cblas argument which could be :unit (true) or :nonunit (false or anything other than true/:unit)
 *
 * Called by nm_cblas_trsm -- basically inline
 */
static inline enum CBLAS_DIAG blas_diag_sym(VALUE op) {
  if (rb_to_id(op) == nm_rb_unit || op == Qtrue) return CblasUnit;
  return CblasNonUnit;
}
Beispiel #12
0
static VALUE rldap_search(int argc, VALUE *argv, VALUE obj)
{
	RLDAP_WRAP *wrapper;
	char *base, *filter;
	int retval, count, i, scope;
	LDAPMessage *res, *msg;
	VALUE ary, rbase, rfilter, rscope;
	ID iscope;
	
	rb_scan_args(argc, argv, "21", &rbase, &rfilter, &rscope);

	switch(TYPE(rscope)) {
		case T_NIL:
			scope = LDAP_SCOPE_SUBTREE;
			break;
		case T_FIXNUM:
			scope = FIX2INT(rscope);
			break;
		case T_SYMBOL:
		case T_STRING:
			iscope = rb_to_id(rscope);
			if (iscope == rb_intern("subtree"))
				scope = LDAP_SCOPE_SUBTREE;
			if (iscope == rb_intern("base"))
				scope = LDAP_SCOPE_BASE;
			if (iscope == rb_intern("one"))
				scope = LDAP_SCOPE_ONE;
			break;
		default:
			rb_raise(rb_eTypeError, "not a valid scope");
			break;
	}
	
	wrapper = get_wrapper(obj);
	base = StringValuePtr(rbase);
	filter = StringValuePtr(rfilter);

	retval = ldap_search_ext_s(wrapper->ld, base, scope, filter, NULL, 0, NULL, NULL, NULL, 0, &res);

	if (retval != LDAP_SUCCESS)
		rldap_raise(retval);

	count = ldap_count_entries(wrapper->ld, res);
	
	if (count == -1) {
		int errno;
		ldap_get_option(wrapper->ld, LDAP_OPT_RESULT_CODE, &errno);
		rldap_raise(errno);
	}
	
	ary = rb_ary_new2((long)count);
	
	msg = ldap_first_entry(wrapper->ld, res);
	
	for (i=0; i<count; i++) {
		rb_ary_store(ary, (long)i, ldapmessage2obj(wrapper->ld, msg));
		msg = ldap_next_entry(wrapper->ld, msg);
	}
	
	return ary;
}
Beispiel #13
0
static VALUE
rb_mod_protected_method_defined(VALUE mod, VALUE mid)
{
    return check_definition(mod, rb_to_id(mid), NOEX_PROTECTED);
}
Beispiel #14
0
static VALUE
rb_mod_private_method_defined(VALUE mod, SEL sel, VALUE mid)
{
    ID id = rb_to_id(mid);
    return check_method_visibility(mod, id, NOEX_PRIVATE);
}
Beispiel #15
0
static VALUE
rb_mod_autoload_p(VALUE mod, VALUE sym)
{
    return rb_autoload_p(mod, rb_to_id(sym));
}
Beispiel #16
0
static VALUE
rb_mod_protected_method_defined(VALUE mod, SEL sel, VALUE mid)
{
    ID id = rb_to_id(mid);
    return check_method_visibility(mod, id, NOEX_PROTECTED);
}
Beispiel #17
0
static VALUE so_to_id(VALUE self, VALUE obj) {
  return ID2SYM(rb_to_id(obj));
}
Beispiel #18
0
static VALUE
rb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname)
{
    rb_alias(mod, rb_to_id(newname), rb_to_id(oldname));
    return mod;
}
Beispiel #19
0
static VALUE rrrd_rrd_fetch(int argc, VALUE *argv, VALUE self) {
  VALUE function, options;
  VALUE resolution, starts_at, ends_at;

  rb_scan_args(argc, argv, "11", &function, &options);

  list arguments = rrrd_list_new();
  rrrd_add_filename_arg(self, &arguments);

  // consolidation function
  function = rb_str_new2(rb_id2name(rb_to_id(function)));
  function = rb_funcall(function, rb_intern("upcase"), 0);
  rrrd_add_arg(&arguments, STR2CSTR(function));

  if (RTEST(options)) {
    // extract options from hash
    resolution = rb_hash_aref(options, ID2SYM(rb_intern("resolution")));
    starts_at = rb_hash_aref(options, ID2SYM(rb_intern("starts_at")));
    ends_at = rb_hash_aref(options, ID2SYM(rb_intern("ends_at")));

    // resolution
    if (RTEST(resolution)) {
      resolution = rb_fix2str(resolution, 10);

      rrrd_add_arg(&arguments, "--resolution");
      rrrd_add_arg(&arguments, STR2CSTR(resolution));
    }

    // start time
    if (RTEST(starts_at)) {
      starts_at = rb_funcall(starts_at, rb_intern("to_i"), 0);
      starts_at = rb_fix2str(starts_at, 10);

      rrrd_add_arg(&arguments, "--start");
      rrrd_add_arg(&arguments, STR2CSTR(starts_at));
    }

    // end time
    if (RTEST(ends_at)) {
      ends_at = rb_funcall(ends_at, rb_intern("to_i"), 0);
      ends_at = rb_fix2str(ends_at, 10);

      rrrd_add_arg(&arguments, "--end");
      rrrd_add_arg(&arguments, STR2CSTR(ends_at));
    }
  }

  time_t start, end;
  unsigned long step, ds_count;
  char **raw_names;
  rrd_value_t *raw_data;

  rrd_fetch(arguments.length, arguments.strings, &start, &end, &step, &ds_count, &raw_names, &raw_data);
  rrrd_free_arguments(arguments);
  rrrd_check_for_errors();

  int i;
  int index = 0;
  VALUE data = rb_ary_new();

  for (i = start + step; i <= end; i+= step) {
    int j;
    VALUE timestamp = rb_time_new(i, 0);
    VALUE values = rb_hash_new();

    for (j = 0; j < ds_count; j++) {
      VALUE key = ID2SYM(rb_intern(raw_names[j]));
      rb_hash_aset(values, key, rb_float_new(raw_data[index++]));
    }

    VALUE args[] = { timestamp, values };
    VALUE tuple = rb_class_new_instance(2, args, Tuple);

    rb_ary_push(data, tuple);
  }

  free(raw_data);

  return data;
}
Beispiel #20
0
VALUE
rb_obj_method(VALUE obj, VALUE vid)
{
    return mnew(CLASS_OF(obj), obj, rb_to_id(vid), rb_cMethod, Qfalse);
}
Beispiel #21
0
static VALUE
nstruct_add_type(VALUE type, int argc, VALUE *argv, VALUE nst)
{
    VALUE ofs, size;
    ID id;
    int i;
    VALUE name=Qnil;
    size_t *shape=NULL;
    int ndim=0;
    ssize_t stride;
    narray_view_t *nt;
    int j;

    for (i=0; i<argc; i++) {
        switch(TYPE(argv[i])) {
        case T_STRING:
        case T_SYMBOL:
            if (NIL_P(name)) {
                name = argv[i];
                break;
            }
            rb_raise(rb_eArgError,"multiple name in struct definition");
        case T_ARRAY:
            if (shape) {
                rb_raise(rb_eArgError,"multiple shape in struct definition");
            }
            ndim = RARRAY_LEN(argv[i]);
            if (ndim > NA_MAX_DIMENSION) {
                rb_raise(rb_eArgError,"too large number of dimensions");
            }
            if (ndim == 0) {
                rb_raise(rb_eArgError,"array is empty");
            }
            shape = ALLOCA_N(size_t, ndim);
            na_array_to_internal_shape(Qnil, argv[i], shape);
            break;
        }
    }

    id = rb_to_id(name);
    name = ID2SYM(id);
    if (rb_obj_is_kind_of(type,cNArray)) {
        narray_t *na;
        GetNArray(type,na);
        type = CLASS_OF(type);
        ndim = na->ndim;
        shape = na->shape;
    }
    type = rb_narray_view_new(type,ndim,shape);
    GetNArrayView(type,nt);

    nt->stridx = ALLOC_N(stridx_t,ndim);
    stride = na_dtype_elmsz(CLASS_OF(type));
    for (j=ndim; j--; ) {
        SDX_SET_STRIDE(nt->stridx[j], stride);
        stride *= shape[j];
    }

    ofs  = rb_iv_get(nst, "__offset__");
    nt->offset = NUM2SIZE(ofs);

    size = rb_funcall(type, rb_intern("byte_size"), 0);
    rb_iv_set(nst, "__offset__", rb_funcall(ofs,'+',1,size));
    rb_ary_push(rb_iv_get(nst,"__members__"),
                rb_ary_new3(4,name,type,ofs,size));  // <- field definition
    return Qnil;
}
Beispiel #22
0
static VALUE
rb_mod_public_instance_method(VALUE mod, VALUE vid)
{
    return mnew(mod, Qundef, rb_to_id(vid), rb_cUnboundMethod, Qtrue);
}
Beispiel #23
0
static VALUE
rb_mod_public_method_defined(VALUE mod, VALUE mid)
{
    return check_definition(mod, rb_to_id(mid), NOEX_PUBLIC);
}