chiark / gitweb /
Initial check-in of catacomb-python.
[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, const PyTypeObject *skel)
240 {
241   PyTypeObject *ty = (PyTypeObject *)_PyObject_GC_Malloc(metaty, 0);
242   if (!skel) skel = &emptytype;
243   memcpy(ty, skel, sizeof(*skel));
244   if (ty->tp_base) Py_INCREF(ty->tp_base);
245   PyObject_INIT(ty, metaty);
246   Py_INCREF(metaty);
247   return (ty);
248 }
249
250 static PyObject *smallprimes(void)
251 {
252   PyObject *v = PyList_New(NPRIME);
253   int i;
254
255   for (i = 0; i < NPRIME; i++)
256     PyList_SetItem(v, i, PyInt_FromLong(primetab[i]));
257   return (v);
258 }
259
260 PyTypeObject *inittype(PyTypeObject *tyskel)
261 {
262   PyTypeObject *ty = newtype(&PyType_Type, tyskel);
263   ty->tp_flags |= Py_TPFLAGS_HEAPTYPE;
264   PyType_Ready(ty);
265   return (ty);
266 }
267
268 void init_base(void) {
269   static const PyMethodDef mzero = { 0 };
270   PyObject *mod;
271   INIT_MODULES;
272   DA_PUSH(&global_pymethods, mzero);
273   mod = Py_InitModule("catacomb._base", DA(&global_pymethods));
274   INSERT_MODULES;
275   INSERT("smallprimes", smallprimes());
276   setconstants(mod);
277 }
278
279 /*----- That's all, folks -------------------------------------------------*/