]> git.draconx.ca Git - cdecl99.git/commitdiff
libcdecl: Rework cdecl_declare output logic.
authorNick Bowler <nbowler@draconx.ca>
Fri, 23 Jun 2023 01:24:19 +0000 (21:24 -0400)
committerNick Bowler <nbowler@draconx.ca>
Fri, 23 Jun 2023 02:08:06 +0000 (22:08 -0400)
Instead of adjusting the output pointer/length values after each
internal call, tweak all the functions in declare.c to take an extra
level of indirection so they can just directly adjust the destination
as they go.

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);
 }