• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 typedef struct {
3     struct _cffi_type_context_s ctx;   /* inlined substructure */
4     PyObject *types_dict;
5     PyObject *included_ffis;
6     PyObject *included_libs;
7     PyObject *_keepalive1;
8     PyObject *_keepalive2;
9 } builder_c_t;
10 
11 
12 static PyObject *all_primitives[_CFFI__NUM_PRIM];
13 static CTypeDescrObject *g_ct_voidp, *g_ct_chararray;
14 
15 static PyObject *build_primitive_type(int num);   /* forward */
16 
17 #define primitive_in_range(num)   ((num) >= 0 && (num) < _CFFI__NUM_PRIM)
18 #define get_primitive_type(num)                                 \
19     ((primitive_in_range(num) && all_primitives[num] != NULL) ? \
20         all_primitives[num] : build_primitive_type(num))
21 
init_global_types_dict(PyObject * ffi_type_dict)22 static int init_global_types_dict(PyObject *ffi_type_dict)
23 {
24     int err;
25     PyObject *ct_void, *ct_char, *ct2, *pnull;
26     /* XXX some leaks in case these functions fail, but well,
27        MemoryErrors during importing an extension module are kind
28        of bad anyway */
29 
30     ct_void = get_primitive_type(_CFFI_PRIM_VOID);         // 'void'
31     if (ct_void == NULL)
32         return -1;
33 
34     ct2 = new_pointer_type((CTypeDescrObject *)ct_void);   // 'void *'
35     if (ct2 == NULL)
36         return -1;
37     g_ct_voidp = (CTypeDescrObject *)ct2;
38 
39     ct_char = get_primitive_type(_CFFI_PRIM_CHAR);         // 'char'
40     if (ct_char == NULL)
41         return -1;
42 
43     ct2 = new_pointer_type((CTypeDescrObject *)ct_char);   // 'char *'
44     if (ct2 == NULL)
45         return -1;
46 
47     ct2 = new_array_type((CTypeDescrObject *)ct2, -1);     // 'char[]'
48     if (ct2 == NULL)
49         return -1;
50     g_ct_chararray = (CTypeDescrObject *)ct2;
51 
52     pnull = new_simple_cdata(NULL, g_ct_voidp);
53     if (pnull == NULL)
54         return -1;
55     err = PyDict_SetItemString(ffi_type_dict, "NULL", pnull);
56     Py_DECREF(pnull);
57     return err;
58 }
59 
free_builder_c(builder_c_t * builder,int ctx_is_static)60 static void free_builder_c(builder_c_t *builder, int ctx_is_static)
61 {
62     if (!ctx_is_static) {
63         size_t i;
64         const void *mem[] = {builder->ctx.types,
65                              builder->ctx.globals,
66                              builder->ctx.struct_unions,
67                              //builder->ctx.fields: allocated with struct_unions
68                              builder->ctx.enums,
69                              builder->ctx.typenames};
70         for (i = 0; i < sizeof(mem) / sizeof(*mem); i++) {
71             if (mem[i] != NULL)
72                 PyMem_Free((void *)mem[i]);
73         }
74     }
75     Py_XDECREF(builder->included_ffis);
76     Py_XDECREF(builder->included_libs);
77     Py_XDECREF(builder->types_dict);
78     Py_XDECREF(builder->_keepalive1);
79     Py_XDECREF(builder->_keepalive2);
80 }
81 
init_builder_c(builder_c_t * builder,const struct _cffi_type_context_s * ctx)82 static int init_builder_c(builder_c_t *builder,
83                           const struct _cffi_type_context_s *ctx)
84 {
85     PyObject *ldict = PyDict_New();
86     if (ldict == NULL)
87         return -1;
88 
89     if (ctx)
90         builder->ctx = *ctx;
91     else
92         memset(&builder->ctx, 0, sizeof(builder->ctx));
93 
94     builder->types_dict = ldict;
95     builder->included_ffis = NULL;
96     builder->included_libs = NULL;
97     builder->_keepalive1 = NULL;
98     builder->_keepalive2 = NULL;
99     return 0;
100 }
101 
build_primitive_type(int num)102 static PyObject *build_primitive_type(int num)
103 {
104     /* XXX too many translations between here and new_primitive_type() */
105     static const char *primitive_name[] = {
106         NULL,
107         "_Bool",
108         "char",
109         "signed char",
110         "unsigned char",
111         "short",
112         "unsigned short",
113         "int",
114         "unsigned int",
115         "long",
116         "unsigned long",
117         "long long",
118         "unsigned long long",
119         "float",
120         "double",
121         "long double",
122         "wchar_t",
123         "int8_t",
124         "uint8_t",
125         "int16_t",
126         "uint16_t",
127         "int32_t",
128         "uint32_t",
129         "int64_t",
130         "uint64_t",
131         "intptr_t",
132         "uintptr_t",
133         "ptrdiff_t",
134         "size_t",
135         "ssize_t",
136         "int_least8_t",
137         "uint_least8_t",
138         "int_least16_t",
139         "uint_least16_t",
140         "int_least32_t",
141         "uint_least32_t",
142         "int_least64_t",
143         "uint_least64_t",
144         "int_fast8_t",
145         "uint_fast8_t",
146         "int_fast16_t",
147         "uint_fast16_t",
148         "int_fast32_t",
149         "uint_fast32_t",
150         "int_fast64_t",
151         "uint_fast64_t",
152         "intmax_t",
153         "uintmax_t",
154         "float _Complex",
155         "double _Complex",
156         "char16_t",
157         "char32_t",
158     };
159     PyObject *x;
160 
161     assert(sizeof(primitive_name) == sizeof(*primitive_name) * _CFFI__NUM_PRIM);
162     if (num == _CFFI_PRIM_VOID) {
163         x = new_void_type();
164     }
165     else if (primitive_in_range(num) && primitive_name[num] != NULL) {
166         x = new_primitive_type(primitive_name[num]);
167     }
168     else if (num == _CFFI__UNKNOWN_PRIM) {
169         PyErr_SetString(FFIError, "primitive integer type with an unexpected "
170                         "size (or not an integer type at all)");
171         return NULL;
172     }
173     else if (num == _CFFI__UNKNOWN_FLOAT_PRIM) {
174         PyErr_SetString(FFIError, "primitive floating-point type with an "
175                         "unexpected size (or not a float type at all)");
176         return NULL;
177     }
178     else if (num == _CFFI__UNKNOWN_LONG_DOUBLE) {
179         PyErr_SetString(FFIError, "primitive floating-point type is "
180                         "'long double', not supported for now with "
181                         "the syntax 'typedef double... xxx;'");
182         return NULL;
183     }
184     else {
185         PyErr_Format(PyExc_NotImplementedError, "prim=%d", num);
186         return NULL;
187     }
188 
189     all_primitives[num] = x;
190     return x;
191 }
192 
realize_global_int(builder_c_t * builder,int gindex)193 static PyObject *realize_global_int(builder_c_t *builder, int gindex)
194 {
195     int neg;
196     char got[64];
197     unsigned long long value;
198     struct _cffi_getconst_s gc;
199     const struct _cffi_global_s *g = &builder->ctx.globals[gindex];
200     gc.ctx = &builder->ctx;
201     gc.gindex = gindex;
202     /* note: we cast g->address to this function type; we do the same
203        in parse_c_type:parse_sequel() too.  Note that the called function
204        may be declared simply with "unsigned long long *" as argument,
205        which is fine as it is the first field in _cffi_getconst_s. */
206     assert(&gc.value == (unsigned long long *)&gc);
207     neg = ((int(*)(struct _cffi_getconst_s *))g->address)(&gc);
208     value = gc.value;
209 
210     switch (neg) {
211 
212     case 0:
213         if (value <= (unsigned long long)LONG_MAX)
214             return PyInt_FromLong((long)value);
215         else
216             return PyLong_FromUnsignedLongLong(value);
217 
218     case 1:
219         if ((long long)value >= (long long)LONG_MIN)
220             return PyInt_FromLong((long)value);
221         else
222             return PyLong_FromLongLong((long long)value);
223 
224     default:
225         break;
226     }
227     if (neg == 2)
228         sprintf(got, "%llu (0x%llx)", value, value);
229     else
230         sprintf(got, "%lld", (long long)value);
231     PyErr_Format(FFIError, "the C compiler says '%.200s' is equal to %s, "
232                            "but the cdef disagrees", g->name, got);
233     return NULL;
234 }
235 
236 static CTypeDescrObject *
unwrap_fn_as_fnptr(PyObject * x)237 unwrap_fn_as_fnptr(PyObject *x)
238 {
239     assert(PyTuple_Check(x));
240     return (CTypeDescrObject *)PyTuple_GET_ITEM(x, 0);
241 }
242 
243 static CTypeDescrObject *
unexpected_fn_type(PyObject * x)244 unexpected_fn_type(PyObject *x)
245 {
246     CTypeDescrObject *ct = unwrap_fn_as_fnptr(x);
247     char *text1 = ct->ct_name;
248     char *text2 = text1 + ct->ct_name_position + 1;
249     assert(text2[-3] == '(');
250     text2[-3] = '\0';
251     PyErr_Format(FFIError, "the type '%s%s' is a function type, not a "
252                            "pointer-to-function type", text1, text2);
253     text2[-3] = '(';
254     return NULL;
255 }
256 
257 static PyObject *
258 realize_c_type_or_func(builder_c_t *builder,
259                        _cffi_opcode_t opcodes[], int index);  /* forward */
260 
261 
262 /* Interpret an opcodes[] array.  If opcodes == ctx->types, store all
263    the intermediate types back in the opcodes[].  Returns a new
264    reference.
265 */
266 static CTypeDescrObject *
realize_c_type(builder_c_t * builder,_cffi_opcode_t opcodes[],int index)267 realize_c_type(builder_c_t *builder, _cffi_opcode_t opcodes[], int index)
268 {
269     PyObject *x = realize_c_type_or_func(builder, opcodes, index);
270     if (x == NULL || CTypeDescr_Check(x))
271         return (CTypeDescrObject *)x;
272     else {
273         unexpected_fn_type(x);
274         Py_DECREF(x);
275         return NULL;
276     }
277 }
278 
_realize_name(char * target,const char * prefix,const char * srcname)279 static void _realize_name(char *target, const char *prefix, const char *srcname)
280 {
281     /* "xyz" => "struct xyz"
282        "$xyz" => "xyz"
283        "$1" => "struct $1"
284     */
285     if (srcname[0] == '$' && srcname[1] != '$' &&
286             !('0' <= srcname[1] && srcname[1] <= '9')) {
287         strcpy(target, &srcname[1]);
288     }
289     else {
290         strcpy(target, prefix);
291         strcat(target, srcname);
292     }
293 }
294 
_unrealize_name(char * target,const char * srcname)295 static void _unrealize_name(char *target, const char *srcname)
296 {
297     /* reverse of _realize_name() */
298     if (strncmp(srcname, "struct ", 7) == 0) {
299         strcpy(target, &srcname[7]);
300     }
301     else if (strncmp(srcname, "union ", 6) == 0) {
302         strcpy(target, &srcname[6]);
303     }
304     else if (strncmp(srcname, "enum ", 5) == 0) {
305         strcpy(target, &srcname[5]);
306     }
307     else {
308         strcpy(target, "$");
309         strcat(target, srcname);
310     }
311 }
312 
313 static PyObject *                                              /* forward */
314 _fetch_external_struct_or_union(const struct _cffi_struct_union_s *s,
315                                 PyObject *included_ffis, int recursion);
316 
317 static PyObject *
_realize_c_struct_or_union(builder_c_t * builder,int sindex)318 _realize_c_struct_or_union(builder_c_t *builder, int sindex)
319 {
320     PyObject *x;
321     _cffi_opcode_t op2;
322     const struct _cffi_struct_union_s *s;
323 
324     if (sindex == _CFFI__IO_FILE_STRUCT) {
325         /* returns a single global cached opaque type */
326         static PyObject *file_struct = NULL;
327         if (file_struct == NULL)
328             file_struct = new_struct_or_union_type("FILE",
329                                                    CT_STRUCT | CT_IS_FILE);
330         Py_XINCREF(file_struct);
331         return file_struct;
332     }
333 
334     s = &builder->ctx.struct_unions[sindex];
335     op2 = builder->ctx.types[s->type_index];
336     if ((((uintptr_t)op2) & 1) == 0) {
337         x = (PyObject *)op2;     /* found already in the "primary" slot */
338         Py_INCREF(x);
339     }
340     else {
341         CTypeDescrObject *ct = NULL;
342 
343         if (!(s->flags & _CFFI_F_EXTERNAL)) {
344             int flags = (s->flags & _CFFI_F_UNION) ? CT_UNION : CT_STRUCT;
345             char *name = alloca(8 + strlen(s->name));
346             _realize_name(name,
347                           (s->flags & _CFFI_F_UNION) ? "union " : "struct ",
348                           s->name);
349             if (strcmp(name, "struct _IO_FILE") == 0)
350                 x = _realize_c_struct_or_union(builder, _CFFI__IO_FILE_STRUCT);
351             else
352                 x = new_struct_or_union_type(name, flags);
353             if (x == NULL)
354                 return NULL;
355 
356             if (!(s->flags & _CFFI_F_OPAQUE)) {
357                 assert(s->first_field_index >= 0);
358                 ct = (CTypeDescrObject *)x;
359                 ct->ct_size = (Py_ssize_t)s->size;
360                 ct->ct_length = s->alignment;   /* may be -1 */
361                 ct->ct_flags &= ~CT_IS_OPAQUE;
362                 ct->ct_flags |= CT_LAZY_FIELD_LIST;
363                 ct->ct_extra = builder;
364             }
365             else
366                 assert(s->first_field_index < 0);
367         }
368         else {
369             assert(s->first_field_index < 0);
370             x = _fetch_external_struct_or_union(s, builder->included_ffis, 0);
371             if (x == NULL) {
372                 if (!PyErr_Occurred())
373                     PyErr_Format(FFIError, "'%s %.200s' should come from "
374                                  "ffi.include() but was not found",
375                                  (s->flags & _CFFI_F_UNION) ? "union"
376                                  : "struct", s->name);
377                 return NULL;
378             }
379             if (!(s->flags & _CFFI_F_OPAQUE)) {
380                 if (((CTypeDescrObject *)x)->ct_flags & CT_IS_OPAQUE) {
381                     const char *prefix = (s->flags & _CFFI_F_UNION) ? "union"
382                                          : "struct";
383                     PyErr_Format(PyExc_NotImplementedError,
384                                  "'%s %.200s' is opaque in the ffi.include(), "
385                                  "but no longer in the ffi doing the include "
386                                  "(workaround: don't use ffi.include() but "
387                                  "duplicate the declarations of everything "
388                                  "using %s %.200s)",
389                                  prefix, s->name, prefix, s->name);
390                     Py_DECREF(x);
391                     return NULL;
392                 }
393             }
394         }
395 
396         /* Update the "primary" OP_STRUCT_UNION slot */
397         assert((((uintptr_t)x) & 1) == 0);
398         assert(builder->ctx.types[s->type_index] == op2);
399         Py_INCREF(x);
400         builder->ctx.types[s->type_index] = x;
401 
402         if (ct != NULL && s->size == (size_t)-2) {
403             /* oops, this struct is unnamed and we couldn't generate
404                a C expression to get its size.  We have to rely on
405                complete_struct_or_union() to compute it now. */
406             if (do_realize_lazy_struct(ct) < 0) {
407                 builder->ctx.types[s->type_index] = op2;
408                 return NULL;
409             }
410         }
411     }
412     return x;
413 }
414 
415 static PyObject *
realize_c_type_or_func(builder_c_t * builder,_cffi_opcode_t opcodes[],int index)416 realize_c_type_or_func(builder_c_t *builder,
417                         _cffi_opcode_t opcodes[], int index)
418 {
419     PyObject *x, *y, *z;
420     _cffi_opcode_t op = opcodes[index];
421     Py_ssize_t length = -1;
422 
423     if ((((uintptr_t)op) & 1) == 0) {
424         x = (PyObject *)op;
425         Py_INCREF(x);
426         return x;
427     }
428 
429     switch (_CFFI_GETOP(op)) {
430 
431     case _CFFI_OP_PRIMITIVE:
432         x = get_primitive_type(_CFFI_GETARG(op));
433         Py_XINCREF(x);
434         break;
435 
436     case _CFFI_OP_POINTER:
437         y = realize_c_type_or_func(builder, opcodes, _CFFI_GETARG(op));
438         if (y == NULL)
439             return NULL;
440         if (CTypeDescr_Check(y)) {
441             x = new_pointer_type((CTypeDescrObject *)y);
442         }
443         else {
444             assert(PyTuple_Check(y));   /* from _CFFI_OP_FUNCTION */
445             x = PyTuple_GET_ITEM(y, 0);
446             Py_INCREF(x);
447         }
448         Py_DECREF(y);
449         break;
450 
451     case _CFFI_OP_ARRAY:
452         length = (Py_ssize_t)opcodes[index + 1];
453         /* fall-through */
454     case _CFFI_OP_OPEN_ARRAY:
455         y = (PyObject *)realize_c_type(builder, opcodes, _CFFI_GETARG(op));
456         if (y == NULL)
457             return NULL;
458         z = new_pointer_type((CTypeDescrObject *)y);
459         Py_DECREF(y);
460         if (z == NULL)
461             return NULL;
462         x = new_array_type((CTypeDescrObject *)z, length);
463         Py_DECREF(z);
464         break;
465 
466     case _CFFI_OP_STRUCT_UNION:
467         x = _realize_c_struct_or_union(builder, _CFFI_GETARG(op));
468         break;
469 
470     case _CFFI_OP_ENUM:
471     {
472         const struct _cffi_enum_s *e;
473         _cffi_opcode_t op2;
474 
475         e = &builder->ctx.enums[_CFFI_GETARG(op)];
476         op2 = builder->ctx.types[e->type_index];
477         if ((((uintptr_t)op2) & 1) == 0) {
478             x = (PyObject *)op2;
479             Py_INCREF(x);
480         }
481         else {
482             PyObject *enumerators = NULL, *enumvalues = NULL, *tmp;
483             Py_ssize_t i, j, n = 0;
484             const char *p;
485             int gindex;
486             PyObject *args;
487             PyObject *basetd = get_primitive_type(e->type_prim);
488             if (basetd == NULL)
489                 return NULL;
490 
491             if (*e->enumerators != '\0') {
492                 n++;
493                 for (p = e->enumerators; *p != '\0'; p++)
494                     n += (*p == ',');
495             }
496             enumerators = PyTuple_New(n);
497             if (enumerators == NULL)
498                 return NULL;
499 
500             enumvalues = PyTuple_New(n);
501             if (enumvalues == NULL) {
502                 Py_DECREF(enumerators);
503                 return NULL;
504             }
505 
506             p = e->enumerators;
507             for (i = 0; i < n; i++) {
508                 j = 0;
509                 while (p[j] != ',' && p[j] != '\0')
510                     j++;
511                 tmp = PyText_FromStringAndSize(p, j);
512                 if (tmp == NULL)
513                     break;
514                 PyTuple_SET_ITEM(enumerators, i, tmp);
515 
516                 gindex = search_in_globals(&builder->ctx, p, j);
517                 assert(gindex >= 0);
518                 assert(builder->ctx.globals[gindex].type_op ==
519                        _CFFI_OP(_CFFI_OP_ENUM, -1));
520 
521                 tmp = realize_global_int(builder, gindex);
522                 if (tmp == NULL)
523                     break;
524                 PyTuple_SET_ITEM(enumvalues, i, tmp);
525 
526                 p += j + 1;
527             }
528 
529             args = NULL;
530             if (!PyErr_Occurred()) {
531                 char *name = alloca(6 + strlen(e->name));
532                 _realize_name(name, "enum ", e->name);
533                 args = Py_BuildValue("(sOOO)", name, enumerators,
534                                      enumvalues, basetd);
535             }
536             Py_DECREF(enumerators);
537             Py_DECREF(enumvalues);
538             if (args == NULL)
539                 return NULL;
540 
541             x = b_new_enum_type(NULL, args);
542             Py_DECREF(args);
543             if (x == NULL)
544                 return NULL;
545 
546             /* Update the "primary" _CFFI_OP_ENUM slot, which
547                may be the same or a different slot than the "current" one */
548             assert((((uintptr_t)x) & 1) == 0);
549             assert(builder->ctx.types[e->type_index] == op2);
550             Py_INCREF(x);
551             builder->ctx.types[e->type_index] = x;
552 
553             /* Done, leave without updating the "current" slot because
554                it may be done already above.  If not, never mind, the
555                next call to realize_c_type() will do it. */
556             return x;
557         }
558         break;
559     }
560 
561     case _CFFI_OP_FUNCTION:
562     {
563         PyObject *fargs;
564         int i, base_index, num_args, ellipsis, abi;
565 
566         y = (PyObject *)realize_c_type(builder, opcodes, _CFFI_GETARG(op));
567         if (y == NULL)
568             return NULL;
569 
570         base_index = index + 1;
571         num_args = 0;
572         /* note that if the arguments are already built, they have a
573            pointer in the 'opcodes' array, and GETOP() returns a
574            random even value.  But OP_FUNCTION_END is odd, so the
575            condition below still works correctly. */
576         while (_CFFI_GETOP(opcodes[base_index + num_args]) !=
577                    _CFFI_OP_FUNCTION_END)
578             num_args++;
579 
580         ellipsis = _CFFI_GETARG(opcodes[base_index + num_args]) & 0x01;
581         abi      = _CFFI_GETARG(opcodes[base_index + num_args]) & 0xFE;
582         switch (abi) {
583         case 0:
584             abi = FFI_DEFAULT_ABI;
585             break;
586         case 2:
587 #if defined(MS_WIN32) && !defined(_WIN64)
588             abi = FFI_STDCALL;
589 #else
590             abi = FFI_DEFAULT_ABI;
591 #endif
592             break;
593         default:
594             PyErr_Format(FFIError, "abi number %d not supported", abi);
595             Py_DECREF(y);
596             return NULL;
597         }
598 
599         fargs = PyTuple_New(num_args);
600         if (fargs == NULL) {
601             Py_DECREF(y);
602             return NULL;
603         }
604 
605         for (i = 0; i < num_args; i++) {
606             z = (PyObject *)realize_c_type(builder, opcodes, base_index + i);
607             if (z == NULL) {
608                 Py_DECREF(fargs);
609                 Py_DECREF(y);
610                 return NULL;
611             }
612             PyTuple_SET_ITEM(fargs, i, z);
613         }
614 
615         z = new_function_type(fargs, (CTypeDescrObject *)y, ellipsis, abi);
616         Py_DECREF(fargs);
617         Py_DECREF(y);
618         if (z == NULL)
619             return NULL;
620 
621         x = PyTuple_Pack(1, z);   /* hack: hide the CT_FUNCTIONPTR.  it will
622                                      be revealed again by the OP_POINTER */
623         Py_DECREF(z);
624         break;
625     }
626 
627     case _CFFI_OP_NOOP:
628         x = realize_c_type_or_func(builder, opcodes, _CFFI_GETARG(op));
629         break;
630 
631     case _CFFI_OP_TYPENAME:
632     {
633         /* essential: the TYPENAME opcode resolves the type index looked
634            up in the 'ctx->typenames' array, but it does so in 'ctx->types'
635            instead of in 'opcodes'! */
636         int type_index = builder->ctx.typenames[_CFFI_GETARG(op)].type_index;
637         x = realize_c_type_or_func(builder, builder->ctx.types, type_index);
638         break;
639     }
640 
641     default:
642         PyErr_Format(PyExc_NotImplementedError, "op=%d", (int)_CFFI_GETOP(op));
643         return NULL;
644     }
645 
646     if (x != NULL && opcodes == builder->ctx.types && opcodes[index] != x) {
647         assert((((uintptr_t)x) & 1) == 0);
648         assert((((uintptr_t)opcodes[index]) & 1) == 1);
649         Py_INCREF(x);
650         opcodes[index] = x;
651     }
652     return x;
653 };
654 
655 static CTypeDescrObject *
realize_c_func_return_type(builder_c_t * builder,_cffi_opcode_t opcodes[],int index)656 realize_c_func_return_type(builder_c_t *builder,
657                            _cffi_opcode_t opcodes[], int index)
658 {
659     PyObject *x;
660     _cffi_opcode_t op = opcodes[index];
661 
662     if ((((uintptr_t)op) & 1) == 0) {
663         /* already built: assert that it is a function and fish
664            for the return type */
665         x = (PyObject *)op;
666         assert(PyTuple_Check(x));   /* from _CFFI_OP_FUNCTION */
667         x = PyTuple_GET_ITEM(x, 0);
668         assert(CTypeDescr_Check(x));
669         assert(((CTypeDescrObject *)x)->ct_flags & CT_FUNCTIONPTR);
670         x = PyTuple_GET_ITEM(((CTypeDescrObject *)x)->ct_stuff, 1);
671         assert(CTypeDescr_Check(x));
672         Py_INCREF(x);
673         return (CTypeDescrObject *)x;
674     }
675     else {
676         assert(_CFFI_GETOP(op) == _CFFI_OP_FUNCTION);
677         return realize_c_type(builder, opcodes, _CFFI_GETARG(opcodes[index]));
678     }
679 }
680 
do_realize_lazy_struct(CTypeDescrObject * ct)681 static int do_realize_lazy_struct(CTypeDescrObject *ct)
682 {
683     /* This is called by force_lazy_struct() in _cffi_backend.c */
684     assert(ct->ct_flags & (CT_STRUCT | CT_UNION));
685 
686     if (ct->ct_flags & CT_LAZY_FIELD_LIST) {
687         builder_c_t *builder;
688         char *p;
689         int n, i, sflags;
690         const struct _cffi_struct_union_s *s;
691         const struct _cffi_field_s *fld;
692         PyObject *fields, *args, *res;
693 
694         assert(!(ct->ct_flags & CT_IS_OPAQUE));
695 
696         builder = ct->ct_extra;
697         assert(builder != NULL);
698 
699         p = alloca(2 + strlen(ct->ct_name));
700         _unrealize_name(p, ct->ct_name);
701 
702         n = search_in_struct_unions(&builder->ctx, p, strlen(p));
703         if (n < 0)
704             Py_FatalError("lost a struct/union!");
705 
706         s = &builder->ctx.struct_unions[n];
707         fld = &builder->ctx.fields[s->first_field_index];
708 
709         /* XXX painfully build all the Python objects that are the args
710            to b_complete_struct_or_union() */
711 
712         fields = PyList_New(s->num_fields);
713         if (fields == NULL)
714             return -1;
715 
716         for (i = 0; i < s->num_fields; i++, fld++) {
717             _cffi_opcode_t op = fld->field_type_op;
718             int fbitsize = -1;
719             PyObject *f;
720             CTypeDescrObject *ctf;
721 
722             switch (_CFFI_GETOP(op)) {
723 
724             case _CFFI_OP_BITFIELD:
725                 assert(fld->field_size >= 0);
726                 fbitsize = (int)fld->field_size;
727                 /* fall-through */
728             case _CFFI_OP_NOOP:
729                 ctf = realize_c_type(builder, builder->ctx.types,
730                                      _CFFI_GETARG(op));
731                 break;
732 
733             default:
734                 Py_DECREF(fields);
735                 PyErr_Format(PyExc_NotImplementedError, "field op=%d",
736                              (int)_CFFI_GETOP(op));
737                 return -1;
738             }
739 
740             if (ctf != NULL && fld->field_offset == (size_t)-1) {
741                 /* unnamed struct, with field positions and sizes entirely
742                    determined by complete_struct_or_union() and not checked.
743                    Or, bitfields (field_size >= 0), similarly not checked. */
744                 assert(fld->field_size == (size_t)-1 || fbitsize >= 0);
745             }
746             else if (ctf == NULL || detect_custom_layout(ct, SF_STD_FIELD_POS,
747                                      ctf->ct_size, fld->field_size,
748                                      "wrong size for field '",
749                                      fld->name, "'") < 0) {
750                 Py_DECREF(fields);
751                 return -1;
752             }
753 
754             f = Py_BuildValue("(sOin)", fld->name, ctf,
755                               fbitsize, (Py_ssize_t)fld->field_offset);
756             if (f == NULL) {
757                 Py_DECREF(fields);
758                 return -1;
759             }
760             PyList_SET_ITEM(fields, i, f);
761         }
762 
763         sflags = 0;
764         if (s->flags & _CFFI_F_CHECK_FIELDS)
765             sflags |= SF_STD_FIELD_POS;
766         if (s->flags & _CFFI_F_PACKED)
767             sflags |= SF_PACKED;
768 
769         args = Py_BuildValue("(OOOnii)", ct, fields, Py_None,
770                              (Py_ssize_t)s->size,
771                              s->alignment,
772                              sflags);
773         Py_DECREF(fields);
774         if (args == NULL)
775             return -1;
776 
777         ct->ct_extra = NULL;
778         ct->ct_flags |= CT_IS_OPAQUE;
779         res = b_complete_struct_or_union(NULL, args);
780         ct->ct_flags &= ~CT_IS_OPAQUE;
781         Py_DECREF(args);
782 
783         if (res == NULL) {
784             ct->ct_extra = builder;
785             return -1;
786         }
787 
788         assert(ct->ct_stuff != NULL);
789         ct->ct_flags &= ~CT_LAZY_FIELD_LIST;
790         Py_DECREF(res);
791         return 1;
792     }
793     else {
794         assert(ct->ct_flags & CT_IS_OPAQUE);
795         return 0;
796     }
797 }
798