]> git.draconx.ca Git - cdecl99.git/blobdiff - src/declare.c
libcdecl: Rework cdecl_declare output logic.
[cdecl99.git] / src / declare.c
index 3b0b7006ed71a1bdb416e7a9ccb52d986eb549cc..8f7d607c4daa8d7560430bbda83ba95305d6ac1c 100644 (file)
 #include <config.h>
 #include <stdio.h>
 #include <stdbool.h>
+#include <inttypes.h>
 #include <assert.h>
 
 #include "cdecl.h"
 #include "cdecl-internal.h"
 
 static size_t
-declare_declarator(char *buf, size_t n, struct cdecl_declarator *d);
+declare_declarator(char **dst, size_t *dstlen, struct cdecl_declarator *d);
 
-static size_t declare_decl(char *buf, size_t n, struct cdecl *decl)
+static size_t declare_decl(char **dst, size_t *dstlen, struct cdecl *decl)
 {
-       size_t ret = 0, rc;
+       size_t ret, rc;
 
-       rc = cdecl__explain_specs(buf, n, decl->specifiers, -1);
+       rc = cdecl__explain_specs(*dst, *dstlen, decl->specifiers, -1);
        if (decl->declarators->type != CDECL_DECL_NULL)
-               ret += cdecl__advance(&buf, &n, rc);
+               ret = cdecl__advance(dst, dstlen, rc);
        else
-               ret += cdecl__advance_(&buf, &n, rc);
+               ret = cdecl__advance_(dst, dstlen, rc);
 
-       return ret + declare_declarator(buf, n, decl->declarators);
+       return ret + declare_declarator(dst, dstlen, decl->declarators);
 }
 
 static size_t
-declare_postfix_child(char *buf, size_t n, struct cdecl_declarator *d)
+declare_postfix_child(char **dst, size_t *dstlen, struct cdecl_declarator *d)
 {
-       size_t ret = 0, rc;
+       size_t ret = 0;
 
-       if (d->type == CDECL_DECL_POINTER) {
-               rc = snprintf(buf, n, "(");
-               ret += cdecl__advance_(&buf, &n, rc);
-       }
+       if (d->type == CDECL_DECL_POINTER)
+               ret += cdecl__emit(dst, dstlen, "(");
 
-       rc = declare_declarator(buf, n, d);
-       ret += cdecl__advance_(&buf, &n, rc);
+       ret += declare_declarator(dst, dstlen, d);
 
-       if (d->type == CDECL_DECL_POINTER) {
-               rc = snprintf(buf, n, ")");
-               ret += cdecl__advance_(&buf, &n, rc);
-       }
+       if (d->type == CDECL_DECL_POINTER)
+               ret += cdecl__emit(dst, dstlen, ")");
 
        return ret;
 }
 
-static size_t declare_pointer(char *buf, size_t n, struct cdecl_pointer *p)
+static size_t
+declare_pointer(char **dst, size_t *dstlen, struct cdecl_pointer *p)
 {
-       size_t ret = 0, rc;
-
-       rc = snprintf(buf, n, "*");
-       if (p->qualifiers)
-               ret += cdecl__advance(&buf, &n, rc);
-       else
-               ret += cdecl__advance_(&buf, &n, rc);
-
-       rc = cdecl__explain_specs(buf, n, p->qualifiers, CDECL_SPEC_QUAL);
-       return ret + rc;
-}
+       struct cdecl_declspec *q = p->qualifiers;
 
-static bool pointer_needs_space(struct cdecl_declarator *d)
-{
-       assert(d->type == CDECL_DECL_POINTER);
+       if (q) {
+               size_t ret, rc;
 
-       if (d->u.pointer.qualifiers)
-               return d->child->type != CDECL_DECL_NULL;
+               ret  = cdecl__emit(dst, dstlen, "* ");
+               rc   = cdecl__explain_specs(*dst, *dstlen, q, -1);
+               return ret + cdecl__advance(dst, dstlen, rc);
+       }
 
-       return false;
+       return cdecl__emit(dst, dstlen, "*");
 }
 
