X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb-python/blobdiff_plain/4abb54de656f0d5c1b35de940fe75e7e3159dee4..refs/heads/mdw/freebin:/catacomb.c diff --git a/catacomb.c b/catacomb.c index b596b5e..23906eb 100644 --- a/catacomb.c +++ b/catacomb.c @@ -30,108 +30,269 @@ /*----- Main code ---------------------------------------------------------*/ -static const struct nameval 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), - C(KOPEN_READ), C(KOPEN_WRITE), C(KOPEN_NOFILE), - C(KEXP_FOREVER), C(KEXP_EXPIRE), - C(KF_ENCMASK), C(KENC_BINARY), C(KENC_MP), C(KENC_STRUCT), - C(KENC_ENCRYPT), C(KENC_STRING), C(KENC_EC), - C(KF_CATMASK), C(KCAT_SYMM), C(KCAT_PRIV), C(KCAT_PUB), C(KCAT_SHARE), - C(KF_NONSECRET), - C(KF_BURN), C(KF_OPT), - C(EC_XONLY), C(EC_YBIT), C(EC_LSB), C(EC_CMPR), C(EC_EXPLY), C(EC_SORT), - C(X25519_KEYSZ), C(X25519_PUBSZ), C(X25519_OUTSZ), - C(X448_KEYSZ), C(X448_PUBSZ), C(X448_OUTSZ), - C(ED25519_KEYSZ), C(ED25519_PUBSZ), C(ED25519_SIGSZ), - C(ED25519_MAXPERSOSZ), - C(ED448_KEYSZ), C(ED448_PUBSZ), C(ED448_SIGSZ), C(ED448_MAXPERSOSZ), - C(AEADF_PCHSZ), C(AEADF_PCMSZ), C(AEADF_PCTSZ), - C(AEADF_AADNDEP), C(AEADF_AADFIRST), C(AEADF_NOAAD), -#define ENTRY(tag, val, str) C(KERR_##tag), - KEY_ERRORS(ENTRY) -#undef ENTRY -#undef C - { 0 } -}; - PyObject *mexp_common(PyObject *me, PyObject *arg, size_t efsz, PyObject *(*id)(PyObject *), int (*fill)(void *, PyObject *, PyObject *, PyObject *), - PyObject *(*exp)(PyObject *, void *, int), + PyObject *(*exp)(PyObject *, void *, size_t), 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; + size_t i = 0, o, n; + int flat; + PyObject *qq = 0, *x = 0, *y = 0, *z = 0, *it = 0; + char *v = 0; + + if (PyTuple_Size(arg) == 1) arg = PyTuple_GET_ITEM(arg, 0); + it = PyObject_GetIter(arg); if (!it) goto end; + qq = PyIter_Next(it); + if (!qq) { + if (!PyErr_Occurred()) z = id(me); + else goto end; + } + flat = !PySequence_Check(qq); + if (!PySequence_Check(arg)) + n = 16; else { - if (n % 2) VALERR("must have even number of arguments"); - n /= 2; - flat = 1; + n = PySequence_Size(arg); + if (n == (size_t)-1 && PyErr_Occurred()) goto end; + if (flat) n /= 2; + if (!n) n = 16; } - 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); + v = xmalloc(n*efsz); + o = 0; + for (;;) { + if (!flat) { + if (!PySequence_Check(qq) || PySequence_Size(qq) != 2) TYERR("want a sequence of pairs"); - } x = PySequence_GetItem(qq, 0); y = PySequence_GetItem(qq, 1); - Py_DECREF(qq); + } else { + x = qq; qq = 0; + y = PyIter_Next(it); + if (!y) { + if (PyErr_Occurred()) goto end; + VALERR("must have even number of operands"); + } } 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; + + if (i >= n) { n *= 2; v = xrealloc(v, n*efsz, i*efsz); } + if (fill(v + o, me, x, y)) { + if (PyErr_Occurred()) goto end; + TYERR("type mismatch"); + } + i++; o += efsz; + Py_DECREF(x); x = 0; + Py_DECREF(y); y = 0; + Py_XDECREF(qq); + + qq = PyIter_Next(it); + if (!qq) { + if (PyErr_Occurred()) goto end; + else break; } - Py_DECREF(x); - Py_DECREF(y); } - z = exp(me, v, n); + + z = exp(me, v, i); end: - if (v) { - for (j = 0, vv = v; j < i; j++, vv += efsz) - drop(vv); - xfree(v); - } - Py_DECREF(arg); + while (i--) { o -= efsz; drop(v + o); } + xfree(v); + Py_XDECREF(it); Py_XDECREF(qq); Py_XDECREF(x); Py_XDECREF(y); return (z); } +int convmpw(PyObject *o, void *pp) +{ + unsigned long u; + unsigned *p = pp; + + if (!convulong(o, &u)) goto end; + if (u > MPW_MAX) VALERR("out of range"); + *p = u; + return (1); +end: + return (0); +} + +static PyTypeObject *thingtab_pytype; + +typedef struct thingentry { + sym_base _b; + PyObject *val; +} thingentry; +#define THING_VAL(x) (((thingentry *)(x))->val) + +typedef struct thingtab_pyobj { + GMAP_PYOBJ_HEAD + sym_table t; +} thingtab_pyobj; +#define THINGTAB_T(x) (&((thingtab_pyobj *)(x))->t) + +static void *thingtab_gmlookup(PyObject *me, PyObject *key, unsigned *f) +{ + const char *p; + + p = TEXT_STR(key); if (!p) return (0); + return (sym_find(THINGTAB_T(me), p, -1, 0, f)); +} + +static void thingtab_gmiterinit(PyObject *me, void *i) + { sym_mkiter(i, THINGTAB_T(me)); } + +static void *thingtab_gmiternext(PyObject *me, void *i) + { sym_iter *it = i; void *e; SYM_NEXT(it, e); return (e); } + +static PyObject *thingtab_gmentrykey(PyObject *me, void *e) + { return (TEXT_FROMSTR(SYM_NAME(e))); } + +static PyObject *thingtab_gmentryvalue(PyObject *me, void *e) + { PyObject *rc = THING_VAL(e); RETURN_OBJ(rc); } + +static const gmap_ops thingtab_gmops = { + sizeof(sym_iter), + thingtab_gmlookup, + thingtab_gmiterinit, + thingtab_gmiternext, + thingtab_gmentrykey, + thingtab_gmentryvalue +}; + +static Py_ssize_t thing_pysize(PyObject *me) + { return gmap_pysize_from_sym(THINGTAB_T(me)); } + +static const PyMappingMethods thingtab_pymapping = { + thing_pysize, + gmap_pylookup, + 0 +}; + +static thingtab_pyobj *make_thingtab(void) +{ + thingtab_pyobj *map = PyObject_NEW(thingtab_pyobj, thingtab_pytype); + + map->gmops = &thingtab_gmops; + sym_create(&map->t); + return (map); +} + +PyObject *make_algtab(const void *tab, size_t esz, + const char *(*namefn)(const void *), + PyObject *(*valfn)(const void *)) +{ + thingtab_pyobj *map = make_thingtab(); + const char *p = tab; + const char *name; + thingentry *e; + unsigned f; + + for (;;) { + name = namefn(p); if (!name) break; + e = sym_find(&map->t, name, -1, sizeof(*e), &f); assert(!f); + e->val = valfn(p); + p += esz; + } + return ((PyObject *)map); +} + +PyObject *make_grouptab(const void *tab, size_t esz, + const char *(*namefn)(const void *), + int (*ixfn)(const void *), PyObject *(*valfn)(int)) +{ + thingtab_pyobj *map = make_thingtab(); + struct { const char *name; int ix; } *ixtab = 0; + PyObject **valtab, **vv; + size_t i = 0, n = 0; + const char *p = tab; + const char *name; + thingentry *e; + unsigned f; + + for (;;) { + name = namefn(p); if (!name) break; + if (i >= n) { + if (!n) n = 16; + else n *= 2; + ixtab = xrealloc(ixtab, n*sizeof(*ixtab), i*sizeof(*ixtab)); + } + ixtab[i].name = name; ixtab[i].ix = ixfn(p); assert(ixtab[i].ix >= 0); + p += esz; i++; + } + n = i; + + valtab = xmalloc(n*sizeof(*valtab)); + for (i = 0; i < n; i++) valtab[i] = 0; + + for (i = 0; i < n; i++) { + e = sym_find(&map->t, ixtab[i].name, -1, sizeof(*e), &f); assert(!f); + vv = &valtab[ixtab[i].ix]; + if (*vv) Py_INCREF(*vv); + else *vv = valfn(ixtab[i].ix); + e->val = *vv; + } + + xfree(ixtab); xfree(valtab); + return ((PyObject *)map); +} + +static const PyTypeObject thingtab_pytype_skel = { + PyVarObject_HEAD_INIT(0, 0) /* Header */ + "_MiscTable", /* @tp_name@ */ + sizeof(thingtab_pyobj), /* @tp_basicsize@ */ + 0, /* @tp_itemsize@ */ + + 0, /* @tp_dealloc@ */ + 0, /* @tp_print@ */ + 0, /* @tp_getattr@ */ + 0, /* @tp_setattr@ */ + 0, /* @tp_compare@ */ + 0, /* @tp_repr@ */ + 0, /* @tp_as_number@ */ + PYSEQUENCE(gmap), /* @tp_as_sequence@ */ + PYMAPPING(thingtab), /* @tp_as_mapping@ */ + 0, /* @tp_hash@ */ + 0, /* @tp_call@ */ + 0, /* @tp_str@ */ + 0, /* @tp_getattro@ */ + 0, /* @tp_setattro@ */ + 0, /* @tp_as_buffer@ */ + Py_TPFLAGS_DEFAULT | /* @tp_flags@ */ + Py_TPFLAGS_BASETYPE, + + /* @tp_doc@ */ + "Class for tables of algorithms and abstract-group data.\n" + " Not instantiable by users.", + + 0, /* @tp_traverse@ */ + 0, /* @tp_clear@ */ + 0, /* @tp_richcompare@ */ + 0, /* @tp_weaklistoffset@ */ + gmap_pyiter, /* @tp_iter@ */ + 0, /* @tp_iternext@ */ + PYMETHODS(gmapro), /* @tp_methods@ */ + 0, /* @tp_members@ */ + 0, /* @tp_getset@ */ + 0, /* @tp_base@ */ + 0, /* @tp_dict@ */ + 0, /* @tp_descr_get@ */ + 0, /* @tp_descr_set@ */ + 0, /* @tp_dictoffset@ */ + 0, /* @tp_init@ */ + PyType_GenericAlloc, /* @tp_alloc@ */ + abstract_pynew, /* @tp_new@ */ + 0, /* @tp_free@ */ + 0 /* @tp_is_gc@ */ +}; + 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])); + PyList_SET_ITEM(v, i, PyInt_FromLong(primetab[i])); return (v); } @@ -140,43 +301,69 @@ static PyObject *meth__ego(PyObject *me, PyObject *arg) char *argv0; if (!PyArg_ParseTuple(arg, "s:_ego", &argv0)) return (0); - if (strcmp(QUIS, "") == 0) + if (STRCMP(QUIS, ==, "")) ego(argv0); RETURN_NONE; } -static PyMethodDef methods[] = { +static const PyMethodDef methods[] = { #define METHNAME(func) meth_##func - METH (_ego, "_ego(ARGV0)") + METH (_ego, "_ego(ARGV0)") #undef METHNAME { 0 } }; static void init_random(void) { -#if PY_MAJOR_VERSION >= 3 || (PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION >= 6) +#if PY_VERSION_HEX >= 0x02060000 char *seed; uint32 r; if (!Py_HashRandomizationFlag) return; seed = getenv("PYTHONHASHSEED"); - if (!seed || strcmp(seed, "random") == 0) r = GR_WORD(&rand_global); + if (!seed || STRCMP(seed, ==, "random")) r = GR_WORD(&rand_global); else r = strtoul(seed, 0, 0); if (!r) r = 0xe011f220; /* zero doesn't work well */ unihash_setkey(&unihash_global, r); #endif } -void init_base(void) +#ifdef PY3 +static PyModuleDef moddef = { + PyModuleDef_HEAD_INIT, + "catacomb._base", /* @m_name@ */ + "Low-level module for Catacomb bindings. Use `catacomb' instead.", + /* @m_doc@ */ + 0, /* @m_size@ */ + 0, /* @m_methods@ */ + 0, /* @m_slots@ */ + 0, /* @m_traverse@ */ + 0, /* @m_clear@ */ + 0 /* @m_free@ */ +}; +#endif + +EXPORT PyMODINIT_FUNC PY23(init_base, PyInit__base)(void) { PyObject *mod; + + modname = TEXT_FROMSTR("catacomb"); addmethods(methods); INIT_MODULES; + INITTYPE(thingtab, root); init_random(); +#ifdef PY3 + moddef.m_methods = donemethods(); + mod = PyModule_Create(&moddef); +#else mod = Py_InitModule("catacomb._base", donemethods()); +#endif INSERT_MODULES; + INSERT("_MiscTable", thingtab_pytype); INSERT("smallprimes", smallprimes()); - setconstants(mod, consts); +#ifdef PY3 + return (mod); +#endif } /*----- That's all, folks -------------------------------------------------*/