예제 #1
0
VALUE
rb_gi_function_info_invoke_raw(GIFunctionInfo *info, VALUE rb_options,
                               GIArgument *return_value)
{
    GICallableInfo *callable_info;
    GIArgument receiver;
    GArray *in_args, *out_args;
    GPtrArray *args_metadata;
    VALUE rb_out_args = Qnil;
    gboolean succeeded;
    GError *error = NULL;
    gboolean unlock_gvl = FALSE;
    VALUE rb_receiver, rb_arguments, rb_unlock_gvl;

    if (RB_TYPE_P(rb_options, RUBY_T_ARRAY)) {
        rb_receiver = Qnil;
        rb_arguments = rb_options;
        rb_unlock_gvl = Qnil;
    } else if (NIL_P(rb_options)) {
        rb_receiver = Qnil;
        rb_arguments = rb_ary_new();
        rb_unlock_gvl = Qnil;
    } else {
        rb_options = rbg_check_hash_type(rb_options);
        rbg_scan_options(rb_options,
                         "receiver", &rb_receiver,
                         "arguments", &rb_arguments,
                         "unlock_gvl", &rb_unlock_gvl,
                         NULL);
    }

    if (NIL_P(rb_receiver)) {
        receiver.v_pointer = NULL;
    } else {
        if (gobject_based_p((GIBaseInfo *)info)) {
            receiver.v_pointer = RVAL2GOBJ(rb_receiver);
        } else {
            receiver.v_pointer = DATA_PTR(rb_receiver);
        }
    }
    rb_arguments = rbg_to_array(rb_arguments);
    if (!NIL_P(rb_unlock_gvl) && RVAL2CBOOL(rb_unlock_gvl)) {
        unlock_gvl = TRUE;
    }

    callable_info = (GICallableInfo *)info;
    arguments_init(&in_args, &out_args, &args_metadata);
    if (receiver.v_pointer) {
        g_array_append_val(in_args, receiver);
    }
    arguments_from_ruby(callable_info, rb_arguments,
                        in_args, out_args, args_metadata);
    {
        InvokeData data;
        data.info = info;
        data.in_args = in_args;
        data.out_args = out_args;
        data.return_value = return_value;
        data.error = &error;
        if (unlock_gvl) {
            rb_thread_call_without_gvl(
                rb_gi_function_info_invoke_raw_call_without_gvl_body, &data,
                NULL, NULL);
        } else {
            rb_gi_function_info_invoke_raw_call(&data);
        }
        succeeded = data.succeeded;
    }

    if (succeeded) {
        rb_out_args = out_arguments_to_ruby(callable_info,
                                            in_args, out_args,
                                            args_metadata);
    }
    arguments_free(in_args, out_args, args_metadata);
    if (!succeeded) {
        RG_RAISE_ERROR(error);
    }

    if (!NIL_P(rb_out_args) && RARRAY_LEN(rb_out_args) == 1) {
        VALUE rb_out_arg;
        rb_out_arg = RARRAY_PTR(rb_out_args)[0];
        if (rb_obj_is_kind_of(rb_out_arg, rb_eException)) {
            rb_exc_raise(rb_out_arg);
        }
    }

    return rb_out_args;
}
예제 #2
0
static int write_element_allow_id(VALUE key, VALUE value, VALUE extra, int allow_id) {
    bson_buffer* buffer = (bson_buffer*)NUM2INT(rb_ary_entry(extra, 0));
    VALUE check_keys = rb_ary_entry(extra, 1);

    if (TYPE(key) == T_SYMBOL) {
        // TODO better way to do this... ?
        key = rb_str_new2(rb_id2name(SYM2ID(key)));
    }

    if (TYPE(key) != T_STRING) {
        rb_raise(rb_eTypeError, "keys must be strings or symbols");
    }

    if (!allow_id && strcmp("_id", RSTRING_PTR(key)) == 0) {
        return ST_CONTINUE;
    }

    if (check_keys == Qtrue) {
        if (RSTRING_LEN(key) > 0 && RSTRING_PTR(key)[0] == '$') {
            rb_raise(rb_eRuntimeError, "key must not start with '$'");
        }
        int i;
        for (i = 0; i < RSTRING_LEN(key); i++) {
            if (RSTRING_PTR(key)[i] == '.') {
                rb_raise(rb_eRuntimeError, "key must not contain '.'");
            }
        }
    }

    switch(TYPE(value)) {
    case T_BIGNUM:
        {
            if (rb_funcall(value, rb_intern(">"), 1, INT2NUM(2147483647)) == Qtrue ||
                rb_funcall(value, rb_intern("<"), 1, INT2NUM(-2147483648)) == Qtrue) {
                rb_raise(rb_eRangeError, "MongoDB can only handle 4-byte ints - try converting to a double before saving");
            }
            write_name_and_type(buffer, key, 0x10);
            VALUE as_f = rb_funcall(value, rb_intern("to_f"), 0);
            int int_value = NUM2LL(as_f);
            buffer_write_bytes(buffer, (char*)&int_value, 4);
            break;
        }
    case T_FIXNUM:
        {
            write_name_and_type(buffer, key, 0x10);
            int int_value = FIX2INT(value);
            buffer_write_bytes(buffer, (char*)&int_value, 4);
            break;
        }
    case T_TRUE:
        {
            write_name_and_type(buffer, key, 0x08);
            buffer_write_bytes(buffer, &one, 1);
            break;
        }
    case T_FALSE:
        {
            write_name_and_type(buffer, key, 0x08);
            buffer_write_bytes(buffer, &zero, 1);
            break;
        }
    case T_FLOAT:
        {
            write_name_and_type(buffer, key, 0x01);
            double d = NUM2DBL(value);
            buffer_write_bytes(buffer, (char*)&d, 8);
            break;
        }
    case T_NIL:
        {
            write_name_and_type(buffer, key, 0x0A);
            break;
        }
    case T_HASH:
        {
            write_name_and_type(buffer, key, 0x03);
            write_doc(buffer, value, check_keys);
            break;
        }
    case T_ARRAY:
        {
            write_name_and_type(buffer, key, 0x04);
            int start_position = buffer->position;

            // save space for length
            int length_location = buffer_save_bytes(buffer, 4);

            int items = RARRAY_LEN(value);
            VALUE* values = RARRAY_PTR(value);
            int i;
            for(i = 0; i < items; i++) {
                char* name;
                asprintf(&name, "%d", i);
                VALUE key = rb_str_new2(name);
                write_element(key, values[i], pack_extra(buffer, check_keys));
                free(name);
            }

            // write null byte and fill in length
            buffer_write_bytes(buffer, &zero, 1);
            int obj_length = buffer->position - start_position;
            memcpy(buffer->buffer + length_location, &obj_length, 4);
            break;
        }
    case T_STRING:
        {
            if (strcmp(rb_class2name(RBASIC(value)->klass),
                       "XGen::Mongo::Driver::Code") == 0) {
                write_name_and_type(buffer, key, 0x0F);

                int start_position = buffer->position;
                int length_location = buffer_save_bytes(buffer, 4);

                int length = RSTRING_LEN(value) + 1;
                buffer_write_bytes(buffer, (char*)&length, 4);
                buffer_write_bytes(buffer, RSTRING_PTR(value), length - 1);
                buffer_write_bytes(buffer, &zero, 1);
                write_doc(buffer, rb_funcall(value, rb_intern("scope"), 0), Qfalse);

                int total_length = buffer->position - start_position;
                memcpy(buffer->buffer + length_location, &total_length, 4);

                break;
            } else {
                write_name_and_type(buffer, key, 0x02);
                int length = RSTRING_LEN(value) + 1;
                buffer_write_bytes(buffer, (char*)&length, 4);
                buffer_write_bytes(buffer, RSTRING_PTR(value), length - 1);
                buffer_write_bytes(buffer, &zero, 1);
                break;
            }
        }
    case T_SYMBOL:
        {
            write_name_and_type(buffer, key, 0x0E);
            const char* str_value = rb_id2name(SYM2ID(value));
            int length = strlen(str_value) + 1;
            buffer_write_bytes(buffer, (char*)&length, 4);
            buffer_write_bytes(buffer, str_value, length);
            break;
        }
    case T_OBJECT:
        {
            // TODO there has to be a better way to do these checks...
            const char* cls = rb_class2name(RBASIC(value)->klass);
            if (strcmp(cls, "XGen::Mongo::Driver::Binary") == 0 ||
                strcmp(cls, "ByteBuffer") == 0) {
                write_name_and_type(buffer, key, 0x05);
                const char subtype = strcmp(cls, "ByteBuffer") ?
                    (const char)FIX2INT(rb_funcall(value, rb_intern("subtype"), 0)) : 2;
                VALUE string_data = rb_funcall(value, rb_intern("to_s"), 0);
                int length = RSTRING_LEN(string_data);
                if (subtype == 2) {
                    const int other_length = length + 4;
                    buffer_write_bytes(buffer, (const char*)&other_length, 4);
                    buffer_write_bytes(buffer, &subtype, 1);
                }
                buffer_write_bytes(buffer, (const char*)&length, 4);
                if (subtype != 2) {
                    buffer_write_bytes(buffer, &subtype, 1);
                }
                buffer_write_bytes(buffer, RSTRING_PTR(string_data), length);
                break;
            }
            if (strcmp(cls, "XGen::Mongo::Driver::ObjectID") == 0) {
                write_name_and_type(buffer, key, 0x07);
                VALUE as_array = rb_funcall(value, rb_intern("to_a"), 0);
                int i;
                for (i = 0; i < 12; i++) {
                    char byte = (char)FIX2INT(RARRAY_PTR(as_array)[i]);
                    buffer_write_bytes(buffer, &byte, 1);
                }
                break;
            }
            if (strcmp(cls, "XGen::Mongo::Driver::DBRef") == 0) {
                write_name_and_type(buffer, key, 0x03);

                int start_position = buffer->position;

                // save space for length
                int length_location = buffer_save_bytes(buffer, 4);

                VALUE ns = rb_funcall(value, rb_intern("namespace"), 0);
                write_element(rb_str_new2("$ref"), ns, pack_extra(buffer, Qfalse));
                VALUE oid = rb_funcall(value, rb_intern("object_id"), 0);
                write_element(rb_str_new2("$id"), oid, pack_extra(buffer, Qfalse));

                // write null byte and fill in length
                buffer_write_bytes(buffer, &zero, 1);
                int obj_length = buffer->position - start_position;
                memcpy(buffer->buffer + length_location, &obj_length, 4);
                break;
            }
            if (strcmp(cls, "XGen::Mongo::Driver::Undefined") == 0) {
                write_name_and_type(buffer, key, 0x06);
                break;
            }
        }
    case T_DATA:
        {
            // TODO again, is this really the only way to do this?
            const char* cls = rb_class2name(RBASIC(value)->klass);
            if (strcmp(cls, "Time") == 0) {
                write_name_and_type(buffer, key, 0x09);
                double t = NUM2DBL(rb_funcall(value, rb_intern("to_f"), 0));
                long long time_since_epoch = (long long)round(t * 1000);
                buffer_write_bytes(buffer, (const char*)&time_since_epoch, 8);
                break;
            }
        }
    case T_REGEXP:
        {
            write_name_and_type(buffer, key, 0x0B);

            int length = RREGEXP_SRC_LEN(value);
            char* pattern = (char*)RREGEXP_SRC_PTR(value);
            buffer_write_bytes(buffer, pattern, length);
            buffer_write_bytes(buffer, &zero, 1);

            long flags = RREGEXP(value)->ptr->options;
            if (flags & IGNORECASE) {
                char ignorecase = 'i';
                buffer_write_bytes(buffer, &ignorecase, 1);
            }
            if (flags & MULTILINE) {
                char multiline = 'm';
                buffer_write_bytes(buffer, &multiline, 1);
            }
            if (flags & EXTENDED) {
                char extended = 'x';
                buffer_write_bytes(buffer, &extended, 1);
            }

            VALUE has_extra = rb_funcall(value, rb_intern("respond_to?"), 1, rb_str_new2("extra_options_str"));
            if (TYPE(has_extra) == T_TRUE) {
                VALUE extra = rb_funcall(value, rb_intern("extra_options_str"), 0);
                int old_position = buffer->position;
                buffer_write_bytes(buffer, RSTRING_PTR(extra), RSTRING_LEN(extra));
                qsort(buffer->buffer + old_position, RSTRING_LEN(extra), sizeof(char), cmp_char);
            }
            buffer_write_bytes(buffer, &zero, 1);

            break;
        }
    default:
        {
            rb_raise(rb_eTypeError, "no c encoder for this type yet (%d)", TYPE(value));
            break;
        }
    }
    return ST_CONTINUE;
}
예제 #3
0
static VALUE
ossl_ocspbres_add_status(VALUE self, VALUE cid, VALUE status,
			 VALUE reason, VALUE revtime,
			 VALUE thisupd, VALUE nextupd, VALUE ext)
{
    OCSP_BASICRESP *bs;
    OCSP_SINGLERESP *single;
    OCSP_CERTID *id;
    int st, rsn;
    ASN1_TIME *ths, *nxt, *rev;
    int error, i, rstatus = 0;
    VALUE tmp;

    st = NUM2INT(status);
    rsn = NIL_P(status) ? 0 : NUM2INT(reason);
    if(!NIL_P(ext)){
	/* All ary's members should be X509Extension */
	Check_Type(ext, T_ARRAY);
	for (i = 0; i < RARRAY_LEN(ext); i++)
	    OSSL_Check_Kind(RARRAY_PTR(ext)[i], cX509Ext);
    }

    error = 0;
    ths = nxt = rev = NULL;
    if(!NIL_P(revtime)){
	tmp = rb_protect(rb_Integer, revtime, &rstatus);
	if(rstatus) goto err;
	rev = X509_gmtime_adj(NULL, NUM2INT(tmp));
    }
    tmp = rb_protect(rb_Integer, thisupd, &rstatus);
    if(rstatus) goto err;
    ths = X509_gmtime_adj(NULL, NUM2INT(tmp));
    tmp = rb_protect(rb_Integer, nextupd, &rstatus);
    if(rstatus) goto err;
    nxt = X509_gmtime_adj(NULL, NUM2INT(tmp));

    GetOCSPBasicRes(self, bs);
    SafeGetOCSPCertId(cid, id);
    if(!(single = OCSP_basic_add1_status(bs, id, st, rsn, rev, ths, nxt))){
	error = 1;
	goto err;
    }

    if(!NIL_P(ext)){
	X509_EXTENSION *x509ext;
	sk_X509_EXTENSION_pop_free(single->singleExtensions, X509_EXTENSION_free);
	single->singleExtensions = NULL;
	for(i = 0; i < RARRAY_LEN(ext); i++){
	    x509ext = DupX509ExtPtr(RARRAY_PTR(ext)[i]);
	    if(!OCSP_SINGLERESP_add_ext(single, x509ext, -1)){
		X509_EXTENSION_free(x509ext);
		error = 1;
		goto err;
	    }
	    X509_EXTENSION_free(x509ext);
	}
    }

 err:
    ASN1_TIME_free(ths);
    ASN1_TIME_free(nxt);
    ASN1_TIME_free(rev);
    if(error) ossl_raise(eOCSPError, NULL);
    if(rstatus) rb_jump_tag(rstatus);

    return self;
}
예제 #4
0
void
callback(ffi_cif *cif, void *resp, void **args, void *ctx)
{
    VALUE self      = (VALUE)ctx;
    VALUE rbargs    = rb_iv_get(self, "@args");
    VALUE ctype     = rb_iv_get(self, "@ctype");
    int argc        = RARRAY_LENINT(rbargs);
    VALUE params    = rb_ary_tmp_new(argc);
    VALUE ret;
    VALUE cPointer;
    int i, type;

    cPointer = rb_const_get(mFiddle, rb_intern("Pointer"));

    for (i = 0; i < argc; i++) {
        type = NUM2INT(RARRAY_PTR(rbargs)[i]);
        switch (type) {
        case TYPE_VOID:
            argc = 0;
            break;
        case TYPE_INT:
            rb_ary_push(params, INT2NUM(*(int *)args[i]));
            break;
        case -TYPE_INT:
            rb_ary_push(params, UINT2NUM(*(unsigned int *)args[i]));
            break;
        case TYPE_VOIDP:
            rb_ary_push(params,
                        rb_funcall(cPointer, rb_intern("[]"), 1,
                                   PTR2NUM(*(void **)args[i])));
            break;
        case TYPE_LONG:
            rb_ary_push(params, LONG2NUM(*(long *)args[i]));
            break;
        case -TYPE_LONG:
            rb_ary_push(params, ULONG2NUM(*(unsigned long *)args[i]));
            break;
        case TYPE_CHAR:
            rb_ary_push(params, INT2NUM(*(signed char *)args[i]));
            break;
        case -TYPE_CHAR:
            rb_ary_push(params, UINT2NUM(*(unsigned char *)args[i]));
            break;
        case TYPE_SHORT:
            rb_ary_push(params, INT2NUM(*(signed short *)args[i]));
            break;
        case -TYPE_SHORT:
            rb_ary_push(params, UINT2NUM(*(unsigned short *)args[i]));
            break;
        case TYPE_DOUBLE:
            rb_ary_push(params, rb_float_new(*(double *)args[i]));
            break;
        case TYPE_FLOAT:
            rb_ary_push(params, rb_float_new(*(float *)args[i]));
            break;
#if HAVE_LONG_LONG
        case TYPE_LONG_LONG:
            rb_ary_push(params, LL2NUM(*(LONG_LONG *)args[i]));
            break;
        case -TYPE_LONG_LONG:
            rb_ary_push(params, ULL2NUM(*(unsigned LONG_LONG *)args[i]));
            break;
#endif
        default:
            rb_raise(rb_eRuntimeError, "closure args: %d", type);
        }
    }

    ret = rb_funcall2(self, rb_intern("call"), argc, RARRAY_PTR(params));
    RB_GC_GUARD(params);

    type = NUM2INT(ctype);
    switch (type) {
    case TYPE_VOID:
        break;
    case TYPE_LONG:
        *(long *)resp = NUM2LONG(ret);
        break;
    case -TYPE_LONG:
        *(unsigned long *)resp = NUM2ULONG(ret);
        break;
    case TYPE_CHAR:
    case TYPE_SHORT:
    case TYPE_INT:
        *(ffi_sarg *)resp = NUM2INT(ret);
        break;
    case -TYPE_CHAR:
    case -TYPE_SHORT:
    case -TYPE_INT:
        *(ffi_arg *)resp = NUM2UINT(ret);
        break;
    case TYPE_VOIDP:
        *(void **)resp = NUM2PTR(ret);
        break;
    case TYPE_DOUBLE:
        *(double *)resp = NUM2DBL(ret);
        break;
    case TYPE_FLOAT:
        *(float *)resp = (float)NUM2DBL(ret);
        break;
#if HAVE_LONG_LONG
    case TYPE_LONG_LONG:
        *(LONG_LONG *)resp = NUM2LL(ret);
        break;
    case -TYPE_LONG_LONG:
        *(unsigned LONG_LONG *)resp = NUM2ULL(ret);
        break;
#endif
    default:
        rb_raise(rb_eRuntimeError, "closure retval: %d", type);
    }
}
예제 #5
0
void
rb_vm_bugreport(void)
{
#ifdef __linux__
# define PROC_MAPS_NAME "/proc/self/maps"
#endif
#ifdef PROC_MAPS_NAME
    enum {other_runtime_info = 1};
#else
    enum {other_runtime_info = 0};
#endif
    const rb_vm_t *const vm = GET_VM();
    if (vm) {
	SDR();
	rb_backtrace_print_as_bugreport();
	fputs("\n", stderr);
    }

#if HAVE_BACKTRACE || defined(_WIN32)
    fprintf(stderr, "-- C level backtrace information "
	    "-------------------------------------------\n");

    {
#if defined __APPLE__
	fprintf(stderr, "\n");
	fprintf(stderr,
		"   See Crash Report log file under the one of following:\n"
		"     * ~/Library/Logs/CrashReporter\n"
		"     * /Library/Logs/CrashReporter\n"
		"     * ~/Library/Logs/DiagnosticReports\n"
		"     * /Library/Logs/DiagnosticReports\n"
		"   the more detail of.\n");
#elif HAVE_BACKTRACE
#define MAX_NATIVE_TRACE 1024
	static void *trace[MAX_NATIVE_TRACE];
	int n = backtrace(trace, MAX_NATIVE_TRACE);
	char **syms = backtrace_symbols(trace, n);

	if (syms) {
#ifdef USE_ELF
	    rb_dump_backtrace_with_lines(n, trace, syms);
#else
	    int i;
	    for (i=0; i<n; i++) {
		fprintf(stderr, "%s\n", syms[i]);
	    }
#endif
	    free(syms);
	}
#elif defined(_WIN32)
	DWORD tid = GetCurrentThreadId();
	HANDLE th = (HANDLE)_beginthread(dump_thread, 0, &tid);
	if (th != (HANDLE)-1)
	    WaitForSingleObject(th, INFINITE);
#endif
    }

    fprintf(stderr, "\n");
#endif /* HAVE_BACKTRACE */

    if (other_runtime_info || vm) {
	fprintf(stderr, "-- Other runtime information "
		"-----------------------------------------------\n\n");
    }
    if (vm) {
	int i;
	VALUE name;
	long len;
	const int max_name_length = 1024;
# define LIMITED_NAME_LENGTH(s) \
	(((len = RSTRING_LEN(s)) > max_name_length) ? max_name_length : (int)len)

	name = vm->progname;
	fprintf(stderr, "* Loaded script: %.*s\n",
		LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
	fprintf(stderr, "\n");
	fprintf(stderr, "* Loaded features:\n\n");
	for (i=0; i<RARRAY_LEN(vm->loaded_features); i++) {
	    name = RARRAY_PTR(vm->loaded_features)[i];
	    if (RB_TYPE_P(name, T_STRING)) {
		fprintf(stderr, " %4d %.*s\n", i,
			LIMITED_NAME_LENGTH(name), RSTRING_PTR(name));
	    }
	    else {
		fprintf(stderr, " %4d #<%s:%p>\n", i,
			rb_class2name(CLASS_OF(name)), (void *)name);
	    }
	}
	fprintf(stderr, "\n");
    }

    {
#ifdef PROC_MAPS_NAME
	{
	    FILE *fp = fopen(PROC_MAPS_NAME, "r");
	    if (fp) {
		fprintf(stderr, "* Process memory map:\n\n");

		while (!feof(fp)) {
		    char buff[0x100];
		    size_t rn = fread(buff, 1, 0x100, fp);
		    if (fwrite(buff, 1, rn, stderr) != rn)
			break;
		}

		fclose(fp);
		fprintf(stderr, "\n\n");
	    }
	}
#endif /* __linux__ */
    }
}
예제 #6
0
#include <ruby.h>
#include <stdio.h>
#include <stdlib.h>

static VALUE rb_mXor;

static VALUE xor_multi(VALUE class, VALUE rb_blocks, VALUE buffer) {
  unsigned int numBlocks = RARRAY_LEN(rb_blocks);
  unsigned long i;
  unsigned long j;
  VALUE *element = RARRAY_PTR(rb_blocks);
  unsigned long length = NUM2INT(buffer);
  unsigned char *outbuf = calloc(length,sizeof(*outbuf));
  unsigned char *data_str;
  VALUE ruby_return_str;
  
  if(outbuf == NULL){
    printf("Unable to allocate memory\n");
    exit;
  }
  
  for(i=0;i<numBlocks;i++){
    data_str = RSTRING_PTR(*element);
    for(j=0;j<length;j++){
      //printf("%i ^= %i ==",outbuf[j],data_str[j]);
      outbuf[j] ^= data_str[j];
      //printf("%i\n",outbuf[j]);
    }
    element++;
  }
  ruby_return_str = rb_str_new2(outbuf);
예제 #7
0
파일: struct.c 프로젝트: nyanp/mruby
mrb_value
mrb_struct_initialize(mrb_state *mrb, mrb_value self, mrb_value values)
{
  return mrb_struct_initialize_withArg(mrb, RARRAY_LEN(values), RARRAY_PTR(values), self);
}
예제 #8
0
static void
error_print(void)
{
    volatile VALUE errat = Qnil;		/* OK */
    VALUE errinfo = GET_THREAD()->errinfo;
    volatile VALUE eclass, e;
    const char *volatile einfo;
    volatile long elen;

    if (NIL_P(errinfo))
	return;

    PUSH_TAG();
    if (EXEC_TAG() == 0) {
	errat = get_backtrace(errinfo);
    }
    else {
	errat = Qnil;
    }
    if (EXEC_TAG())
	goto error;
    if (NIL_P(errat)) {
	const char *file = rb_sourcefile();
	int line = rb_sourceline();
	if (!file)
	    warn_printf("%d", line);
	else if (!line)
	    warn_printf("%s", file);
	else
	    warn_printf("%s:%d", file, line);
    }
    else if (RARRAY_LEN(errat) == 0) {
	error_pos();
    }
    else {
	VALUE mesg = RARRAY_PTR(errat)[0];

	if (NIL_P(mesg))
	    error_pos();
	else {
	    warn_print2(RSTRING_PTR(mesg), RSTRING_LEN(mesg));
	}
    }

    eclass = CLASS_OF(errinfo);
    if (EXEC_TAG() == 0) {
	e = rb_funcall(errinfo, rb_intern("message"), 0, 0);
	StringValue(e);
	einfo = RSTRING_PTR(e);
	elen = RSTRING_LEN(e);
    }
    else {
	einfo = "";
	elen = 0;
    }
    if (EXEC_TAG())
	goto error;
    if (eclass == rb_eRuntimeError && elen == 0) {
	warn_print(": unhandled exception\n");
    }
    else {
	VALUE epath;

	epath = rb_class_name(eclass);
	if (elen == 0) {
	    warn_print(": ");
	    warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
	    warn_print("\n");
	}
	else {
	    char *tail = 0;
	    long len = elen;

	    if (RSTRING_PTR(epath)[0] == '#')
		epath = 0;
	    if ((tail = memchr(einfo, '\n', elen)) != 0) {
		len = tail - einfo;
		tail++;		/* skip newline */
	    }
	    warn_print(": ");
	    warn_print2(einfo, len);
	    if (epath) {
		warn_print(" (");
		warn_print2(RSTRING_PTR(epath), RSTRING_LEN(epath));
		warn_print(")\n");
	    }
	    if (tail) {
		warn_print2(tail, elen - len - 1);
		if (einfo[elen-1] != '\n') warn_print2("\n", 1);
	    }
	}
    }

    if (!NIL_P(errat)) {
	long i;
	long len = RARRAY_LEN(errat);
	VALUE *ptr = RARRAY_PTR(errat);
        int skip = eclass == rb_eSysStackError;

#define TRACE_MAX (TRACE_HEAD+TRACE_TAIL+5)
#define TRACE_HEAD 8
#define TRACE_TAIL 5

	for (i = 1; i < len; i++) {
	    if (TYPE(ptr[i]) == T_STRING) {
		warn_printf("\tfrom %s\n", RSTRING_PTR(ptr[i]));
	    }
	    if (skip && i == TRACE_HEAD && len > TRACE_MAX) {
		warn_printf("\t ... %ld levels...\n",
			    len - TRACE_HEAD - TRACE_TAIL);
		i = len - TRACE_TAIL;
	    }
	}
    }
  error:
    POP_TAG();
}
예제 #9
0
static VALUE array_spec_rb_ary_aref(int argc, VALUE *argv, VALUE self) {
  VALUE ary, args;
  rb_scan_args(argc, argv, "1*", &ary, &args);
  return rb_ary_aref((int)RARRAY_LEN(args), RARRAY_PTR(args), ary);
}
예제 #10
0
static inline int
caller_setup_args(const rb_thread_t *th, rb_control_frame_t *cfp, VALUE flag,
		  int argc, rb_iseq_t *blockiseq, rb_block_t **block)
{
    rb_block_t *blockptr = 0;

    if (block) {
	if (flag & VM_CALL_ARGS_BLOCKARG_BIT) {
	    rb_proc_t *po;
	    VALUE proc;

	    proc = *(--cfp->sp);

	    if (proc != Qnil) {
		if (!rb_obj_is_proc(proc)) {
		    VALUE b = rb_check_convert_type(proc, T_DATA, "Proc", "to_proc");
		    if (NIL_P(b) || !rb_obj_is_proc(b)) {
			rb_raise(rb_eTypeError,
				 "wrong argument type %s (expected Proc)",
				 rb_obj_classname(proc));
		    }
		    proc = b;
		}
		GetProcPtr(proc, po);
		blockptr = &po->block;
		RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp)->proc = proc;
		*block = blockptr;
	    }
	}
	else if (blockiseq) {
	    blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
	    blockptr->iseq = blockiseq;
	    blockptr->proc = 0;
	    *block = blockptr;
	}
    }

    /* expand top of stack? */
    if (flag & VM_CALL_ARGS_SPLAT_BIT) {
	VALUE ary = *(cfp->sp - 1);
	VALUE *ptr;
	int i;
	VALUE tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a");

	if (NIL_P(tmp)) {
	    /* do nothing */
	}
	else {
	    long len = RARRAY_LEN(tmp);
	    ptr = RARRAY_PTR(tmp);
	    cfp->sp -= 1;

	    CHECK_STACK_OVERFLOW(cfp, len);

	    for (i = 0; i < len; i++) {
		*cfp->sp++ = ptr[i];
	    }
	    argc += i-1;
	}
    }

    return argc;
}
예제 #11
0
static inline int
vm_yield_setup_block_args(rb_thread_t *th, const rb_iseq_t * iseq,
			  int orig_argc, VALUE *argv,
			  const rb_block_t *blockptr)
{
    int i;
    int argc = orig_argc;
    const int m = iseq->argc;
    VALUE ary, arg0;
    int opt_pc = 0;

    th->mark_stack_len = argc;

    /*
     * yield [1, 2]
     *  => {|a|} => a = [1, 2]
     *  => {|a, b|} => a, b = [1, 2]
     */
    arg0 = argv[0];
    if (!(iseq->arg_simple & 0x02) &&          /* exclude {|a|} */
            (m + iseq->arg_post_len) > 0 &&    /* this process is meaningful */
            argc == 1 && !NIL_P(ary = rb_check_array_type(arg0))) { /* rhs is only an array */
        th->mark_stack_len = argc = RARRAY_LENINT(ary);

        CHECK_STACK_OVERFLOW(th->cfp, argc);

        MEMCPY(argv, RARRAY_PTR(ary), VALUE, argc);
    }
    else {
        argv[0] = arg0;
    }

    for (i=argc; i<m; i++) {
        argv[i] = Qnil;
    }

    if (iseq->arg_rest == -1 && iseq->arg_opts == 0) {
        const int arg_size = iseq->arg_size;
        if (arg_size < argc) {
            /*
             * yield 1, 2
             * => {|a|} # truncate
             */
            th->mark_stack_len = argc = arg_size;
        }
    }
    else {
        int r = iseq->arg_rest;

        if (iseq->arg_post_len ||
                iseq->arg_opts) { /* TODO: implement simple version for (iseq->arg_post_len==0 && iseq->arg_opts > 0) */
	    opt_pc = vm_yield_setup_block_args_complex(th, iseq, argc, argv);
        }
        else {
            if (argc < r) {
                /* yield 1
                 * => {|a, b, *r|}
                 */
                for (i=argc; i<r; i++) {
                    argv[i] = Qnil;
                }
                argv[r] = rb_ary_new();
            }
            else {
                argv[r] = rb_ary_new4(argc-r, &argv[r]);
            }
        }

        th->mark_stack_len = iseq->arg_size;
    }

    /* {|&b|} */
    if (iseq->arg_block != -1) {
        VALUE procval = Qnil;

        if (blockptr) {
	    if (blockptr->proc == 0) {
		procval = rb_vm_make_proc(th, blockptr, rb_cProc);
	    }
	    else {
		procval = blockptr->proc;
	    }
        }

        argv[iseq->arg_block] = procval;
    }

    th->mark_stack_len = 0;
    return opt_pc;
}
예제 #12
0
static VALUE sFactoryCall (VALUE args) {
  VALUE *argsP = RARRAY_PTR(args);
  return rb_method_call(1, argsP, argsP[1]);
}
예제 #13
0
파일: rhosupport.c 프로젝트: 4nkh/rhodes
static VALUE find_file(VALUE fname)
{
    VALUE res = 0;
    int nOK = 0;

    //RAWLOG_INFO1("find_file: fname: %s", RSTRING_PTR(fname));
#ifdef RHODES_EMULATOR
    if ( strncmp(RSTRING_PTR(fname), rho_simconf_getRhodesPath(), strlen(rho_simconf_getRhodesPath())) == 0 )
        res = fname;
    else
#endif

    if ( strncmp(RSTRING_PTR(fname), rho_native_rhopath(), strlen(rho_native_rhopath())) == 0 ){
        res = rb_str_dup(fname);
        rb_str_cat(res,RHO_RB_EXT,strlen(RHO_RB_EXT));
        //RAWLOG_INFO1("find_file: res: %s", RSTRING_PTR(res));
    } else if ( strncmp(RSTRING_PTR(fname), rho_native_reruntimepath(), strlen(rho_native_reruntimepath())) == 0 ){
        res = rb_str_dup(fname);
        rb_str_cat(res,RHO_RB_EXT,strlen(RHO_RB_EXT));
        //RAWLOG_INFO1("find_file: res: %s", RSTRING_PTR(res));
    }else{
        int i = 0;
        VALUE load_path = GET_VM()->load_path;
        //VALUE dir;
        VALUE fname1 = checkRhoBundleInPath(fname);
        //RAWLOG_INFO1("find_file: fname after checkRhoBundleInPath: %s", RSTRING_PTR(fname));

        //TODO: support document relative require in case of multiple apps
        if (RARRAY_LEN(load_path)>1){
            for( ; i < RARRAY_LEN(load_path); i++ ){
                VALUE dir = RARRAY_PTR(load_path)[i];

#ifdef RHODES_EMULATOR
                res = check_app_file_exist(dir, fname1, rho_simconf_getString("platform"));
#endif
                if ( !res )
                    res = check_app_file_exist(dir, fname1, 0 );

                if (res)
                {
                    nOK = 1;
                    break;
                }
            }
            if ( !nOK )
            {
#ifdef RHODES_EMULATOR
                //check for extensions
/*                res = rb_str_new2(rho_simconf_getRhodesPath() );
                rb_str_cat2(res,"/lib/extensions/");

                res = check_extension(res, fname, 1);
                if ( !res )
                {
                    res = rb_str_new2(rho_native_rhopath() );
                    rb_str_cat2(res,"/extensions/");

                    res = check_extension(res, fname,1);
                }

                if ( !res )
                {
                    res = rb_str_new2( rho_simconf_getString("ext_path") );
                    res = check_extension(res, fname, 0);
                }
*/
                const char* szPaths = rho_simconf_getString("ext_path");
                const char* szPath = szPaths;
                const char* szSep = strchr(szPath, ';');
                res = 0;
                for( ; szSep; szSep = strchr(szPath, ';') )
                {
                    res = rb_str_new( szPath, szSep-szPath);
                    rb_str_cat2(res,"/");
                    rb_str_append(res,fname);
                    rb_str_cat2(res,RHO_RB_EXT);

                    if ( eaccess(RSTRING_PTR(res), R_OK) == 0 )
                        break;

                    res = rb_str_new( szPath, szSep-szPath);
                    rb_str_cat2(res,"/app/");
                    rb_str_append(res,fname);
                    rb_str_cat2(res,RHO_RB_EXT);

                    if ( eaccess(RSTRING_PTR(res), R_OK) == 0 )
                        break;

                    res = 0;
                    szPath = szSep+1;
                }

                if( res )
                    nOK = 1;
                else
                    return 0;
#else
                return 0;
#endif
                
            }
        } /*else {
            dir = RARRAY_PTR(load_path)[RARRAY_LEN(load_path)-1];

            res = rb_str_dup(dir);
            rb_str_cat(res,"/",1);
            rb_str_cat(res,RSTRING_PTR(fname),RSTRING_LEN(fname));
            rb_str_cat(res,RHO_RB_EXT,strlen(RHO_RB_EXT));

            if ( g_curAppPath != 0 && eaccess(RSTRING_PTR(res), R_OK) != 0 ){
                res = rb_str_new2(g_curAppPath);
                rb_str_cat(res,"/",1);
                rb_str_cat(res,RSTRING_PTR(fname),RSTRING_LEN(fname));
                rb_str_cat(res,RHO_RB_EXT,strlen(RHO_RB_EXT));
            }
        } */
    }

    //RAWLOG_INFO1("find_file: RhoPreparePath: %s", RSTRING_PTR(res));
    res = RhoPreparePath(res);
    if ( !nOK )
        nOK = 1;//eaccess(RSTRING_PTR(res), R_OK) == 0 ? 1 : 0;

    return nOK ? res : 0;
}
예제 #14
0
/* TODO: Fix memory leak on error */
static mrb_value
mrb_grn_table_sort(mrb_state *mrb, mrb_value self)
{
  grn_ctx *ctx = (grn_ctx *)mrb->ud;
  grn_obj *table;
  grn_obj *result = NULL;
  grn_table_sort_key *keys;
  int i, n_keys;
  int offset = 0;
  int limit = -1;
  mrb_value mrb_keys;
  mrb_value mrb_options = mrb_nil_value();

  table = DATA_PTR(self);
  mrb_get_args(mrb, "o|H", &mrb_keys, &mrb_options);

  mrb_keys = mrb_convert_type(mrb, mrb_keys,
                              MRB_TT_ARRAY, "Array", "to_ary");

  n_keys = RARRAY_LEN(mrb_keys);
  keys = GRN_MALLOCN(grn_table_sort_key, n_keys);
  for (i = 0; i < n_keys; i++) {
    mrb_value mrb_sort_options;
    mrb_value mrb_sort_key;
    mrb_value mrb_sort_order;

    mrb_sort_options = RARRAY_PTR(mrb_keys)[i];
    mrb_sort_key = grn_mrb_options_get_lit(mrb, mrb_sort_options, "key");
    switch (mrb_type(mrb_sort_key)) {
    case MRB_TT_STRING :
      keys[i].key = grn_obj_column(ctx, table,
                                   RSTRING_PTR(mrb_sort_key),
                                   RSTRING_LEN(mrb_sort_key));
      break;
    case MRB_TT_SYMBOL :
      {
        const char *name;
        mrb_int name_length;
        name = mrb_sym2name_len(mrb, mrb_symbol(mrb_sort_key), &name_length);
        keys[i].key = grn_obj_column(ctx, table, name, name_length);
      }
      break;
    default :
      /* TODO: free */
      mrb_raisef(mrb, E_ARGUMENT_ERROR,
                 "sort key must be string or symbol: %S",
                 mrb_sort_key);
      break;
    }

    keys[i].flags = 0;
    mrb_sort_order = grn_mrb_options_get_lit(mrb, mrb_sort_options, "order");
    if (mrb_nil_p(mrb_sort_order) ||
        (mrb_symbol(mrb_sort_order) == mrb_intern_lit(mrb, "ascending"))) {
      keys[i].flags |= GRN_TABLE_SORT_ASC;
    } else {
      keys[i].flags |= GRN_TABLE_SORT_DESC;
    }
  }

  if (!mrb_nil_p(mrb_options)) {
    mrb_value mrb_offset;
    mrb_value mrb_limit;

    mrb_offset = grn_mrb_options_get_lit(mrb, mrb_options, "offset");
    if (!mrb_nil_p(mrb_offset)) {
      offset = mrb_fixnum(mrb_offset);
    }

    mrb_limit = grn_mrb_options_get_lit(mrb, mrb_options, "limit");
    if (!mrb_nil_p(mrb_limit)) {
      limit = mrb_fixnum(mrb_limit);
    }
  }

  result = grn_table_create(ctx, NULL, 0, NULL, GRN_TABLE_NO_KEY,
                            NULL, table);
  grn_table_sort(ctx, table, offset, limit, result, keys, n_keys);
  for (i = 0; i < n_keys; i++) {
    grn_obj_unlink(ctx, keys[i].key);
  }
  GRN_FREE(keys);
  grn_mrb_ctx_check(mrb);

  return grn_mrb_value_from_grn_obj(mrb, result);
}
예제 #15
0
파일: rack_plugin.c 프로젝트: Algy/uwsgi
static struct uwsgi_buffer *uwsgi_ruby_backtrace(struct wsgi_request *wsgi_req) {
	VALUE err = rb_errinfo();
	VALUE ary = rb_funcall(err, rb_intern("backtrace"), 0);
	int i;
	struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
	char *filename = NULL;
	char *function = NULL;
	for (i=0; i<RARRAY_LEN(ary); i++) {
		char *bt = RSTRING_PTR(RARRAY_PTR(ary)[i]);
		// ok let's start the C dance to parse the backtrace
		char *colon = strchr(bt, ':');
		if (!colon) continue;
		filename = uwsgi_concat2n(bt, (int) (colon-bt), "", 0);
		uint16_t filename_len = colon-bt;
		colon++; if (*colon == 0) goto error;
		char *lineno_ptr = colon;
		colon = strchr(lineno_ptr, ':');
		if (!colon) goto error;
		int64_t lineno = uwsgi_str_num(lineno_ptr, (int) (colon-lineno_ptr));
		colon++; if (*colon == 0) goto error;
		colon = strchr(lineno_ptr, '`');
		if (!colon) goto error;
		colon++; if (*colon == 0) goto error;
		char *function_ptr = colon;
		char *function_end = strchr(function_ptr, '\'');
		if (!function_end) goto error;
		function = uwsgi_concat2n(function_ptr, (int) (function_end-function_ptr), "", 0);
		uint16_t function_len = function_end-function_ptr;

		if (uwsgi_buffer_u16le(ub, filename_len)) goto error;
		if (uwsgi_buffer_append(ub, filename, filename_len)) goto error;
		if (uwsgi_buffer_append_valnum(ub, lineno)) goto error;
		if (uwsgi_buffer_u16le(ub, function_len)) goto error;
		if (uwsgi_buffer_append(ub, function, function_len)) goto error;

		// in ruby we do not have text/code nor custom
		if (uwsgi_buffer_u16le(ub, 0)) goto error;
		if (uwsgi_buffer_append(ub, "", 0)) goto error;
		if (uwsgi_buffer_u16le(ub, 0)) goto error;
		if (uwsgi_buffer_append(ub, "", 0)) goto error;

		free(filename);
		filename = NULL;
		free(function);
		function = NULL;
	}

	return ub;

error:
	uwsgi_buffer_destroy(ub);

	if (filename) {
		free(filename);
	}

	if (function) {
		free(function);
	}

	return NULL;
}
예제 #16
0
static VALUE
eval_expression(VALUE args)
{
  return rb_funcall2(rb_mKernel, idEval, 2, RARRAY_PTR(args));
}
예제 #17
0
static void
process_sflag(int *sflag)
{
    if (*sflag > 0) {
	long n;
	VALUE *args;
	VALUE argv = rb_argv;

	n = RARRAY_LEN(argv);
	args = RARRAY_PTR(argv);
	while (n > 0) {
	    VALUE v = *args++;
	    char *s = StringValuePtr(v);
	    char *p;
	    int hyphen = FALSE;

	    if (s[0] != '-')
		break;
	    n--;
	    if (s[1] == '-' && s[2] == '\0')
		break;

	    v = Qtrue;
	    /* check if valid name before replacing - with _ */
	    for (p = s + 1; *p; p++) {
		if (*p == '=') {
		    *p++ = '\0';
		    v = rb_str_new2(p);
		    break;
		}
		if (*p == '-') {
		    hyphen = TRUE;
		}
		else if (*p != '_' && !ISALNUM(*p)) {
		    VALUE name_error[2];
		    name_error[0] =
			rb_str_new2("invalid name for global variable - ");
		    if (!(p = strchr(p, '='))) {
			rb_str_cat2(name_error[0], s);
		    }
		    else {
			rb_str_cat(name_error[0], s, p - s);
		    }
		    name_error[1] = args[-1];
		    rb_exc_raise(rb_class_new_instance(2, name_error, rb_eNameError));
		}
	    }
	    s[0] = '$';
	    if (hyphen) {
		for (p = s + 1; *p; ++p) {
		    if (*p == '-')
			*p = '_';
		}
	    }
	    rb_gv_set(s, v);
	}
	n = RARRAY_LEN(argv) - n;
	while (n--) {
	    rb_ary_shift(argv);
	}
	*sflag = -1;
    }
}
예제 #18
0
   post_readline_pos       =                     UClientImage_Base::body->data();
   post_readline_watermark = post_readline_pos + UClientImage_Base::body->size();

   U_INTERNAL_DUMP("post_readline_pos = %p post_readline_watermark = %p", post_readline_pos, post_readline_watermark)

   U_RETURN(Qnil);
}

