• 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_now(builder_c_t * builder,_cffi_opcode_t op,_cffi_opcode_t opcodes[],int index)416 realize_c_type_or_func_now(builder_c_t *builder, _cffi_opcode_t op,
417                            _cffi_opcode_t opcodes[], int index)
418 {
419     PyObject *x, *y, *z;
420     Py_ssize_t length = -1;
421 
422     switch (_CFFI_GETOP(op)) {
423 
424     case _CFFI_OP_PRIMITIVE:
425         x = get_primitive_type(_CFFI_GETARG(op));
426         Py_XINCREF(x);
427         break;
428 
429     case _CFFI_OP_POINTER:
430         y = realize_c_type_or_func(builder, opcodes, _CFFI_GETARG(op));
431         if (y == NULL)
432             return NULL;
433         if (CTypeDescr_Check(y)) {
434             x = new_pointer_type((CTypeDescrObject *)y);
435         }
436         else {
437             assert(PyTuple_Check(y));   /* from _CFFI_OP_FUNCTION */
438             x = PyTuple_GET_ITEM(y, 0);
439             Py_INCREF(x);
440         }
441         Py_DECREF(y);
442         break;
443 
444     case _CFFI_OP_ARRAY:
445         length = (Py_ssize_t)opcodes[index + 1];
446         /* fall-through */
447     case _CFFI_OP_OPEN_ARRAY:
448         y = (PyObject *)realize_c_type(builder, opcodes, _CFFI_GETARG(op));
449         if (y == NULL)
450             return NULL;
451         z = new_pointer_type((CTypeDescrObject *)y);
452         Py_DECREF(y);
453         if (z == NULL)
454             return NULL;
455         x = new_array_type((CTypeDescrObject *)z, length);
456         Py_DECREF(z);
457         break;
458 
459     case _CFFI_OP_STRUCT_UNION:
460         x = _realize_c_struct_or_union(builder, _CFFI_GETARG(op));
461         break;
462 
463     case _CFFI_OP_ENUM:
464     {
465         const struct _cffi_enum_s *e;
466         _cffi_opcode_t op2;
467 
468         e = &builder->ctx.enums[_CFFI_GETARG(op)];
469         op2 = builder->ctx.types[e->type_index];
470         if ((((uintptr_t)op2) & 1) == 0) {
471             x = (PyObject *)op2;
472             Py_INCREF(x);
473         }
474         else {
475             PyObject *enumerators = NULL, *enumvalues = NULL, *tmp;
476             Py_ssize_t i, j, n = 0;
477             const char *p;
478             int gindex;
479             PyObject *args;
480             PyObject *basetd = get_primitive_type(e->type_prim);
481             if (basetd == NULL)
482                 return NULL;
483 
484             if (*e->enumerators != '\0') {
485                 n++;
486                 for (p = e->enumerators; *p != '\0'; p++)
487                     n += (*p == ',');
488             }
489             enumerators = PyTuple_New(n);
490             if (enumerators == NULL)
491                 return NULL;
492 
493             enumvalues = PyTuple_New(n);
494             if (enumvalues == NULL) {
495                 Py_DECREF(enumerators);
496                 return NULL;
497             }
498 
499             p = e->enumerators;
500             for (i = 0; i < n; i++) {
501                 j = 0;
502                 while (p[j] != ',' && p[j] != '\0')
503                     j++;
504                 tmp = PyText_FromStringAndSize(p, j);
505                 if (tmp == NULL)
506                     break;
507                 PyTuple_SET_ITEM(enumerators, i, tmp);
508 
509                 gindex = search_in_globals(&builder->ctx, p, j);
510                 assert(gindex >= 0);
511                 assert(builder->ctx.globals[gindex].type_op ==
512                        _CFFI_OP(_CFFI_OP_ENUM, -1));
513 
514                 tmp = realize_global_int(builder, gindex);
515                 if (tmp == NULL)
516                     break;
517                 PyTuple_SET_ITEM(enumvalues, i, tmp);
518 
519                 p += j + 1;
520             }
521 
522             args = NULL;
523             if (!PyErr_Occurred()) {
524                 char *name = alloca(6 + strlen(e->name));
525                 _realize_name(name, "enum ", e->name);
526                 args = Py_BuildValue("(sOOO)", name, enumerators,
527                                      enumvalues, basetd);
528             }
529             Py_DECREF(enumerators);
530             Py_DECREF(enumvalues);
531             if (args == NULL)
532                 return NULL;
533 
534             x = b_new_enum_type(NULL, args);
535             Py_DECREF(args);
536             if (x == NULL)
537                 return NULL;
538 
539             /* Update the "primary" _CFFI_OP_ENUM slot, which
540                may be the same or a different slot than the "current" one */
541             assert((((uintptr_t)x) & 1) == 0);
542             assert(builder->ctx.types[e->type_index] == op2);
543             Py_INCREF(x);
544             builder->ctx.types[e->type_index] = x;
545 
546             /* Done, leave without updating the "current" slot because
547                it may be done already above.  If not, never mind, the
548                next call to realize_c_type() will do it. */
549             return x;
550         }
551         break;
552     }
553 
554     case _CFFI_OP_FUNCTION:
555     {
556         PyObject *fargs;
557         int i, base_index, num_args, ellipsis, abi;
558 
559         y = (PyObject *)realize_c_type(builder, opcodes, _CFFI_GETARG(op));
560         if (y == NULL)
561             return NULL;
562 
563         base_index = index + 1;
564         num_args = 0;
565         /* note that if the arguments are already built, they have a
566            pointer in the 'opcodes' array, and GETOP() returns a
567            random even value.  But OP_FUNCTION_END is odd, so the
568            condition below still works correctly. */
569         while (_CFFI_GETOP(opcodes[base_index + num_args]) !=
570                    _CFFI_OP_FUNCTION_END)
571             num_args++;
572 
573         ellipsis = _CFFI_GETARG(opcodes[base_index + num_args]) & 0x01;
574         abi      = _CFFI_GETARG(opcodes[base_index + num_args]) & 0xFE;
575         switch (abi) {
576         case 0:
577             abi = FFI_DEFAULT_ABI;
578             break;
579         case 2:
580 #if defined(MS_WIN32) && !defined(_WIN64)
581             abi = FFI_STDCALL;
582 #else
583             abi = FFI_DEFAULT_ABI;
584 #endif
585             break;
586         default:
587             PyErr_Format(FFIError, "abi number %d not supported", abi);
588             Py_DECREF(y);
589             return NULL;
590         }
591 
592         fargs = PyTuple_New(num_args);
593         if (fargs == NULL) {
594             Py_DECREF(y);
595             return NULL;
596         }
597 
598         for (i = 0; i < num_args; i++) {
599             z = (PyObject *)realize_c_type(builder, opcodes, base_index + i);
600             if (z == NULL) {
601                 Py_DECREF(fargs);
602                 Py_DECREF(y);
603                 return NULL;
604             }
605             PyTuple_SET_ITEM(fargs, i, z);
606         }
607 
608         z = new_function_type(fargs, (CTypeDescrObject *)y, ellipsis, abi);
609         Py_DECREF(fargs);
610         Py_DECREF(y);
611         if (z == NULL)
612             return NULL;
613 
614         x = PyTuple_Pack(1, z);   /* hack: hide the CT_FUNCTIONPTR.  it will
615                                      be revealed again by the OP_POINTER */
616         Py_DECREF(z);
617         break;
618     }
619 
620     case _CFFI_OP_NOOP:
621         x = realize_c_type_or_func(builder, opcodes, _CFFI_GETARG(op));
622         break;
623 
624     case _CFFI_OP_TYPENAME:
625     {
626         /* essential: the TYPENAME opcode resolves the type index looked
627            up in the 'ctx->typenames' array, but it does so in 'ctx->types'
628            instead of in 'opcodes'! */
629         int type_index = builder->ctx.typenames[_CFFI_GETARG(op)].type_index;
630         x = realize_c_type_or_func(builder, builder->ctx.types, type_index);
631         break;
632     }
633 
634     default:
635         PyErr_Format(PyExc_NotImplementedError, "op=%d", (int)_CFFI_GETOP(op));
636         return NULL;
637     }
638 
639     return x;
640 }
641 
642 static int _realize_recursion_level;
643 
644 static PyObject *
realize_c_type_or_func(builder_c_t * builder,_cffi_opcode_t opcodes[],int index)645 realize_c_type_or_func(builder_c_t *builder,
646                         _cffi_opcode_t opcodes[], int index)
647 {
648     PyObject *x;
649      _cffi_opcode_t op = opcodes[index];
650 
651     if ((((uintptr_t)op) & 1) == 0) {
652         x = (PyObject *)op;
653         Py_INCREF(x);
654         return x;
655     }
656 
657     if (_realize_recursion_level >= 1000) {
658         PyErr_Format(PyExc_RuntimeError,
659             "type-building recursion too deep or infinite.  "
660             "This is known to occur e.g. in ``struct s { void(*callable)"
661             "(struct s); }''.  Please report if you get this error and "
662             "really need support for your case.");
663         return NULL;
664     }
665     _realize_recursion_level++;
666     x = realize_c_type_or_func_now(builder, op, opcodes, index);
667     _realize_recursion_level--;
668 
669     if (x != NULL && opcodes == builder->ctx.types && opcodes[index] != x) {
670         assert((((uintptr_t)x) & 1) == 0);
671         assert((((uintptr_t)opcodes[index]) & 1) == 1);
672         Py_INCREF(x);
673         opcodes[index] = x;
674     }
675     return x;
676 }
677 
678 static CTypeDescrObject *
realize_c_func_return_type(builder_c_t * builder,_cffi_opcode_t opcodes[],int index)679 realize_c_func_return_type(builder_c_t *builder,
680                            _cffi_opcode_t opcodes[], int index)
681 {
682     PyObject *x;
683     _cffi_opcode_t op = opcodes[index];
684 
685     if ((((uintptr_t)op) & 1) == 0) {
686         /* already built: assert that it is a function and fish
687            for the return type */
688         x = (PyObject *)op;
689         assert(PyTuple_Check(x));   /* from _CFFI_OP_FUNCTION */
690         x = PyTuple_GET_ITEM(x, 0);
691         assert(CTypeDescr_Check(x));
692         assert(((CTypeDescrObject *)x)->ct_flags & CT_FUNCTIONPTR);
693         x = PyTuple_GET_ITEM(((CTypeDescrObject *)x)->ct_stuff, 1);
694         assert(CTypeDescr_Check(x));
695         Py_INCREF(x);
696         return (CTypeDescrObject *)x;
697     }
698     else {
699         assert(_CFFI_GETOP(op) == _CFFI_OP_FUNCTION);
700         return realize_c_type(builder, opcodes, _CFFI_GETARG(opcodes[index]));
701     }
702 }
703 
do_realize_lazy_struct(CTypeDescrObject * ct)704 static int do_realize_lazy_struct(CTypeDescrObject *ct)
705 {
706     /* This is called by force_lazy_struct() in _cffi_backend.c */
707     assert(ct->ct_flags & (CT_STRUCT | CT_UNION));
708 
709     if (ct->ct_flags & CT_LAZY_FIELD_LIST) {
710         builder_c_t *builder;
711         char *p;
712         int n, i, sflags;
713         const struct _cffi_struct_union_s *s;
714         const struct _cffi_field_s *fld;
715         PyObject *fields, *args, *res;
716 
717         assert(!(ct->ct_flags & CT_IS_OPAQUE));
718 
719         builder = ct->ct_extra;
720         assert(builder != NULL);
721 
722         p = alloca(2 + strlen(ct->ct_name));
723         _unrealize_name(p, ct->ct_name);
724 
725         n = search_in_struct_unions(&builder->ctx, p, strlen(p));
726         if (n < 0)
727             Py_FatalError("lost a struct/union!");
728 
729         s = &builder->ctx.struct_unions[n];
730         fld = &builder->ctx.fields[s->first_field_index];
731 
732         /* XXX painfully build all the Python objects that are the args
733            to b_complete_struct_or_union() */
734 
735         fields = PyList_New(s->num_fields);
736         if (fields == NULL)
737             return -1;
738 
739         for (i = 0; i < s->num_fields; i++, fld++) {
740             _cffi_opcode_t op = fld->field_type_op;
741             int fbitsize = -1;
742             PyObject *f;
743             CTypeDescrObject *ctf;
744 
745             switch (_CFFI_GETOP(op)) {
746 
747             case _CFFI_OP_BITFIELD:
748                 assert(fld->field_size >= 0);
749                 fbitsize = (int)fld->field_size;
750                 /* fall-through */
751             case _CFFI_OP_NOOP:
752                 ctf = realize_c_type(builder, builder->ctx.types,
753                                      _CFFI_GETARG(op));
754                 break;
755 
756             default:
757                 Py_DECREF(fields);
758                 PyErr_Format(PyExc_NotImplementedError, "field op=%d",
759                              (int)_CFFI_GETOP(op));
760                 return -1;
761             }
762 
763             if (ctf != NULL && fld->field_offset == (size_t)-1) {
764                 /* unnamed struct, with field positions and sizes entirely
765                    determined by complete_struct_or_union() and not checked.
766                    Or, bitfields (field_size >= 0), similarly not checked. */
767                 assert(fld->field_size == (size_t)-1 || fbitsize >= 0);
768             }
769             else if (ctf == NULL || detect_custom_layout(ct, SF_STD_FIELD_POS,
770                                      ctf->ct_size, fld->field_size,
771                                      "wrong size for field '",
772                                      fld->name, "'") < 0) {
773                 Py_DECREF(fields);
774                 return -1;
775             }
776 
777             f = Py_BuildValue("(sOin)", fld->name, ctf,
778                               fbitsize, (Py_ssize_t)fld->field_offset);
779             if (f == NULL) {
780                 Py_DECREF(fields);
781                 return -1;
782             }
783             PyList_SET_ITEM(fields, i, f);
784         }
785 
786         sflags = 0;
787         if (s->flags & _CFFI_F_CHECK_FIELDS)
788             sflags |= SF_STD_FIELD_POS;
789         if (s->flags & _CFFI_F_PACKED)
790             sflags |= SF_PACKED;
791 
792         args = Py_BuildValue("(OOOnii)", ct, fields, Py_None,
793                              (Py_ssize_t)s->size,
794                              s->alignment,
795                              sflags);
796         Py_DECREF(fields);
797         if (args == NULL)
798             return -1;
799 
800         ct->ct_extra = NULL;
801         ct->ct_flags |= CT_IS_OPAQUE;
802         res = b_complete_struct_or_union(NULL, args);
803         ct->ct_flags &= ~CT_IS_OPAQUE;
804         Py_DECREF(args);
805 
806         if (res == NULL) {
807             ct->ct_extra = builder;
808             return -1;
809         }
810 
811         assert(ct->ct_stuff != NULL);
812         ct->ct_flags &= ~CT_LAZY_FIELD_LIST;
813         Py_DECREF(res);
814         return 1;
815     }
816     else {
817         assert(ct->ct_flags & CT_IS_OPAQUE);
818         return 0;
819     }
820 }
821