b6a86d2e |
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), |
73a712fa |
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 |
b6a86d2e |
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 | |
73a712fa |
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_) |
b6a86d2e |
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 | |
73a712fa |
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_) |
b6a86d2e |
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 | |
73a712fa |
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 | |
b6a86d2e |
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 | |
f0526039 |
295 | void *newtype(PyTypeObject *metaty, |
296 | const PyTypeObject *skel, |
297 | const char *name) |
b6a86d2e |
298 | { |
f0526039 |
299 | PyHeapTypeObject *ty = |
300 | (PyHeapTypeObject *)_PyObject_GC_Malloc(_PyObject_VAR_SIZE(metaty, 0)); |
b6a86d2e |
301 | if (!skel) skel = &emptytype; |
302 | memcpy(ty, skel, sizeof(*skel)); |
f0526039 |
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); |
b6a86d2e |
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 | { |
f0526039 |
340 | PyTypeObject *ty = newtype(&PyType_Type, tyskel, 0); |
b6a86d2e |
341 | ty->tp_flags |= Py_TPFLAGS_HEAPTYPE; |
342 | PyType_Ready(ty); |
343 | return (ty); |
344 | } |
345 | |
73a712fa |
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 | |
b6a86d2e |
363 | void init_base(void) { |
364 | static const PyMethodDef mzero = { 0 }; |
365 | PyObject *mod; |
73a712fa |
366 | addmethods(methods); |
b6a86d2e |
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 -------------------------------------------------*/ |