More fixing for modern Pythons. No longer works with 2.2. Sorry.
[pyke] / catacomb.c
1 /* -*-c-*-
2 *
3 * $Id$
4 *
5 * Where the fun begins
6 *
7 * (c) 2004 Straylight/Edgeware
8 */
9
10 /*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of the Python interface to Catacomb.
13 *
14 * Catacomb/Python is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * Catacomb/Python is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with Catacomb/Python; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 */
28
29 /*----- Header files ------------------------------------------------------*/
30
31 #include "catacomb-python.h"
32
33 /*----- Main code ---------------------------------------------------------*/
34
35 static void setconstants(PyObject *mod)
36 {
37 static const struct { const char *name; unsigned long value; } consts[] = {
38 #define C(x) { #x, x }
39 C(FTY_PRIME), C(FTY_BINARY),
40 C(PGEN_PASS), C(PGEN_FAIL), C(PGEN_BEGIN), C(PGEN_TRY), C(PGEN_DONE),
41 C(PGEN_ABORT),
42 C(MPW_MAX),
43 C(PMODE_READ), C(PMODE_VERIFY),
44 #undef C
45 { 0 }
46 };
47 int i;
48 PyObject *x;
49
50 for (i = 0; consts[i].name; i++) {
51 if (consts[i].value > LONG_MAX)
52 x = PyLong_FromUnsignedLong(consts[i].value);
53 else
54 x = PyInt_FromLong(consts[i].value);
55 PyModule_AddObject(mod, (/*unconst*/ char *)consts[i].name, x);
56 }
57 }
58
59 PyObject *getu32(uint32 w)
60 {
61 if (w <= 0x7fffffff)
62 return (PyInt_FromLong(w));
63 else
64 return (PyLong_FromUnsignedLong(w));
65 }
66
67 PyObject *getbool(int b)
68 {
69 if (b) RETURN_TRUE;
70 else RETURN_FALSE;
71 }
72
73 PyObject *abstract_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
74 {
75 PyErr_SetString(PyExc_TypeError, "can't instantiate this class");
76 return (0);
77 }
78
79 int convulong(PyObject *o, void *pp)
80 {
81 long i;
82 unsigned long *p = pp;
83 PyObject *t;
84
85 if (PyInt_Check(o)) {
86 i = PyInt_AS_LONG(o);
87 if (i < 0) TYERR("must be nonnegative");
88 *p = i;
89 } else {
90 if ((t = PyNumber_Long(o)) == 0) goto end;
91 *p = PyLong_AsUnsignedLong(t);
92 Py_DECREF(t);
93 if (PyErr_Occurred()) goto end;
94 }
95 return (1);
96 end:
97 return (0);
98 }
99
100 int convu32(PyObject *o, void *pp)
101 {
102 unsigned long u;
103 uint32 *p = pp;
104
105 if (!convulong(o, &u)) goto end;
106 if (u > 0xffffffff) TYERR("out of range");
107 *p = u;
108 return (1);
109 end:
110 return (0);
111 }
112
113 int convuint(PyObject *o, void *pp)
114 {
115 unsigned long u;
116 unsigned *p = pp;
117
118 if (!convulong(o, &u)) goto end;
119 if (u > UINT_MAX) TYERR("out of range");
120 *p = u;
121 return (1);
122 end:
123 return (0);
124 }
125
126 int convmpw(PyObject *o, void *pp)
127 {
128 unsigned long u;
129 unsigned *p = pp;
130
131 if (!convulong(o, &u)) goto end;
132 if (u > MPW_MAX) TYERR("out of range");
133 *p = u;
134 return (1);
135 end:
136 return (0);
137 }
138
139 int convszt(PyObject *o, void *pp)
140 {
141 unsigned long u;
142 size_t *p = pp;
143
144 if (!convulong(o, &u)) goto end;
145 if (u > ~(size_t)0) TYERR("out of range");
146 *p = u;
147 return (1);
148 end:
149 return (0);
150 }
151
152 int convbool(PyObject *o, void *pp)
153 {
154 *(int *)pp = PyObject_IsTrue(o);
155 return (1);
156 }
157
158 PyObject *mexp_common(PyObject *me, PyObject *arg,
159 size_t efsz,
160 PyObject *(*id)(PyObject *),
161 int (*fill)(void *, PyObject *,
162 PyObject *, PyObject *),
163 PyObject *(*exp)(PyObject *, void *, int),
164 void (*drop)(void *))
165 {
166 int i = 0, j, n, flat;
167 PyObject *qq, *x, *y, *z = 0;
168 char *v = 0, *vv;
169
170 if (PyTuple_Size(arg) == 1)
171 arg = PyTuple_GetItem(arg, 0);
172 Py_INCREF(arg);
173 if (!PySequence_Check(arg)) TYERR("not a sequence");
174 n = PySequence_Size(arg); if (!n) { z = id(me); goto end; }
175 x = PySequence_GetItem(arg, 0);
176 if (PySequence_Check(x))
177 flat = 0;
178 else {
179 if (n % 2) VALERR("must have even number of arguments");
180 n /= 2;
181 flat = 1;
182 }
183 Py_DECREF(x);
184
185 v = xmalloc(n * efsz);
186 for (i = j = 0, vv = v; i < n; i++, vv += efsz) {
187 if (flat) {
188 x = PySequence_GetItem(arg, j++);
189 y = PySequence_GetItem(arg, j++);
190 } else {
191 qq = PySequence_GetItem(arg, j++);
192 if (!qq) goto end;
193 if (!PySequence_Check(qq) || PySequence_Size(qq) != 2) {
194 Py_DECREF(qq);
195 TYERR("want a sequence of pairs");
196 }
197 x = PySequence_GetItem(qq, 0);
198 y = PySequence_GetItem(qq, 1);
199 Py_DECREF(qq);
200 }
201 if (!x || !y) goto end;
202 if (fill(vv, me, x, y)) {
203 Py_DECREF(x);
204 Py_DECREF(y);
205 if (!PyErr_Occurred())
206 PyErr_SetString(PyExc_TypeError, "type mismatch");
207 goto end;
208 }
209 Py_DECREF(x);
210 Py_DECREF(y);
211 }
212 z = exp(me, v, n);
213
214 end:
215 if (v) {
216 for (j = 0, vv = v; j < i; j++, vv += efsz)
217 drop(vv);
218 xfree(v);
219 }
220 Py_DECREF(arg);
221 return (z);
222 }
223
224 DA_DECL(method_v, PyMethodDef);
225 static method_v global_pymethods = DA_INIT;
226 void addmethods(const PyMethodDef *m)
227 {
228 size_t n;
229
230 for (n = 0; m[n].ml_name; n++);
231 DA_ENSURE(&global_pymethods, n);
232 memcpy(DA(&global_pymethods) + DA_LEN(&global_pymethods),
233 m, n * sizeof(*m));
234 DA_EXTEND(&global_pymethods, n);
235 }
236
237 static const PyTypeObject emptytype = { 0 };
238
239 void *newtype(PyTypeObject *metaty,
240 const PyTypeObject *skel,
241 const char *name)
242 {
243 PyHeapTypeObject *ty =
244 (PyHeapTypeObject *)_PyObject_GC_Malloc(_PyObject_VAR_SIZE(metaty, 0));
245 if (!skel) skel = &emptytype;
246 memcpy(ty, skel, sizeof(*skel));
247 if (ty->type.tp_base) Py_INCREF(ty->type.tp_base);
248 #define COPY(blah) do { \
249 if (ty->type.tp_as_##blah) { \
250 memcpy(&ty->as_##blah, \
251 ty->type.tp_as_##blah, \
252 sizeof(ty->as_##blah)); \
253 ty->type.tp_as_##blah = &ty->as_##blah; \
254 } \
255 } while (0)
256 COPY(number);
257 COPY(sequence);
258 COPY(mapping);
259 COPY(buffer);
260 #undef COPY
261 if (name)
262 ty->name = PyString_FromString(name);
263 else if (ty->type.tp_name)
264 ty->name = PyString_FromString(ty->type.tp_name);
265 if (ty->name)
266 ty->type.tp_name = PyString_AS_STRING(ty->name);
267 PyObject_INIT(&ty->type, metaty);
268 Py_INCREF(metaty);
269 return (ty);
270 }
271
272 static PyObject *smallprimes(void)
273 {
274 PyObject *v = PyList_New(NPRIME);
275 int i;
276
277 for (i = 0; i < NPRIME; i++)
278 PyList_SetItem(v, i, PyInt_FromLong(primetab[i]));
279 return (v);
280 }
281
282 PyTypeObject *inittype(PyTypeObject *tyskel)
283 {
284 PyTypeObject *ty = newtype(&PyType_Type, tyskel, 0);
285 ty->tp_flags |= Py_TPFLAGS_HEAPTYPE;
286 PyType_Ready(ty);
287 return (ty);
288 }
289
290 void init_base(void) {
291 static const PyMethodDef mzero = { 0 };
292 PyObject *mod;
293 INIT_MODULES;
294 DA_PUSH(&global_pymethods, mzero);
295 mod = Py_InitModule("catacomb._base", DA(&global_pymethods));
296 INSERT_MODULES;
297 INSERT("smallprimes", smallprimes());
298 setconstants(mod);
299 }
300
301 /*----- That's all, folks -------------------------------------------------*/