]> git.draconx.ca Git - cdecl99.git/blobdiff - src/explain.c
Add support for pointer declarators.
[cdecl99.git] / src / explain.c
index 823cb3a17fe23127ca64677981b9fb1a28120cdd..c6c7e9c49b4ffcd87cc259ca3209068329b45951 100644 (file)
@@ -154,20 +154,71 @@ static size_t explain_pre_specs(char *buf, size_t n, struct cdecl_declspec *s)
        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);
 }