From 5b6fc836137be0073e1a15895c6375429762c147 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Tue, 5 Jul 2011 22:43:42 -0400 Subject: [PATCH] Kill the "horizontal" declarator chain. The "next" pointer in declarators is used in exactly one place: the list of declarators of a declaration. Move this chain to the toplevel so that we get a list of declarations instead: now every struct cdecl has exatly one declarator. This helps eliminate the nasty hack in "explain" to print multiple declarators. --- src/cdecl.h | 4 +++- src/cdecl99.c | 10 ++-------- src/parse.y | 45 ++++++++++++++++++++++++++++++--------------- 3 files changed, 35 insertions(+), 24 deletions(-) diff --git a/src/cdecl.h b/src/cdecl.h index 883a4e4..95d7634 100644 --- a/src/cdecl.h +++ b/src/cdecl.h @@ -48,6 +48,8 @@ enum { }; struct cdecl { + struct cdecl *next; + struct cdecl_declspec { struct cdecl_declspec *next; unsigned type; @@ -55,7 +57,7 @@ struct cdecl { } *specifiers; struct cdecl_declarator { - struct cdecl_declarator *next, *child; + struct cdecl_declarator *child; unsigned type; union { char *ident; diff --git a/src/cdecl99.c b/src/cdecl99.c index d966805..639edea 100644 --- a/src/cdecl99.c +++ b/src/cdecl99.c @@ -40,21 +40,15 @@ static int cmd_explain(char *cmd, char *arg) static char *buf; struct cdecl *decl; - struct cdecl_declarator *d; size_t rc; decl = cdecl_parse_decl(arg); if (!decl) goto out; - for (d = decl->declarators; d; d = d->next) { - struct cdecl decl_tmp = { - .specifiers = decl->specifiers, - .declarators = d, - }; - + for (struct cdecl *i = decl; i; i = i->next) { retry: - rc = cdecl_explain(buf, bufsz, &decl_tmp); + rc = cdecl_explain(buf, bufsz, i); if (rc >= bufsz) { char *tmp; diff --git a/src/parse.y b/src/parse.y index 7d4c3dc..86091f9 100644 --- a/src/parse.y +++ b/src/parse.y @@ -76,8 +76,10 @@ static void free_declspec(struct cdecl_declspec *x) static void free_declarator(struct cdecl_declarator *x) { struct cdecl_declarator *p; + while (x) { - p = x->next; + p = x->child; + switch (x->type) { case CDECL_DECL_NULL: break; @@ -94,23 +96,31 @@ static void free_declarator(struct cdecl_declarator *x) assert(0); } - free_declarator(x->child); free(x); x = p; } } -static void free_decl(struct cdecl *decl) +static void free_decl(struct cdecl *x) { - free_declspec(decl->specifiers); - free_declarator(decl->declarators); - free(decl); + struct cdecl *p; + + while (x) { + p = x->next; + + /* The specifiers may be shared by an entire chain. */ + if (!p || p->specifiers != x->specifiers) + free_declspec(x->specifiers); + + free_declarator(x->declarators); + free(x); + x = p; + } } void cdecl_free(struct cdecl *decl) { - if (decl) - free_decl(decl); + free_decl(decl); } %} @@ -165,8 +175,8 @@ void cdecl_free(struct cdecl *decl) %type declspec_notype declspec_noid typespec_noid typespec %type qualifier qualifiers %type declspecs declspecs_noid -%type direct_declarator declarator declarators pointer array -%type declaration +%type direct_declarator declarator pointer array +%type declaration declarators declarator_wrap %% @@ -175,9 +185,10 @@ input: declaration { }; declaration: declspecs declarators T_SEMICOLON { - ALLOC_STRUCT($$, struct cdecl, - .specifiers = $1, - .declarators = $2); + $$ = $2; + + for (struct cdecl *i = $$; i; i = i->next) + i->specifiers = $1; }; declspecs: declspec_notype declspecs { @@ -198,10 +209,14 @@ qualifiers: { $$ = NULL; } | qualifiers qualifier { $$->next = $1; } -declarators: declarator | declarator T_COMMA declarators { +declarators: declarator_wrap | declarator_wrap T_COMMA declarators { $$ = $1; $$->next = $3; -}; +} + +declarator_wrap: declarator { + ALLOC_STRUCT($$, struct cdecl, .declarators = $1); +} declspec_simple: T_AUTO { $$ = CDECL_STOR_AUTO; } | T_TYPEDEF { $$ = CDECL_STOR_TYPEDEF; } -- 2.43.2