catacomb.c, ec.c, group.c, mp.c: Count base/exponent pairs with `size_t'.
[catacomb-python] / catacomb.c
CommitLineData
d7ab1bab 1/* -*-c-*-
2 *
d7ab1bab 3 * Where the fun begins
4 *
5 * (c) 2004 Straylight/Edgeware
6 */
7
b2687a0a 8/*----- Licensing notice --------------------------------------------------*
d7ab1bab 9 *
10 * This file is part of the Python interface to Catacomb.
11 *
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.
b2687a0a 16 *
d7ab1bab 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.
b2687a0a 21 *
d7ab1bab 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.
25 */
26
27/*----- Header files ------------------------------------------------------*/
28
29#include "catacomb-python.h"
30
31/*----- Main code ---------------------------------------------------------*/
32
d7ab1bab 33PyObject *mexp_common(PyObject *me, PyObject *arg,
34 size_t efsz,
35 PyObject *(*id)(PyObject *),
36 int (*fill)(void *, PyObject *,
37 PyObject *, PyObject *),
01d4fd84 38 PyObject *(*exp)(PyObject *, void *, size_t),
d7ab1bab 39 void (*drop)(void *))
40{
01d4fd84
MW
41 size_t i = 0, j, n;
42 int flat;
d7ab1bab 43 PyObject *qq, *x, *y, *z = 0;
44 char *v = 0, *vv;
45
c51a597d
MW
46 if (PyTuple_GET_SIZE(arg) == 1)
47 arg = PyTuple_GET_ITEM(arg, 0);
d7ab1bab 48 if (!PySequence_Check(arg)) TYERR("not a sequence");
4281a7ee
MW
49 n = PySequence_Size(arg); if (n < 0) goto end;
50 if (!n) { z = id(me); goto end; }
d7ab1bab 51 x = PySequence_GetItem(arg, 0);
52 if (PySequence_Check(x))
53 flat = 0;
54 else {
55 if (n % 2) VALERR("must have even number of arguments");
56 n /= 2;
57 flat = 1;
58 }
59 Py_DECREF(x);
60
61 v = xmalloc(n * efsz);
62 for (i = j = 0, vv = v; i < n; i++, vv += efsz) {
63 if (flat) {
64 x = PySequence_GetItem(arg, j++);
65 y = PySequence_GetItem(arg, j++);
66 } else {
67 qq = PySequence_GetItem(arg, j++);
68 if (!qq) goto end;
69 if (!PySequence_Check(qq) || PySequence_Size(qq) != 2) {
70 Py_DECREF(qq);
71 TYERR("want a sequence of pairs");
72 }
73 x = PySequence_GetItem(qq, 0);
74 y = PySequence_GetItem(qq, 1);
75 Py_DECREF(qq);
76 }
77 if (!x || !y) goto end;
78 if (fill(vv, me, x, y)) {
79 Py_DECREF(x);
80 Py_DECREF(y);
81 if (!PyErr_Occurred())
82 PyErr_SetString(PyExc_TypeError, "type mismatch");
83 goto end;
84 }
85 Py_DECREF(x);
86 Py_DECREF(y);
87 }
88 z = exp(me, v, n);
89
90end:
91 if (v) {
92 for (j = 0, vv = v; j < i; j++, vv += efsz)
93 drop(vv);
94 xfree(v);
95 }
d7ab1bab 96 return (z);
97}
98
10e6f88a
MW
99int convmpw(PyObject *o, void *pp)
100{
101 unsigned long u;
102 unsigned *p = pp;
103
104 if (!convulong(o, &u)) goto end;
105 if (u > MPW_MAX) VALERR("out of range");
106 *p = u;
107 return (1);
108end:
109 return (0);
110}
111
a539ffb8
MW
112static PyTypeObject *thingtab_pytype;
113
114typedef struct thingentry {
115 sym_base _b;
116 PyObject *val;
117} thingentry;
118#define THING_VAL(x) (((thingentry *)(x))->val)
119
120typedef struct thingtab_pyobj {
121 GMAP_PYOBJ_HEAD
122 sym_table t;
123} thingtab_pyobj;
124#define THINGTAB_T(x) (&((thingtab_pyobj *)(x))->t)
125
126static void *thingtab_gmlookup(PyObject *me, PyObject *key, unsigned *f)
127{
128 const char *p;
129
2135a6d3 130 p = TEXT_STR(key); if (!p) return (0);
a539ffb8
MW
131 return (sym_find(THINGTAB_T(me), p, -1, 0, f));
132}
133
134static void thingtab_gmiterinit(PyObject *me, void *i)
135 { sym_mkiter(i, THINGTAB_T(me)); }
136
137static void *thingtab_gmiternext(PyObject *me, void *i)
138 { sym_iter *it = i; void *e; SYM_NEXT(it, e); return (e); }
139
140static PyObject *thingtab_gmentrykey(PyObject *me, void *e)
2135a6d3 141 { return (TEXT_FROMSTR(SYM_NAME(e))); }
a539ffb8
MW
142
143static PyObject *thingtab_gmentryvalue(PyObject *me, void *e)
144 { PyObject *rc = THING_VAL(e); RETURN_OBJ(rc); }
145
146static const gmap_ops thingtab_gmops = {
147 sizeof(sym_iter),
148 thingtab_gmlookup,
149 thingtab_gmiterinit,
150 thingtab_gmiternext,
151 thingtab_gmentrykey,
152 thingtab_gmentryvalue
153};
154
155static Py_ssize_t thing_pysize(PyObject *me)
156 { return gmap_pysize_from_sym(THINGTAB_T(me)); }
157
158static const PyMappingMethods thingtab_pymapping = {
159 thing_pysize,
160 gmap_pylookup,
161 0
162};
163
164static thingtab_pyobj *make_thingtab(void)
165{
166 thingtab_pyobj *map = PyObject_NEW(thingtab_pyobj, thingtab_pytype);
167
168 map->gmops = &thingtab_gmops;
169 sym_create(&map->t);
170 return (map);
171}
172
173PyObject *make_algtab(const void *tab, size_t esz,
174 const char *(*namefn)(const void *),
175 PyObject *(*valfn)(const void *))
176{
177 thingtab_pyobj *map = make_thingtab();
178 const char *p = tab;
179 const char *name;
180 thingentry *e;
181 unsigned f;
182
183 for (;;) {
184 name = namefn(p); if (!name) break;
185 e = sym_find(&map->t, name, -1, sizeof(*e), &f); assert(!f);
186 e->val = valfn(p);
187 p += esz;
188 }
189 return ((PyObject *)map);
190}
191
192PyObject *make_grouptab(const void *tab, size_t esz,
193 const char *(*namefn)(const void *),
194 int (*ixfn)(const void *), PyObject *(*valfn)(int))
195{
196 thingtab_pyobj *map = make_thingtab();
197 struct { const char *name; int ix; } *ixtab = 0;
198 PyObject **valtab, **vv;
199 size_t i = 0, n = 0;
200 const char *p = tab;
201 const char *name;
202 thingentry *e;
203 unsigned f;
204
205 for (;;) {
206 name = namefn(p); if (!name) break;
207 if (i >= n) {
208 if (!n) n = 16;
209 else n *= 2;
210 ixtab = xrealloc(ixtab, n*sizeof(*ixtab), i*sizeof(*ixtab));
211 }
212 ixtab[i].name = name; ixtab[i].ix = ixfn(p); assert(ixtab[i].ix >= 0);
213 p += esz; i++;
214 }
215 n = i;
216
217 valtab = xmalloc(n*sizeof(*valtab));
218 for (i = 0; i < n; i++) valtab[i] = 0;
219
220 for (i = 0; i < n; i++) {
221 e = sym_find(&map->t, ixtab[i].name, -1, sizeof(*e), &f); assert(!f);
222 vv = &valtab[ixtab[i].ix];
223 if (*vv) Py_INCREF(*vv);
224 else *vv = valfn(ixtab[i].ix);
225 e->val = *vv;
226 }
227
228 xfree(ixtab); xfree(valtab);
229 return ((PyObject *)map);
230}
231
232static const PyTypeObject thingtab_pytype_skel = {
591bf41b 233 PyVarObject_HEAD_INIT(0, 0) /* Header */
a539ffb8
MW
234 "_MiscTable", /* @tp_name@ */
235 sizeof(thingtab_pyobj), /* @tp_basicsize@ */
236 0, /* @tp_itemsize@ */
237
238 0, /* @tp_dealloc@ */
239 0, /* @tp_print@ */
240 0, /* @tp_getattr@ */
241 0, /* @tp_setattr@ */
242 0, /* @tp_compare@ */
243 0, /* @tp_repr@ */
244 0, /* @tp_as_number@ */
245 PYSEQUENCE(gmap), /* @tp_as_sequence@ */
246 PYMAPPING(thingtab), /* @tp_as_mapping@ */
247 0, /* @tp_hash@ */
248 0, /* @tp_call@ */
249 0, /* @tp_str@ */
250 0, /* @tp_getattro@ */
251 0, /* @tp_setattro@ */
252 0, /* @tp_as_buffer@ */
253 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
254 Py_TPFLAGS_BASETYPE,
255
256 /* @tp_doc@ */
257 "Class for tables of algorithms and abstract-group data.\n"
258 " Not instantiable by users.",
259
260 0, /* @tp_traverse@ */
261 0, /* @tp_clear@ */
262 0, /* @tp_richcompare@ */
263 0, /* @tp_weaklistoffset@ */
264 gmap_pyiter, /* @tp_iter@ */
265 0, /* @tp_iternext@ */
266 PYMETHODS(gmapro), /* @tp_methods@ */
267 0, /* @tp_members@ */
268 0, /* @tp_getset@ */
269 0, /* @tp_base@ */
270 0, /* @tp_dict@ */
271 0, /* @tp_descr_get@ */
272 0, /* @tp_descr_set@ */
273 0, /* @tp_dictoffset@ */
274 0, /* @tp_init@ */
275 PyType_GenericAlloc, /* @tp_alloc@ */
276 abstract_pynew, /* @tp_new@ */
277 0, /* @tp_free@ */
278 0 /* @tp_is_gc@ */
279};
280
d7ab1bab 281static PyObject *smallprimes(void)
282{
283 PyObject *v = PyList_New(NPRIME);
284 int i;
285
286 for (i = 0; i < NPRIME; i++)
c51a597d 287 PyList_SET_ITEM(v, i, PyInt_FromLong(primetab[i]));
d7ab1bab 288 return (v);
289}
290
46e6ad89 291static PyObject *meth__ego(PyObject *me, PyObject *arg)
292{
293 char *argv0;
294 if (!PyArg_ParseTuple(arg, "s:_ego", &argv0))
295 return (0);
20441612 296 if (STRCMP(QUIS, ==, "<UNNAMED>"))
46e6ad89 297 ego(argv0);
298 RETURN_NONE;
299}
300
c263b05c 301static const PyMethodDef methods[] = {
46e6ad89 302#define METHNAME(func) meth_##func
d96c882e 303 METH (_ego, "_ego(ARGV0)")
46e6ad89 304#undef METHNAME
305 { 0 }
306};
307
bb87b97a
MW
308static void init_random(void)
309{
d610b03d 310#if PY_VERSION_HEX >= 0x02060000
bb87b97a
MW
311 char *seed;
312 uint32 r;
313
314 if (!Py_HashRandomizationFlag) return;
315 seed = getenv("PYTHONHASHSEED");
20441612 316 if (!seed || STRCMP(seed, ==, "random")) r = GR_WORD(&rand_global);
bb87b97a
MW
317 else r = strtoul(seed, 0, 0);
318 if (!r) r = 0xe011f220; /* zero doesn't work well */
319 unihash_setkey(&unihash_global, r);
320#endif
321}
322
f7623015
MW
323#ifdef PY3
324static PyModuleDef moddef = {
325 PyModuleDef_HEAD_INIT,
326 "catacomb._base", /* @m_name@ */
327 "Low-level module for Catacomb bindings. Use `catacomb' instead.",
328 /* @m_doc@ */
329 0, /* @m_size@ */
330 0, /* @m_methods@ */
331 0, /* @m_slots@ */
332 0, /* @m_traverse@ */
333 0, /* @m_clear@ */
334 0 /* @m_free@ */
335};
336#endif
337
338EXPORT PyMODINIT_FUNC PY23(init_base, PyInit__base)(void)
11cb3d97 339{
d7ab1bab 340 PyObject *mod;
c5236b64 341
2135a6d3 342 modname = TEXT_FROMSTR("catacomb");
46e6ad89 343 addmethods(methods);
d7ab1bab 344 INIT_MODULES;
a539ffb8 345 INITTYPE(thingtab, root);
bb87b97a 346 init_random();
f7623015
MW
347#ifdef PY3
348 moddef.m_methods = donemethods();
349 mod = PyModule_Create(&moddef);
350#else
11cb3d97 351 mod = Py_InitModule("catacomb._base", donemethods());
f7623015 352#endif
d7ab1bab 353 INSERT_MODULES;
a539ffb8 354 INSERT("_MiscTable", thingtab_pytype);
d7ab1bab 355 INSERT("smallprimes", smallprimes());
f7623015
MW
356#ifdef PY3
357 return (mod);
358#endif
d7ab1bab 359}
360
361/*----- That's all, folks -------------------------------------------------*/