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