static VALUE proc_call(VALUE procval, SEL sel, int argc, const VALUE *argv) { #if 0 rb_proc_t *proc; rb_block_t *blockptr = 0; GetProcPtr(procval, proc); if (BUILTIN_TYPE(proc->block.iseq) != T_NODE && proc->block.iseq->arg_block != -1) { if (rb_block_given_p()) { rb_proc_t *proc; VALUE procval; procval = rb_block_proc(); GetProcPtr(procval, proc); blockptr = &proc->block; } } return vm_invoke_proc(GET_THREAD(), proc, proc->block.self, argc, argv, blockptr); #endif rb_vm_block_t *proc; GetProcPtr(procval, proc); return rb_vm_block_eval(proc, argc, argv); }
static VALUE proc_eq(VALUE self, SEL sel, VALUE other) { if (self == other) { return Qtrue; } else if (rb_obj_is_kind_of(other, rb_cProc)) { rb_vm_block_t *self_b, *other_b; GetProcPtr(self, self_b); GetProcPtr(other, other_b); return self_b == other_b ? Qtrue : Qfalse; } return Qfalse; }
static VALUE proc_dup(VALUE self) { VALUE procval = proc_alloc(rb_cProc); rb_proc_t *src, *dst; GetProcPtr(self, src); GetProcPtr(procval, dst); dst->block = src->block; dst->envval = src->envval; dst->safe_level = dst->safe_level; dst->special_cref_stack = src->special_cref_stack; return procval; }
VALUE rb_vm_make_proc(rb_thread_t *th, const rb_block_t *block, VALUE klass) { VALUE procval, envval, blockprocval = 0; rb_proc_t *proc; rb_control_frame_t *cfp = RUBY_VM_GET_CFP_FROM_BLOCK_PTR(block); if (block->proc) { rb_bug("rb_vm_make_proc: Proc value is already created."); } if (GC_GUARDED_PTR_REF(cfp->lfp[0])) { rb_proc_t *p; blockprocval = vm_make_proc_from_block( th, (rb_block_t *)GC_GUARDED_PTR_REF(*cfp->lfp)); GetProcPtr(blockprocval, p); *cfp->lfp = GC_GUARDED_PTR(&p->block); } envval = rb_vm_make_env_object(th, cfp); if (PROCDEBUG) { check_env_value(envval); } procval = rb_proc_alloc(klass); GetProcPtr(procval, proc); proc->blockprocval = blockprocval; proc->block.self = block->self; proc->block.lfp = block->lfp; proc->block.dfp = block->dfp; proc->block.iseq = block->iseq; proc->block.proc = procval; proc->envval = envval; proc->safe_level = th->safe_level; if (VMDEBUG) { if (th->stack < block->dfp && block->dfp < th->stack + th->stack_size) { rb_bug("invalid ptr: block->dfp"); } if (th->stack < block->lfp && block->lfp < th->stack + th->stack_size) { rb_bug("invalid ptr: block->lfp"); } } return procval; }
static VALUE proc_hash(VALUE self, SEL sel) { rb_vm_block_t *b; GetProcPtr(self, b); return LONG2FIX(b); }
int rb_proc_arity(VALUE proc) { rb_vm_block_t *b; GetProcPtr(proc, b); return rb_vm_arity_n(b->arity); }
static VALUE proc_dup(VALUE self, SEL sel) { rb_vm_block_t *src; GetProcPtr(self, src); return Data_Wrap_Struct(CLASS_OF(self), NULL, NULL, src); }
VALUE rb_proc_call_with_block(VALUE self, int argc, VALUE *argv, VALUE pass_procval) { rb_proc_t *proc; rb_block_t *block = 0; GetProcPtr(self, proc); if (!NIL_P(pass_procval)) { rb_proc_t *pass_proc; GetProcPtr(pass_procval, pass_proc); block = &pass_proc->block; } return rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self, argc, argv, block); }
static VALUE proc_yield(int argc, VALUE *argv, VALUE procval) { rb_proc_t *proc; GetProcPtr(procval, proc); return th_invoke_proc(GET_THREAD(), proc, proc->block.self, argc, argv); }
/* * call-seq: * proc.dump(limit) => String * * Dump a Proc to a String. */ static VALUE proc_dump(VALUE self, VALUE limit) { if(rb_safe_level() >= 4) { /* no access to potentially sensitive data from the sandbox */ rb_raise(rb_eSecurityError, "Insecure: can't dump proc"); } { #ifdef RUBY_VM rb_proc_t * p; VALUE iseq, str; rb_iseq_t * iseqdat; GetProcPtr(self, p); iseq = p->block.iseq->self; iseqdat = iseq_check(iseq); iseqdat->type = ISEQ_TYPE_TOP; /* TODO: is this right? */ str = marshal_dump(iseq, limit); return str; #else struct BLOCK * b; VALUE body, var, arr; Data_Get_Struct(self, struct BLOCK, b); body = wrap_node(b->body); var = wrap_node(b->var); arr = rb_assoc_new(body, var); return marshal_dump(arr, limit); #endif } }
static VALUE proc_to_s(VALUE self) { VALUE str = 0; rb_proc_t *proc; const char *cname = rb_obj_classname(self); rb_iseq_t *iseq; const char *is_lambda; GetProcPtr(self, proc); iseq = proc->block.iseq; is_lambda = proc->is_lambda ? " (lambda)" : ""; if (RUBY_VM_NORMAL_ISEQ_P(iseq)) { int line_no = 0; if (iseq->insn_info_table) { line_no = rb_iseq_first_lineno(iseq); } str = rb_sprintf("#<%s:%p@%s:%d%s>", cname, (void *)self, RSTRING_PTR(iseq->filename), line_no, is_lambda); } else { str = rb_sprintf("#<%s:%p%s>", cname, (void *)proc->block.iseq, is_lambda); } if (OBJ_TAINTED(self)) { OBJ_TAINT(str); } return str; }
static VALUE proc_arity(VALUE self) { rb_proc_t *proc; rb_iseq_t *iseq; GetProcPtr(self, proc); iseq = proc->block.iseq; if (iseq) { if (BUILTIN_TYPE(iseq) != T_NODE) { if (iseq->arg_rest < 0) { return INT2FIX(iseq->argc); } else { return INT2FIX(-(iseq->argc + 1 + iseq->arg_post_len)); } } else { NODE *node = (NODE *)iseq; if (nd_type(node) == NODE_IFUNC && node->nd_cfnc == bmcall) { /* method(:foo).to_proc.arity */ return INT2FIX(method_arity(node->nd_tval)); } } } return INT2FIX(-1); }
static VALUE proc_to_s(VALUE self) { VALUE str = 0; rb_proc_t *proc; char *cname = rb_obj_classname(self); rb_iseq_t *iseq; GetProcPtr(self, proc); iseq = proc->block.iseq; if (RUBY_VM_NORMAL_ISEQ_P(iseq)) { int line_no = 0; if (iseq->insn_info_tbl) { line_no = iseq->insn_info_tbl[0].line_no; } str = rb_sprintf("#<%s:%lx@%s:%d>", cname, self, RSTRING_PTR(iseq->filename), line_no); } else { str = rb_sprintf("#<%s:%p>", cname, proc->block.iseq); } if (OBJ_TAINTED(self)) { OBJ_TAINT(str); } return str; }
static VALUE proc_dup(VALUE self) { VALUE procval = rb_proc_alloc(rb_cProc); rb_proc_t *src, *dst; GetProcPtr(self, src); GetProcPtr(procval, dst); dst->block = src->block; dst->block.proc = procval; dst->envval = src->envval; dst->safe_level = src->safe_level; dst->is_lambda = src->is_lambda; return procval; }
static sighandler_t trap_handler(VALUE *cmd, int sig) { sighandler_t func = sighandler; VALUE command; if (NIL_P(*cmd)) { func = SIG_IGN; } else { command = rb_check_string_type(*cmd); if (!NIL_P(command)) { SafeStringValue(command); /* taint check */ *cmd = command; switch (RSTRING_LEN(command)) { case 0: goto sig_ign; break; case 14: if (strncmp(RSTRING_PTR(command), "SYSTEM_DEFAULT", 14) == 0) { func = SIG_DFL; *cmd = 0; } break; case 7: if (strncmp(RSTRING_PTR(command), "SIG_IGN", 7) == 0) { sig_ign: func = SIG_IGN; *cmd = 0; } else if (strncmp(RSTRING_PTR(command), "SIG_DFL", 7) == 0) { sig_dfl: func = default_handler(sig); *cmd = 0; } else if (strncmp(RSTRING_PTR(command), "DEFAULT", 7) == 0) { goto sig_dfl; } break; case 6: if (strncmp(RSTRING_PTR(command), "IGNORE", 6) == 0) { goto sig_ign; } break; case 4: if (strncmp(RSTRING_PTR(command), "EXIT", 4) == 0) { *cmd = Qundef; } break; } } else { rb_proc_t *proc; GetProcPtr(*cmd, proc); } } return func; }
static void signal_exec(VALUE cmd, int sig) { rb_proc_t *proc; VALUE signum = INT2FIX(sig); GetProcPtr(cmd, proc); vm_invoke_proc(GET_THREAD(), proc, proc->block.self, 1, &signum, 0); }
VALUE rb_proc_call(VALUE self, VALUE args) { rb_proc_t *proc; GetProcPtr(self, proc); return rb_vm_invoke_proc(GET_THREAD(), proc, proc->block.self, RARRAY_LEN(args), RARRAY_PTR(args), 0); }
static VALUE proc_lambda_p(VALUE procval) { rb_proc_t *proc; GetProcPtr(procval, proc); return proc->is_lambda ? Qtrue : Qfalse; }
static VALUE proc_lambda_p(VALUE procval, SEL sel) { rb_vm_block_t *proc; GetProcPtr(procval, proc); return (proc->flags & VM_BLOCK_LAMBDA) == VM_BLOCK_LAMBDA ? Qtrue : Qfalse; }
static VALUE proc_references(VALUE rbproc) { rb_proc_t* proc; GetProcPtr(rbproc, proc); if (!NIL_P(proc->envval)) return env_references(proc->envval); return rb_ary_new(); }
VALUE proc_invoke(VALUE self, VALUE args, VALUE alt_self, VALUE alt_klass) { rb_proc_t *proc; GetProcPtr(self, proc); /* ignore self and klass */ return th_invoke_proc(GET_THREAD(), proc, proc->block.self, RARRAY_LEN(args), RARRAY_PTR(args)); }
static VALUE proc_new(VALUE klass, int is_lambda) { VALUE procval = Qnil; rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = th->cfp; rb_block_t *block; if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0 && !RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) { block = GC_GUARDED_PTR_REF(cfp->lfp[0]); cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } else { cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0 && !RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) { block = GC_GUARDED_PTR_REF(cfp->lfp[0]); if (block->proc) { return block->proc; } /* TODO: check more (cfp limit, called via cfunc, etc) */ while (cfp->dfp != block->dfp) { cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } if (is_lambda) { rb_warn("tried to create Proc object without a block"); } } else { rb_raise(rb_eArgError, "tried to create Proc object without a block"); } } procval = block->proc; if (procval && RBASIC(procval)->klass == klass) { return procval; } procval = vm_make_proc(th, cfp, block, klass); if (is_lambda) { rb_proc_t *proc; GetProcPtr(procval, proc); proc->is_lambda = Qtrue; } return procval; }
static void vm_caller_setup_arg_block(const rb_thread_t *th, rb_control_frame_t *reg_cfp, struct rb_calling_info *calling, const struct rb_call_info *ci, rb_iseq_t *blockiseq, const int is_super) { if (ci->flag & VM_CALL_ARGS_BLOCKARG) { rb_proc_t *po; VALUE proc; proc = *(--reg_cfp->sp); if (NIL_P(proc)) { calling->blockptr = NULL; } else if (SYMBOL_P(proc) && rb_method_basic_definition_p(rb_cSymbol, idTo_proc)) { calling->blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp); calling->blockptr->iseq = (rb_iseq_t *)proc; calling->blockptr->proc = proc; } else if (RUBY_VM_IFUNC_P(proc)) { calling->blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp); calling->blockptr->iseq = (rb_iseq_t *)proc; calling->blockptr->proc = proc; } else { if (!rb_obj_is_proc(proc)) { VALUE b; 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); calling->blockptr = &po->block; RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp)->proc = proc; } } else if (blockiseq != 0) { /* likely */ rb_block_t *blockptr = calling->blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP(reg_cfp); blockptr->iseq = blockiseq; blockptr->proc = 0; } else { if (is_super) { calling->blockptr = GET_BLOCK_PTR(); } else { calling->blockptr = NULL; } } }
static VALUE proc_hash(VALUE self) { int hash; rb_proc_t *proc; GetProcPtr(self, proc); hash = (long)proc->block.iseq; hash ^= (long)proc->envval; hash ^= (long)proc->block.lfp >> 16; return INT2FIX(hash); }
VALUE rb_proc_call(VALUE self, VALUE args) { #if 0 rb_proc_t *proc; GetProcPtr(self, proc); return vm_invoke_proc(GET_THREAD(), proc, proc->block.self, RARRAY_LEN(args), RARRAY_PTR(args), 0); #endif return proc_call(self, 0, RARRAY_LEN(args), RARRAY_PTR(args)); }
static VALUE proc_eq(VALUE self, VALUE other) { if (self == other) { return Qtrue; } else { if (TYPE(other) == T_DATA && RBASIC(other)->klass == rb_cProc && CLASS_OF(self) == CLASS_OF(other)) { rb_proc_t *p1, *p2; GetProcPtr(self, p1); GetProcPtr(other, p2); if (p1->block.iseq == p2->block.iseq && p1->envval == p2->envval) { return Qtrue; } } } return Qfalse; }
VALUE rb_proc_new( VALUE (*func)(ANYARGS), /* VALUE yieldarg[, VALUE procarg] */ VALUE val) { rb_proc_t *proc; VALUE procval = rb_iterate((VALUE(*)(VALUE))mproc, 0, func, val); GetProcPtr(procval, proc); ((NODE*)proc->block.iseq)->u3.state = 1; return procval; }
static VALUE proc_new(VALUE klass, int is_lambda) { VALUE procval = Qnil; rb_thread_t *th = GET_THREAD(); rb_control_frame_t *cfp = th->cfp; rb_block_t *block; if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0 && !RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) { block = GC_GUARDED_PTR_REF(cfp->lfp[0]); } else { cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); if ((GC_GUARDED_PTR_REF(cfp->lfp[0])) != 0 && !RUBY_VM_CLASS_SPECIAL_P(cfp->lfp[0])) { block = GC_GUARDED_PTR_REF(cfp->lfp[0]); if (is_lambda) { rb_warn("tried to create Proc object without a block"); } } else { rb_raise(rb_eArgError, "tried to create Proc object without a block"); } } procval = block->proc; if (procval) { if (RBASIC(procval)->klass == klass) { return procval; } else { VALUE newprocval = proc_dup(procval); RBASIC(newprocval)->klass = klass; return newprocval; } } procval = rb_vm_make_proc(th, block, klass); if (is_lambda) { rb_proc_t *proc; GetProcPtr(procval, proc); proc->is_lambda = Qtrue; } return procval; }
static rb_iseq_t * get_proc_iseq(VALUE self) { rb_proc_t *proc; rb_iseq_t *iseq; GetProcPtr(self, proc); iseq = proc->block.iseq; if (!RUBY_VM_NORMAL_ISEQ_P(iseq)) return 0; return iseq; }
static inline int block_proc_is_lambda(const VALUE procval) { rb_proc_t *proc; if (procval) { GetProcPtr(procval, proc); return proc->is_lambda; } else { return 0; } }