Ejemplo n.º 1
0
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 */
}
Ejemplo n.º 2
0
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));
}