From 225fb0d496bd8f9fcbc2f800819a83c71d763a61 Mon Sep 17 00:00:00 2001 From: Nick Bowler Date: Fri, 23 Jun 2023 00:05:41 -0400 Subject: [PATCH] libcdecl: Accumulate output length in structure. Instead of cascading the lengths back via function return values, since we now have a state structure we can just track the total length in one place. This is quite a lot conceptually simpler and cuts out a good chunk of code. --- src/cdecl-internal.h | 1 + src/declare.c | 88 +++++++++++++++-------------------- src/explain.c | 107 ++++++++++++++++++------------------------- src/output.c | 1 + 4 files changed, 85 insertions(+), 112 deletions(-) diff --git a/src/cdecl-internal.h b/src/cdecl-internal.h index 0064617..4024cab 100644 --- a/src/cdecl-internal.h +++ b/src/cdecl-internal.h @@ -43,6 +43,7 @@ struct cdecl_declspec *cdecl__normalize_specs(struct cdecl_declspec *specs); struct output_state { char *dst; size_t dstlen; + size_t accum; }; size_t cdecl__advance(struct output_state *dst, size_t amount); diff --git a/src/declare.c b/src/declare.c index 5bf9d37..0ee9640 100644 --- a/src/declare.c +++ b/src/declare.c @@ -25,103 +25,89 @@ #include "cdecl.h" #include "cdecl-internal.h" -static size_t +static void declare_declarator(struct output_state *dst, struct cdecl_declarator *d); -static size_t declare_decl(struct output_state *dst, struct cdecl *decl) +static void declare_decl(struct output_state *dst, struct cdecl *decl) { - size_t ret; - - ret = cdecl__emit_specs(dst, decl->specifiers, -1); + cdecl__emit_specs(dst, decl->specifiers, -1); if (decl->declarators->type != CDECL_DECL_NULL) - ret += cdecl__emit(dst, " "); + cdecl__emit(dst, " "); - return ret + declare_declarator(dst, decl->declarators); + declare_declarator(dst, decl->declarators); } -static size_t +static void declare_postfix_child(struct output_state *dst, struct cdecl_declarator *d) { - size_t ret = 0; - if (d->type == CDECL_DECL_POINTER) - ret += cdecl__emit(dst, "("); + cdecl__emit(dst, "("); - ret += declare_declarator(dst, d); + declare_declarator(dst, d); if (d->type == CDECL_DECL_POINTER) - ret += cdecl__emit(dst, ")"); - - return ret; + cdecl__emit(dst, ")"); } -static size_t -declare_pointer(struct output_state *dst, struct cdecl_pointer *p) +static void declare_pointer(struct output_state *dst, struct cdecl_pointer *p) { struct cdecl_declspec *q = p->qualifiers; if (q) { - size_t ret; - - ret = cdecl__emit(dst, "* "); - ret += cdecl__emit_specs(dst, q, -1); - return ret + cdecl__emit(dst, " "); + cdecl__emit(dst, "* "); + cdecl__emit_specs(dst, q, -1); + cdecl__emit(dst, " "); + } else { + cdecl__emit(dst, "*"); } - - return cdecl__emit(dst, "*"); } -static size_t declare_array(struct output_state *dst, struct cdecl_array *a) +static void declare_array(struct output_state *dst, struct cdecl_array *a) { - size_t ret; - - ret = cdecl__emit(dst, "["); + cdecl__emit(dst, "["); if (a->vla) { const char *s = a->vla[0] ? a->vla : "*"; - ret += cdecl__emit(dst, s); + cdecl__emit(dst, s); } else { size_t rc = snprintf(dst->dst, dst->dstlen, "%.0" PRIuMAX, a->length); - ret += cdecl__advance(dst, rc); + cdecl__advance(dst, rc); } - return ret + cdecl__emit(dst, "]"); + cdecl__emit(dst, "]"); } -static size_t +static void declare_function(struct output_state *dst, struct cdecl_function *f) { struct cdecl *p; - size_t ret; - ret = cdecl__emit(dst, "("); + cdecl__emit(dst, "("); for (p = f->parameters; p; p = p->next) { - ret += declare_decl(dst, p); + declare_decl(dst, p); if (p->next) - ret += cdecl__emit(dst, ", "); + cdecl__emit(dst, ", "); else if (f->variadic) - ret += cdecl__emit(dst, ", ..."); + cdecl__emit(dst, ", ..."); } - return ret + cdecl__emit(dst, ")"); + cdecl__emit(dst, ")"); } -static size_t +static void declare_declarator(struct output_state *dst, struct cdecl_declarator *d) { - size_t ret = 0; - for (; d; d = d->child) { switch (d->type) { case CDECL_DECL_NULL: break; case CDECL_DECL_IDENT: - ret += cdecl__emit(dst, d->u.ident); + cdecl__emit(dst, d->u.ident); break; case CDECL_DECL_POINTER: - ret += declare_pointer(dst, &d->u.pointer); + declare_pointer(dst, &d->u.pointer); break; /* * Arrays and functions are special: since they are postfix, @@ -129,22 +115,24 @@ declare_declarator(struct output_state *dst, struct cdecl_declarator *d) * "bodies". */ case CDECL_DECL_ARRAY: - ret += declare_postfix_child(dst, d->child); - return ret + declare_array(dst, &d->u.array); + declare_postfix_child(dst, d->child); + declare_array(dst, &d->u.array); + return; case CDECL_DECL_FUNCTION: - ret += declare_postfix_child(dst, d->child); - return ret + declare_function(dst, &d->u.function); + declare_postfix_child(dst, d->child); + declare_function(dst, &d->u.function); + return; default: assert(0); } } - - return ret; } size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl) { struct output_state dst = { buf, n }; - return declare_decl(&dst, decl); + declare_decl(&dst, decl); + + return dst.accum; } diff --git a/src/explain.c b/src/explain.c index e6b4f16..26d39e7 100644 --- a/src/explain.c +++ b/src/explain.c @@ -27,50 +27,39 @@ #define PRE_SPECS (CDECL_SPEC_FUNC|CDECL_SPEC_STOR) #define POST_SPECS (CDECL_SPEC_QUAL|CDECL_SPEC_TYPE) -static size_t explain_specs(struct output_state *dst, struct cdecl_declspec *s, unsigned mask) +static void explain_specs(struct output_state *dst, struct cdecl_declspec *s, unsigned mask) { - size_t ret; + size_t rc; - ret = cdecl__emit_specs(dst, s, mask); - return ret + cdecl__emit(dst, " " + !ret); -} - -static size_t -explain_specs_post(struct output_state *dst, struct cdecl_declspec *s) -{ - return cdecl__emit_specs(dst, s, POST_SPECS); + rc = cdecl__emit_specs(dst, s, mask); + cdecl__emit(dst, " " + !rc); } /* * If declarator declares an identifier foo, then emit "foo as "; otherwise * emit nothing. */ -static size_t +static void explain_name(struct output_state *dst, struct cdecl_declarator *d) { - size_t ret; - while (d->child) d = d->child; - if (d->type != CDECL_DECL_IDENT) - return 0; - - ret = cdecl__emit(dst, d->u.ident); - return ret + cdecl__emit(dst, " as "); + if (d->type == CDECL_DECL_IDENT) { + cdecl__emit(dst, d->u.ident); + cdecl__emit(dst, " as "); + } } /* * For a pointer declarator, emit "[QUAL ]pointer to ", where * QUAL is the (possibly empty) list of qualifiers. */ -static size_t +static void explain_pointer(struct output_state *dst, struct cdecl_pointer *p) { - size_t ret; - - ret = explain_specs(dst, p->qualifiers, -1); - return ret + cdecl__emit(dst, "pointer to "); + explain_specs(dst, p->qualifiers, -1); + cdecl__emit(dst, "pointer to "); } /* @@ -78,39 +67,34 @@ explain_pointer(struct output_state *dst, struct cdecl_pointer *p) * for a variable-length array X is the (possibly omitted) identifier name, * and for normal arrays X is the (possibly omitted) length. */ -static size_t +static void explain_array(struct output_state *dst, struct cdecl_array *a) { - size_t ret = 0, rc = 0; + size_t rc = 0; if (a->vla) - ret += cdecl__emit(dst, "variable-length "); - ret += cdecl__emit(dst, "array "); + cdecl__emit(dst, "variable-length "); + cdecl__emit(dst, "array "); if (a->vla) { rc = cdecl__emit(dst, a->vla); - ret += rc; } else { rc = snprintf(dst->dst, dst->dstlen, "%.0" PRIuMAX, a->length); - ret += cdecl__advance(dst, rc); + cdecl__advance(dst, rc); } - return ret + cdecl__emit(dst, " of " + !rc); + cdecl__emit(dst, " of " + !rc); } -static size_t +static void explain_declarators(struct output_state *dst, struct cdecl_declarator *decl); -static size_t explain_decl(struct output_state *dst, struct cdecl *decl) +static void explain_decl(struct output_state *dst, struct cdecl *decl) { - size_t ret; - - ret = explain_name(dst, decl->declarators); - ret += explain_specs(dst, decl->specifiers, PRE_SPECS); - ret += explain_declarators(dst, decl->declarators); - ret += explain_specs_post(dst, decl->specifiers); - - return ret; + explain_name(dst, decl->declarators); + explain_specs(dst, decl->specifiers, PRE_SPECS); + explain_declarators(dst, decl->declarators); + cdecl__emit_specs(dst, decl->specifiers, POST_SPECS); } /* @@ -118,50 +102,49 @@ static size_t explain_decl(struct output_state *dst, struct cdecl *decl) * PARAM is the (omitted in the case of an empty non-prototype identifier * list) parameter or identifier lists enclosed in parentheses. */ -static size_t +static void explain_function(struct output_state *dst, struct cdecl_function *f) { - size_t ret = 0; - - ret += cdecl__emit(dst, "function "); + cdecl__emit(dst, "function "); if (f->parameters) { struct cdecl *p; - ret += cdecl__emit(dst, "("); + cdecl__emit(dst, "("); for (p = f->parameters; p; p = p->next) { - ret += explain_decl(dst, p); + explain_decl(dst, p); if (p->next) - ret += cdecl__emit(dst, ", "); + cdecl__emit(dst, ", "); } if (f->variadic) - ret += cdecl__emit(dst, ", ...) "); + cdecl__emit(dst, ", ...) "); else - ret += cdecl__emit(dst, ") "); + cdecl__emit(dst, ") "); } - return ret + cdecl__emit(dst, "returning "); + cdecl__emit(dst, "returning "); } -static size_t +static void explain_declarators(struct output_state *dst, struct cdecl_declarator *d) { - size_t ret; - if (d->type == CDECL_DECL_IDENT || d->type == CDECL_DECL_NULL) - return 0; + return; - ret = explain_declarators(dst, d->child); + explain_declarators(dst, d->child); switch (d->type) { case CDECL_DECL_POINTER: - return ret + explain_pointer(dst, &d->u.pointer); + explain_pointer(dst, &d->u.pointer); + return; case CDECL_DECL_ARRAY: - return ret + explain_array(dst, &d->u.array); + explain_array(dst, &d->u.array); + return; case CDECL_DECL_FUNCTION: - return ret + explain_function(dst, &d->u.function); + explain_function(dst, &d->u.function); + return; default: assert(0); } @@ -170,12 +153,12 @@ explain_declarators(struct output_state *dst, struct cdecl_declarator *d) size_t cdecl_explain(char *buf, size_t n, struct cdecl *decl) { struct output_state dst = { buf, n }; - size_t ret; if (cdecl_is_abstract(decl->declarators)) - ret = cdecl__emit(&dst, "type "); + cdecl__emit(&dst, "type "); else - ret = cdecl__emit(&dst, "declare "); + cdecl__emit(&dst, "declare "); - return ret + explain_decl(&dst, decl); + explain_decl(&dst, decl); + return dst.accum; } diff --git a/src/output.c b/src/output.c index cf5e2ff..b33816a 100644 --- a/src/output.c +++ b/src/output.c @@ -32,6 +32,7 @@ size_t cdecl__advance(struct output_state *dst, size_t amount) dst->dst += x; dst->dstlen -= x; + dst->accum += amount; return amount; } -- 2.43.2