return ret;
}
+static struct cdecl_declarator *next_declarator(struct cdecl_declarator *d)
+{
+ switch (d->type) {
+ case CDECL_DECL_IDENT:
+ return NULL;
+ case CDECL_DECL_POINTER:
+ return d->u.pointer.declarator;
+ default:
+ abort();
+ }
+}
+
+/* Renders the name of the thing being declared. */
+static size_t
+explain_prologue(char *buf, size_t n, struct cdecl_declarator *d)
+{
+ while (d) {
+ if (d->type == CDECL_DECL_IDENT)
+ return snprintf(buf, n, "declare %s as", d->u.ident);
+ d = next_declarator(d);
+ }
+}
+
+static size_t
+explain_pointer(char *buf, size_t n, struct cdecl_pointer *p)
+{
+ size_t ret = 0, rc;
+
+ rc = explain_qualifiers(buf, n, p->qualifiers);
+ ret += advance(&buf, &n, rc);
+
+ return ret + snprintf(buf, n, "pointer to");
+}
+
+static size_t
+explain_declarators(char *buf, size_t n, struct cdecl_declarator *d)
+{
+ size_t ret = 0, rc;
+
+ if (d->type == CDECL_DECL_IDENT)
+ return 0;
+
+ rc = explain_declarators(buf, n, next_declarator(d));
+ ret += advance(&buf, &n, rc);
+
+ switch (d->type) {
+ case CDECL_DECL_POINTER:
+ return ret + explain_pointer(buf, n, &d->u.pointer);
+ default:
+ abort();
+ }
+}
size_t cdecl_explain(char *buf, size_t n, struct cdecl *decl)
{
size_t ret = 0, rc;
- /*
- * XXX: This won't work when we add support for more complicated
- * declarators.
- */
- rc = output(buf, n, 0, "declare %s as", decl->declarators->ident);
+ rc = explain_prologue(buf, n, decl->declarators);
ret += advance(&buf, &n, rc);
rc = explain_pre_specs(buf, n, decl->specifiers);
ret += advance(&buf, &n, rc);
+ rc = explain_declarators(buf, n, decl->declarators);
+ ret += advance(&buf, &n, rc);
+
return ret + explain_post_specs(buf, n, decl->specifiers);
}