5 * (c) 2004 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of the Python interface to Catacomb.
12 * Catacomb/Python is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * Catacomb/Python is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with Catacomb/Python; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 /*----- Header files ------------------------------------------------------*/
29 #include "catacomb-python.h"
31 /*----- Main code ---------------------------------------------------------*/
33 PyObject *mexp_common(PyObject *me, PyObject *arg,
35 PyObject *(*id)(PyObject *),
36 int (*fill)(void *, PyObject *,
37 PyObject *, PyObject *),
38 PyObject *(*exp)(PyObject *, void *, int),
41 int i = 0, j, n, flat;
42 PyObject *qq, *x, *y, *z = 0;
45 if (PyTuple_GET_SIZE(arg) == 1)
46 arg = PyTuple_GET_ITEM(arg, 0);
48 if (!PySequence_Check(arg)) TYERR("not a sequence");
49 n = PySequence_Size(arg); if (n < 0) goto end;
50 if (!n) { z = id(me); goto end; }
51 x = PySequence_GetItem(arg, 0);
52 if (PySequence_Check(x))
55 if (n % 2) VALERR("must have even number of arguments");
61 v = xmalloc(n * efsz);
62 for (i = j = 0, vv = v; i < n; i++, vv += efsz) {
64 x = PySequence_GetItem(arg, j++);
65 y = PySequence_GetItem(arg, j++);
67 qq = PySequence_GetItem(arg, j++);
69 if (!PySequence_Check(qq) || PySequence_Size(qq) != 2) {
71 TYERR("want a sequence of pairs");
73 x = PySequence_GetItem(qq, 0);
74 y = PySequence_GetItem(qq, 1);
77 if (!x || !y) goto end;
78 if (fill(vv, me, x, y)) {
81 if (!PyErr_Occurred())
82 PyErr_SetString(PyExc_TypeError, "type mismatch");
92 for (j = 0, vv = v; j < i; j++, vv += efsz)
100 int convmpw(PyObject *o, void *pp)
105 if (!convulong(o, &u)) goto end;
106 if (u > MPW_MAX) VALERR("out of range");
113 static PyTypeObject *thingtab_pytype;
115 typedef struct thingentry {
119 #define THING_VAL(x) (((thingentry *)(x))->val)
121 typedef struct thingtab_pyobj {
125 #define THINGTAB_T(x) (&((thingtab_pyobj *)(x))->t)
127 static void *thingtab_gmlookup(PyObject *me, PyObject *key, unsigned *f)
131 p = TEXT_STR(key); if (!p) return (0);
132 return (sym_find(THINGTAB_T(me), p, -1, 0, f));
135 static void thingtab_gmiterinit(PyObject *me, void *i)
136 { sym_mkiter(i, THINGTAB_T(me)); }
138 static void *thingtab_gmiternext(PyObject *me, void *i)
139 { sym_iter *it = i; void *e; SYM_NEXT(it, e); return (e); }
141 static PyObject *thingtab_gmentrykey(PyObject *me, void *e)
142 { return (TEXT_FROMSTR(SYM_NAME(e))); }
144 static PyObject *thingtab_gmentryvalue(PyObject *me, void *e)
145 { PyObject *rc = THING_VAL(e); RETURN_OBJ(rc); }
147 static const gmap_ops thingtab_gmops = {
153 thingtab_gmentryvalue
156 static Py_ssize_t thing_pysize(PyObject *me)
157 { return gmap_pysize_from_sym(THINGTAB_T(me)); }
159 static const PyMappingMethods thingtab_pymapping = {
165 static thingtab_pyobj *make_thingtab(void)
167 thingtab_pyobj *map = PyObject_NEW(thingtab_pyobj, thingtab_pytype);
169 map->gmops = &thingtab_gmops;
174 PyObject *make_algtab(const void *tab, size_t esz,
175 const char *(*namefn)(const void *),
176 PyObject *(*valfn)(const void *))
178 thingtab_pyobj *map = make_thingtab();
185 name = namefn(p); if (!name) break;
186 e = sym_find(&map->t, name, -1, sizeof(*e), &f); assert(!f);
190 return ((PyObject *)map);
193 PyObject *make_grouptab(const void *tab, size_t esz,
194 const char *(*namefn)(const void *),
195 int (*ixfn)(const void *), PyObject *(*valfn)(int))
197 thingtab_pyobj *map = make_thingtab();
198 struct { const char *name; int ix; } *ixtab = 0;
199 PyObject **valtab, **vv;
207 name = namefn(p); if (!name) break;
211 ixtab = xrealloc(ixtab, n*sizeof(*ixtab), i*sizeof(*ixtab));
213 ixtab[i].name = name; ixtab[i].ix = ixfn(p); assert(ixtab[i].ix >= 0);
218 valtab = xmalloc(n*sizeof(*valtab));
219 for (i = 0; i < n; i++) valtab[i] = 0;
221 for (i = 0; i < n; i++) {
222 e = sym_find(&map->t, ixtab[i].name, -1, sizeof(*e), &f); assert(!f);
223 vv = &valtab[ixtab[i].ix];
224 if (*vv) Py_INCREF(*vv);
225 else *vv = valfn(ixtab[i].ix);
229 xfree(ixtab); xfree(valtab);
230 return ((PyObject *)map);
233 static const PyTypeObject thingtab_pytype_skel = {
234 PyVarObject_HEAD_INIT(0, 0) /* Header */
235 "_MiscTable", /* @tp_name@ */
236 sizeof(thingtab_pyobj), /* @tp_basicsize@ */
237 0, /* @tp_itemsize@ */
239 0, /* @tp_dealloc@ */
241 0, /* @tp_getattr@ */
242 0, /* @tp_setattr@ */
243 0, /* @tp_compare@ */
245 0, /* @tp_as_number@ */
246 PYSEQUENCE(gmap), /* @tp_as_sequence@ */
247 PYMAPPING(thingtab), /* @tp_as_mapping@ */
251 0, /* @tp_getattro@ */
252 0, /* @tp_setattro@ */
253 0, /* @tp_as_buffer@ */
254 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
258 "Class for tables of algorithms and abstract-group data.\n"
259 " Not instantiable by users.",
261 0, /* @tp_traverse@ */
263 0, /* @tp_richcompare@ */
264 0, /* @tp_weaklistoffset@ */
265 gmap_pyiter, /* @tp_iter@ */
266 0, /* @tp_iternext@ */
267 PYMETHODS(gmapro), /* @tp_methods@ */
268 0, /* @tp_members@ */
272 0, /* @tp_descr_get@ */
273 0, /* @tp_descr_set@ */
274 0, /* @tp_dictoffset@ */
276 PyType_GenericAlloc, /* @tp_alloc@ */
277 abstract_pynew, /* @tp_new@ */
282 static PyObject *smallprimes(void)
284 PyObject *v = PyList_New(NPRIME);
287 for (i = 0; i < NPRIME; i++)
288 PyList_SET_ITEM(v, i, PyInt_FromLong(primetab[i]));
292 static PyObject *meth__ego(PyObject *me, PyObject *arg)
295 if (!PyArg_ParseTuple(arg, "s:_ego", &argv0))
297 if (STRCMP(QUIS, ==, "<UNNAMED>"))
302 static const PyMethodDef methods[] = {
303 #define METHNAME(func) meth_##func
304 METH (_ego, "_ego(ARGV0)")
309 static void init_random(void)
311 #if PY_VERSION_HEX >= 0x02060000
315 if (!Py_HashRandomizationFlag) return;
316 seed = getenv("PYTHONHASHSEED");
317 if (!seed || STRCMP(seed, ==, "random")) r = GR_WORD(&rand_global);
318 else r = strtoul(seed, 0, 0);
319 if (!r) r = 0xe011f220; /* zero doesn't work well */
320 unihash_setkey(&unihash_global, r);
324 EXPORT void init_base(void)
328 modname = TEXT_FROMSTR("catacomb");
331 INITTYPE(thingtab, root);
333 mod = Py_InitModule("catacomb._base", donemethods());
335 INSERT("_MiscTable", thingtab_pytype);
336 INSERT("smallprimes", smallprimes());
339 /*----- That's all, folks -------------------------------------------------*/