static VALUE URUBY_io_read(VALUE obj, VALUE args)
{
   U_TRACE(0, "URUBY_io_read(%llu,%llu)", obj, args)

   // When EOF is reached, this method returns nil if length is given and not nil, or "" if length is not given or is nil

   U_INTERNAL_DUMP("post_readline_pos = %p post_readline_watermark = %p RARRAY_LEN(args) = %d RARRAY_PTR(args)[0] = %p",
                    post_readline_pos,     post_readline_watermark,     RARRAY_LEN(args),     RARRAY_PTR(args)[0])

   if (RARRAY_LEN(args) > 0 &&
       RARRAY_PTR(args)[0] != Qnil)
      {
      if (post_readline_pos >= post_readline_watermark)
         {
         post_readline_pos = post_readline_watermark = U_NULLPTR; // all the readline buffer has been consumed

         U_RETURN(Qnil);
         }

      U_INTERNAL_DUMP("hint = %ld", NUM2LONG(RARRAY_PTR(args)[0]))
      }

   if (post_readline_pos < post_readline_watermark)
예제 #19
0
파일: vm_eval.c 프로젝트: 3runo5ouza/rhodes
/*RHO static*/ VALUE
eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref, const char *file, int line)
{
    int state;
    VALUE result = Qundef;
    VALUE envval;
    rb_binding_t *bind = 0;
    rb_thread_t *th = GET_THREAD();
    rb_env_t *env = NULL;
    rb_block_t block;
    volatile int parse_in_eval;
    volatile int mild_compile_error;

    if (file == 0) {
	file = rb_sourcefile();
	line = rb_sourceline();
    }

    parse_in_eval = th->parse_in_eval;
    mild_compile_error = th->mild_compile_error;
    PUSH_TAG();
    if ((state = EXEC_TAG()) == 0) {
	rb_iseq_t *iseq;
	volatile VALUE iseqval;

	if (scope != Qnil) {
	    if (rb_obj_is_kind_of(scope, rb_cBinding)) {
		GetBindingPtr(scope, bind);
		envval = bind->env;
	    }
	    else {
		rb_raise(rb_eTypeError,
			 "wrong argument type %s (expected Binding)",
			 rb_obj_classname(scope));
	    }
	    GetEnvPtr(envval, env);
	    th->base_block = &env->block;
	}
	else {
	    rb_control_frame_t *cfp = rb_vm_get_ruby_level_next_cfp(th, th->cfp);

	    if (cfp != 0) {
		block = *RUBY_VM_GET_BLOCK_PTR_IN_CFP(cfp);
		th->base_block = &block;
		th->base_block->self = self;
		th->base_block->iseq = cfp->iseq;	/* TODO */
	    }
	    else {
		rb_raise(rb_eRuntimeError, "Can't eval on top of Fiber or Thread");
	    }
	}

    //RHO
    if ( TYPE(src) != T_STRING ){
        iseqval = src;
    }else
    //RHO
    {
	    /* make eval iseq */
	    th->parse_in_eval++;
	    th->mild_compile_error++;
	    iseqval = rb_iseq_compile(src, rb_str_new2(file), INT2FIX(line));
	    th->mild_compile_error--;
	    th->parse_in_eval--;
    }

	vm_set_eval_stack(th, iseqval, cref);
	th->base_block = 0;

	if (0) {		/* for debug */
	    printf("%s\n", RSTRING_PTR(rb_iseq_disasm(iseqval)));
	}

	/* save new env */
	GetISeqPtr(iseqval, iseq);
	if (bind && iseq->local_size > 0) {
	    bind->env = rb_vm_make_env_object(th, th->cfp);
	}

	/* kick */
	CHECK_STACK_OVERFLOW(th->cfp, iseq->stack_max);
	result = vm_exec(th);
    }
    POP_TAG();
    th->mild_compile_error = mild_compile_error;
    th->parse_in_eval = parse_in_eval;

    if (state) {
	if (state == TAG_RAISE) {
	    VALUE errinfo = th->errinfo;
	    if (strcmp(file, "(eval)") == 0) {
		VALUE mesg, errat, bt2;
		extern VALUE rb_get_backtrace(VALUE info);
		ID id_mesg;

		CONST_ID(id_mesg, "mesg");
		errat = rb_get_backtrace(errinfo);
		mesg = rb_attr_get(errinfo, id_mesg);
		if (!NIL_P(errat) && TYPE(errat) == T_ARRAY &&
		    (bt2 = vm_backtrace(th, -2), RARRAY_LEN(bt2) > 0)) {
		    if (!NIL_P(mesg) && TYPE(mesg) == T_STRING && !RSTRING_LEN(mesg)) {
			if (OBJ_FROZEN(mesg)) {
			    VALUE m = rb_str_cat(rb_str_dup(RARRAY_PTR(errat)[0]), ": ", 2);
			    rb_ivar_set(errinfo, id_mesg, rb_str_append(m, mesg));
			}
			else {
			    rb_str_update(mesg, 0, 0, rb_str_new2(": "));
			    rb_str_update(mesg, 0, 0, RARRAY_PTR(errat)[0]);
			}
		    }
		    RARRAY_PTR(errat)[0] = RARRAY_PTR(bt2)[0];
		}
	    }
	    rb_exc_raise(errinfo);
	}
	JUMP_TAG(state);
    }
    return result;
}
예제 #20
0
static VALUE
actiongroup_add_radio_actions(int argc, VALUE *argv, VALUE self)
{
    VALUE entries, value, proc;
    guint i;
    guint n_entries;
    GtkRadioActionEntry* gentries;

    rb_scan_args(argc, argv, "12", &entries, &value, &proc);

    if (NIL_P(value)) value = -1;
    if (NIL_P(proc) && rb_block_given_p()){
        proc = rb_block_proc();
        G_RELATIVE(self, proc);
    }
    n_entries = (guint)RARRAY_LEN(entries);
    gentries = g_new0(GtkRadioActionEntry, n_entries);

    for (i = 0; i < n_entries; i++){
        VALUE entry;
	int size;

	entry = RARRAY_PTR(entries)[i];
	size = RARRAY_LEN(entry);
        if (size < 1)
            rb_raise(rb_eArgError, "wrong array parameter");

        gentries[i].name = RVAL2CSTR_ACCEPT_NIL(RARRAY_PTR(entry)[0]);

        if (size < 2) continue;

        if (NIL_P(RARRAY_PTR(entry)[1])){
            gentries[i].stock_id = NULL;
        } else if (SYMBOL_P(RARRAY_PTR(entry)[1])){
            gentries[i].stock_id = rb_id2name(SYM2ID(RARRAY_PTR(entry)[1]));
        } else if (TYPE(RARRAY_PTR(entry)[1]) == T_STRING){
            gentries[i].stock_id = RVAL2CSTR(RARRAY_PTR(entry)[1]);
        } else{
            rb_raise(rb_eArgError,
		     "invalid argument %s (expect Symbol or String)",
                     rb_class2name(CLASS_OF(RARRAY_PTR(entry)[1])));
        }

        if (size < 3) continue;
        gentries[i].label = RVAL2CSTR_ACCEPT_NIL(RARRAY_PTR(entry)[2]);
        if (size < 4) continue;
        gentries[i].accelerator = RVAL2CSTR_ACCEPT_NIL(RARRAY_PTR(entry)[3]);
        if (size < 4) continue;
        gentries[i].tooltip = RVAL2CSTR_ACCEPT_NIL(RARRAY_PTR(entry)[4]);
        if (size < 5) continue;
        gentries[i].value = NUM2INT(RARRAY_PTR(entry)[5]);
    }
    gtk_action_group_add_radio_actions(_SELF(self), gentries,
				       n_entries, NUM2INT(value),
                                       G_CALLBACK(activate_radio_action),
				       (gpointer)proc);
    g_free(gentries);

    return self;
}
예제 #21
0
파일: io.c 프로젝트: bigted6969/mruby-io
static mrb_value
mrb_io_s_select(mrb_state *mrb, mrb_value klass)
{
  mrb_value *argv;
  mrb_int argc;
  mrb_value read, read_io, write, except, timeout, list;
  struct timeval *tp, timerec;
  fd_set pset, rset, wset, eset;
  fd_set *rp, *wp, *ep;
  struct mrb_io *fptr;
  int pending = 0;
  mrb_value result;
  int max = 0;
  int interrupt_flag = 0;
  int i, n;

  mrb_get_args(mrb, "*", &argv, &argc);

  if (argc < 1 || argc > 4) {
    mrb_raisef(mrb, E_ARGUMENT_ERROR, "wrong number of arguments (%S for 1..4)", mrb_fixnum_value(argc));
  }

  timeout = mrb_nil_value();
  except = mrb_nil_value();
  write = mrb_nil_value();
  if (argc > 3)
    timeout = argv[3];
  if (argc > 2)
    except = argv[2];
  if (argc > 1)
    write = argv[1];
  read = argv[0];

  if (mrb_nil_p(timeout)) {
    tp = NULL;
  } else {
    timerec = time2timeval(mrb, timeout);
    tp = &timerec;
  }

  FD_ZERO(&pset);
  if (!mrb_nil_p(read)) {
    mrb_check_type(mrb, read, MRB_TT_ARRAY);
    rp = &rset;
    FD_ZERO(rp);
    for (i = 0; i < RARRAY_LEN(read); i++) {
      read_io = RARRAY_PTR(read)[i];
      fptr = (struct mrb_io *)mrb_get_datatype(mrb, read_io, &mrb_io_type);
      FD_SET(fptr->fd, rp);
      if (mrb_io_read_data_pending(mrb, read_io)) {
        pending++;
        FD_SET(fptr->fd, &pset);
      }
      if (max < fptr->fd)
        max = fptr->fd;
    }
    if (pending) {
      timerec.tv_sec = timerec.tv_usec = 0;
      tp = &timerec;
    }
  } else {
    rp = NULL;
  }

  if (!mrb_nil_p(write)) {
    mrb_check_type(mrb, write, MRB_TT_ARRAY);
    wp = &wset;
    FD_ZERO(wp);
    for (i = 0; i < RARRAY_LEN(write); i++) {
      fptr = (struct mrb_io *)mrb_get_datatype(mrb, RARRAY_PTR(write)[i], &mrb_io_type);
      FD_SET(fptr->fd, wp);
      if (max < fptr->fd)
        max = fptr->fd;
      if (fptr->fd2 >= 0) {
        FD_SET(fptr->fd2, wp);
        if (max < fptr->fd2)
          max = fptr->fd2;
      }
    }
  } else {
    wp = NULL;
  }

  if (!mrb_nil_p(except)) {
    mrb_check_type(mrb, except, MRB_TT_ARRAY);
    ep = &eset;
    FD_ZERO(ep);
    for (i = 0; i < RARRAY_LEN(except); i++) {
      fptr = (struct mrb_io *)mrb_get_datatype(mrb, RARRAY_PTR(except)[i], &mrb_io_type);
      FD_SET(fptr->fd, ep);
      if (max < fptr->fd)
        max = fptr->fd;
      if (fptr->fd2 >= 0) {
        FD_SET(fptr->fd2, ep);
        if (max < fptr->fd2)
          max = fptr->fd2;
      }
    }
  } else {
    ep = NULL;
  }

  max++;

retry:
  n = select(max, rp, wp, ep, tp);
  if (n < 0) {
    if (errno != EINTR)
      mrb_sys_fail(mrb, "select failed");
    if (tp == NULL)
      goto retry;
    interrupt_flag = 1;
  }

  if (!pending && n == 0)
    return mrb_nil_value();

  result = mrb_ary_new_capa(mrb, 3);
  mrb_ary_push(mrb, result, rp? mrb_ary_new(mrb) : mrb_ary_new_capa(mrb, 0));
  mrb_ary_push(mrb, result, wp? mrb_ary_new(mrb) : mrb_ary_new_capa(mrb, 0));
  mrb_ary_push(mrb, result, ep? mrb_ary_new(mrb) : mrb_ary_new_capa(mrb, 0));

  if (interrupt_flag == 0) {
    if (rp) {
      list = RARRAY_PTR(result)[0];
      for (i = 0; i < RARRAY_LEN(read); i++) {
        fptr = (struct mrb_io *)mrb_get_datatype(mrb, RARRAY_PTR(read)[i], &mrb_io_type);
        if (FD_ISSET(fptr->fd, rp) ||
            FD_ISSET(fptr->fd, &pset)) {
          mrb_ary_push(mrb, list, RARRAY_PTR(read)[i]);
        }
      }
    }

    if (wp) {
      list = RARRAY_PTR(result)[1];
      for (i = 0; i < RARRAY_LEN(write); i++) {
        fptr = (struct mrb_io *)mrb_get_datatype(mrb, RARRAY_PTR(write)[i], &mrb_io_type);
        if (FD_ISSET(fptr->fd, wp)) {
          mrb_ary_push(mrb, list, RARRAY_PTR(write)[i]);
        } else if (fptr->fd2 >= 0 && FD_ISSET(fptr->fd2, wp)) {
          mrb_ary_push(mrb, list, RARRAY_PTR(write)[i]);
        }
      }
    }

    if (ep) {
      list = RARRAY_PTR(result)[2];
      for (i = 0; i < RARRAY_LEN(except); i++) {
        fptr = (struct mrb_io *)mrb_get_datatype(mrb, RARRAY_PTR(except)[i], &mrb_io_type);
        if (FD_ISSET(fptr->fd, ep)) {
          mrb_ary_push(mrb, list, RARRAY_PTR(except)[i]);
        } else if (fptr->fd2 >= 0 && FD_ISSET(fptr->fd2, wp)) {
          mrb_ary_push(mrb, list, RARRAY_PTR(except)[i]);
        }
      }
    }
  }

  return result;
}
예제 #22
0
static VALUE
actiongroup_add_actions(VALUE self, VALUE entries)
{
    guint i;
    VALUE action_procs;
    guint n_entries = (guint)RARRAY_LEN(entries);
    GtkActionEntry* gentries = g_new0(GtkActionEntry, n_entries);

    if (rb_ivar_defined(self, id_action_procs) == Qtrue){
        action_procs = rb_ivar_get(self, id_action_procs);
    } else {
        action_procs = rb_hash_new();
    }

    for (i = 0; i < n_entries; i++){
        VALUE entry;
        int size;

	entry = RARRAY_PTR(entries)[i];
	size = RARRAY_LEN(entry);
        if (size < 1)
            rb_raise(rb_eArgError, "wrong array parameter");

        gentries[i].name = RVAL2CSTR_ACCEPT_NIL(RARRAY_PTR(entry)[0]);
        gentries[i].callback = G_CALLBACK(activate_action);

        if (size < 2) continue;

        if (NIL_P(RARRAY_PTR(entry)[1])){
            gentries[i].stock_id = NULL;
        } else if (SYMBOL_P(RARRAY_PTR(entry)[1])){
            gentries[i].stock_id = rb_id2name(SYM2ID(RARRAY_PTR(entry)[1]));
        } else if (TYPE(RARRAY_PTR(entry)[1]) == T_STRING){
            gentries[i].stock_id = RVAL2CSTR(RARRAY_PTR(entry)[1]);
        } else{
            rb_raise(rb_eArgError,
		     "invalid argument %s (expect Symbol or String)",
                     rb_class2name(CLASS_OF(RARRAY_PTR(entry)[1])));
        }

        if (size < 3) continue;
        gentries[i].label = RVAL2CSTR_ACCEPT_NIL(RARRAY_PTR(entry)[2]);
        if (size < 4) continue;
        gentries[i].accelerator = RVAL2CSTR_ACCEPT_NIL(RARRAY_PTR(entry)[3]);
        if (size < 4) continue;
        gentries[i].tooltip = RVAL2CSTR_ACCEPT_NIL(RARRAY_PTR(entry)[4]);
        if (size < 5) continue;
        rb_hash_aset(action_procs, RARRAY_PTR(entry)[0], RARRAY_PTR(entry)[5]);
    }
    rb_ivar_set(self, id_action_procs, action_procs);
    gtk_action_group_add_actions(_SELF(self), gentries, n_entries,
				 (gpointer)self);
    g_free(gentries);

    return self;
}
예제 #23
0
static VALUE
rbg_rval2gtktoggleactionentries_body(VALUE value)
{
    long i;
    struct rbg_rval2gtktoggleactionentries_args *args = (struct rbg_rval2gtktoggleactionentries_args *)value;

    for (i = 0; i < args->n; i++) {
        VALUE entry;
        long n;

        RARRAY_PTR(args->ary)[i] = rb_ary_dup(rb_ary_to_ary(RARRAY_PTR(args->ary)[i]));
        entry = RARRAY_PTR(args->ary)[i];
        n = RARRAY_LEN(entry);

        args->result[i].callback = G_CALLBACK(activate_toggle_action);

        if (n < 1 || n > 7)
            rb_raise(rb_eArgError, "entry does not contain right number of entries %ld (1..7)", n);

        args->result[i].name = RVAL2CSTR_ACCEPT_NIL(RARRAY_PTR(entry)[0]);

        switch (n) {
        case 7:
            args->result[i].is_active = RVAL2CBOOL(RARRAY_PTR(entry)[6]);
        case 6:
            /* TODO: Call #to_proc on entry 5? */
            rb_hash_aset(args->procs, RARRAY_PTR(entry)[0], RARRAY_PTR(entry)[5]);
        case 5:
            args->result[i].tooltip = RVAL2CSTR_ACCEPT_NIL(RARRAY_PTR(entry)[4]);
        case 4:
            args->result[i].accelerator = RVAL2CSTR_ACCEPT_NIL(RARRAY_PTR(entry)[3]);
        case 3:
            args->result[i].label = RVAL2CSTR_ACCEPT_NIL(RARRAY_PTR(entry)[2]);
        case 2:
            args->result[i].stock_id = RVAL2CSTR_ACCEPT_SYMBOL_ACCEPT_NIL(RARRAY_PTR(entry)[1]);
            break;
        default:
            break;
        }
    }

    return Qnil;
}
예제 #24
0
파일: api.c 프로젝트: twobitfool/win32-api
/*
 * call-seq:
 *    Win32::API.new(function, prototype='V', return='L', dll='kernel32')
 *
 * Creates and returns a new Win32::API object. The +function+ is the name
 * of the Windows function.
 *
 * The +prototype+ is the function prototype for +function+. This can be a
 * string or an array of characters.  The possible valid characters are 'I'
 * (integer), 'L' (long), 'V' (void), 'P' (pointer), 'K' (callback) or 'S'
 * (string).
 *
 * The default is void ('V').
 *
 * Constant (const char*) strings should use 'S'. Pass by reference string
 * buffers should use 'P'. The former is faster, but cannot be modified.
 *
 * The +return+ argument is the return type for the function.  The valid
 * characters are the same as for the +prototype+.  The default is 'L' (long).
 *
 * The +dll+ is the name of the DLL file that the function is exported from.
 * The default is 'kernel32'.
 *
 * If the function cannot be found then an API::Error is raised (a subclass
 * of RuntimeError).
 *
 * Example:
 *
 *    require 'win32/api'
 *    include Win32
 *
 *    buf = 0.chr * 260
 *    len = [buf.length].pack('L')
 *
 *    GetUserName = API.new('GetUserName', 'PP', 'I', 'advapi32')
 *    GetUserName.call(buf, len)
 *
 *    puts buf.strip
 */
