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;
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;
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);
}
%}
%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 {
- ALLOC_STRUCT($$, struct cdecl,
- .specifiers = $1,
- .declarators = $2);
+ $$ = $2;
+
+ for (struct cdecl *i = $$; i; i = i->next)
+ i->specifiers = $1;
};
declspecs: declspec_notype declspecs {
$$->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; }