/* -*-c-*-
*
- * $Id$
- *
* Where the fun begins
*
* (c) 2004 Straylight/Edgeware
*/
-/*----- Licensing notice --------------------------------------------------*
+/*----- Licensing notice --------------------------------------------------*
*
* This file is part of the Python interface to Catacomb.
*
* 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.
/*----- 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 *),
PyObject *qq, *x, *y, *z = 0;
char *v = 0, *vv;
- if (PyTuple_Size(arg) == 1)
- arg = PyTuple_GetItem(arg, 0);
+ 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) { z = id(me); goto end; }
+ 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;
return (z);
}
-DA_DECL(method_v, PyMethodDef);
-static method_v global_pymethods = DA_INIT;
-void addmethods(const PyMethodDef *m)
+int convmpw(PyObject *o, void *pp)
{
- size_t n;
+ unsigned long u;
+ unsigned *p = pp;
- 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);
+ if (!convulong(o, &u)) goto end;
+ if (u > MPW_MAX) VALERR("out of range");
+ *p = u;
+ return (1);
+end:
+ return (0);
}
-static const PyTypeObject emptytype = { 0 };
+static PyTypeObject *thingtab_pytype;
+
+typedef struct thingentry {
+ sym_base _b;
+ PyObject *val;
+} thingentry;
+#define THING_VAL(x) (((thingentry *)(x))->val)
-void *newtype(PyTypeObject *metaty,
- const PyTypeObject *skel,
- const char *name)
+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)
{
- PyHeapTypeObject *ty =
- (PyHeapTypeObject *)_PyObject_GC_Malloc(_PyObject_VAR_SIZE(metaty, 0));
- if (!skel) skel = &emptytype;
- memcpy(ty, skel, sizeof(*skel));
- if (ty->type.tp_base) Py_INCREF(ty->type.tp_base);
-#define COPY(blah) do { \
- if (ty->type.tp_as_##blah) { \
- memcpy(&ty->as_##blah, \
- ty->type.tp_as_##blah, \
- sizeof(ty->as_##blah)); \
- ty->type.tp_as_##blah = &ty->as_##blah; \
- } \
- } while (0)
- COPY(number);
- COPY(sequence);
- COPY(mapping);
- COPY(buffer);
-#undef COPY
- if (name)
- ty->name = PyString_FromString(name);
- else if (ty->type.tp_name)
- ty->name = PyString_FromString(ty->type.tp_name);
- if (ty->name)
- ty->type.tp_name = PyString_AS_STRING(ty->name);
- PyObject_INIT(&ty->type, metaty);
- Py_INCREF(metaty);
- return (ty);
+ 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);
}
-PyTypeObject *inittype(PyTypeObject *tyskel)
+static PyObject *meth__ego(PyObject *me, PyObject *arg)
{
- PyTypeObject *ty = newtype(&PyType_Type, tyskel, 0);
- ty->tp_flags |= Py_TPFLAGS_HEAPTYPE;
- PyType_Ready(ty);
- return (ty);
+ char *argv0;
+ if (!PyArg_ParseTuple(arg, "s:_ego", &argv0))
+ return (0);
+ if (STRCMP(QUIS, ==, "<UNNAMED>"))
+ ego(argv0);
+ RETURN_NONE;
}
-void init_base(void) {
- static const PyMethodDef mzero = { 0 };
+static const PyMethodDef methods[] = {
+#define METHNAME(func) meth_##func
+ METH (_ego, "_ego(ARGV0)")
+#undef METHNAME
+ { 0 }
+};
+
+static void init_random(void)
+{
+#if PY_VERSION_HEX >= 0x02060000
+ char *seed;
+ uint32 r;
+
+ if (!Py_HashRandomizationFlag) return;
+ seed = getenv("PYTHONHASHSEED");
+ 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
+}
+
+#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;
- DA_PUSH(&global_pymethods, mzero);
- mod = Py_InitModule("catacomb._base", DA(&global_pymethods));
+ 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);
+#ifdef PY3
+ return (mod);
+#endif
}
/*----- That's all, folks -------------------------------------------------*/