X-Git-Url: https://git.distorted.org.uk/~mdw/catacomb-python/blobdiff_plain/b115b0c0883c2af8170b0e733bb1c47b40f2647e..d91d53e0e3b769955cc2adfb8aed493ce84367d3:/catacomb.c diff --git a/catacomb.c b/catacomb.c index a914bff..23906eb 100644 --- a/catacomb.c +++ b/catacomb.c @@ -35,65 +35,72 @@ PyObject *mexp_common(PyObject *me, PyObject *arg, 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_GET_SIZE(arg) == 1) - arg = PyTuple_GET_ITEM(arg, 0); - Py_INCREF(arg); - if (!PySequence_Check(arg)) TYERR("not a sequence"); - n = PySequence_Size(arg); if (n < 0) goto end; - 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); } @@ -128,7 +135,7 @@ static void *thingtab_gmlookup(PyObject *me, PyObject *key, unsigned *f) { const char *p; - p = PyString_AsString(key); if (!p) return (0); + p = TEXT_STR(key); if (!p) return (0); return (sym_find(THINGTAB_T(me), p, -1, 0, f)); } @@ -139,7 +146,7 @@ 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 (PyString_FromString(SYM_NAME(e))); } + { return (TEXT_FROMSTR(SYM_NAME(e))); } static PyObject *thingtab_gmentryvalue(PyObject *me, void *e) { PyObject *rc = THING_VAL(e); RETURN_OBJ(rc); } @@ -231,7 +238,7 @@ PyObject *make_grouptab(const void *tab, size_t esz, } static const PyTypeObject thingtab_pytype_skel = { - PyObject_HEAD_INIT(0) 0, /* Header */ + PyVarObject_HEAD_INIT(0, 0) /* Header */ "_MiscTable", /* @tp_name@ */ sizeof(thingtab_pyobj), /* @tp_basicsize@ */ 0, /* @tp_itemsize@ */ @@ -321,19 +328,42 @@ static void init_random(void) #endif } -EXPORT 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 = PyString_FromString("catacomb"); + 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()); +#ifdef PY3 + return (mod); +#endif } /*----- That's all, folks -------------------------------------------------*/