-static size_t declare_array(char *buf, size_t n, struct cdecl_array *a)
+static size_t declare_array(char **dst, size_t *dstlen, struct cdecl_array *a)
 {
-       size_t ret = 0, rc;
+       size_t ret;
 
-       rc = snprintf(buf, n, "[");
-       ret += cdecl__advance_(&buf, &n, rc);
+       ret = cdecl__emit(dst, dstlen, "[");
 
-       if (a->vla)
-               rc = snprintf(buf, n, "%s", a->vla[0] ? a->vla : "*");
-       else
-               rc = snprintf(buf, n, "%.0ju", a->length);
-       ret += cdecl__advance_(&buf, &n, rc);
+       if (a->vla) {
+               const char *s = a->vla[0] ? a->vla : "*";
+               ret += cdecl__emit(dst, dstlen, s);
+       } else {
+               size_t rc = snprintf(*dst, *dstlen, "%.0" PRIuMAX, a->length);
+               ret += cdecl__advance_(dst, dstlen, rc);
+       }
 
-       return ret + snprintf(buf, n, "]");
+       return ret + cdecl__emit(dst, dstlen, "]");
 }
 
-static size_t declare_function(char *buf, size_t n, struct cdecl_function *f)
+static size_t
+declare_function(char **dst, size_t *dstlen, struct cdecl_function *f)
 {
-       size_t ret = 0, rc;
+       struct cdecl *p;
+       size_t ret;
 
-       rc = snprintf(buf, n, "(");
-       ret += cdecl__advance_(&buf, &n, rc);
+       ret = cdecl__emit(dst, dstlen, "(");
 
-       for (struct cdecl *p = f->parameters; p; p = p->next) {
-               rc = declare_decl(buf, n, p);
-               ret += cdecl__advance_(&buf, &n, rc);
+       for (p = f->parameters; p; p = p->next) {
+               ret += declare_decl(dst, dstlen, p);
 
-               rc = 0;
                if (p->next)
-                       rc = snprintf(buf, n, ", ");
+                       ret += cdecl__emit(dst, dstlen, ", ");
                else if (f->variadic)
-                       rc = snprintf(buf, n, ", ...");
-               ret += cdecl__advance_(&buf, &n, rc);
+                       ret += cdecl__emit(dst, dstlen, ", ...");
        }
 
-       return ret + snprintf(buf, n, ")");
+       return ret + cdecl__emit(dst, dstlen, ")");
 }
 
 static size_t
-declare_declarator(char *buf, size_t n, struct cdecl_declarator *d)
+declare_declarator(char **dst, size_t *dstlen, struct cdecl_declarator *d)
 {
-       size_t ret = 0, rc;
+       size_t ret = 0;
 
        for (; d; d = d->child) {
                switch (d->type) {
                case CDECL_DECL_NULL:
                        break;
                case CDECL_DECL_IDENT:
-                       rc = snprintf(buf, n, "%s", d->u.ident);
-                       ret += cdecl__advance_(&buf, &n, rc);
+                       ret += cdecl__emit(dst, dstlen, d->u.ident);
                        break;
                case CDECL_DECL_POINTER:
-                       rc = declare_pointer(buf, n, &d->u.pointer);
-                       if (pointer_needs_space(d))
-                               ret += cdecl__advance(&buf, &n, rc);
-                       else
-                               ret += cdecl__advance_(&buf, &n, rc);
+                       ret += declare_pointer(dst, dstlen, &d->u.pointer);
                        break;
                /*
                 * Arrays and functions are special: since they are postfix,
@@ -149,13 +131,11 @@ declare_declarator(char *buf, size_t n, struct cdecl_declarator *d)
                 * "bodies".
                 */
                case CDECL_DECL_ARRAY:
-                       rc = declare_postfix_child(buf, n, d->child);
-                       ret += cdecl__advance_(&buf, &n, rc);
-                       return ret + declare_array(buf, n, &d->u.array);
+                       ret += declare_postfix_child(dst, dstlen, d->child);
+                       return ret + declare_array(dst, dstlen, &d->u.array);
                case CDECL_DECL_FUNCTION:
-                       rc = declare_postfix_child(buf, n, d->child);
-                       ret += cdecl__advance_(&buf, &n, rc);
-                       return ret + declare_function(buf, n, &d->u.function);
+                       ret += declare_postfix_child(dst, dstlen, d->child);
+                       return ret + declare_function(dst, dstlen, &d->u.function);
                default:
                        assert(0);
                }
@@ -166,5 +146,5 @@ declare_declarator(char *buf, size_t n, struct cdecl_declarator *d)
 
 size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl)
 {
-       return declare_decl(buf, n, decl);
+       return declare_decl(&buf, &n, decl);
 }