diff options
author | Armin Rigo <arigo@tunes.org> | 2015-10-06 13:13:48 +0200 |
---|---|---|
committer | Armin Rigo <arigo@tunes.org> | 2015-10-06 13:13:48 +0200 |
commit | 67f86579509f430050cd1cdc97e51d7b30fe5ed1 (patch) | |
tree | 87f555b955874d6b697d0026972dfe96947951f2 /c/parse_c_type.c | |
parent | 11d0661446ac6460cce7c851c4e672d32efe0fd8 (diff) | |
download | cffi-67f86579509f430050cd1cdc97e51d7b30fe5ed1.tar.gz |
Parse __cdecl and __stdcall in the built-in parser
Diffstat (limited to 'c/parse_c_type.c')
-rw-r--r-- | c/parse_c_type.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/c/parse_c_type.c b/c/parse_c_type.c index 6fcd73c..511f243 100644 --- a/c/parse_c_type.c +++ b/c/parse_c_type.c @@ -40,6 +40,9 @@ enum token_e { TOK_UNSIGNED, TOK_VOID, TOK_VOLATILE, + + TOK_CDECL, + TOK_STDCALL, }; typedef struct { @@ -154,6 +157,8 @@ static void next_token(token_t *tok) switch (*p) { case '_': if (tok->size == 5 && !memcmp(p, "_Bool", 5)) tok->kind = TOK__BOOL; + if (tok->size == 7 && !memcmp(p,"__cdecl",7)) tok->kind = TOK_CDECL; + if (tok->size == 9 && !memcmp(p,"__stdcall",9))tok->kind = TOK_STDCALL; break; case 'c': if (tok->size == 4 && !memcmp(p, "char", 4)) tok->kind = TOK_CHAR; @@ -225,7 +230,7 @@ static int parse_sequel(token_t *tok, int outer) type). The 'outer' argument is the index of the opcode outside this "sequel". */ - int check_for_grouping; + int check_for_grouping, abi=0; _cffi_opcode_t result, *p_current; header: @@ -242,6 +247,12 @@ static int parse_sequel(token_t *tok, int outer) /* ignored for now */ next_token(tok); goto header; + case TOK_CDECL: + case TOK_STDCALL: + /* must be in a function; checked below */ + abi = tok->kind; + next_token(tok); + goto header; default: break; } @@ -258,6 +269,11 @@ static int parse_sequel(token_t *tok, int outer) while (tok->kind == TOK_OPEN_PAREN) { next_token(tok); + if (tok->kind == TOK_CDECL || tok->kind == TOK_STDCALL) { + abi = tok->kind; + next_token(tok); + } + if ((check_for_grouping--) == 1 && (tok->kind == TOK_STAR || tok->kind == TOK_CONST || tok->kind == TOK_VOLATILE || @@ -275,7 +291,14 @@ static int parse_sequel(token_t *tok, int outer) } else { /* function type */ - int arg_total, base_index, arg_next, has_ellipsis=0; + int arg_total, base_index, arg_next, flags=0; + + if (abi == TOK_STDCALL) { + flags = 2; + /* note that an ellipsis below will overwrite this flags, + which is the goal: variadic functions are always cdecl */ + } + abi = 0; if (tok->kind == TOK_VOID && get_following_char(tok) == ')') { next_token(tok); @@ -304,7 +327,7 @@ static int parse_sequel(token_t *tok, int outer) _cffi_opcode_t oarg; if (tok->kind == TOK_DOTDOTDOT) { - has_ellipsis = 1; + flags = 1; /* ellipsis */ next_token(tok); break; } @@ -328,8 +351,7 @@ static int parse_sequel(token_t *tok, int outer) next_token(tok); } } - tok->output[arg_next] = _CFFI_OP(_CFFI_OP_FUNCTION_END, - has_ellipsis); + tok->output[arg_next] = _CFFI_OP(_CFFI_OP_FUNCTION_END, flags); } if (tok->kind != TOK_CLOSE_PAREN) @@ -337,6 +359,9 @@ static int parse_sequel(token_t *tok, int outer) next_token(tok); } + if (abi != 0) + return parse_error(tok, "expected '('"); + while (tok->kind == TOK_OPEN_BRACKET) { *p_current = _CFFI_OP(_CFFI_GETOP(*p_current), tok->output_index); p_current = tok->output + tok->output_index; |