/* NOTE: mouse_tc_check() handles GETMAGIC */ int mouse_tc_check(pTHX_ SV* const tc_code, SV* const sv) { CV* const cv = (CV*)SvRV(tc_code); assert(SvTYPE(cv) == SVt_PVCV); if(CvXSUB(cv) == XS_Mouse_constraint_check){ /* built-in type constraints */ MAGIC* const mg = (MAGIC*)CvXSUBANY(cv).any_ptr; assert(CvXSUBANY(cv).any_ptr != NULL); assert(mg->mg_ptr != NULL); SvGETMAGIC(sv); /* call the check function directly, skipping call_sv() */ return CALL_FPTR((check_fptr_t)mg->mg_ptr)(aTHX_ mg->mg_obj, sv); } else { /* custom */ int ok; dSP; dMY_CXT; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv); if( MY_CXT.tc_extra_args ) { AV* const av = MY_CXT.tc_extra_args; I32 const len = AvFILLp(av) + 1; int i; for(i = 0; i < len; i++) { XPUSHs( AvARRAY(av)[i] ); } } PUTBACK; call_sv(tc_code, G_SCALAR); SPAGAIN; ok = sv_true(POPs); PUTBACK; FREETMPS; LEAVE; return ok; } }
static void _MopMmV_wrapper (pTHX_ CV *cv) { bool has_events; I32 j, count; SV** args; CV* body; SV* object = newRV_noinc((SV*) cv); AV* results = newAV(); dXSARGS; has_events = MopOV_has_events(object); body = (CV*) CvXSUBANY(cv).any_uv; if (has_events) { Newx(args, items, SV*); for (j = 0; j < items; j++) { args[j] = ST(j); } MopOV_fire_event(object, newSVpv("before:EXECUTE", 14), args, items-1); } { ENTER; PUSHMARK(SP); for (j = 0; j < items; j++) { PUSHs(args[j]); } PUTBACK; count = call_sv((SV*) body, GIMME_V); SPAGAIN; while (count-- > 0) { av_push(results, POPs); } LEAVE; } for (j = 0; j < av_len(results) + 1; j++) { ST(j) = *av_fetch(results, av_len(results) - j, 0); } if (has_events) { MopOV_fire_event(object, newSVpv("after:EXECUTE", 13), args, items-1); } XSRETURN(av_len(results) + 1); }
static void xs_new(pTHX_ SV *cv) { dXSARGS; if (items < 1) croak("Usage: class, ref"); #ifndef MULTIPLICITY AV *slots = CvXSUBANY(cv).any_ptr; #else MAGIC *mg = mg_findext(cv, PERL_MAGIC_ext, &ATTRS_TBL); AV *slots = (AV *)mg->mg_obj; #endif SV *class = ST(0); HV *hash = newHV(); SV *obj = sv_2mortal(newRV_noinc((SV *)hash)); // don't move to the end(leaks) SV **args; // uniq args int args_count = args_to_uniq(&ST(1), items - 1, &args); // skip 1(class) int slots_count = av_top_index(slots) + 1; for (int i = 0; i < slots_count; i++) { // NEXT_SLOT: ECAslot *slot = sv2slot(av_fetch_or_croak(slots, i)); // iterage args, null if matched for (int j = 0; j < args_count; j += 2) { SV *tmp = args[j]; if (!tmp) continue; // already matched if (!sv_cmp(tmp, slot->key)) { if (slot->check) do_check(slot->check, args[j + 1], slot->key); hv_he_store_or_croak(hash, slot->key, args[j + 1]); args[j] = NULL; goto NEXT_SLOT; args[j] = NULL; // mark as consumed } } // slot not found in passed args, decide what to do if (slot->type == ECA_REQUIRED) { croak("Attribute \"%s\" is required", SvPV_nolen(slot->key)); } else if (slot->type == ECA_DEFAULT) { hv_he_store_or_croak(hash, slot->key, slot->value); } else if (slot->type == ECA_DEFAULT_CODE) { invoke_and_store(class, slot->value, hash, slot->key); } NEXT_SLOT:; // simulate continue label }
SV* THX_newMopMmV(pTHX_ SV* code, U32 flags) { SV* method; CV* cv = (CV*) newSV(0); sv_upgrade((SV*) cv, SVt_PVCV); CvISXSUB_on(cv); CvXSUB(cv) = _MopMmV_wrapper; CvXSUBANY(cv).any_uv = PTR2UV(code); CvFILE(cv) = __FILE__; CvANON_off(cv); CvMETHOD_on(cv); SvREFCNT_inc(code); method = newMopOV(newRV_inc((SV*) cv)); if (flags & MopMmVf_STEAL_STASH) { MopMmV_assign_to_stash(method, CvGV(SvRV(code)), CvSTASH(SvRV(code))); } return method; }
static CV *coroae_closure_sighandler(int sigfd) { CV *xsub = newXS(NULL, XS_coroae_sighandler, "uwsgi::coroae"); CvXSUBANY(xsub).any_ptr = (void *) sigfd; return xsub; }
static CV *coroae_closure_acceptor(struct uwsgi_socket *uwsgi_sock) { CV *xsub = newXS(NULL, XS_coroae_acceptor, "uwsgi::coroae"); CvXSUBANY(xsub).any_ptr = uwsgi_sock; return xsub; }
SV* THX_MopMmV_get_body(pTHX_ SV* metamethod) { return newRV_noinc((SV*) CvXSUBANY((CV*) SvRV(metamethod)).any_uv); }