summaryrefslogtreecommitdiff
path: root/c/parse_c_type.c
diff options
context:
space:
mode:
authorArmin Rigo <arigo@tunes.org>2015-10-06 13:13:48 +0200
committerArmin Rigo <arigo@tunes.org>2015-10-06 13:13:48 +0200
commit67f86579509f430050cd1cdc97e51d7b30fe5ed1 (patch)
tree87f555b955874d6b697d0026972dfe96947951f2 /c/parse_c_type.c
parent11d0661446ac6460cce7c851c4e672d32efe0fd8 (diff)
downloadcffi-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.c35
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;