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.
struct cdecl_declspec {
struct cdecl_declspec *next;
unsigned type;
struct cdecl_declspec {
struct cdecl_declspec *next;
unsigned type;
} *specifiers;
struct cdecl_declarator {
} *specifiers;
struct cdecl_declarator {
- struct cdecl_declarator *next, *child;
+ struct cdecl_declarator *child;
unsigned type;
union {
char *ident;
unsigned type;
union {
char *ident;
static char *buf;
struct cdecl *decl;
static char *buf;
struct cdecl *decl;
- struct cdecl_declarator *d;
size_t rc;
decl = cdecl_parse_decl(arg);
if (!decl)
goto out;
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) {
- rc = cdecl_explain(buf, bufsz, &decl_tmp);
+ rc = cdecl_explain(buf, bufsz, i);
if (rc >= bufsz) {
char *tmp;
if (rc >= bufsz) {
char *tmp;
static void free_declarator(struct cdecl_declarator *x)
{
struct cdecl_declarator *p;
static void free_declarator(struct cdecl_declarator *x)
{
struct cdecl_declarator *p;
switch (x->type) {
case CDECL_DECL_NULL:
break;
switch (x->type) {
case CDECL_DECL_NULL:
break;
- free_declarator(x->child);
-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)
{
}
void cdecl_free(struct cdecl *decl)
{
- if (decl)
- free_decl(decl);
%type <declspec> declspec_notype declspec_noid typespec_noid typespec
%type <declspec> qualifier qualifiers
%type <declspec> declspecs declspecs_noid
%type <declspec> declspec_notype declspec_noid typespec_noid typespec
%type <declspec> qualifier qualifiers
%type <declspec> declspecs declspecs_noid
-%type <declarator> direct_declarator declarator declarators pointer array
-%type <decl> declaration
+%type <declarator> direct_declarator declarator pointer array
+%type <decl> declaration declarators declarator_wrap
};
declaration: declspecs declarators T_SEMICOLON {
};
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 {
};
declspecs: declspec_notype declspecs {
-declarators: declarator | declarator T_COMMA declarators {
+declarators: declarator_wrap | declarator_wrap T_COMMA declarators {
+}
+
+declarator_wrap: declarator {
+ ALLOC_STRUCT($$, struct cdecl, .declarators = $1);
+}
declspec_simple: T_AUTO { $$ = CDECL_STOR_AUTO; }
| T_TYPEDEF { $$ = CDECL_STOR_TYPEDEF; }
declspec_simple: T_AUTO { $$ = CDECL_STOR_AUTO; }
| T_TYPEDEF { $$ = CDECL_STOR_TYPEDEF; }