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