cdump: ignore __attribute__ (gcc extension).
authorRusty Russell <rusty@rustcorp.com.au>
Fri, 14 Nov 2014 02:45:18 +0000 (13:15 +1030)
committerRusty Russell <rusty@rustcorp.com.au>
Fri, 14 Nov 2014 02:45:18 +0000 (13:15 +1030)
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ccan/cdump/cdump.c
ccan/cdump/test/run-attributes.c [new file with mode: 0644]

index fb942594e0578f15ec9b37d4a60071296f9507ed..f080b968b5732593dbed861d241614878c5191bf 100644 (file)
@@ -390,6 +390,28 @@ static bool tok_maybe_take_cdump_note(const tal_t *ctx,
        return true;
 }
 
+/* __attribute__((...)) */
+static bool tok_ignore_attribute(struct parse_state *ps)
+{
+       if (!tok_take_if(&ps->toks, "__attribute__"))
+               return true;
+
+       if (!tok_take_if(&ps->toks, "(") || !tok_take_if(&ps->toks, "(")) {
+               complain(ps, "Expected (( after __attribute__");
+               return false;
+       }
+
+       if (!tok_take_expr(ps, ")")) {
+               complain(ps, "Expected expression after __attribute__((");
+               return false;
+       }
+       if (!tok_take_if(&ps->toks, ")")) {
+               complain(ps, "Expected )) __attribute__((");
+               return false;
+       }
+       return true;
+}
+
 /* struct|union ... */
 static bool tok_take_conglom(struct parse_state *ps,
                             enum cdump_type_kind conglom_kind)