static VALUE api_init(int argc, VALUE* argv, VALUE self)
{
   HMODULE hLibrary;
   FARPROC fProc;
   Win32API* ptr;
   int i;
   char* first  = "A";
   char* second = "W";
   VALUE v_proc, v_proto, v_return, v_dll;

   rb_scan_args(argc, argv, "13", &v_proc, &v_proto, &v_return, &v_dll);

   Data_Get_Struct(self, Win32API, ptr);

   // Convert a string prototype to an array of characters
   if(rb_respond_to(v_proto, rb_intern("split")))
      v_proto = rb_str_split(v_proto, "");

   // Convert a nil or empty prototype to 'V' (void) automatically
   if(NIL_P(v_proto) || RARRAY_LEN(v_proto) == 0){
      v_proto = rb_ary_new();
      rb_ary_push(v_proto, rb_str_new2("V"));
   }

   // Set an arbitrary limit of 20 parameters
   if(20 < RARRAY_LEN(v_proto))
      rb_raise(rb_eArgError, "too many parameters: %d\n", RARRAY_LEN(v_proto));

   // Set the default dll to 'kernel32'
   if(NIL_P(v_dll))
      v_dll = rb_str_new2("kernel32");

   // Set the default return type to 'L' (DWORD)
   if(NIL_P(v_return))
      v_return = rb_str_new2("L");

   SafeStringValue(v_dll);
   SafeStringValue(v_proc);

   hLibrary = LoadLibrary(TEXT(RSTRING_PTR(v_dll)));

   // The most likely cause of failure is a bad DLL load path
   if(!hLibrary){
      rb_raise(cAPILoadError, "LoadLibrary() function failed for '%s': %s",
         RSTRING_PTR(v_dll),
         StringError(GetLastError())
      );
   }

   ptr->library = hLibrary;

   /* Attempt to get the function.  If it fails, try again with an 'A'
    * appended.  If that fails, try again with a 'W' appended. If that
    * still fails, raise an API::LoadLibraryError.
    */

   fProc = GetProcAddress(hLibrary, TEXT(RSTRING_PTR(v_proc)));

   // Skip the ANSI and Wide function checks for MSVCRT functions.
   if(!fProc){
      if(strstr(RSTRING_PTR(v_dll), "msvcr")){
         rb_raise(
            cAPILoadError,
            "Unable to load function '%s'",
            RSTRING_PTR(v_proc)
         );
      }
      else{
         VALUE v_ascii = rb_str_new3(v_proc);
         v_ascii = rb_str_cat(v_ascii, first, 1);
         fProc = GetProcAddress(hLibrary, TEXT(RSTRING_PTR(v_ascii)));

         if(!fProc){
            VALUE v_unicode = rb_str_new3(v_proc);
            v_unicode = rb_str_cat(v_unicode, second, 1);
            fProc = GetProcAddress(hLibrary, TEXT(RSTRING_PTR(v_unicode)));

            if(!fProc){
               rb_raise(
                  cAPILoadError,
                  "Unable to load function '%s', '%s', or '%s'",
                  RSTRING_PTR(v_proc),
                  RSTRING_PTR(v_ascii),
                  RSTRING_PTR(v_unicode)
               );
            }
            else{
               rb_iv_set(self, "@effective_function_name", v_unicode);
            }
         }
         else{
            rb_iv_set(self, "@effective_function_name", v_ascii);
         }
      }
   }
   else{
      rb_iv_set(self, "@effective_function_name", v_proc);
   }

   ptr->function = fProc;

   // Push the numeric prototypes onto our int array for later use.

   for(i = 0; i < RARRAY_LEN(v_proto); i++){
      SafeStringValue(RARRAY_PTR(v_proto)[i]);
      switch(*(char*)StringValuePtr(RARRAY_PTR(v_proto)[i])){
         case 'L':
            ptr->prototype[i] = _T_LONG;
            break;
         case 'P':
            ptr->prototype[i] = _T_POINTER;
            break;
         case 'I': case 'B':
            ptr->prototype[i] = _T_INTEGER;
            break;
         case 'V':
            ptr->prototype[i] = _T_VOID;
            break;
         case 'K':
            ptr->prototype[i] = _T_CALLBACK;
            break;
         case 'S':
            ptr->prototype[i] = _T_STRING;
            break;
         default:
            rb_raise(cAPIProtoError, "Illegal prototype '%s'",
               StringValuePtr(RARRAY_PTR(v_proto)[i])
            );
      }
   }

   // Store the return type for later use.

   // Automatically convert empty strings or nil to type void.
   if(NIL_P(v_return) || RSTRING_LEN(v_return) == 0){
      v_return = rb_str_new2("V");
      ptr->return_type = _T_VOID;
   }
   else{
      SafeStringValue(v_return);
      switch(*RSTRING_PTR(v_return)){
         case 'L':
            ptr->return_type = _T_LONG;
            break;
         case 'P':
            ptr->return_type = _T_POINTER;
            break;
         case 'I': case 'B':
            ptr->return_type = _T_INTEGER;
            break;
         case 'V':
            ptr->return_type = _T_VOID;
            break;
         case 'S':
            ptr->return_type = _T_STRING;
            break;
         default:
            rb_raise(cAPIProtoError, "Illegal return type '%s'",
               RSTRING_PTR(v_return)
            );
      }
   }

   rb_iv_set(self, "@dll_name", v_dll);
   rb_iv_set(self, "@function_name", v_proc);
   rb_iv_set(self, "@prototype", v_proto);
   rb_iv_set(self, "@return_type", v_return);

   return self;
}
예제 #25
0
파일: kernel.c 프로젝트: anoiaque/MacRuby
PRIMITIVE const VALUE *
vm_ary_ptr(VALUE ary)
{
    return RARRAY_PTR(ary);
}
예제 #26
0
파일: api.c 프로젝트: twobitfool/win32-api
/*
 * call-seq:
 *
 *    API::Function.new(address, prototype = 'V', return_type = 'L')
 *
 * Creates and returns an API::Function object. This object is similar to an
 * API object, except that instead of a character function name you pass a
 * function pointer address as the first argument, and there's no associated
 * DLL file.
 *
 * Once you have your API::Function object you can then call it the same way
 * you would an API object.
 *
 * Example:
 *
 *    require 'win32/api'
 *    include Win32
 *
 *    LoadLibrary = API.new('LoadLibrary', 'P', 'L')
 *    GetProcAddress = API.new('GetProcAddress', 'LP', 'L')
 *
 *    # Play a system beep
 *    hlib = LoadLibrary.call('user32')
 *    addr = GetProcAddress.call(hlib, 'MessageBeep')
 *    func = Win32::API::Function.new(addr, 'L', 'L')
 *    func.call(0)
 */
