diff options
Diffstat (limited to 'ext/Safe/Safe.xs')
-rw-r--r-- | ext/Safe/Safe.xs | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/ext/Safe/Safe.xs b/ext/Safe/Safe.xs new file mode 100644 index 0000000000..4437284932 --- /dev/null +++ b/ext/Safe/Safe.xs @@ -0,0 +1,113 @@ +#include "EXTERN.h" +#include "perl.h" +#include "XSUB.h" + +MODULE = Safe PACKAGE = Safe + +void +safe_call_sv(package, mask, codesv) + char * package + SV * mask + SV * codesv + CODE: + int i; + char *str; + STRLEN len; + + ENTER; + SAVETMPS; + save_hptr(&defstash); + save_aptr(&endav); + SAVEPPTR(op_mask); + Newz(666, op_mask, maxo, char); + SAVEFREEPV(op_mask); + str = SvPV(mask, len); + if (maxo != len) + croak("Bad mask length"); + for (i = 0; i < maxo; i++) + op_mask[i] = str[i]; + defstash = gv_stashpv(package, TRUE); + endav = (AV*)sv_2mortal((SV*)newAV()); /* Ignore END blocks for now */ + GvHV(gv_fetchpv("main::", TRUE, SVt_PVHV)) = defstash; + PUSHMARK(sp); + i = perl_call_sv(codesv, G_SCALAR|G_EVAL|G_KEEPERR); + SPAGAIN; + ST(0) = i ? newSVsv(POPs) : &sv_undef; + PUTBACK; + FREETMPS; + LEAVE; + sv_2mortal(ST(0)); + +void +op_mask() + CODE: + ST(0) = sv_newmortal(); + if (op_mask) + sv_setpvn(ST(0), op_mask, maxo); + +void +mask_to_ops(mask) + SV * mask + PPCODE: + STRLEN len; + char *maskstr = SvPV(mask, len); + int i; + if (maxo != len) + croak("Bad mask length"); + for (i = 0; i < maxo; i++) + if (maskstr[i]) + XPUSHs(sv_2mortal(newSVpv(op_name[i], 0))); + +void +ops_to_mask(...) + CODE: + int i, j; + char *mask, *op; + Newz(666, mask, maxo, char); + for (i = 0; i < items; i++) + { + op = SvPV(ST(i), na); + for (j = 0; j < maxo && strNE(op, op_name[j]); j++) /* nothing */ ; + if (j < maxo) + mask[j] = 1; + else + { + Safefree(mask); + croak("bad op name \"%s\" in mask", op); + } + } + ST(0) = sv_newmortal(); + sv_usepvn(ST(0), mask, maxo); + +void +opname(...) + PPCODE: + int i, opcode; + for (i = 0; i < items; i++) + { + opcode = SvIV(ST(i)); + if (opcode < 0 || opcode >= maxo) + croak("opcode out of range"); + XPUSHs(sv_2mortal(newSVpv(op_name[opcode], 0))); + } + +void +opcode(...) + PPCODE: + int i, j; + char *op; + for (i = 0; i < items; i++) + { + op = SvPV(ST(i), na); + for (j = 0; j < maxo && strNE(op, op_name[j]); j++) /* nothing */ ; + if (j == maxo) + croak("bad op name \"%s\"", op); + XPUSHs(sv_2mortal(newSViv(j))); + } + +int +MAXO() + CODE: + RETVAL = maxo; + OUTPUT: + RETVAL |