@@ -415,6 +437,9 @@ static bool tok_take_conglom(struct parse_state *ps,
        if (!tok_maybe_take_cdump_note(e, ps, &e->note))
                return false;
 
+       if (!tok_ignore_attribute(ps))
+               return false;
+
        if (!tok_take_if(&ps->toks, "{")) {
                complain(ps, "Expected { for struct/union");
                return false;
@@ -426,6 +451,9 @@ static bool tok_take_conglom(struct parse_state *ps,
                const struct token *quals;
                unsigned int num_quals = 0;
 
+               if (!tok_ignore_attribute(ps))
+                       return false;
+
                /* Anything can have these prepended. */
                quals = ps->toks;
                while (tok_take_if(&ps->toks, "const")
@@ -455,6 +483,9 @@ static bool tok_take_conglom(struct parse_state *ps,
                        while (tok_take_if(&ps->toks, "*"))
                                m->type = ptr_of(ps, m->type);
 
+                       if (!tok_ignore_attribute(ps))
+                               return false;
+
                        m->name = tok_take_ident(e, &ps->toks);
                        if (!m->name) {
                                complain(ps, "Expected name for member");
@@ -471,6 +502,9 @@ static bool tok_take_conglom(struct parse_state *ps,
                        if (!tok_maybe_take_cdump_note(e->u.members,
                                                       ps, &m->note))
                                return false;
+
+                       if (!tok_ignore_attribute(ps))
+                               return false;
                } while (tok_take_if(&ps->toks, ","));
 
                if (!tok_take_if(&ps->toks, ";")) {
@@ -479,10 +513,19 @@ static bool tok_take_conglom(struct parse_state *ps,
                }
        }
 
-       if (tok_take_if(&ps->toks, "}") && tok_take_if(&ps->toks, ";"))
-               return true;
-       complain(ps, "Expected }; at end of struct/union");
-       return false;
+       if (!tok_take_if(&ps->toks, "}")) {
+               complain(ps, "Expected } at end of struct/union");
+               return false;
+       }
+
+       if (!tok_ignore_attribute(ps))
+               return false;
+
+       if (!tok_take_if(&ps->toks, ";")) {
+               complain(ps, "Expected ; at end of struct/union");
+               return false;
+       }
+       return true;
 }
 
 /* enum ... */
@@ -510,6 +553,9 @@ static bool tok_take_enum(struct parse_state *ps)
        if (!tok_maybe_take_cdump_note(e, ps, &e->note))
                return false;
 
+       if (!tok_ignore_attribute(ps))
+               return false;
+
        if (!tok_take_if(&ps->toks, "{")) {
                complain(ps, "Expected { after enum name");
                return false;
@@ -546,11 +592,19 @@ static bool tok_take_enum(struct parse_state *ps)
                        v->value = NULL;
        } while (tok_take_if(&ps->toks, ","));
 
-       if (tok_take_if(&ps->toks, "}") && tok_take_if(&ps->toks, ";"))
-               return true;
+       if (!tok_take_if(&ps->toks, "}")) {
+               complain(ps, "Expected } at end of enum");
+               return false;
+       }
 
-       complain(ps, "Expected }; at end of enum");
-       return false;
+       if (!tok_ignore_attribute(ps))
+               return false;
+
+       if (!tok_take_if(&ps->toks, ";")) {
+               complain(ps, "Expected ; at end of enum");
+               return false;
+       }
+       return true;
 }
 
 static bool gather_undefines(const char *name,
@@ -608,6 +662,8 @@ struct cdump_definitions *cdump_extract(const tal_t *ctx, const char *code,
 
        toks = ps.toks = tokenize(ps.defs, code);
        while (tok_peek(&ps.toks)) {
+               if (!tok_ignore_attribute(&ps))
+                       goto fail;
                if (tok_take_if(&ps.toks, "struct")) {
                        if (!tok_take_conglom(&ps, CDUMP_STRUCT))
                                goto fail;
diff --git a/ccan/cdump/test/run-attributes.c b/ccan/cdump/test/run-attributes.c
new file mode 100644 (file)
index 0000000..1034bde
--- /dev/null
@@ -0,0 +1,68 @@
+#include <ccan/cdump/cdump.h>
+/* Include the C files directly. */
+#include <ccan/cdump/cdump.c>
+#include <ccan/tap/tap.h>
+
+int main(void)
+{
+       struct cdump_definitions *defs;
+       const struct cdump_type *t;
+       char *ctx = tal(NULL, char), *problems;
+
+       /* This is how many tests you plan to run */
+       plan_tests(37);
+
+       defs = cdump_extract(ctx, "__attribute__((xxx)) enum foo __attribute__((xxx)) { BAR } __attribute__((xxx));", NULL);
+       ok1(defs);
+       ok1(tal_parent(defs) == ctx);
+
+       ok1(strmap_empty(&defs->structs));
+       ok1(strmap_empty(&defs->unions));
+       t = strmap_get(&defs->enums, "foo");
+       ok1(t);
+       ok1(t->kind == CDUMP_ENUM);
+       ok1(streq(t->name, "foo"));
+       ok1(tal_count(t->u.enum_vals) == 1);
+       ok1(streq(t->u.enum_vals[0].name, "BAR"));
+       ok1(!t->u.enum_vals[0].value);
+
+       defs = cdump_extract(ctx, "__attribute__((xxx)) struct foo __attribute__((xxx)) { int __attribute__((xxx)) x __attribute__((xxx)); } __attribute__((xxx));", &problems);
+       ok1(defs);
+       ok1(tal_parent(defs) == ctx);
+       ok1(!problems);
+
+       ok1(strmap_empty(&defs->enums));
+       ok1(strmap_empty(&defs->unions));
+       t = strmap_get(&defs->structs, "foo");
+       ok1(t);
+       ok1(t->kind == CDUMP_STRUCT);
+       ok1(streq(t->name, "foo"));
+       ok1(tal_count(t->u.members) == 1);
+       ok1(streq(t->u.members[0].name, "x"));
+       ok1(t->u.members[0].type->kind == CDUMP_UNKNOWN);
+       ok1(streq(t->u.members[0].type->name, "int"));
+
+       defs = cdump_extract(ctx, "struct foo { int x, __attribute__((xxx)) y; };", &problems);
+       ok1(defs);
+       ok1(tal_parent(defs) == ctx);
+       ok1(!problems);
+
+       ok1(strmap_empty(&defs->enums));
+       ok1(strmap_empty(&defs->unions));
+       t = strmap_get(&defs->structs, "foo");
+       ok1(t);
+       ok1(t->kind == CDUMP_STRUCT);
+       ok1(streq(t->name, "foo"));
+       ok1(tal_count(t->u.members) == 2);
+
+       ok1(streq(t->u.members[0].name, "x"));
+       ok1(t->u.members[0].type->kind == CDUMP_UNKNOWN);
+       ok1(streq(t->u.members[0].type->name, "int"));
+
+       ok1(streq(t->u.members[1].name, "y"));
+       ok1(t->u.members[1].type->kind == CDUMP_UNKNOWN);
+       ok1(streq(t->u.members[1].type->name, "int"));
+
+       /* This exits depending on whether all tests passed */
+       return exit_status();
+}