[pypy-commit] creflect default: Fix error cases
arigo
noreply at buildbot.pypy.org
Sat Nov 29 10:33:56 CET 2014
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r112:873c4b857b75
Date: 2014-11-29 10:34 +0100
http://bitbucket.org/cffi/creflect/changeset/873c4b857b75/
Log: Fix error cases
diff --git a/creflect/src/c_decl_parser.c b/creflect/src/c_decl_parser.c
--- a/creflect/src/c_decl_parser.c
+++ b/creflect/src/c_decl_parser.c
@@ -156,11 +156,21 @@
}
}
+static crx_type_t *parse_error(crxp_token_t *tok, const char *msg)
+{
+ if (tok->kind != TOK_ERROR)
+ tok->cb->error(tok->cb, msg);
+ tok->kind = TOK_ERROR;
+ return NULL;
+}
+
static intptr_t *alloc_ds(crxp_token_t *tok, size_t num)
{
intptr_t *result = tok->delay_slots;
- if (num > (tok->all_delay_slots + NUM_DELAY_SLOTS - tok->delay_slots))
- abort(); // XXX out of memory
+ if (num > (tok->all_delay_slots + NUM_DELAY_SLOTS - tok->delay_slots)) {
+ parse_error(tok, "type too lengthy");
+ return NULL;
+ }
tok->delay_slots += num;
return result;
}
@@ -169,12 +179,18 @@
static void parse_sequel(crxp_token_t *tok, intptr_t ds_end)
{
+ intptr_t *ds;
while (tok->kind == TOK_STAR || tok->kind == TOK_CONST) {
- alloc_ds(tok, 1)[0] = tok->kind;
+ ds = alloc_ds(tok, 1);
+ if (ds == NULL)
+ return;
+ ds[0] = tok->kind;
next_token(tok);
}
- intptr_t *ds, *jump_slot = alloc_ds(tok, 1);
+ intptr_t *jump_slot = alloc_ds(tok, 1);
+ if (jump_slot == NULL)
+ return;
*jump_slot = ds_end;
next_right_part:
@@ -194,6 +210,8 @@
else {
/* function type */
ds = alloc_ds(tok, 2);
+ if (ds == NULL)
+ return;
ds[0] = TOK_OPEN_PAREN;
ds[1] = 0;
if (tok->kind == TOK_VOID &&
@@ -209,6 +227,8 @@
}
crx_type_t *t1 = parse_complete(tok, 1);
intptr_t *ds_type = alloc_ds(tok, 1);
+ if (ds_type == NULL)
+ return;
assert(ds_type == ds + 2 + ds[1]);
*ds_type = (intptr_t)t1;
ds[1]++;
@@ -218,12 +238,17 @@
}
}
intptr_t *ds_next = alloc_ds(tok, 1);
+ if (ds_next == NULL)
+ return;
assert(ds_next == ds + 2 + ds[1]);
*ds_next = *jump_slot;
*jump_slot = -(ds - tok->all_delay_slots);
}
- assert(tok->kind == TOK_CLOSE_PAREN); // XXX
+ if (tok->kind != TOK_CLOSE_PAREN) {
+ parse_error(tok, "expected ')'");
+ return;
+ }
next_token(tok);
goto next_right_part;
@@ -232,7 +257,10 @@
uintptr_t length = (uintptr_t)-1;
next_token(tok);
if (tok->kind != TOK_CLOSE_BRACKET) {
- assert(tok->kind == TOK_INTEGER); // XXX
+ if (tok->kind != TOK_INTEGER) {
+ parse_error(tok, "expected an integer constant");
+ return;
+ }
if (sizeof(uintptr_t) > sizeof(unsigned long))
length = strtoull(tok->p, NULL, 10);
@@ -240,10 +268,16 @@
length = strtoul(tok->p, NULL, 10);
next_token(tok);
}
- assert(tok->kind == TOK_CLOSE_BRACKET); // XXX
+
+ if (tok->kind != TOK_CLOSE_BRACKET) {
+ parse_error(tok, "expected ']'");
+ return;
+ }
next_token(tok);
ds = alloc_ds(tok, 3);
+ if (ds == NULL)
+ return;
ds[0] = TOK_OPEN_BRACKET;
ds[1] = (intptr_t)length;
ds[2] = *jump_slot;
@@ -258,6 +292,8 @@
static crx_type_t *fetch_delay_slots(crxp_token_t *tok, crx_type_t *t1,
intptr_t *delay_slot, int is_func_arg)
{
+ if (tok->kind == TOK_ERROR)
+ return NULL;
tok->delay_slots = delay_slot;
while (1) {
intptr_t tok_kind = *delay_slot++;
@@ -313,12 +349,6 @@
}
}
-static crx_type_t *parse_error(crxp_token_t *tok)
-{
- tok->kind = TOK_ERROR;
- return NULL;
-}
-
static crx_type_t *parse_complete(crxp_token_t *tok, int is_func_arg)
{
crx_type_t *t1;
@@ -334,28 +364,30 @@
case TOK_SHORT:
if (modifiers_length != 0)
- return parse_error(tok);
+ return parse_error(tok, "'short' after another 'short' or 'long'");
modifiers_length--;
next_token(tok);
goto modifiers;
case TOK_LONG:
- if (modifiers_length != 0 && modifiers_length != 1)
- return parse_error(tok);
+ 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);
+ 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);
+ return parse_error(tok, "multiple 'signed' or 'unsigned'");
modifiers_sign--;
next_token(tok);
goto modifiers;
@@ -372,7 +404,7 @@
case TOK_CHAR:
if (modifiers_length != 0)
- return parse_error(tok);
+ return parse_error(tok,"cannot combine with 'short' or 'long'");
size = sizeof(char);
name = "char";
next_token(tok);
@@ -409,15 +441,14 @@
{
char identifier[1024];
if (tok->size >= 1024)
- return parse_error(tok); // XXX
+ return parse_error(tok, "identifier name too long");
memcpy(identifier, tok->p, tok->size);
identifier[tok->size] = 0;
t1 = tok->cb->get_user_type(tok->cb, identifier);
break;
}
default:
- tok->kind = TOK_ERROR;
- return NULL;
+ return parse_error(tok, "identifier expected");
}
next_token(tok);
}
@@ -445,5 +476,6 @@
if (token.kind == TOK_END)
return NULL;
+ parse_error(&token, "unexpected symbol");
return token.p;
}
diff --git a/test/test_c_decl_parser.py b/test/test_c_decl_parser.py
--- a/test/test_c_decl_parser.py
+++ b/test/test_c_decl_parser.py
@@ -14,7 +14,7 @@
printf("%s\n", t1->text);
}
else {
- printf("error: %s\n ", argv[1]);
+ printf("%s\n", argv[1]);
while (p > argv[1]) {
printf(" ");
p--;
@@ -44,8 +44,9 @@
print got.rstrip()
assert got == expected_output + '\n'
-def parse_error(input, expected_location):
- parse(input, 'error: %s\n %s^' % (input, " " * expected_location))
+def parse_error(input, expected_msg, expected_location):
+ exp = 'ERROR: %s\n%s\n%s^' % (expected_msg, input, " " * expected_location)
+ parse(input, exp)
def test_c_decl_parser():
parse("int **", "PTR PTR int")
@@ -82,5 +83,23 @@
parse("int(long(char))", "FUNC( PTR FUNC( char -> long ) -> int )")
def test_c_decl_error():
- parse_error("*", 0)
- parse_error("int ]**", 4)
+ parse_error("short short int", "'short' after another 'short' or 'long'", 6)
+ parse_error("long long long", "'long long long' is too long", 10)
+ parse_error("short long", "'long' after 'short'", 6)
+ parse_error("signed unsigned int", "multiple 'signed' or 'unsigned'", 7)
+ parse_error("unsigned signed int", "multiple 'signed' or 'unsigned'", 9)
+ parse_error("long char", "cannot combine with 'short' or 'long'", 5)
+ parse_error("short char", "cannot combine with 'short' or 'long'", 6)
+ #
+ parse_error("", "identifier expected", 0)
+ parse_error("]", "identifier expected", 0)
+ parse_error("*", "identifier expected", 0)
+ parse_error("int ]**", "unexpected symbol", 4)
+ parse_error("int(int]", "expected ')'", 7)
+ parse_error("int(*]", "expected ')'", 5)
+ parse_error("int(]", "identifier expected", 4)
+ parse_error("int[?]", "expected an integer constant", 4)
+ parse_error("int[24)", "expected ']'", 6)
+ #
+ parse_error("int" + "[]" * 2500, "type too lengthy", 3337)
+ parse_error("f" * 1200, "identifier name too long", 0)
More information about the pypy-commit
mailing list