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; }
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; }
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; }
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); } }
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__ */ } }
#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);
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); }
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(); }
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); }
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; }
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; }
static VALUE sFactoryCall (VALUE args) { VALUE *argsP = RARRAY_PTR(args); return rb_method_call(1, argsP, argsP[1]); }
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; }
/* 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); }
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; }
static VALUE eval_expression(VALUE args) { return rb_funcall2(rb_mKernel, idEval, 2, RARRAY_PTR(args)); }
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; } }
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)
/*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 = █ 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; }
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; }
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; }
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; }
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; }
/* * 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; }
PRIMITIVE const VALUE * vm_ary_ptr(VALUE ary) { return RARRAY_PTR(ary); }
/* * 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; }
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); }
/* * 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; }
/* * _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); }
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"); } }