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 *), | |
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 | ||
90 | end: | |
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 |
99 | int 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); | |
108 | end: | |
109 | return (0); | |
110 | } | |
111 | ||
a539ffb8 MW |
112 | static PyTypeObject *thingtab_pytype; |
113 | ||
114 | typedef struct thingentry { | |
115 | sym_base _b; | |
116 | PyObject *val; | |
117 | } thingentry; | |
118 | #define THING_VAL(x) (((thingentry *)(x))->val) | |
119 | ||
120 | typedef struct thingtab_pyobj { | |
121 | GMAP_PYOBJ_HEAD | |
122 | sym_table t; | |
123 | } thingtab_pyobj; | |
124 | #define THINGTAB_T(x) (&((thingtab_pyobj *)(x))->t) | |
125 | ||
126 | static 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 | ||
134 | static void thingtab_gmiterinit(PyObject *me, void *i) | |
135 | { sym_mkiter(i, THINGTAB_T(me)); } | |
136 | ||
137 | static void *thingtab_gmiternext(PyObject *me, void *i) | |
138 | { sym_iter *it = i; void *e; SYM_NEXT(it, e); return (e); } | |
139 | ||
140 | static PyObject *thingtab_gmentrykey(PyObject *me, void *e) | |
2135a6d3 | 141 | { return (TEXT_FROMSTR(SYM_NAME(e))); } |
a539ffb8 MW |
142 | |
143 | static PyObject *thingtab_gmentryvalue(PyObject *me, void *e) | |
144 | { PyObject *rc = THING_VAL(e); RETURN_OBJ(rc); } | |
145 | ||
146 | static 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 | ||
155 | static Py_ssize_t thing_pysize(PyObject *me) | |
156 | { return gmap_pysize_from_sym(THINGTAB_T(me)); } | |
157 | ||
158 | static const PyMappingMethods thingtab_pymapping = { | |
159 | thing_pysize, | |
160 | gmap_pylookup, | |
161 | 0 | |
162 | }; | |
163 | ||
164 | static 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 | ||
173 | PyObject *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 | ||
192 | PyObject *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 | ||
232 | static 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 | 281 | static 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 | 291 | static 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 | 301 | static 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 |
308 | static 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 |
324 | static 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 | ||
338 | EXPORT 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 -------------------------------------------------*/ |