[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