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