static VALUE func_init(int argc, VALUE* argv, VALUE self){
   Win32API* ptr;
   int i;
   VALUE v_address, v_proto, v_return;

   rb_scan_args(argc, argv, "12", &v_address, &v_proto, &v_return);

   Data_Get_Struct(self, Win32API, ptr);

   // Convert a string prototype to an array of characters
   if(rb_respond_to(v_proto, rb_intern("split")))
      v_proto = rb_str_split(v_proto, "");

   // Convert a nil or empty prototype to 'V' (void) automatically
   if(NIL_P(v_proto) || RARRAY_LEN(v_proto) == 0){
      v_proto = rb_ary_new();
      rb_ary_push(v_proto, rb_str_new2("V"));
   }

   // Set an arbitrary limit of 20 parameters
   if(20 < RARRAY_LEN(v_proto))
      rb_raise(rb_eArgError, "too many parameters: %d\n", RARRAY_LEN(v_proto));

   // Set the default return type to 'L' (DWORD)
   if(NIL_P(v_return))
      v_return = rb_str_new2("L");

   ptr->function = (FARPROC)NUM2LONG(v_address);

   // Push the numeric prototypes onto our int array for later use.

   for(i = 0; i < RARRAY_LEN(v_proto); i++){
      SafeStringValue(RARRAY_PTR(v_proto)[i]);
      switch(*(char*)StringValuePtr(RARRAY_PTR(v_proto)[i])){
         case 'L':
            ptr->prototype[i] = _T_LONG;
            break;
         case 'P':
            ptr->prototype[i] = _T_POINTER;
            break;
         case 'I': case 'B':
            ptr->prototype[i] = _T_INTEGER;
            break;
         case 'V':
            ptr->prototype[i] = _T_VOID;
            break;
         case 'K':
            ptr->prototype[i] = _T_CALLBACK;
            break;
         case 'S':
            ptr->prototype[i] = _T_STRING;
            break;
         default:
            rb_raise(cAPIProtoError, "Illegal prototype '%s'",
               StringValuePtr(RARRAY_PTR(v_proto)[i])
            );
      }
   }

   // Store the return type for later use.

   // Automatically convert empty strings or nil to type void.
   if(NIL_P(v_return) || RSTRING_LEN(v_return) == 0){
      v_return = rb_str_new2("V");
      ptr->return_type = _T_VOID;
   }
   else{
      SafeStringValue(v_return);
      switch(*RSTRING_PTR(v_return)){
         case 'L':
            ptr->return_type = _T_LONG;
            break;
         case 'P':
            ptr->return_type = _T_POINTER;
            break;
         case 'I': case 'B':
            ptr->return_type = _T_INTEGER;
            break;
         case 'V':
            ptr->return_type = _T_VOID;
            break;
         case 'S':
            ptr->return_type = _T_STRING;
            break;
         default:
            rb_raise(cAPIProtoError, "Illegal return type '%s'",
               RSTRING_PTR(v_return)
            );
      }
   }

   rb_iv_set(self, "@address", v_address);
   rb_iv_set(self, "@prototype", v_proto);
   rb_iv_set(self, "@return_type", v_return);

   return self;
}
예제 #27
0
static force_inline VALUE
vm_block_eval(RoxorVM *vm, rb_vm_block_t *b, SEL sel, VALUE self,
	int argc, const VALUE *argv)
{
    if ((b->flags & VM_BLOCK_IFUNC) == VM_BLOCK_IFUNC) {
	// Special case for blocks passed with rb_objc_block_call(), to
	// preserve API compatibility.
	VALUE (*pimp)(VALUE, VALUE, int, const VALUE *) =
	    (VALUE (*)(VALUE, VALUE, int, const VALUE *))b->imp;

	return (*pimp)(argc == 0 ? Qnil : argv[0], b->userdata, argc, argv);
    }
    else if ((b->flags & VM_BLOCK_EMPTY) == VM_BLOCK_EMPTY) {
	// Trying to call an empty block!
	return Qnil;
    }

    rb_vm_arity_t arity = b->arity;    

    if (argc < arity.min || argc > arity.max) {
	if (arity.max != -1
		&& (b->flags & VM_BLOCK_LAMBDA) == VM_BLOCK_LAMBDA) {
	    short limit = (argc < arity.min) ? arity.min : arity.max;
	    rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)",
		    argc, limit);
	}

	VALUE *new_argv;
	if (argc == 1 && TYPE(argv[0]) == T_ARRAY
		&& (arity.min > 1
		    || (arity.min == 1 && arity.min != arity.max))) {
	    // Expand the array.
	    const long ary_len = RARRAY_LEN(argv[0]);
	    if (ary_len > 0) {
		new_argv = (VALUE *)RARRAY_PTR(argv[0]);
	    }
	    else {
		new_argv = NULL;
	    }
	    argv = new_argv;
	    argc = ary_len;
	    if (argc >= arity.min
		    && (argc <= arity.max || b->arity.max == -1)) {
		goto block_call;
	    }
	}

	int new_argc;
	if (argc <= arity.min) {
	    new_argc = arity.min;
	}
	else if (argc > arity.max && b->arity.max != -1) {
	    new_argc = arity.max;
	}
	else {
	    new_argc = argc;
	}

	if (new_argc > 0) {
	    new_argv = (VALUE *)xmalloc_ptrs(sizeof(VALUE) * new_argc);
	    for (int i = 0; i < new_argc; i++) {
		new_argv[i] = i < argc ? argv[i] : Qnil;
	    }
	}
	else {
	    new_argv = NULL;
	}

	argc = new_argc;
	argv = new_argv;
    }
