Checkin, Debianized and more or less complete.
[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 C(KOPEN_READ), C(KOPEN_WRITE), C(KOPEN_NOFILE),
45 C(KEXP_FOREVER), C(KEXP_EXPIRE),
46 C(KF_ENCMASK), C(KENC_BINARY), C(KENC_MP), C(KENC_STRUCT),
47 C(KENC_ENCRYPT), C(KENC_STRING), C(KENC_EC),
48 C(KF_CATMASK), C(KCAT_SYMM), C(KCAT_PRIV), C(KCAT_PUB), C(KCAT_SHARE),
49 C(KF_NONSECRET),
50 C(KF_BURN), C(KF_OPT),
51 #define ENTRY(tag, val, str) C(KERR_##tag),
52 KEY_ERRORS(ENTRY)
53 #undef ENTRY
54 #undef C
55 { 0 }
56 };
57 int i;
58 PyObject *x;
59
60 for (i = 0; consts[i].name; i++) {
61 if (consts[i].value > LONG_MAX)
62 x = PyLong_FromUnsignedLong(consts[i].value);
63 else
64 x = PyInt_FromLong(consts[i].value);
65 PyModule_AddObject(mod, (/*unconst*/ char *)consts[i].name, x);
66 }
67 }
68
69 #define GETU_(n) \
70 PyObject *getu##n(uint##n w) \
71 { \
72 if (w <= MASK##n) \
73 return (PyInt_FromLong(w)); \
74 else \
75 return (PyLong_FromUnsignedLong(w)); \
76 }
77 DOUINTSZ(GETU_)
78
79 PyObject *getbool(int b)
80 {
81 if (b) RETURN_TRUE;
82 else RETURN_FALSE;
83 }
84
85 PyObject *abstract_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
86 {
87 PyErr_SetString(PyExc_TypeError, "can't instantiate this class");
88 return (0);
89 }
90
91 int convulong(PyObject *o, void *pp)
92 {
93 long i;
94 unsigned long *p = pp;
95 PyObject *t;
96
97 if (PyInt_Check(o)) {
98 i = PyInt_AS_LONG(o);
99 if (i < 0) TYERR("must be nonnegative");
100 *p = i;
101 } else {
102 if ((t = PyNumber_Long(o)) == 0) goto end;
103 *p = PyLong_AsUnsignedLong(t);
104 Py_DECREF(t);
105 if (PyErr_Occurred()) goto end;
106 }
107 return (1);
108 end:
109 return (0);
110 }
111
112 #define CONVU_(n) \
113 int convu##n(PyObject *o, void *pp) \
114 { \
115 unsigned long u; \
116 uint##n *p = pp; \
117 \
118 if (!convulong(o, &u)) goto end; \
119 if (u > MASK##n) TYERR("out of range"); \
120 *p = u; \
121 return (1); \
122 end: \
123 return (0); \
124 }
125 DOUINTSZ(CONVU_)
126
127 int convuint(PyObject *o, void *pp)
128 {
129 unsigned long u;
130 unsigned *p = pp;
131
132 if (!convulong(o, &u)) goto end;
133 if (u > UINT_MAX) TYERR("out of range");
134 *p = u;
135 return (1);
136 end:
137 return (0);
138 }
139
140 int convmpw(PyObject *o, void *pp)
141 {
142 unsigned long u;
143 unsigned *p = pp;
144
145 if (!convulong(o, &u)) goto end;
146 if (u > MPW_MAX) TYERR("out of range");
147 *p = u;
148 return (1);
149 end:
150 return (0);
151 }
152
153 int convszt(PyObject *o, void *pp)
154 {
155 unsigned long u;
156 size_t *p = pp;
157
158 if (!convulong(o, &u)) goto end;
159 if (u > ~(size_t)0) TYERR("out of range");
160 *p = u;
161 return (1);
162 end:
163 return (0);
164 }
165
166 int convbool(PyObject *o, void *pp)
167 {
168 *(int *)pp = PyObject_IsTrue(o);
169 return (1);
170 }
171
172 PyObject *mexp_common(PyObject *me, PyObject *arg,
173 size_t efsz,
174 PyObject *(*id)(PyObject *),
175 int (*fill)(void *, PyObject *,
176 PyObject *, PyObject *),
177 PyObject *(*exp)(PyObject *, void *, int),
178 void (*drop)(void *))
179 {
180 int i = 0, j, n, flat;
181 PyObject *qq, *x, *y, *z = 0;
182 char *v = 0, *vv;
183
184 if (PyTuple_Size(arg) == 1)
185 arg = PyTuple_GetItem(arg, 0);
186 Py_INCREF(arg);
187 if (!PySequence_Check(arg)) TYERR("not a sequence");
188 n = PySequence_Size(arg); if (!n) { z = id(me); goto end; }
189 x = PySequence_GetItem(arg, 0);
190 if (PySequence_Check(x))
191 flat = 0;
192 else {
193 if (n % 2) VALERR("must have even number of arguments");
194 n /= 2;
195 flat = 1;
196 }
197 Py_DECREF(x);
198
199 v = xmalloc(n * efsz);
200 for (i = j = 0, vv = v; i < n; i++, vv += efsz) {
201 if (flat) {
202 x = PySequence_GetItem(arg, j++);
203 y = PySequence_GetItem(arg, j++);
204 } else {
205 qq = PySequence_GetItem(arg, j++);
206 if (!qq) goto end;
207 if (!PySequence_Check(qq) || PySequence_Size(qq) != 2) {
208 Py_DECREF(qq);
209 TYERR("want a sequence of pairs");
210 }
211 x = PySequence_GetItem(qq, 0);
212 y = PySequence_GetItem(qq, 1);
213 Py_DECREF(qq);
214 }
215 if (!x || !y) goto end;
216 if (fill(vv, me, x, y)) {
217 Py_DECREF(x);
218 Py_DECREF(y);
219 if (!PyErr_Occurred())
220 PyErr_SetString(PyExc_TypeError, "type mismatch");
221 goto end;
222 }
223 Py_DECREF(x);
224 Py_DECREF(y);
225 }
226 z = exp(me, v, n);
227
228 end:
229 if (v) {
230 for (j = 0, vv = v; j < i; j++, vv += efsz)
231 drop(vv);
232 xfree(v);
233 }
234 Py_DECREF(arg);
235 return (z);
236 }
237
238 PyObject * mkexc(PyObject *mod, PyObject *base,
239 const char *name, PyMethodDef *mm)
240 {
241 PyObject *nameobj = 0;
242 PyObject *dict = 0;
243 PyObject *exc = 0;
244 PyObject *func = 0;
245 PyObject *meth = 0;
246
247 if ((nameobj = PyString_FromFormat("%s.%s",
248 PyModule_GetName(mod),
249 name)) == 0 ||
250 (dict = PyDict_New()) == 0 ||
251 (exc = PyErr_NewException(PyString_AS_STRING(nameobj),
252 base, dict)) == 0)
253 goto fail;
254
255 if (mm) {
256 while (mm->ml_name) {
257 if ((func = PyCFunction_NewEx(mm, 0, mod)) == 0 ||
258 (meth = PyMethod_New(func, 0, exc)) == 0 ||
259 PyDict_SetItemString(dict, mm->ml_name, meth))
260 goto fail;
261 Py_DECREF(func); func = 0;
262 Py_DECREF(meth); meth = 0;
263 mm++;
264 }
265 }
266
267 done:
268 Py_XDECREF(nameobj);
269 Py_XDECREF(dict);
270 return (exc);
271
272 fail:
273 Py_XDECREF(exc);
274 Py_XDECREF(func);
275 Py_XDECREF(meth);
276 exc = 0;
277 goto done;
278 }
279
280 DA_DECL(method_v, PyMethodDef);
281 static method_v global_pymethods = DA_INIT;
282 void addmethods(const PyMethodDef *m)
283 {
284 size_t n;
285
286 for (n = 0; m[n].ml_name; n++);
287 DA_ENSURE(&global_pymethods, n);
288 memcpy(DA(&global_pymethods) + DA_LEN(&global_pymethods),
289 m, n * sizeof(*m));
290 DA_EXTEND(&global_pymethods, n);
291 }
292
293 static const PyTypeObject emptytype = { 0 };
294
295 void *newtype(PyTypeObject *metaty,
296 const PyTypeObject *skel,
297 const char *name)
298 {
299 PyHeapTypeObject *ty =
300 (PyHeapTypeObject *)_PyObject_GC_Malloc(_PyObject_VAR_SIZE(metaty, 0));
301 if (!skel) skel = &emptytype;
302 memcpy(ty, skel, sizeof(*skel));
303 if (ty->type.tp_base) Py_INCREF(ty->type.tp_base);
304 #define COPY(blah) do { \
305 if (ty->type.tp_as_##blah) { \
306 memcpy(&ty->as_##blah, \
307 ty->type.tp_as_##blah, \
308 sizeof(ty->as_##blah)); \
309 ty->type.tp_as_##blah = &ty->as_##blah; \
310 } \
311 } while (0)
312 COPY(number);
313 COPY(sequence);
314 COPY(mapping);
315 COPY(buffer);
316 #undef COPY
317 if (name)
318 ty->name = PyString_FromString(name);
319 else if (ty->type.tp_name)
320 ty->name = PyString_FromString(ty->type.tp_name);
321 if (ty->name)
322 ty->type.tp_name = PyString_AS_STRING(ty->name);
323 PyObject_INIT(&ty->type, metaty);
324 Py_INCREF(metaty);
325 return (ty);
326 }
327
328 static PyObject *smallprimes(void)
329 {
330 PyObject *v = PyList_New(NPRIME);
331 int i;
332
333 for (i = 0; i < NPRIME; i++)
334 PyList_SetItem(v, i, PyInt_FromLong(primetab[i]));
335 return (v);
336 }
337
338 PyTypeObject *inittype(PyTypeObject *tyskel)
339 {
340 PyTypeObject *ty = newtype(&PyType_Type, tyskel, 0);
341 ty->tp_flags |= Py_TPFLAGS_HEAPTYPE;
342 PyType_Ready(ty);
343 return (ty);
344 }
345
346 static PyObject *meth__ego(PyObject *me, PyObject *arg)
347 {
348 char *argv0;
349 if (!PyArg_ParseTuple(arg, "s:_ego", &argv0))
350 return (0);
351 if (strcmp(QUIS, "<UNNAMED>") == 0)
352 ego(argv0);
353 RETURN_NONE;
354 }
355
356 static PyMethodDef methods[] = {
357 #define METHNAME(func) meth_##func
358 METH (_ego, "_ego(ARGV0)")
359 #undef METHNAME
360 { 0 }
361 };
362
363 void init_base(void) {
364 static const PyMethodDef mzero = { 0 };
365 PyObject *mod;
366 addmethods(methods);
367 INIT_MODULES;
368 DA_PUSH(&global_pymethods, mzero);
369 mod = Py_InitModule("catacomb._base", DA(&global_pymethods));
370 INSERT_MODULES;
371 INSERT("smallprimes", smallprimes());
372 setconstants(mod);
373 }
374
375 /*----- That's all, folks -------------------------------------------------*/