From b6a86d2eeff0cc45053e38970493bf6108f53a4f Mon Sep 17 00:00:00 2001 From: mdw Date: Sun, 10 Apr 2005 18:03:11 +0000 Subject: [PATCH 1/1] Initial check-in of catacomb-python. --- catacomb-python.h | 520 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ catacomb.c | 279 +++++++++++++++++++++++++++++ 2 files changed, 799 insertions(+) create mode 100644 catacomb-python.h create mode 100644 catacomb.c diff --git a/catacomb-python.h b/catacomb-python.h new file mode 100644 index 0000000..c93ef07 --- /dev/null +++ b/catacomb-python.h @@ -0,0 +1,520 @@ +/* -*-c-*- + * + * $Id$ + * + * Definitions for Catacomb bindings + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the Python interface to Catacomb. + * + * Catacomb/Python is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Catacomb/Python is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Catacomb/Python; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef CATACOMB_PYTHON_H +#define CATACOMB_PYTHON_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +/*----- Utility macros ----------------------------------------------------*/ + +#define RETURN_OBJ(obj) do { Py_INCREF(obj); return (obj); } while (0) +#define RETURN_NONE RETURN_OBJ(Py_None) +#define RETURN_NOTIMPL RETURN_OBJ(Py_NotImplemented) +#define RETURN_TRUE RETURN_OBJ(Py_True) +#define RETURN_FALSE RETURN_OBJ(Py_False) +#define RETURN_ME RETURN_OBJ(me) + +#define EXCERR(exc, str) do { \ + PyErr_SetString(exc, str); \ + goto end; \ +} while (0) +#define VALERR(str) EXCERR(PyExc_ValueError, str) +#define TYERR(str) EXCERR(PyExc_TypeError, str) +#define ZDIVERR(str) EXCERR(PyExc_ZeroDivisionError, str) +#define SYNERR(str) EXCERR(PyExc_SyntaxError, str) +#define SYSERR(str) EXCERR(PyExc_SystemError, str) +#define OSERR(name) do { \ + PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); \ + goto end; \ +} while (0) +#define PGENERR do { pgenerr(); goto end; } while (0) + +#define CONVFUNC(ty, cty, ext) \ + int conv##ty(PyObject *o, void *p) \ + { \ + if (!PyObject_TypeCheck(o, ty##_pytype)) \ + TYERR("wanted a " #ty); \ + *(cty *)p = ext(o); \ + return (1); \ + end: \ + return (0); \ + } + +#define root_pytype 0 +#define type_pytype &PyType_Type +#define INITTYPE(ty, base) do { \ + ty##_pytype_skel.tp_base = base##_pytype; \ + ty##_pytype = inittype(&ty##_pytype_skel); \ +} while (0) + +#define INSERT(name, ob) do { \ + PyObject *_o = (PyObject *)(ob); \ + Py_INCREF(_o); \ + PyModule_AddObject(mod, name, _o); \ +} while (0) + +#define METH(func, doc) \ + { #func, METHNAME(func), METH_VARARGS, doc }, +#define KWMETH(func, doc) \ + { #func, (PyCFunction)METHNAME(func), \ + METH_VARARGS | METH_KEYWORDS, doc }, + +#define GET(func, doc) \ + { #func, GETSETNAME(get, func), 0, doc }, +#define GETSET(func, doc) \ + { #func, GETSETNAME(get, func), GETSETNAME(set, func), doc }, + +#define MEMBER(name, ty, f, doc) \ + { #name, ty, offsetof(MEMBERSTRUCT, name), f, doc }, + +#define MODULES(DO) \ + DO(bytestring) \ + DO(rand) DO(algorithms) DO(pubkey) DO(pgen) \ + DO(mp) DO(field) DO(ec) DO(group) \ + DO(passphrase) +#define DOMODINIT(m) m##_pyinit(); +#define DOMODINSERT(m) m##_pyinsert(mod); +#define INIT_MODULES do { MODULES(DOMODINIT) } while (0) +#define INSERT_MODULES do { MODULES(DOMODINSERT) } while (0) + +#define DO(m) \ + extern void m##_pyinit(void); \ + extern void m##_pyinsert(PyObject *); +MODULES(DO) +#undef DO + +/*----- Bytestrings -------------------------------------------------------*/ + +PyTypeObject *bytestring_pyobj; +PyObject *bytestring_pywrap(const void *, size_t); +PyObject *bytestring_pywrapbuf(buf *); + +/*----- Multiprecision arithmetic -----------------------------------------*/ + +typedef struct mp_pyobj { + PyObject_HEAD + mp *x; +} mp_pyobj; + +extern PyTypeObject *mp_pytype; +extern PyTypeObject *gf_pytype; +#define MP_X(o) (((mp_pyobj *)(o))->x) +#define MP_PYCHECK(o) PyObject_TypeCheck((o), mp_pytype) +#define GF_PYCHECK(o) PyObject_TypeCheck((o), gf_pytype) + +extern mp *mp_frompylong(PyLongObject *); +extern PyLongObject *mp_topylong(mp *); +extern mp *tomp(PyObject *); +extern mp *getmp(PyObject *); +extern int convmp(PyObject *, void *); +extern mp *getgf(PyObject *); +extern int convgf(PyObject *, void *); +extern PyObject *mp_pywrap(mp *); +extern PyObject *gf_pywrap(mp *); +extern mp *mp_frompyobject(PyObject *, int); +extern PyObject *mp_topystring(mp *, int, + const char *, const char *, const char *); +extern int mp_tolong_checked(mp *, long *); + +/*----- Abstract fields ---------------------------------------------------*/ + +typedef struct field_pyobj { + PyTypeObject ty; + field *f; +} field_pyobj; + +extern PyTypeObject *fe_pytype; +#define FE_PYCHECK(o) PyObject_TypeCheck((o), fe_pytype) +#define FE_F(o) (((fe_pyobj *)(o))->f) +#define FE_FOBJ(o) ((PyObject *)(o)->ob_type) +#define FE_X(o) (((fe_pyobj *)(o))->x) +extern PyObject *fe_pywrap(PyObject *, mp *); +extern mp *getfe(field *, PyObject *); + +typedef struct fe_pyobj { + PyObject_HEAD + field *f; + PyObject *fobj; /* to keep it alive */ + mp *x; +} fe_pyobj; + +extern PyTypeObject *field_pytype; +extern PyTypeObject *primefield_pytype; +extern PyTypeObject *niceprimefield_pytype; +extern PyTypeObject *binfield_pytype; +extern PyTypeObject *binpolyfield_pytype; +extern PyTypeObject *binnormfield_pytype; +#define FIELD_PYCHECK(o) PyObject_TypeCheck((o), field_pytype) +#define FIELD_F(o) (((field_pyobj *)(o))->f) +extern PyObject *field_pywrap(field *); +extern field *field_copy(field *); + +/*----- Elliptic curves ---------------------------------------------------*/ + +typedef struct ecpt_pyobj { + PyObject_HEAD + ec_curve *c; + ec p; +} ecpt_pyobj; + +extern PyTypeObject *ecpt_pytype, *ecptcurve_pytype; +#define ECPT_PYCHECK(o) PyObject_TypeCheck((o), ecpt_pytype) +#define ECPTCURVE_PYCHECK(o) PyObject_TypeCheck((o), ecptcurve_pytype) +#define ECPT_C(o) (((ecpt_pyobj *)(o))->c) +#define ECPT_COBJ(o) ((PyObject *)(o)->ob_type) +#define ECPT_FOBJ(o) ECCURVE_FOBJ(ECPT_COBJ((o))) +#define ECPT_P(o) (&((ecpt_pyobj *)(o))->p) +extern PyObject *ecpt_pywrap(PyObject *, ec *); +extern PyObject *ecpt_pywrapout(void *, ec *); +extern int toecpt(ec_curve *, ec *, PyObject *); +extern int getecpt(ec_curve *, ec *, PyObject *); +extern void getecptout(ec *, PyObject *); +extern int convec(PyObject *, void *); + +typedef struct eccurve_pyobj { + PyTypeObject ty; + ec_curve *c; + PyObject *fobj; +} eccurve_pyobj; + +extern PyTypeObject *eccurve_pytype; +extern PyTypeObject *ecprimecurve_pytype; +extern PyTypeObject *ecprimeprojcurve_pytype; +extern PyTypeObject *ecbincurve_pytype; +extern PyTypeObject *ecbinprojcurve_pytype; +#define ECCURVE_PYCHECK(o) PyObject_TypeCheck((o), eccurve_pytype) +#define ECCURVE_C(o) (((eccurve_pyobj *)(o))->c) +#define ECCURVE_FOBJ(o) (((eccurve_pyobj *)(o))->fobj) +extern PyObject *eccurve_pywrap(PyObject *, ec_curve *); +extern ec_curve *eccurve_copy(ec_curve *); + +typedef struct ecinfo_pyobj { + PyObject_HEAD + ec_info ei; + PyObject *cobj; +} ecinfo_pyobj; + +extern PyTypeObject *ecinfo_pytype; +#define ECINFO_PYCHECK(o) PyObject_TypeCheck((o), ecinfo_pytype) +#define ECINFO_EI(o) (&((ecinfo_pyobj *)(o))->ei) +#define ECINFO_COBJ(o) (((ecinfo_pyobj *)(o))->cobj) +extern void ecinfo_copy(ec_info *, const ec_info *); +extern PyObject *ecinfo_pywrap(ec_info *); + +/*----- Cyclic groups -----------------------------------------------------*/ + +typedef struct fginfo_pyobj { + PyObject_HEAD + gprime_param dp; +} fginfo_pyobj; + +PyTypeObject *fginfo_pytype, *dhinfo_pytype, *bindhinfo_pytype; +#define FGINFO_DP(fg) (&((fginfo_pyobj *)(fg))->dp) +PyObject *fginfo_pywrap(gprime_param *, PyTypeObject *); + +typedef struct ge_pyobj { + PyObject_HEAD + ge *x; + group *g; +} ge_pyobj; + +extern PyTypeObject *ge_pytype; +#define GE_PYCHECK(o) PyObject_TypeCheck((o), ge_pytype) +#define GE_X(o) (((ge_pyobj *)(o))->x) +#define GE_G(o) (((ge_pyobj *)(o))->g) +#define GE_GOBJ(o) ((PyObject *)(group_pyobj *)(o)->ob_type) +extern PyObject *ge_pywrap(PyObject *, ge *); + +typedef struct group_pyobj { + PyTypeObject ty; + group *g; +} group_pyobj; + +extern PyTypeObject *group_pytype; +extern PyTypeObject *primegroup_pytype, *bingroup_pytype, *ecgroup_pytype; +#define GROUP_G(o) (((group_pyobj *)(o))->g) +extern PyObject *group_pywrap(group *); +extern group *group_copy(group *); + +/*----- Random number generators ------------------------------------------*/ + +#define f_freeme 1u + +typedef struct grand_pyobj { + PyObject_HEAD + unsigned f; + grand *r; +} grand_pyobj; + +extern PyTypeObject *grand_pytype, *truerand_pytype; +extern PyTypeObject *lcrand_pytype,* fibrand_pytype; +extern PyTypeObject *dsarand_pytype, *bbs_pytype; +extern PyObject *rand_pyobj; +#define GRAND_PYCHECK(o) PyObject_TypeCheck((o), grand_pytype) +#define GRAND_F(o) (((grand_pyobj *)(o))->f) +#define GRAND_R(o) (((grand_pyobj *)(o))->r) +extern PyObject *grand_pywrap(grand *, unsigned); +extern int convgrand(PyObject *, void *); + +/*----- Key sizes ---------------------------------------------------------*/ + +typedef struct keysz_pyobj { + PyObject_HEAD + int dfl; +} keysz_pyobj; + +typedef struct keyszrange_pyobj { + PyObject_HEAD + int dfl; + int min, max, mod; +} keyszrange_pyobj; + +typedef struct keyszset_pyobj { + PyObject_HEAD + int dfl; + PyObject *set; +} keyszset_pyobj; + +#define KEYSZ_PYCHECK(o) PyObject_TypeCheck((o), keysz_pytype) +extern PyObject *keysz_pywrap(const octet *); + +/*----- Symmetric cryptography --------------------------------------------*/ + +typedef struct gccipher_pyobj { + PyTypeObject ty; + gccipher *cc; +} gccipher_pyobj; + +extern PyTypeObject *gccipher_pytype; +#define GCCIPHER_PYCHECK(o) PyObject_TypeCheck((o), gccipher_pytype) +#define GCCIPHER_CC(o) (((gccipher_pyobj *)(o))->cc) +#define GCCIPHER_F(o) (((gccipher_pyobj *)(o))->f) +extern PyObject *gccipher_pywrap(gccipher *); +extern int convgccipher(PyObject *, void *); +extern int convgcipher(PyObject *, void *); + +typedef struct gcipher_pyobj { + PyObject_HEAD + unsigned f; + gcipher *c; +} gcipher_pyobj; + +extern PyTypeObject *gcipher_pytype; +#define GCIPHER_PYCHECK(o) PyObject_TypeCheck((o), gcipher_pytype) +#define GCIPHER_C(o) (((gcipher_pyobj *)(o))->c) +#define GCIPHER_F(o) (((gcipher_pyobj *)(o))->f) +extern PyObject *gcipher_pywrap(PyObject *, gcipher *, unsigned); +extern int convgcipher(PyObject *, void *); + +typedef struct gchash_pyobj { + PyTypeObject ty; + gchash *ch; +} gchash_pyobj; + +extern PyTypeObject *gchash_pytype; +#define GCHASH_PYCHECK(o) PyObject_TypeCheck((o), gchash_pytype) +#define GCHASH_CH(o) (((gchash_pyobj *)(o))->ch) +#define GCHASH_F(o) (((gchash_pyobj *)(o))->f) +extern PyObject *gchash_pywrap(gchash *); +extern int convgchash(PyObject *, void *); + +typedef struct ghash_pyobj { + PyObject_HEAD + unsigned f; + ghash *h; +} ghash_pyobj; + +extern PyTypeObject *ghash_pytype, *gmhash_pytype; +extern PyObject *sha_pyobj, *has160_pyobj; +#define GHASH_PYCHECK(o) PyObject_TypeCheck((o), ghash_pytype) +#define GHASH_H(o) (((ghash_pyobj *)(o))->h) +#define GHASH_F(o) (((ghash_pyobj *)(o))->f) +extern PyObject *ghash_pywrap(PyObject *, ghash *, unsigned); +extern int convghash(PyObject *, void *); +extern int convgmhash(PyObject *, void *); + +typedef struct gcmac_pyobj { + PyTypeObject ty; + gcmac *cm; +} gcmac_pyobj; + +extern PyTypeObject *gcmac_pytype; +#define GCMAC_PYCHECK(o) PyObject_TypeCheck((o), gcmac_pytype) +#define GCMAC_CM(o) (((gcmac_pyobj *)(o))->cm) +#define GCMAC_F(o) (((gcmac_pyobj *)(o))->f) +extern PyObject *gcmac_pywrap(gcmac *); +extern int convgcmac(PyObject *, void *); + +typedef struct gmac_pyobj { + PyTypeObject ty; + unsigned f; + gmac *m; + PyObject *nameobj; +} gmac_pyobj; + +extern PyTypeObject *gmac_pytype; +#define GMAC_PYCHECK(o) PyObject_TypeCheck((o), gmac_pytype) +#define GMAC_M(o) (((gmac_pyobj *)(o))->m) +#define GMAC_NAMEOBJ(o) (((gmac_pyobj *)(o))->nameobj) +#define GMAC_F(o) (((gmac_pyobj *)(o))->f) +extern PyObject *gmac_pywrap(PyObject *, gmac *, unsigned); +extern int convgmac(PyObject *, void *); + +/*----- Public key crypto -------------------------------------------------*/ + +/*----- Key generation ----------------------------------------------------*/ + +typedef struct pfilt_pyobj { + PyObject_HEAD + pfilt f; + int st; +} pfilt_pyobj; + +extern PyTypeObject *pfilt_pytype; +#define PFILT_PYCHECK(o) PyObject_TypeCheck(o, pfilt_pytype) +#define PFILT_F(o) (&((pfilt_pyobj *)(o))->f) +#define PFILT_ST(o) (((pfilt_pyobj *)(o))->st) + +typedef struct { pgen_proc *proc; void *ctx; } pgev; +#define PGEV_HEAD PyObject_HEAD pgev pg; + +typedef struct pgev_pyobj { + PGEV_HEAD +} pgev_pyobj; + +extern PyTypeObject *pgev_pytype; +#define PGEV_PYCHECK(o) PyObject_TypeCheck(o, pgev_pytype) +#define PGEV_PG(o) (&((pgev_pyobj *)(o))->pg) + +extern int convpgev(PyObject *, void *); +extern void droppgev(pgev *); +extern void pgenerr(void); + +/*----- Core utility functions --------------------------------------------*/ + +extern PyObject *mexp_common(PyObject *, PyObject *, size_t, + PyObject *(*id)(PyObject *), + int (*fill)(void *, PyObject *, + PyObject *, PyObject *), + PyObject *(*exp)(PyObject *, void *, int), + void (*drop)(void *)); + +extern int convulong(PyObject *, void *); +extern int convu32(PyObject *, void *); +extern int convmpw(PyObject *, void *); +extern int convuint(PyObject *, void *); +extern int convszt(PyObject *, void *); +extern int convbool(PyObject *, void *); +extern PyObject *abstract_pynew(PyTypeObject *, PyObject *, PyObject *); +extern PyObject *getbool(int); +extern PyObject *getu32(uint32); +extern void *newtype(PyTypeObject *, const PyTypeObject *); +extern PyTypeObject *inittype(PyTypeObject *); +extern void addmethods(const PyMethodDef *); + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/catacomb.c b/catacomb.c new file mode 100644 index 0000000..742ce5f --- /dev/null +++ b/catacomb.c @@ -0,0 +1,279 @@ +/* -*-c-*- + * + * $Id$ + * + * Where the fun begins + * + * (c) 2004 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the Python interface to Catacomb. + * + * Catacomb/Python is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Catacomb/Python is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Catacomb/Python; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "catacomb-python.h" + +/*----- Main code ---------------------------------------------------------*/ + +static void setconstants(PyObject *mod) +{ + static const struct { const char *name; unsigned long value; } consts[] = { +#define C(x) { #x, x } + C(FTY_PRIME), C(FTY_BINARY), + C(PGEN_PASS), C(PGEN_FAIL), C(PGEN_BEGIN), C(PGEN_TRY), C(PGEN_DONE), + C(PGEN_ABORT), + C(MPW_MAX), + C(PMODE_READ), C(PMODE_VERIFY), +#undef C + { 0 } + }; + int i; + PyObject *x; + + for (i = 0; consts[i].name; i++) { + if (consts[i].value > LONG_MAX) + x = PyLong_FromUnsignedLong(consts[i].value); + else + x = PyInt_FromLong(consts[i].value); + PyModule_AddObject(mod, (/*unconst*/ char *)consts[i].name, x); + } +} + +PyObject *getu32(uint32 w) +{ + if (w <= 0x7fffffff) + return (PyInt_FromLong(w)); + else + return (PyLong_FromUnsignedLong(w)); +} + +PyObject *getbool(int b) +{ + if (b) RETURN_TRUE; + else RETURN_FALSE; +} + +PyObject *abstract_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw) +{ + PyErr_SetString(PyExc_TypeError, "can't instantiate this class"); + return (0); +} + +int convulong(PyObject *o, void *pp) +{ + long i; + unsigned long *p = pp; + PyObject *t; + + if (PyInt_Check(o)) { + i = PyInt_AS_LONG(o); + if (i < 0) TYERR("must be nonnegative"); + *p = i; + } else { + if ((t = PyNumber_Long(o)) == 0) goto end; + *p = PyLong_AsUnsignedLong(t); + Py_DECREF(t); + if (PyErr_Occurred()) goto end; + } + return (1); +end: + return (0); +} + +int convu32(PyObject *o, void *pp) +{ + unsigned long u; + uint32 *p = pp; + + if (!convulong(o, &u)) goto end; + if (u > 0xffffffff) TYERR("out of range"); + *p = u; + return (1); +end: + return (0); +} + +int convuint(PyObject *o, void *pp) +{ + unsigned long u; + unsigned *p = pp; + + if (!convulong(o, &u)) goto end; + if (u > UINT_MAX) TYERR("out of range"); + *p = u; + return (1); +end: + return (0); +} + +int convmpw(PyObject *o, void *pp) +{ + unsigned long u; + unsigned *p = pp; + + if (!convulong(o, &u)) goto end; + if (u > MPW_MAX) TYERR("out of range"); + *p = u; + return (1); +end: + return (0); +} + +int convszt(PyObject *o, void *pp) +{ + unsigned long u; + size_t *p = pp; + + if (!convulong(o, &u)) goto end; + if (u > ~(size_t)0) TYERR("out of range"); + *p = u; + return (1); +end: + return (0); +} + +int convbool(PyObject *o, void *pp) +{ + *(int *)pp = PyObject_IsTrue(o); + return (1); +} + +PyObject *mexp_common(PyObject *me, PyObject *arg, + size_t efsz, + PyObject *(*id)(PyObject *), + int (*fill)(void *, PyObject *, + PyObject *, PyObject *), + PyObject *(*exp)(PyObject *, void *, int), + void (*drop)(void *)) +{ + int i = 0, j, n, flat; + PyObject *qq, *x, *y, *z = 0; + char *v = 0, *vv; + + if (PyTuple_Size(arg) == 1) + arg = PyTuple_GetItem(arg, 0); + Py_INCREF(arg); + if (!PySequence_Check(arg)) TYERR("not a sequence"); + n = PySequence_Size(arg); if (!n) { z = id(me); goto end; } + x = PySequence_GetItem(arg, 0); + if (PySequence_Check(x)) + flat = 0; + else { + if (n % 2) VALERR("must have even number of arguments"); + n /= 2; + flat = 1; + } + Py_DECREF(x); + + v = xmalloc(n * efsz); + for (i = j = 0, vv = v; i < n; i++, vv += efsz) { + if (flat) { + x = PySequence_GetItem(arg, j++); + y = PySequence_GetItem(arg, j++); + } else { + qq = PySequence_GetItem(arg, j++); + if (!qq) goto end; + if (!PySequence_Check(qq) || PySequence_Size(qq) != 2) { + Py_DECREF(qq); + TYERR("want a sequence of pairs"); + } + x = PySequence_GetItem(qq, 0); + y = PySequence_GetItem(qq, 1); + Py_DECREF(qq); + } + if (!x || !y) goto end; + if (fill(vv, me, x, y)) { + Py_DECREF(x); + Py_DECREF(y); + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_TypeError, "type mismatch"); + goto end; + } + Py_DECREF(x); + Py_DECREF(y); + } + z = exp(me, v, n); + +end: + if (v) { + for (j = 0, vv = v; j < i; j++, vv += efsz) + drop(vv); + xfree(v); + } + Py_DECREF(arg); + return (z); +} + +DA_DECL(method_v, PyMethodDef); +static method_v global_pymethods = DA_INIT; +void addmethods(const PyMethodDef *m) +{ + size_t n; + + for (n = 0; m[n].ml_name; n++); + DA_ENSURE(&global_pymethods, n); + memcpy(DA(&global_pymethods) + DA_LEN(&global_pymethods), + m, n * sizeof(*m)); + DA_EXTEND(&global_pymethods, n); +} + +static const PyTypeObject emptytype = { 0 }; + +void *newtype(PyTypeObject *metaty, const PyTypeObject *skel) +{ + PyTypeObject *ty = (PyTypeObject *)_PyObject_GC_Malloc(metaty, 0); + if (!skel) skel = &emptytype; + memcpy(ty, skel, sizeof(*skel)); + if (ty->tp_base) Py_INCREF(ty->tp_base); + PyObject_INIT(ty, metaty); + Py_INCREF(metaty); + return (ty); +} + +static PyObject *smallprimes(void) +{ + PyObject *v = PyList_New(NPRIME); + int i; + + for (i = 0; i < NPRIME; i++) + PyList_SetItem(v, i, PyInt_FromLong(primetab[i])); + return (v); +} + +PyTypeObject *inittype(PyTypeObject *tyskel) +{ + PyTypeObject *ty = newtype(&PyType_Type, tyskel); + ty->tp_flags |= Py_TPFLAGS_HEAPTYPE; + PyType_Ready(ty); + return (ty); +} + +void init_base(void) { + static const PyMethodDef mzero = { 0 }; + PyObject *mod; + INIT_MODULES; + DA_PUSH(&global_pymethods, mzero); + mod = Py_InitModule("catacomb._base", DA(&global_pymethods)); + INSERT_MODULES; + INSERT("smallprimes", smallprimes()); + setconstants(mod); +} + +/*----- That's all, folks -------------------------------------------------*/ -- 2.11.0