#if ROXOR_VM_DEBUG
    printf("yield block %p argc %d arity %d\n", b, argc, arity.real);
#endif

block_call:

    if (b->flags & VM_BLOCK_ACTIVE) {
	b = dup_block(b);
    }
    b->flags |= VM_BLOCK_ACTIVE;

    Class old_current_class = vm->get_current_class();
    vm->set_current_class((Class)b->klass);

    struct Finally {
	RoxorVM *vm;
	rb_vm_block_t *b;
	Class c;
	Finally(RoxorVM *_vm, rb_vm_block_t *_b, Class _c) {
	    vm = _vm;
	    b = _b;
	    c = _c;
	}
	~Finally() {
	    b->flags &= ~VM_BLOCK_ACTIVE;
	    vm->set_current_class(c);
	}
    } finalizer(vm, b, old_current_class);

    if (b->flags & VM_BLOCK_METHOD) {
	rb_vm_method_t *m = (rb_vm_method_t *)b->imp;
	return rb_vm_dispatch(vm, (struct mcache *)m->cache, 0, m->recv,
		(Class)m->oclass, m->sel, NULL, DISPATCH_FCALL, argc, argv);
    }
    return __rb_vm_bcall(self, sel, (VALUE)b->dvars, b, b->imp, b->arity,
	    argc, argv);
}
예제 #28
0
파일: api.c 프로젝트: twobitfool/win32-api
/*
 * call-seq:
 *    Win32::API#call(arg1, arg2, ...)
 *
 * Calls the function pointer with the given arguments (if any). Note that,
 * while this method will catch some prototype mismatches (raising a TypeError
 * in the process), it is not fulproof.  It is ultimately your job to make
 * sure the arguments match the +prototype+ specified in the constructor.
 *
 * For convenience, nil is converted to NULL, true is converted to TRUE (1)
 * and false is converted to FALSE (0).
 */
