summaryrefslogtreecommitdiff
path: root/ext/Safe/Safe.xs
diff options
context:
space:
mode:
Diffstat (limited to 'ext/Safe/Safe.xs')
-rw-r--r--ext/Safe/Safe.xs113
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