Updated documentation for findCaller() to indicate that a 3-tuple is now returned...
[python.git] / Modules / _ctypes / stgdict.c
blob8fd9a1e576382bb0a0de401c160a48959d851023
1 /*****************************************************************
2 This file should be kept compatible with Python 2.3, see PEP 291.
3 *****************************************************************/
5 #include "Python.h"
6 #include <ffi.h>
7 #ifdef MS_WIN32
8 #include <windows.h>
9 #endif
10 #include "ctypes.h"
12 /******************************************************************/
14 StdDict - a dictionary subclass, containing additional C accessible fields
16 XXX blabla more
19 /* Seems we need this, otherwise we get problems when calling
20 * PyDict_SetItem() (ma_lookup is NULL)
22 static int
23 StgDict_init(StgDictObject *self, PyObject *args, PyObject *kwds)
25 if (PyDict_Type.tp_init((PyObject *)self, args, kwds) < 0)
26 return -1;
27 return 0;
30 static int
31 StgDict_clear(StgDictObject *self)
33 Py_CLEAR(self->proto);
34 Py_CLEAR(self->argtypes);
35 Py_CLEAR(self->converters);
36 Py_CLEAR(self->restype);
37 Py_CLEAR(self->checker);
38 return 0;
41 static void
42 StgDict_dealloc(StgDictObject *self)
44 StgDict_clear(self);
45 PyMem_Free(self->ffi_type_pointer.elements);
46 PyDict_Type.tp_dealloc((PyObject *)self);
49 int
50 StgDict_clone(StgDictObject *dst, StgDictObject *src)
52 char *d, *s;
53 int size;
55 StgDict_clear(dst);
56 PyMem_Free(dst->ffi_type_pointer.elements);
57 dst->ffi_type_pointer.elements = NULL;
59 d = (char *)dst;
60 s = (char *)src;
61 memcpy(d + sizeof(PyDictObject),
62 s + sizeof(PyDictObject),
63 sizeof(StgDictObject) - sizeof(PyDictObject));
65 Py_XINCREF(dst->proto);
66 Py_XINCREF(dst->argtypes);
67 Py_XINCREF(dst->converters);
68 Py_XINCREF(dst->restype);
69 Py_XINCREF(dst->checker);
71 if (src->ffi_type_pointer.elements == NULL)
72 return 0;
73 size = sizeof(ffi_type *) * (src->length + 1);
74 dst->ffi_type_pointer.elements = PyMem_Malloc(size);
75 if (dst->ffi_type_pointer.elements == NULL)
76 return -1;
77 memcpy(dst->ffi_type_pointer.elements,
78 src->ffi_type_pointer.elements,
79 size);
80 return 0;
83 PyTypeObject StgDict_Type = {
84 PyObject_HEAD_INIT(NULL)
86 "StgDict",
87 sizeof(StgDictObject),
89 (destructor)StgDict_dealloc, /* tp_dealloc */
90 0, /* tp_print */
91 0, /* tp_getattr */
92 0, /* tp_setattr */
93 0, /* tp_compare */
94 0, /* tp_repr */
95 0, /* tp_as_number */
96 0, /* tp_as_sequence */
97 0, /* tp_as_mapping */
98 0, /* tp_hash */
99 0, /* tp_call */
100 0, /* tp_str */
101 0, /* tp_getattro */
102 0, /* tp_setattro */
103 0, /* tp_as_buffer */
104 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
105 0, /* tp_doc */
106 0, /* tp_traverse */
107 0, /* tp_clear */
108 0, /* tp_richcompare */
109 0, /* tp_weaklistoffset */
110 0, /* tp_iter */
111 0, /* tp_iternext */
112 0, /* tp_methods */
113 0, /* tp_members */
114 0, /* tp_getset */
115 0, /* tp_base */
116 0, /* tp_dict */
117 0, /* tp_descr_get */
118 0, /* tp_descr_set */
119 0, /* tp_dictoffset */
120 (initproc)StgDict_init, /* tp_init */
121 0, /* tp_alloc */
122 0, /* tp_new */
123 0, /* tp_free */
126 /* May return NULL, but does not set an exception! */
127 StgDictObject *
128 PyType_stgdict(PyObject *obj)
130 PyTypeObject *type;
132 if (!PyType_Check(obj))
133 return NULL;
134 type = (PyTypeObject *)obj;
135 if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS))
136 return NULL;
137 if (!type->tp_dict || !StgDict_CheckExact(type->tp_dict))
138 return NULL;
139 return (StgDictObject *)type->tp_dict;
142 /* May return NULL, but does not set an exception! */
144 This function should be as fast as possible, so we don't call PyType_stgdict
145 above but inline the code, and avoid the PyType_Check().
147 StgDictObject *
148 PyObject_stgdict(PyObject *self)
150 PyTypeObject *type = self->ob_type;
151 if (!PyType_HasFeature(type, Py_TPFLAGS_HAVE_CLASS))
152 return NULL;
153 if (!type->tp_dict || !StgDict_CheckExact(type->tp_dict))
154 return NULL;
155 return (StgDictObject *)type->tp_dict;
158 /* descr is the descriptor for a field marked as anonymous. Get all the
159 _fields_ descriptors from descr->proto, create new descriptors with offset
160 and index adjusted, and stuff them into type.
162 static int
163 MakeFields(PyObject *type, CFieldObject *descr,
164 Py_ssize_t index, Py_ssize_t offset)
166 Py_ssize_t i;
167 PyObject *fields;
168 PyObject *fieldlist;
170 fields = PyObject_GetAttrString(descr->proto, "_fields_");
171 if (fields == NULL)
172 return -1;
173 fieldlist = PySequence_Fast(fields, "_fields_ must be a sequence");
174 Py_DECREF(fields);
175 if (fieldlist == NULL)
176 return -1;
178 for (i = 0; i < PySequence_Fast_GET_SIZE(fieldlist); ++i) {
179 PyObject *pair = PySequence_Fast_GET_ITEM(fieldlist, i); /* borrowed */
180 PyObject *fname, *ftype, *bits;
181 CFieldObject *fdescr;
182 CFieldObject *new_descr;
183 /* Convert to PyArg_UnpackTuple... */
184 if (!PyArg_ParseTuple(pair, "OO|O", &fname, &ftype, &bits)) {
185 Py_DECREF(fieldlist);
186 return -1;
188 fdescr = (CFieldObject *)PyObject_GetAttr(descr->proto, fname);
189 if (fdescr == NULL) {
190 Py_DECREF(fieldlist);
191 return -1;
193 if (fdescr->ob_type != &CField_Type) {
194 PyErr_SetString(PyExc_TypeError, "unexpected type");
195 Py_DECREF(fdescr);
196 Py_DECREF(fieldlist);
197 return -1;
199 if (fdescr->anonymous) {
200 int rc = MakeFields(type, fdescr,
201 index + fdescr->index,
202 offset + fdescr->offset);
203 Py_DECREF(fdescr);
204 if (rc == -1) {
205 Py_DECREF(fieldlist);
206 return -1;
208 continue;
210 new_descr = (CFieldObject *)PyObject_CallObject((PyObject *)&CField_Type, NULL);
211 if (new_descr == NULL) {
212 Py_DECREF(fdescr);
213 Py_DECREF(fieldlist);
214 return -1;
216 assert(new_descr->ob_type == &CField_Type);
217 new_descr->size = fdescr->size;
218 new_descr->offset = fdescr->offset + offset;
219 new_descr->index = fdescr->index + index;
220 new_descr->proto = fdescr->proto;
221 Py_XINCREF(new_descr->proto);
222 new_descr->getfunc = fdescr->getfunc;
223 new_descr->setfunc = fdescr->setfunc;
225 Py_DECREF(fdescr);
227 if (-1 == PyObject_SetAttr(type, fname, (PyObject *)new_descr)) {
228 Py_DECREF(fieldlist);
229 Py_DECREF(new_descr);
230 return -1;
232 Py_DECREF(new_descr);
234 Py_DECREF(fieldlist);
235 return 0;
238 /* Iterate over the names in the type's _anonymous_ attribute, if present,
240 static int
241 MakeAnonFields(PyObject *type)
243 PyObject *anon;
244 PyObject *anon_names;
245 Py_ssize_t i;
247 anon = PyObject_GetAttrString(type, "_anonymous_");
248 if (anon == NULL) {
249 PyErr_Clear();
250 return 0;
252 anon_names = PySequence_Fast(anon, "_anonymous_ must be a sequence");
253 Py_DECREF(anon);
254 if (anon_names == NULL)
255 return -1;
257 for (i = 0; i < PySequence_Fast_GET_SIZE(anon_names); ++i) {
258 PyObject *fname = PySequence_Fast_GET_ITEM(anon_names, i); /* borrowed */
259 CFieldObject *descr = (CFieldObject *)PyObject_GetAttr(type, fname);
260 if (descr == NULL) {
261 Py_DECREF(anon_names);
262 return -1;
264 assert(descr->ob_type == &CField_Type);
265 descr->anonymous = 1;
267 /* descr is in the field descriptor. */
268 if (-1 == MakeFields(type, (CFieldObject *)descr,
269 ((CFieldObject *)descr)->index,
270 ((CFieldObject *)descr)->offset)) {
271 Py_DECREF(descr);
272 Py_DECREF(anon_names);
273 return -1;
275 Py_DECREF(descr);
278 Py_DECREF(anon_names);
279 return 0;
283 Retrive the (optional) _pack_ attribute from a type, the _fields_ attribute,
284 and create an StgDictObject. Used for Structure and Union subclasses.
287 StructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
289 StgDictObject *stgdict, *basedict;
290 int len, offset, size, align, i;
291 int union_size, total_align;
292 int field_size = 0;
293 int bitofs;
294 PyObject *isPacked;
295 int pack = 0;
296 int ffi_ofs;
297 int big_endian;
299 /* HACK Alert: I cannot be bothered to fix ctypes.com, so there has to
300 be a way to use the old, broken sematics: _fields_ are not extended
301 but replaced in subclasses.
303 XXX Remove this in ctypes 1.0!
305 int use_broken_old_ctypes_semantics;
307 if (fields == NULL)
308 return 0;
310 #ifdef WORDS_BIGENDIAN
311 big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 0 : 1;
312 #else
313 big_endian = PyObject_HasAttrString(type, "_swappedbytes_") ? 1 : 0;
314 #endif
316 use_broken_old_ctypes_semantics = \
317 PyObject_HasAttrString(type, "_use_broken_old_ctypes_structure_semantics_");
319 isPacked = PyObject_GetAttrString(type, "_pack_");
320 if (isPacked) {
321 pack = PyInt_AsLong(isPacked);
322 if (pack < 0 || PyErr_Occurred()) {
323 Py_XDECREF(isPacked);
324 PyErr_SetString(PyExc_ValueError,
325 "_pack_ must be a non-negative integer");
326 return -1;
328 Py_DECREF(isPacked);
329 } else
330 PyErr_Clear();
332 len = PySequence_Length(fields);
333 if (len == -1) {
334 PyErr_SetString(PyExc_TypeError,
335 "'_fields_' must be a sequence of pairs");
336 return -1;
339 stgdict = PyType_stgdict(type);
340 if (!stgdict)
341 return -1;
342 /* If this structure/union is already marked final we cannot assign
343 _fields_ anymore. */
345 if (stgdict->flags & DICTFLAG_FINAL) {/* is final ? */
346 PyErr_SetString(PyExc_AttributeError,
347 "_fields_ is final");
348 return -1;
351 if (stgdict->ffi_type_pointer.elements)
352 PyMem_Free(stgdict->ffi_type_pointer.elements);
354 basedict = PyType_stgdict((PyObject *)((PyTypeObject *)type)->tp_base);
355 if (basedict && !use_broken_old_ctypes_semantics) {
356 size = offset = basedict->size;
357 align = basedict->align;
358 union_size = 0;
359 total_align = align ? align : 1;
360 stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
361 stgdict->ffi_type_pointer.elements = PyMem_Malloc(sizeof(ffi_type *) * (basedict->length + len + 1));
362 memset(stgdict->ffi_type_pointer.elements, 0,
363 sizeof(ffi_type *) * (basedict->length + len + 1));
364 memcpy(stgdict->ffi_type_pointer.elements,
365 basedict->ffi_type_pointer.elements,
366 sizeof(ffi_type *) * (basedict->length));
367 ffi_ofs = basedict->length;
368 } else {
369 offset = 0;
370 size = 0;
371 align = 0;
372 union_size = 0;
373 total_align = 1;
374 stgdict->ffi_type_pointer.type = FFI_TYPE_STRUCT;
375 stgdict->ffi_type_pointer.elements = PyMem_Malloc(sizeof(ffi_type *) * (len + 1));
376 memset(stgdict->ffi_type_pointer.elements, 0,
377 sizeof(ffi_type *) * (len + 1));
378 ffi_ofs = 0;
381 #define realdict ((PyObject *)&stgdict->dict)
382 for (i = 0; i < len; ++i) {
383 PyObject *name = NULL, *desc = NULL;
384 PyObject *pair = PySequence_GetItem(fields, i);
385 PyObject *prop;
386 StgDictObject *dict;
387 int bitsize = 0;
389 if (!pair || !PyArg_ParseTuple(pair, "OO|i", &name, &desc, &bitsize)) {
390 PyErr_SetString(PyExc_AttributeError,
391 "'_fields_' must be a sequence of pairs");
392 Py_XDECREF(pair);
393 return -1;
395 dict = PyType_stgdict(desc);
396 if (dict == NULL) {
397 Py_DECREF(pair);
398 PyErr_Format(PyExc_TypeError,
399 "second item in _fields_ tuple (index %d) must be a C type",
401 return -1;
403 stgdict->ffi_type_pointer.elements[ffi_ofs + i] = &dict->ffi_type_pointer;
404 dict->flags |= DICTFLAG_FINAL; /* mark field type final */
405 if (PyTuple_Size(pair) == 3) { /* bits specified */
406 switch(dict->ffi_type_pointer.type) {
407 case FFI_TYPE_UINT8:
408 case FFI_TYPE_UINT16:
409 case FFI_TYPE_UINT32:
410 case FFI_TYPE_SINT64:
411 case FFI_TYPE_UINT64:
412 break;
414 case FFI_TYPE_SINT8:
415 case FFI_TYPE_SINT16:
416 case FFI_TYPE_SINT32:
417 if (dict->getfunc != getentry("c")->getfunc
418 #ifdef CTYPES_UNICODE
419 && dict->getfunc != getentry("u")->getfunc
420 #endif
422 break;
423 /* else fall through */
424 default:
425 PyErr_Format(PyExc_TypeError,
426 "bit fields not allowed for type %s",
427 ((PyTypeObject *)desc)->tp_name);
428 Py_DECREF(pair);
429 return -1;
431 if (bitsize <= 0 || bitsize > dict->size * 8) {
432 PyErr_SetString(PyExc_ValueError,
433 "number of bits invalid for bit field");
434 Py_DECREF(pair);
435 return -1;
437 } else
438 bitsize = 0;
439 if (isStruct) {
440 prop = CField_FromDesc(desc, i,
441 &field_size, bitsize, &bitofs,
442 &size, &offset, &align,
443 pack, big_endian);
444 } else /* union */ {
445 size = 0;
446 offset = 0;
447 align = 0;
448 prop = CField_FromDesc(desc, i,
449 &field_size, bitsize, &bitofs,
450 &size, &offset, &align,
451 pack, big_endian);
452 union_size = max(size, union_size);
454 total_align = max(align, total_align);
456 if (!prop) {
457 Py_DECREF(pair);
458 Py_DECREF((PyObject *)stgdict);
459 return -1;
461 if (-1 == PyDict_SetItem(realdict, name, prop)) {
462 Py_DECREF(prop);
463 Py_DECREF(pair);
464 Py_DECREF((PyObject *)stgdict);
465 return -1;
467 Py_DECREF(pair);
468 Py_DECREF(prop);
470 #undef realdict
471 if (!isStruct)
472 size = union_size;
474 /* Adjust the size according to the alignment requirements */
475 size = ((size + total_align - 1) / total_align) * total_align;
477 stgdict->ffi_type_pointer.alignment = total_align;
478 stgdict->ffi_type_pointer.size = size;
480 stgdict->size = size;
481 stgdict->align = total_align;
482 stgdict->length = len; /* ADD ffi_ofs? */
484 /* We did check that this flag was NOT set above, it must not
485 have been set until now. */
486 if (stgdict->flags & DICTFLAG_FINAL) {
487 PyErr_SetString(PyExc_AttributeError,
488 "Structure or union cannot contain itself");
489 return -1;
491 stgdict->flags |= DICTFLAG_FINAL;
493 return MakeAnonFields(type);