static PyObject * _fetch_external_struct_or_union(const struct _cffi_struct_union_s *s, PyObject *included_ffis, int recursion) { Py_ssize_t i; if (included_ffis == NULL) return NULL; if (recursion > 100) { PyErr_SetString(PyExc_RuntimeError, "recursion overflow in ffi.include() delegations"); return NULL; } for (i = 0; i < PyTuple_GET_SIZE(included_ffis); i++) { FFIObject *ffi1; const struct _cffi_struct_union_s *s1; int sindex; PyObject *x; ffi1 = (FFIObject *)PyTuple_GET_ITEM(included_ffis, i); sindex = search_in_struct_unions(&ffi1->types_builder.ctx, s->name, strlen(s->name)); if (sindex < 0) /* not found at all */ continue; s1 = &ffi1->types_builder.ctx.struct_unions[sindex]; if ((s1->flags & (_CFFI_F_EXTERNAL | _CFFI_F_UNION)) == (s->flags & _CFFI_F_UNION)) { /* s1 is not external, and the same kind (struct or union) as s */ return _realize_c_struct_or_union(&ffi1->types_builder, sindex); } /* not found, look more recursively */ x = _fetch_external_struct_or_union( s, ffi1->types_builder.included_ffis, recursion + 1); if (x != NULL || PyErr_Occurred()) return x; /* either found, or got an error */ } return NULL; /* not found at all, leave without an error */ }
static int parse_complete(token_t *tok) { unsigned int t0; _cffi_opcode_t t1; int modifiers_length, modifiers_sign; qualifiers: switch (tok->kind) { case TOK_CONST: /* ignored for now */ next_token(tok); goto qualifiers; case TOK_VOLATILE: /* ignored for now */ next_token(tok); goto qualifiers; default: ; } modifiers_length = 0; modifiers_sign = 0; modifiers: switch (tok->kind) { case TOK_SHORT: if (modifiers_length != 0) return parse_error(tok, "'short' after another 'short' or 'long'"); modifiers_length--; next_token(tok); goto modifiers; case TOK_LONG: if (modifiers_length < 0) return parse_error(tok, "'long' after 'short'"); if (modifiers_length >= 2) return parse_error(tok, "'long long long' is too long"); modifiers_length++; next_token(tok); goto modifiers; case TOK_SIGNED: if (modifiers_sign) return parse_error(tok, "multiple 'signed' or 'unsigned'"); modifiers_sign++; next_token(tok); goto modifiers; case TOK_UNSIGNED: if (modifiers_sign) return parse_error(tok, "multiple 'signed' or 'unsigned'"); modifiers_sign--; next_token(tok); goto modifiers; default: break; } if (modifiers_length || modifiers_sign) { switch (tok->kind) { case TOK_VOID: case TOK__BOOL: case TOK_FLOAT: case TOK_STRUCT: case TOK_UNION: case TOK_ENUM: return parse_error(tok, "invalid combination of types"); case TOK_DOUBLE: if (modifiers_sign != 0 || modifiers_length != 1) return parse_error(tok, "invalid combination of types"); next_token(tok); t0 = _CFFI_PRIM_LONGDOUBLE; break; case TOK_CHAR: if (modifiers_length != 0) return parse_error(tok, "invalid combination of types"); modifiers_length = -2; /* fall-through */ case TOK_INT: next_token(tok); /* fall-through */ default: if (modifiers_sign >= 0) switch (modifiers_length) { case -2: t0 = _CFFI_PRIM_SCHAR; break; case -1: t0 = _CFFI_PRIM_SHORT; break; case 1: t0 = _CFFI_PRIM_LONG; break; case 2: t0 = _CFFI_PRIM_LONGLONG; break; default: t0 = _CFFI_PRIM_INT; break; } else switch (modifiers_length) { case -2: t0 = _CFFI_PRIM_UCHAR; break; case -1: t0 = _CFFI_PRIM_USHORT; break; case 1: t0 = _CFFI_PRIM_ULONG; break; case 2: t0 = _CFFI_PRIM_ULONGLONG; break; default: t0 = _CFFI_PRIM_UINT; break; } } t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, t0); } else { switch (tok->kind) { case TOK_INT: t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_INT); break; case TOK_CHAR: t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_CHAR); break; case TOK_VOID: t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_VOID); break; case TOK__BOOL: t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_BOOL); break; case TOK_FLOAT: t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_FLOAT); break; case TOK_DOUBLE: t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, _CFFI_PRIM_DOUBLE); break; case TOK_IDENTIFIER: { const char *replacement; int n = search_in_typenames(tok->info->ctx, tok->p, tok->size); if (n >= 0) { t1 = _CFFI_OP(_CFFI_OP_TYPENAME, n); break; } n = search_standard_typename(tok->p, tok->size); if (n >= 0) { t1 = _CFFI_OP(_CFFI_OP_PRIMITIVE, n); break; } replacement = get_common_type(tok->p, tok->size); if (replacement != NULL) { n = parse_common_type_replacement(tok, replacement); if (n < 0) return parse_error(tok, "internal error, please report!"); t1 = _CFFI_OP(_CFFI_OP_NOOP, n); break; } return parse_error(tok, "undefined type name"); } case TOK_STRUCT: case TOK_UNION: { int n, kind = tok->kind; next_token(tok); if (tok->kind != TOK_IDENTIFIER) return parse_error(tok, "struct or union name expected"); n = search_in_struct_unions(tok->info->ctx, tok->p, tok->size); if (n < 0) { if (kind == TOK_STRUCT && tok->size == 8 && !memcmp(tok->p, "_IO_FILE", 8)) n = _CFFI__IO_FILE_STRUCT; else return parse_error(tok, "undefined struct/union name"); } else if (((tok->info->ctx->struct_unions[n].flags & _CFFI_F_UNION) != 0) ^ (kind == TOK_UNION)) return parse_error(tok, "wrong kind of tag: struct vs union"); t1 = _CFFI_OP(_CFFI_OP_STRUCT_UNION, n); break; } case TOK_ENUM: { int n; next_token(tok); if (tok->kind != TOK_IDENTIFIER) return parse_error(tok, "enum name expected"); n = search_in_enums(tok->info->ctx, tok->p, tok->size); if (n < 0) return parse_error(tok, "undefined enum name"); t1 = _CFFI_OP(_CFFI_OP_ENUM, n); break; } default: return parse_error(tok, "identifier expected"); } next_token(tok); } return parse_sequel(tok, write_ds(tok, t1)); }