#ifdef __cplusplus
extern
"C"
{
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "Python.h"
#include "perlmodule.h"
#include "py2pl.h"
#include "util.h"
#ifdef __cplusplus
}
#endif
#ifdef CREATE_PERL
static
PerlInterpreter *my_perl;
#endif
staticforward PyObject * special_perl_eval(PyObject *, PyObject *);
staticforward PyObject * special_perl_use(PyObject *, PyObject *);
staticforward PyObject * special_perl_require(PyObject *, PyObject *);
PyObject * newPerlPkg_object(PyObject *base, PyObject *pkg);
staticforward
void
PerlPkg_dealloc(PerlPkg_object *self);
staticforward PyObject * PerlPkg_repr(PerlPkg_object *self, PyObject *args);
staticforward PyObject * PerlPkg_getattr(PerlPkg_object *self,
char
*name);
PyObject * newPerlObj_object(SV *obj, PyObject *pkg);
staticforward
void
PerlObj_dealloc(PerlObj_object *self);
staticforward PyObject * PerlObj_repr(PerlObj_object *self);
staticforward PyObject * PerlObj_str(PerlObj_object *self);
staticforward PyObject * PerlObj_call(PerlObj_object *self, PyObject *args, PyObject *kw);
staticforward PyObject * PerlObj_getattr(PerlObj_object *self,
char
*name);
staticforward PyObject * PerlObj_mp_subscript(PerlObj_object *self, PyObject *key);
PyObject * newPerlSub_object(PyObject *base,
PyObject *pkg,
SV *cv);
PyObject * newPerlMethod_object(PyObject *base,
PyObject *pkg,
SV *obj);
PyObject * newPerlCfun_object(PyObject* (*cfun)(PyObject *self, PyObject *args));
staticforward
void
PerlSub_dealloc(PerlSub_object *self);
staticforward PyObject * PerlSub_call(PerlSub_object *self, PyObject *args, PyObject *kw);
staticforward PyObject * PerlSub_repr(PerlSub_object *self, PyObject *args);
staticforward PyObject * PerlSub_getattr(PerlSub_object *self,
char
*name);
staticforward
int
PerlSub_setattr(PerlSub_object *self,
char
*name,
PyObject *value);
PyObject *
newPerlPkg_object(PyObject *base, PyObject *package) {
PerlPkg_object *
const
self = PyObject_NEW(PerlPkg_object, &PerlPkg_type);
#if PY_MAJOR_VERSION >= 3
char
*
const
bs = PyBytes_AsString(base);
char
*
const
pkg = PyBytes_AsString(package);
#else
char
*
const
bs = PyString_AsString(base);
char
*
const
pkg = PyString_AsString(package);
#endif
char
*
const
str = (
char
*)
malloc
((
strlen
(bs) +
strlen
(pkg) +
strlen
(
"::"
) + 1)
*
sizeof
(
char
));
if
(!self) {
free
(str);
PyErr_Format(PyExc_MemoryError,
"Couldn't create Perl Package object.\n"
);
return
NULL;
}
sprintf
(str,
"%s%s::"
, bs, pkg);
Py_INCREF(base);
Py_INCREF(package);
self->base = base;
self->pkg = package;
#if PY_MAJOR_VERSION >= 3
self->full = PyBytes_FromString(str);
#else
self->full = PyString_FromString(str);
#endif
free
(str);
return
(PyObject*)self;
}
static
void
PerlPkg_dealloc(PerlPkg_object *self) {
Py_XDECREF(self->pkg);
Py_XDECREF(self->base);
Py_XDECREF(self->full);
PyObject_Del(self);
}
static
PyObject *
PerlPkg_repr(PerlPkg_object *self, PyObject *args) {
PyObject *s;
char
*
const
str = (
char
*)
malloc
((
strlen
(
"<perl package: ''>"
)
+ PyObject_Length(self->full)
+ 1) *
sizeof
(
char
));
#if PY_MAJOR_VERSION >= 3
sprintf
(str,
"<perl package: '%s'>"
, PyBytes_AsString(self->full));
s = PyUnicode_FromString(str);
#else
sprintf
(str,
"<perl package: '%s'>"
, PyString_AsString(self->full));
s = PyString_FromString(str);
#endif
free
(str);
return
s;
}
static
PyObject *
PerlPkg_getattr(PerlPkg_object *self,
char
*name) {
if
(
strcmp
(name,
"__methods__"
) == 0) {
return
get_perl_pkg_subs(self->full);
}
else
if
(
strcmp
(name,
"__members__"
) == 0) {
PyObject *retval = PyList_New(0);
return
retval ? retval : NULL;
}
else
if
(
strcmp
(name,
"__dict__"
) == 0) {
PyObject *retval = PyDict_New();
return
retval ? retval : NULL;
}
else
if
(PKG_EQ(self,
"main::"
) &&
strcmp
(name,
"eval"
)==0) {
return
newPerlCfun_object(&special_perl_eval);
}
else
if
(PKG_EQ(self,
"main::"
) &&
strcmp
(name,
"use"
)==0) {
return
newPerlCfun_object(&special_perl_use);
}
else
if
(PKG_EQ(self,
"main::"
) &&
strcmp
(name,
"require"
)==0) {
return
newPerlCfun_object(&special_perl_require);
}
else
{
#if PY_MAJOR_VERSION >= 3
PyObject *
const
tmp = PyBytes_FromString(name);
char
*
const
full_c = PyBytes_AsString(self->full);
#else
PyObject *
const
tmp = PyString_FromString(name);
char
*
const
full_c = PyString_AsString(self->full);
#endif
PyObject *
const
res = perl_pkg_exists(full_c, name)
? newPerlPkg_object(self->full, tmp)
: newPerlSub_object(self->full, tmp, NULL);
Py_DECREF(tmp);
return
res;
}
}
static
PyObject * module_dir(PerlPkg_object *self, PyObject *args) {
return
get_perl_pkg_subs(self->full);
}
static
struct
PyMethodDef PerlPkg_methods[] = {
{
"__dir__"
, (PyCFunction)module_dir, METH_NOARGS, NULL},
{NULL}
};
static
char
PerlPkg_type__doc__[] =
"_perl_pkg -- Wrap a Perl package in a Python class"
;
PyTypeObject PerlPkg_type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_perl_pkg"
,
sizeof
(PerlPkg_object),
0,
(destructor)PerlPkg_dealloc,
(printfunc)0,
(getattrfunc)PerlPkg_getattr,
(setattrfunc)0,
#if PY_MAJOR_VERSION < 3
(cmpfunc)0,
#else
0,
#endif
(reprfunc)PerlPkg_repr,
0,
0,
0,
(hashfunc)0,
(ternaryfunc)0,
(reprfunc)PerlPkg_repr,
0,
0,
0,
Py_TPFLAGS_DEFAULT,
PerlPkg_type__doc__,
(traverseproc)0,
(inquiry)0,
0,
0,
0,
0,
PerlPkg_methods,
};
PyObject *
newPerlObj_object(SV *obj, PyObject *package) {
PerlObj_object *
const
self = PyObject_NEW(PerlObj_object, &PerlObj_type);
if
(!self) {
PyErr_Format(PyExc_MemoryError,
"Couldn't create Perl Obj object.\n"
);
return
NULL;
}
Py_INCREF(package);
SvREFCNT_inc(obj);
self->pkg = package;
self->obj = obj;
return
(PyObject*)self;
}
static
void
PerlObj_dealloc(PerlObj_object *self) {
Py_XDECREF(self->pkg);
if
(self->obj) sv_2mortal(self->obj);
PyObject_Del(self);
}
static
PyObject *
PerlObj_repr(PerlObj_object *self) {
PyObject *s;
char
*
const
str = (
char
*)
malloc
((
strlen
(
"<perl object: ''>"
)
+ PyObject_Length(self->pkg)
+ 1) *
sizeof
(
char
));
#if PY_MAJOR_VERSION >= 3
sprintf
(str,
"<perl object: '%s'>"
, PyBytes_AsString(self->pkg));
s = PyUnicode_FromString(str);
#else
sprintf
(str,
"<perl object: '%s'>"
, PyString_AsString(self->pkg));
s = PyString_FromString(str);
#endif
free
(str);
return
s;
}
static
PyObject *
PerlObj_str(PerlObj_object *self) {
STRLEN len;
SV*
const
sv = ((SvTHINKFIRST(self->obj) && !SvIsCOW(self->obj)) || isGV_with_GP(self->obj))
? sv_mortalcopy(self->obj)
: self->obj;
char
*
const
str = SvPVutf8(sv, len);
return
PyUnicode_DecodeUTF8(str, len,
"replace"
);
}
static
PyObject *
PerlObj_getattr(PerlObj_object *self,
char
*name) {
PyObject *retval = NULL;
if
(
strcmp
(name,
"__methods__"
) == 0) {
return
get_perl_pkg_subs(self->pkg);
}
else
if
(
strcmp
(name,
"__members__"
) == 0) {
retval = PyList_New(0);
return
retval ? retval : NULL;
}
else
if
(
strcmp
(name,
"__dict__"
) == 0) {
retval = PyDict_New();
return
retval ? retval : NULL;
}
else
{
SV *
const
obj = (SV*)SvRV(self->obj);
HV *
const
pkg = SvSTASH(obj);
GV *
const
gv = Perl_gv_fetchmethod_autoload(aTHX_ pkg, name, TRUE);
if
(gv && isGV(gv)) {
#if PY_MAJOR_VERSION >= 3
PyObject *
const
py_name = PyBytes_FromString(name);
#else
PyObject *
const
py_name = PyString_FromString(name);
#endif
retval = newPerlMethod_object(self->pkg, py_name, self->obj);
Py_DECREF(py_name);
}
else
{
GV*
const
gv = Perl_gv_fetchmethod_autoload(aTHX_ pkg,
"__getattr__"
, FALSE);
if
(gv && isGV(gv)) {
dSP;
ENTER;
SAVETMPS;
SV *
const
rv = sv_2mortal(newRV((SV*)GvCV(gv)));
PUSHMARK(SP);
XPUSHs(self->obj);
XPUSHs(sv_2mortal(newSVpv(name, 0)));
PUTBACK;
int
const
count = call_sv(rv, G_ARRAY);
SPAGAIN;
if
(count > 1)
croak(
"__getattr__ may only return a single scalar or an empty list!\n"
);
if
(count == 1) {
retval = Pl2Py(POPs);
}
PUTBACK;
FREETMPS;
LEAVE;
}
if
(! retval) {
char
attribute_error[
strlen
(name) + 21];
sprintf
(attribute_error,
"attribute %s not found"
, name);
PyErr_SetString(PyExc_AttributeError, attribute_error);
}
}
return
retval;
}
}
static
PyObject*
PerlObj_mp_subscript(PerlObj_object *self, PyObject *key) {
PyObject *item = NULL;
PyObject *key_str = PyObject_Str(key);
#if PY_MAJOR_VERSION >= 3
PyObject* string_as_bytes = PyUnicode_AsUTF8String(key_str);
char
*
const
name = PyBytes_AsString(string_as_bytes);
#else
char
*
const
name = PyString_AsString(key_str);
#endif
SV *
const
obj = (SV*)SvRV(self->obj);
HV *
const
pkg = SvSTASH(obj);
GV*
const
gv = Perl_gv_fetchmethod_autoload(aTHX_ pkg,
"__getitem__"
, FALSE);
if
(gv && isGV(gv)) {
dSP;
ENTER;
SAVETMPS;
SV *
const
rv = sv_2mortal(newRV((SV*)GvCV(gv)));
PUSHMARK(SP);
XPUSHs(self->obj);
XPUSHs(sv_2mortal(newSVpv(name, 0)));
PUTBACK;
int
const
count = call_sv(rv, G_ARRAY);
SPAGAIN;
if
(count > 1)
croak(
"__getitem__ may only return a single scalar or an empty list!\n"
);
if
(count == 1) {
item = Pl2Py(POPs);
}
PUTBACK;
FREETMPS;
LEAVE;
if
(count == 0) {
char
attribute_error[
strlen
(name) + 21];
sprintf
(attribute_error,
"attribute %s not found"
, name);
PyErr_SetString(PyExc_KeyError, attribute_error);
}
}
else
{
PyErr_Format(PyExc_TypeError,
"'%.200s' object is unsubscriptable"
, Py_TYPE(self)->tp_name);
}
#if PY_MAJOR_VERSION >= 3
Py_DECREF(string_as_bytes);
#endif
Py_DECREF(key_str);
return
item;
}
static
PyObject *
PerlObj_call(PerlObj_object *self, PyObject *args, PyObject *kw) {
dSP;
int
i;
int
const
len = PyObject_Length(args);
int
count;
PyObject *retval;
ENTER;
SAVETMPS;
PUSHMARK(SP);
if
(self->obj) XPUSHs(self->obj);
if
(kw) {
AV *
const
positional = newAV();
for
(i=0; i<len; i++) {
SV *
const
arg = Py2Pl(PyTuple_GetItem(args, i));
av_push(positional, sv_isobject(arg) ? SvREFCNT_inc(arg) : arg);
}
XPUSHs((SV *) sv_2mortal((SV *) newRV_inc((SV *) positional)));
SV *
const
kw_hash = Py2Pl(kw);
XPUSHs(kw_hash);
sv_2mortal(kw_hash);
sv_2mortal((SV *)positional);
}
else
{
for
(i=0; i<len; i++) {
SV *
const
arg = Py2Pl(PyTuple_GetItem(args, i));
XPUSHs(arg);
if
(! sv_isobject(arg))
sv_2mortal(arg);
}
}
PUTBACK;
Py_INCREF(self);
count = perl_call_sv(self->obj, G_EVAL);
SPAGAIN;
Py_DECREF(self);
if
(SvTRUE(ERRSV)) {
PyObject *exc = Pl2Py(ERRSV);
PyErr_SetObject(PyExc_Perl, exc);
ERRSV = NULL;
return
NULL;
}
if
(count == 0) {
Py_INCREF(Py_None);
retval = Py_None;
}
else
if
(count == 1) {
retval = Pl2Py(POPs);
}
else
{
AV *
const
lst = newAV();
av_extend(lst, count);
for
(i = count - 1; i >= 0; i--) {
av_store(lst, i, SvREFCNT_inc(POPs));
}
SV *
const
rv_lst = newRV_inc((SV*)lst);
retval = Pl2Py(rv_lst);
SvREFCNT_dec(rv_lst);
sv_2mortal((SV*)lst);
}
PUTBACK;
FREETMPS;
LEAVE;
return
retval;
}
#if PY_MAJOR_VERSION >= 3 // Python 3 rich compare
static
PyObject*
PerlObj_richcompare(PerlObj_object *o1, PerlObj_object *o2,
int
op) {
if
(!PerlObjObject_Check(o1) || !PerlObjObject_Check(o2)) {
Py_RETURN_FALSE;
}
SV *
const
obj = (SV*)SvRV(o1->obj);
HV *
const
pkg = SvSTASH(obj);
const
char
* method_name = NULL;
switch
(op) {
case
Py_LT: method_name =
"__lt__"
;
break
;
case
Py_LE: method_name =
"__le__"
;
break
;
case
Py_EQ: method_name =
"__eq__"
;
break
;
case
Py_NE: method_name =
"__ne__"
;
break
;
case
Py_GT: method_name =
"__gt__"
;
break
;
case
Py_GE: method_name =
"__ge__"
;
break
;
}
GV*
const
gv = Perl_gv_fetchmethod_autoload(aTHX_ pkg, method_name, FALSE);
if
(gv && isGV(gv)) {
int
retval;
dSP;
ENTER;
SAVETMPS;
SV *
const
rv = sv_2mortal(newRV((SV*)GvCV(gv)));
PUSHMARK(SP);
XPUSHs(o1->obj);
XPUSHs(o2->obj);
PUTBACK;
int
const
count = call_sv(rv, G_SCALAR);
SPAGAIN;
if
(count > 1)
croak(
"%s may only return a single scalar!\n"
, method_name);
if
(count == 1) {
SV *
const
result = POPs;
if
(!SvIOK(result))
croak(
"%s must return an integer!\n"
, method_name);
retval = SvIV(result);
}
PUTBACK;
FREETMPS;
LEAVE;
if
(retval == 0) {Py_RETURN_TRUE;}
Py_RETURN_FALSE;
}
if
(SvRV(o1->obj) == SvRV(o2->obj)) {
if
(op == Py_EQ) {Py_RETURN_TRUE;}
Py_RETURN_FALSE;
}
if
(SvRV(o1->obj) != SvRV(o2->obj)) {
if
(op == Py_NE) {Py_RETURN_TRUE;}
Py_RETURN_FALSE;
}
Py_RETURN_NOTIMPLEMENTED;
}
#else // Python 2 __cmp__ method
static
int
PerlObj_compare(PerlObj_object *o1, PerlObj_object *o2) {
SV *
const
obj = (SV*)SvRV(o1->obj);
HV *
const
pkg = SvSTASH(obj);
GV*
const
gv = Perl_gv_fetchmethod_autoload(aTHX_ pkg,
"__cmp__"
, FALSE);
if
(gv && isGV(gv)) {
int
retval;
dSP;
ENTER;
SAVETMPS;
SV *
const
rv = sv_2mortal(newRV((SV*)GvCV(gv)));
PUSHMARK(SP);
XPUSHs(o1->obj);
XPUSHs(o2->obj);
PUTBACK;
int
const
count = call_sv(rv, G_SCALAR);
SPAGAIN;
if
(count > 1)
croak(
"__cmp__ may only return a single scalar!\n"
);
if
(count == 1) {
SV *
const
result = POPs;
if
(!SvIOK(result))
croak(
"__cmp__ must return an integer!\n"
);
retval = SvIV(result);
}
PUTBACK;
FREETMPS;
LEAVE;
return
retval;
}
if
(SvRV(o1->obj) == SvRV(o2->obj))
return
0;
return
1;
}
#endif
static
PyObject * object_dir(PerlObj_object *self, PyObject *args) {
return
get_perl_pkg_subs(self->pkg);
}
static
struct
PyMethodDef PerlObj_methods[] = {
{
"__dir__"
, (PyCFunction)object_dir, METH_NOARGS, NULL},
{NULL}
};
static
char
PerlObj_type__doc__[] =
"_perl_obj -- Wrap a Perl object in a Python class"
;
PyMappingMethods mp_methods = {
(lenfunc) 0,
(binaryfunc) PerlObj_mp_subscript,
(objobjargproc) 0,
};
PyTypeObject PerlObj_type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_perl_obj"
,
sizeof
(PerlObj_object),
0,
(destructor)PerlObj_dealloc,
(printfunc)0,
(getattrfunc)PerlObj_getattr,
(setattrfunc)0,
#if PY_MAJOR_VERSION < 3
(cmpfunc)PerlObj_compare,
#else
0,
#endif
(reprfunc)PerlObj_repr,
0,
0,
&mp_methods,
(hashfunc)0,
(ternaryfunc)PerlObj_call,
(reprfunc)PerlObj_str,
0L,0L,0L,0L,
PerlObj_type__doc__,
(traverseproc)0,
(inquiry)0,
#if PY_MAJOR_VERSION < 3
0,
#else
(richcmpfunc)PerlObj_richcompare,
#endif
0,
0,
0,
PerlObj_methods,
};
PyObject *
newPerlSub_object(PyObject *package, PyObject *sub, SV *cv) {
PerlSub_object *
const
self = PyObject_NEW(PerlSub_object, &PerlSub_type);
char
*str = NULL;
if
(!self) {
PyErr_Format(PyExc_MemoryError,
"Couldn't create Perl Sub object.\n"
);
return
NULL;
}
if
(package && sub) {
str =
malloc
((PyObject_Length(package) + PyObject_Length(sub) + 1)
*
sizeof
(
char
));
#if PY_MAJOR_VERSION >= 3
sprintf
(str,
"%s%s"
, PyBytes_AsString(package),
PyBytes_AsString(sub));
#else
sprintf
(str,
"%s%s"
, PyString_AsString(package),
PyString_AsString(sub));
#endif
Py_INCREF(sub);
Py_INCREF(package);
self->sub = sub;
self->pkg = package;
#if PY_MAJOR_VERSION >= 3
self->full = PyBytes_FromString(str);
#else
self->full = PyString_FromString(str);
#endif
}
else
{
self->sub = NULL;
self->pkg = NULL;
self->full = NULL;
}
if
(cv) {
self->ref = cv;
self->conf = 1;
}
else
if
(str) {
self->ref = (SV*)perl_get_cv(str,0);
self->conf = self->ref ? 1 : 0;
}
else
{
croak(
"Can't call newPerlSub_object() with all NULL arguments!\n"
);
}
SvREFCNT_inc(self->ref);
self->obj = NULL;
self->flgs = G_ARRAY;
self->cfun = 0;
if
(str)
free
(str);
return
(PyObject*)self;
}
PyObject *
newPerlMethod_object(PyObject *package, PyObject *sub, SV *obj) {
PerlSub_object *
const
self = (PerlSub_object*)newPerlSub_object(package,
sub, NULL);
self->obj = obj;
SvREFCNT_inc(obj);
return
(PyObject*)self;
}
PyObject * newPerlCfun_object(PyObject* (*cfun)(PyObject *self,
PyObject *args))
{
PerlSub_object *
const
self = PyObject_NEW(PerlSub_object, &PerlSub_type);
self->pkg = NULL;
self->sub = NULL;
self->full = NULL;
self->ref = NULL;
self->obj = NULL;
self->flgs = 0;
self->cfun = cfun;
return
(PyObject *)self;
}
static
void
PerlSub_dealloc(PerlSub_object *self) {
Py_XDECREF(self->sub);
Py_XDECREF(self->pkg);
Py_XDECREF(self->full);
if
(self->obj) SvREFCNT_dec(self->obj);
if
(self->ref) SvREFCNT_dec(self->ref);
PyObject_Del(self);
}
static
PyObject *
PerlSub_call(PerlSub_object *self, PyObject *args, PyObject *kw) {
dSP;
int
i;
int
const
len = PyObject_Length(args);
int
count;
PyObject *retval;
if
(self->cfun)
return
self->cfun((PyObject*)self, args);
ENTER;
SAVETMPS;
PUSHMARK(SP);
if
(self->obj) XPUSHs(self->obj);
if
(kw) {
AV *
const
positional = newAV();
for
(i=0; i<len; i++) {
SV *
const
arg = Py2Pl(PyTuple_GetItem(args, i));
av_push(positional, sv_isobject(arg) ? SvREFCNT_inc(arg) : arg);
}
XPUSHs((SV *) sv_2mortal((SV *) newRV_inc((SV *) positional)));
SV *
const
kw_hash = Py2Pl(kw);
XPUSHs(kw_hash);
sv_2mortal(kw_hash);
sv_2mortal((SV *)positional);
}
else
{
for
(i=0; i<len; i++) {
SV *
const
arg = Py2Pl(PyTuple_GetItem(args, i));
XPUSHs(arg);
if
(! sv_isobject(arg))
sv_2mortal(arg);
}
}
PUTBACK;
Py_INCREF(self);
if
(self->ref)
count = perl_call_sv(self->ref, self->flgs | G_EVAL);
else
if
(self->sub && self->obj)
#if PY_MAJOR_VERSION >= 3
count = perl_call_method(PyBytes_AsString(self->sub), self->flgs | G_EVAL);
#else
count = perl_call_method(PyString_AsString(self->sub), self->flgs | G_EVAL);
#endif
else
{
croak(
"Error: PerlSub called, but no C function, sub, or name found!\n"
);
}
SPAGAIN;
Py_DECREF(self);
if
(SvTRUE(ERRSV)) {
PyObject *exc = Pl2Py(ERRSV);
PyErr_SetObject(PyExc_Perl, exc);
ERRSV = NULL;
return
NULL;
}
if
(count == 0) {
Py_INCREF(Py_None);
retval = Py_None;
}
else
if
(count == 1) {
retval = Pl2Py(POPs);
}
else
{
AV *
const
lst = newAV();
av_extend(lst, count);
for
(i = count - 1; i >= 0; i--) {
av_store(lst, i, SvREFCNT_inc(POPs));
}
SV *
const
rv_lst = newRV_inc((SV*)lst);
retval = Pl2Py(rv_lst);
SvREFCNT_dec(rv_lst);
sv_2mortal((SV*)lst);
}
PUTBACK;
FREETMPS;
LEAVE;
return
retval;
}
static
PyObject *
PerlSub_repr(PerlSub_object *self, PyObject *args) {
PyObject *s;
char
*
const
str = (
char
*)
malloc
((
strlen
(
"<perl sub: ''>"
)
+ (self->full
? PyObject_Length(self->full)
:
strlen
(
"anonymous"
))
+ 1) *
sizeof
(
char
));
#if PY_MAJOR_VERSION >= 3
sprintf
(str,
"<perl sub: '%s'>"
, (self->full
? PyBytes_AsString(self->full)
:
"anonymous"
));
s = PyUnicode_FromString(str);
#else
sprintf
(str,
"<perl sub: '%s'>"
, (self->full
? PyString_AsString(self->full)
:
"anonymous"
));
s = PyString_FromString(str);
#endif
free
(str);
return
s;
}
static
PyObject *
PerlSub_getattr(PerlSub_object *self,
char
*name) {
PyObject *retval = NULL;
if
(
strcmp
(name,
"flags"
)==0) {
retval = PyInt_FromLong((
long
)self->flgs);
}
else
if
(
strcmp
(name,
"G_VOID"
)==0) {
retval = PyInt_FromLong((
long
)G_VOID);
}
else
if
(
strcmp
(name,
"G_SCALAR"
)==0) {
retval = PyInt_FromLong((
long
)G_SCALAR);
}
else
if
(
strcmp
(name,
"G_ARRAY"
)==0) {
retval = PyInt_FromLong((
long
)G_ARRAY);
}
else
if
(
strcmp
(name,
"G_DISCARD"
)==0) {
retval = PyInt_FromLong((
long
)G_DISCARD);
}
else
if
(
strcmp
(name,
"G_NOARGS"
)==0) {
retval = PyInt_FromLong((
long
)G_NOARGS);
}
else
if
(
strcmp
(name,
"G_EVAL"
)==0) {
retval = PyInt_FromLong((
long
)G_EVAL);
}
else
if
(
strcmp
(name,
"G_KEEPERR"
)==0) {
retval = PyInt_FromLong((
long
)G_KEEPERR);
}
else
{
PyErr_Format(PyExc_AttributeError,
"Attribute '%s' not found for Perl sub '%s'"
, name,
#if PY_MAJOR_VERSION < 3
(self->full
? PyString_AsString(self->full)
: (self->pkg ? PyString_AsString(self->pkg) :
""
))
#else
(self->full
? PyBytes_AsString(self->full)
: (self->pkg ? PyBytes_AsString(self->pkg) :
""
))
#endif
);
retval = NULL;
}
return
retval;
}
static
int
PerlSub_setattr(PerlSub_object *self,
char
*name, PyObject *v) {
if
(
strcmp
(name,
"flags"
)==0 && PyInt_Check(v)) {
self->flgs = (
int
)PyInt_AsLong(v);
return
0;
}
else
if
(
strcmp
(name,
"flags"
)==0) {
PyErr_Format(PyExc_TypeError,
"'flags' can only be set from an integer. '%s'"
,
#if PY_MAJOR_VERSION < 3
(self->pkg ? PyString_AsString(self->pkg) :
""
));
#else
(self->pkg ? PyBytes_AsString(self->pkg) :
""
));
#endif
return
-1;
}
else
{
PyErr_Format(PyExc_AttributeError,
"Attribute '%s' not found for Perl sub '%s'"
, name,
#if PY_MAJOR_VERSION < 3
(self->full
? PyString_AsString(self->full)
: (self->pkg ? PyString_AsString(self->pkg) :
""
))
#else
(self->full
? PyBytes_AsString(self->full)
: (self->pkg ? PyBytes_AsString(self->pkg) :
""
))
#endif
);
return
-1;
}
}
static
struct
PyMethodDef PerlSub_methods[] = {
{NULL, NULL}
};
static
char
PerlSub_type__doc__[] =
"_perl_sub -- Wrap a Perl sub in a Python class"
;
PyTypeObject PerlSub_type = {
PyVarObject_HEAD_INIT(NULL, 0)
"_perl_sub"
,
sizeof
(PerlSub_object),
0,
(destructor)PerlSub_dealloc,
(printfunc)0,
(getattrfunc)PerlSub_getattr,
(setattrfunc)PerlSub_setattr,
#if PY_MAJOR_VERSION < 3
(cmpfunc)0,
#else
0,
#endif
(reprfunc)PerlSub_repr,
0,
0,
0,
(hashfunc)0,
(ternaryfunc)PerlSub_call,
(reprfunc)PerlSub_repr,
0L,0L,0L,0L,
PerlSub_type__doc__,
};
static
PyMethodDef perl_functions[] = {
{NULL, NULL}
};
static
PyObject * special_perl_eval(PyObject *ignored, PyObject *args) {
dSP;
SV *code;
int
i;
int
count;
PyObject *retval;
PyObject *
const
s = PyTuple_GetItem(args, 0);
#if PY_MAJOR_VERSION >= 3
int
is_string = PyBytes_Check(s) || PyUnicode_Check(s);
#else
int
is_string = PyString_Check(s);
#endif
if
(!is_string) {
return
NULL;
}
ENTER;
SAVETMPS;
PUSHMARK(SP);
PUTBACK;
#if PY_MAJOR_VERSION >= 3
PyObject* s_bytes = 0;
char
* s_c_bytes = 0;
if
(PyUnicode_Check(s)) {
s_bytes = PyUnicode_AsUTF8String(s);
s_c_bytes = PyBytes_AsString(s_bytes);
}
else
s_c_bytes = PyBytes_AsString(s);
#else
char
* s_c_bytes = PyString_AsString(s);
#endif
code = newSVpv(s_c_bytes,0);
count = perl_eval_sv(code, G_EVAL);
#if PY_MAJOR_VERSION >= 3
Py_XDECREF(s_bytes);
#endif
SPAGAIN;
if
(SvTRUE(ERRSV)) {
warn(
"%s\n"
, SvPV_nolen(ERRSV));
}
if
(count == 0) {
retval = Py_None;
Py_INCREF(retval);
}
else
if
(count == 1) {
SV *
const
s = POPs;
retval = Pl2Py(s);
}
else
{
AV *
const
lst = newAV();
for
(i=0; i<count; i++) {
av_push(lst, POPs);
}
retval = Pl2Py((SV*)lst);
sv_2mortal((SV*)lst);
}
PUTBACK;
FREETMPS;
LEAVE;
return
retval;
}
static
PyObject * special_perl_use(PyObject *ignored, PyObject *args) {
PyObject * s = PyTuple_GetItem(args, 0);
char
*str;
#if PY_MAJOR_VERSION >= 3
int
is_string = PyBytes_Check(s) || PyUnicode_Check(s);
#else
int
is_string = PyString_Check(s);
#endif
if
(!is_string) {
return
NULL;
}
#if PY_MAJOR_VERSION >= 3
PyObject* s_bytes = 0;
char
* s_c_bytes = 0;
if
(PyUnicode_Check(s)) {
s_bytes = PyUnicode_AsUTF8String(s);
s_c_bytes = PyBytes_AsString(s_bytes);
}
else
s_c_bytes = PyBytes_AsString(s);
#else
char
* s_c_bytes = PyString_AsString(s);
#endif
Printf((
"calling use...'%s'\n"
, s_c_bytes));
str =
malloc
((
strlen
(
"use "
)
+ PyObject_Length(s) + 1) *
sizeof
(
char
));
sprintf
(str,
"use %s"
, s_c_bytes);
Printf((
"eval-ing now!\n"
));
perl_eval_pv(str, TRUE);
Printf((
"'twas called!\n"
));
free
(str);
#if PY_MAJOR_VERSION >= 3
Py_XDECREF(s_bytes);
#endif
Py_INCREF(Py_None);
return
Py_None;
}
static
PyObject * special_perl_require(PyObject *ignored, PyObject *args) {
PyObject *
const
s = PyTuple_GetItem(args, 0);
#if PY_MAJOR_VERSION >= 3
int
is_string = PyBytes_Check(s) || PyUnicode_Check(s);
#else
int
is_string = PyString_Check(s);
#endif
if
(!is_string) {
return
NULL;
}
#if PY_MAJOR_VERSION >= 3
PyObject* s_bytes = 0;
char
* s_c_bytes = 0;
if
(PyUnicode_Check(s)) {
s_bytes = PyUnicode_AsUTF8String(s);
s_c_bytes = PyBytes_AsString(s_bytes);
}
else
s_c_bytes = PyBytes_AsString(s);
#else
char
* s_c_bytes = PyString_AsString(s);
#endif
perl_require_pv(s_c_bytes);
#if PY_MAJOR_VERSION >= 3
Py_XDECREF(s_bytes);
#endif
Py_INCREF(Py_None);
return
Py_None;
}
#ifdef CREATE_PERL
static
void
create_perl()
{
int
argc = 1;
char
*
const
argv[] = {
"perl"
};
my_perl = perl_alloc();
perl_construct(my_perl);
perl_parse(my_perl, NULL, argc, argv, NULL);
perl_run(my_perl);
}
#endif
PyObject *PyExc_Perl;
void
initperl(
void
){
PyObject *m, *d, *p;
#if PY_MAJOR_VERSION >= 3
PyObject *dummy1 = PyBytes_FromString(
""
),
*dummy2 = PyBytes_FromString(
"main"
);
#else
PyObject *dummy1 = PyString_FromString(
""
),
*dummy2 = PyString_FromString(
"main"
);
#endif
#if PY_MAJOR_VERSION >= 3
PerlPkg_type.ob_base.ob_base.ob_type = &PyType_Type;
PyType_Ready(&PerlPkg_type);
PerlObj_type.ob_base.ob_base.ob_type = &PyType_Type;
PyType_Ready(&PerlObj_type);
PerlSub_type.ob_base.ob_base.ob_type = &PyType_Type;
PyType_Ready(&PerlSub_type);
#else
PerlPkg_type.ob_type = &PyType_Type;
PerlObj_type.ob_type = &PyType_Type;
PerlSub_type.ob_type = &PyType_Type;
#endif
#if PY_MAJOR_VERSION >= 3
static
struct
PyModuleDef perl_module = {
PyModuleDef_HEAD_INIT,
"perl"
,
"perl -- Access a Perl interpreter transparently"
,
-1,
perl_functions,
0,
0,
0,
0
};
m = PyModule_Create(&perl_module);
#else
m = Py_InitModule4(
"perl"
,
perl_functions,
"perl -- Access a Perl interpreter transparently"
,
(PyObject*)NULL,
PYTHON_API_VERSION);
#endif
m = PyImport_AddModule(
"sys"
);
d = PyModule_GetDict(m);
d = PyDict_GetItemString(d,
"modules"
);
p = newPerlPkg_object(dummy1, dummy2);
PyDict_SetItemString(d,
"perl"
, p);
Py_DECREF(p);
#ifdef CREATE_PERL
create_perl();
#endif
PyExc_Perl = PyErr_NewException(
"perl.Exception"
, NULL, NULL);
Py_DECREF(dummy1);
Py_DECREF(dummy2);
}