static VALUE api_call(int argc, VALUE* argv, VALUE self){
   VALUE v_proto, v_args, v_arg, v_return;
   Win32API* ptr;
   unsigned long return_value;
   int i = 0;
   int len;

   struct{
      unsigned long params[20];
   } param;

   Data_Get_Struct(self, Win32API, ptr);

   rb_scan_args(argc, argv, "0*", &v_args);

   v_proto = rb_iv_get(self, "@prototype");

   // For void prototypes, allow either no args or an explicit nil
   if(RARRAY_LEN(v_proto) != RARRAY_LEN(v_args)){
      char* c = StringValuePtr(RARRAY_PTR(v_proto)[0]);
      if(!strcmp(c, "V")){
         rb_ary_push(v_args, Qnil);
      }
      else{
         rb_raise(rb_eArgError,
            "wrong number of parameters: expected %d, got %d",
            RARRAY_LEN(v_proto), RARRAY_LEN(v_args)
         );
      }
   }

   len = RARRAY_LEN(v_proto);

   for(i = 0; i < len; i++){
      v_arg = RARRAY_PTR(v_args)[i];

      // Convert nil to NULL.  Otherwise convert as appropriate.
      if(NIL_P(v_arg))
         param.params[i] = (unsigned long)NULL;
      else if(v_arg == Qtrue)
         param.params[i] = TRUE;
      else if(v_arg == Qfalse)
         param.params[i] = FALSE;
      else
         switch(ptr->prototype[i]){
            case _T_LONG:
               param.params[i] = NUM2ULONG(v_arg);
               break;
            case _T_INTEGER:
               param.params[i] = NUM2INT(v_arg);
               break;
            case _T_POINTER:
               if(FIXNUM_P(v_arg)){
                  param.params[i] = NUM2ULONG(v_arg);
               }
               else{
                  StringValue(v_arg);
                  rb_str_modify(v_arg);
                  param.params[i] = (unsigned long)StringValuePtr(v_arg);
               }
               break;
            case _T_CALLBACK:
               ActiveCallback = v_arg;
               v_proto = rb_iv_get(ActiveCallback, "@prototype");
               param.params[i] = (LPARAM)NUM2ULONG(rb_iv_get(ActiveCallback, "@address"));;
               break;
            case _T_STRING:
               param.params[i] = (unsigned long)RSTRING_PTR(v_arg);
               break;
            default:
               param.params[i] = NUM2ULONG(v_arg);
         }
   }

   /* Call the function, get the return value */
   return_value = ptr->function(param);


   /* Return the appropriate type based on the return type specified
    * in the constructor.
    */
   switch(ptr->return_type){
      case _T_INTEGER:
         v_return = INT2NUM(return_value);
         break;
      case _T_LONG:
         v_return = ULONG2NUM(return_value);
         break;
      case _T_VOID:
         v_return = Qnil;
         break;
      case _T_POINTER:
         if(!return_value){
            v_return = Qnil;
         }
         else{
            VALUE v_efunc = rb_iv_get(self, "@effective_function_name");
            char* efunc = RSTRING_PTR(v_efunc);
            if(efunc[strlen(efunc)-1] == 'W'){
               v_return = rb_str_new(
                  (TCHAR*)return_value,
                  wcslen((wchar_t*)return_value)*2
               );
            }
            else{
               v_return = rb_str_new2((TCHAR*)return_value);
            }
         }
         break;
      case _T_STRING:
         {
            VALUE v_efunc = rb_iv_get(self, "@effective_function_name");
            char* efunc = RSTRING_PTR(v_efunc);

            if(efunc[strlen(efunc)-1] == 'W'){
               v_return = rb_str_new(
                  (TCHAR*)return_value,
                  wcslen((wchar_t*)return_value)*2
               );
            }
            else{
               v_return = rb_str_new2((TCHAR*)return_value);
            }
         }
         break;
      default:
         v_return = INT2NUM(0);
   }

   return v_return;
}
예제 #29
0
/*
 * _expression_ から {Groonga::Snippet} を生成する。 _tags_ には
 * キーワードの前後に挿入するタグの配列を以下のような形式で指定
 * する。
 *
 * <pre>
 * !!!ruby
 *   [
 *    ["キーワード前に挿入する文字列1", "キーワード後に挿入する文字列1"],
 *    ["キーワード前に挿入する文字列2", "キーワード後に挿入する文字列2"],
 *    # ...,
 *   ]
 * </pre>
 *
 * もし、1つのスニペットの中に _tags_ で指定したタグより多くの
 * キーワードが含まれている場合は、以下のように、また、先頭
 * のタグから順番に使われる。
 *
 * <pre>
 * !!!ruby
 *   expression.parse("Ruby groonga 検索")
 *   tags = [["<tag1>", "</tag1>"], ["<tag2>", "</tag2>"]]
 *   snippet = expression.snippet(tags)
 *   p snippet.execute("Rubyでgroonga使って全文検索、高速検索。")
 *      # => ["<tag1>Ruby</tag1>で<tag2>groonga</tag2>"
 *      # =>  "使って全文<tag1>検索</tag1>、高速<tag2>検索</tag2>。"]
 * </pre>
 *
 * @overload snippet(tags, options)
 *   @param tags [Array<string>] キーワードの前後に挿入するタグの配列
 *     (詳細は上記を参照)
 *   @param options [::Hash] The name and value
 *     pairs. Omitted names are initialized as the default value.
 *   @option options :normalize (false)
 *     キーワード文字列・スニペット元の文字列を正規化するかど
 *     うか。省略した場合は +false+ で正規化しない。
 *   @option options :skip_leading_spaces (false)
 *     先頭の空白を無視するかどうか。省略した場合は +false+ で無
 *     視しない。
 *   @option options :width (100)
 *     スニペット文字列の長さ。省略した場合は100文字。
 *   @option options :max_results (3)
 *     生成するスニペットの最大数。省略した場合は3。
 *   @option options :html_escape (false)
 *     スニペット内の +<+, +>+, +&+, +"+ をHTMLエスケープするか
 *     どうか。省略した場合は +false+ で、HTMLエスケープしない。
 * @return [Groonga::Snippet]
 */
static VALUE
rb_grn_expression_snippet (int argc, VALUE *argv, VALUE self)
{
    grn_ctx *context = NULL;
    grn_obj *expression;
    grn_obj *snippet;
    VALUE options;
    VALUE rb_normalize, rb_skip_leading_spaces;
    VALUE rb_width, rb_max_results, rb_tags;
    VALUE rb_html_escape;
    VALUE *rb_tag_values;
    VALUE related_object;
    unsigned int i;
    int flags = GRN_SNIP_COPY_TAG;
    unsigned int width = 100;
    unsigned int max_results = 3;
    unsigned int n_tags = 0;
    char **open_tags = NULL;
    unsigned int *open_tag_lengths = NULL;
    char **close_tags = NULL;
    unsigned int *close_tag_lengths = NULL;
    grn_snip_mapping *mapping = NULL;

    rb_grn_expression_deconstruct(SELF(self), &expression, &context,
                                  NULL, NULL,
                                  NULL, NULL, NULL);

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

    rb_grn_scan_options(options,
                        "normalize", &rb_normalize,
                        "skip_leading_spaces", &rb_skip_leading_spaces,
                        "width", &rb_width,
                        "max_results", &rb_max_results,
                        "html_escape", &rb_html_escape,
                        NULL);

    if (TYPE(rb_tags) != T_ARRAY) {
        rb_raise(rb_eArgError,
                 "tags should be "
                 "[\"open_tag\", \"close_tag\"] or "
                 "[[\"open_tag1\", \"close_tag1\"], ...]: %s",
                 rb_grn_inspect(rb_tags));
    }

    if (TYPE(RARRAY_PTR(rb_tags)[0]) == T_STRING) {
        rb_tags = rb_ary_new_from_args(1, rb_tags);
    }

    rb_tag_values = RARRAY_PTR(rb_tags);
    n_tags = RARRAY_LEN(rb_tags);
    open_tags = ALLOCA_N(char *, n_tags);
    open_tag_lengths = ALLOCA_N(unsigned int, n_tags);
    close_tags = ALLOCA_N(char *, n_tags);
    close_tag_lengths = ALLOCA_N(unsigned int, n_tags);
    for (i = 0; i < n_tags; i++) {
        VALUE *tag_pair;

        if (TYPE(rb_tag_values[i]) != T_ARRAY ||
            RARRAY_LEN(rb_tag_values[i]) != 2) {
            rb_raise(rb_eArgError,
                     "tags should be "
                     "[\"open_tag\", \"close_tag\"] or"
                     "[[\"open_tag1\", \"close_tag1\"], ...]: %s",
                     rb_grn_inspect(rb_tags));
        }
        tag_pair = RARRAY_PTR(rb_tag_values[i]);
        open_tags[i] = StringValuePtr(tag_pair[0]);
        open_tag_lengths[i] = RSTRING_LEN(tag_pair[0]);
        close_tags[i] = StringValuePtr(tag_pair[1]);
        close_tag_lengths[i] = RSTRING_LEN(tag_pair[1]);
    }

    if (RVAL2CBOOL(rb_normalize))
        flags |= GRN_SNIP_NORMALIZE;
    if (RVAL2CBOOL(rb_skip_leading_spaces))
        flags |= GRN_SNIP_SKIP_LEADING_SPACES;

    if (!NIL_P(rb_width))
        width = NUM2UINT(rb_width);

    if (!NIL_P(rb_max_results))
        max_results = NUM2UINT(rb_max_results);

    if (RVAL2CBOOL(rb_html_escape))
        mapping = (grn_snip_mapping *)-1;

    snippet = grn_expr_snip(context, expression, flags, width, max_results,
                            n_tags,
                            (const char **)open_tags, open_tag_lengths,
                            (const char **)close_tags, close_tag_lengths,
                            mapping);
    related_object =
        rb_ary_new_from_args(2, self, rb_ary_new_from_values(argc, argv));
    rb_grn_context_check(context, related_object);

    return GRNOBJECT2RVAL(Qnil, context, snippet, GRN_TRUE);
}
예제 #30
0
zval *value_to_zval(VALUE v) {
    zval *zv;
    MAKE_STD_ZVAL(zv);

    switch (TYPE(v)) {
        case T_FALSE:
            ZVAL_FALSE(zv);
            return zv;
        case T_TRUE:
            ZVAL_TRUE(zv);
            return zv;
        case T_UNDEF:
        case T_NIL:
            ZVAL_NULL(zv);
            return zv;
        case T_FIXNUM:
            ZVAL_LONG(zv, rb_fix2int(v));
            return zv;
        case T_BIGNUM:
            ZVAL_LONG(zv, rb_big2long(v)); // FIXME: bignum over long
            return zv;
        case T_FLOAT:
            ZVAL_DOUBLE(zv, RFLOAT_VALUE(v));
            return zv;
        case T_ARRAY:
            {
                int i;
                array_init(zv);
                for(i=0;i<RARRAY_LEN(v);++i) {
                    zval *add = value_to_zval(RARRAY_PTR(v)[i]);
                    zend_hash_next_index_insert(Z_ARRVAL_P(zv), &add, sizeof(zval *), NULL);
                }
                return zv;
            }
        case T_HASH:
            {
                array_init(zv);
                rb_hash_foreach(v, hash_to_zval, (VALUE)zv);
                return zv;
            }
        case T_SYMBOL:
            {
                VALUE symbol_str = rb_sym_to_s(v);
                ZVAL_STRINGL(zv, StringValuePtr(symbol_str), RSTRING_LEN(symbol_str), 1);
                return zv;
            }
        case T_STRING:
            {
                ZVAL_STRINGL(zv, StringValuePtr(v), RSTRING_LEN(v), 1);
                return zv;
            }
        default:
            {
                if (CLASS_OF(v) == cPhpEmbedValue) {
                    php_value* pv;
                    Data_Get_Struct(v, php_value, pv);
                    MAKE_COPY_ZVAL(&pv->value, zv);
                    return zv;
                }
            }
            FREE_ZVAL(zv);
            rb_raise(rb_eRuntimeError, "no implemented");
    }
}