From: Nick Bowler Date: Fri, 23 Jun 2023 03:25:50 +0000 (-0400) Subject: libcdecl: Use a structure for dst/dstlen in output routines. X-Git-Tag: v1.3~151 X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/commitdiff_plain/0b2a2978f09f5d9b56d8655dd60eaffbe9006b7a libcdecl: Use a structure for dst/dstlen in output routines. Since pretty much all the output functions now just directly pass the dst and dstlen pointers around without touching them in any other way, it is more efficient to use a structure so there is only one pointer. --- diff --git a/src/cdecl-internal.h b/src/cdecl-internal.h index e0052bd..0064617 100644 --- a/src/cdecl-internal.h +++ b/src/cdecl-internal.h @@ -40,10 +40,14 @@ void cdecl__errmsg(unsigned msg); struct cdecl_declspec *cdecl__normalize_specs(struct cdecl_declspec *specs); -size_t cdecl__advance(char **buf, size_t *n, size_t amount); - -size_t cdecl__emit(char **dst, size_t *dstlen, const char *src); -size_t cdecl__emit_specs(char **dst, size_t *dstlen, +struct output_state { + char *dst; + size_t dstlen; +}; + +size_t cdecl__advance(struct output_state *dst, size_t amount); +size_t cdecl__emit(struct output_state *dst, const char *src); +size_t cdecl__emit_specs(struct output_state *dst, struct cdecl_declspec *s, unsigned mask); diff --git a/src/declare.c b/src/declare.c index 318ccac..5bf9d37 100644 --- a/src/declare.c +++ b/src/declare.c @@ -26,90 +26,90 @@ #include "cdecl-internal.h" static size_t -declare_declarator(char **dst, size_t *dstlen, struct cdecl_declarator *d); +declare_declarator(struct output_state *dst, struct cdecl_declarator *d); -static size_t declare_decl(char **dst, size_t *dstlen, struct cdecl *decl) +static size_t declare_decl(struct output_state *dst, struct cdecl *decl) { size_t ret; - ret = cdecl__emit_specs(dst, dstlen, decl->specifiers, -1); + ret = cdecl__emit_specs(dst, decl->specifiers, -1); if (decl->declarators->type != CDECL_DECL_NULL) - ret += cdecl__emit(dst, dstlen, " "); + ret += cdecl__emit(dst, " "); - return ret + declare_declarator(dst, dstlen, decl->declarators); + return ret + declare_declarator(dst, decl->declarators); } static size_t -declare_postfix_child(char **dst, size_t *dstlen, struct cdecl_declarator *d) +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, dstlen, "("); + ret += cdecl__emit(dst, "("); - ret += declare_declarator(dst, dstlen, d); + ret += declare_declarator(dst, d); if (d->type == CDECL_DECL_POINTER) - ret += cdecl__emit(dst, dstlen, ")"); + ret += cdecl__emit(dst, ")"); return ret; } static size_t -declare_pointer(char **dst, size_t *dstlen, struct cdecl_pointer *p) +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, dstlen, "* "); - ret += cdecl__emit_specs(dst, dstlen, q, -1); - return ret + cdecl__emit(dst, dstlen, " "); + ret = cdecl__emit(dst, "* "); + ret += cdecl__emit_specs(dst, q, -1); + return ret + cdecl__emit(dst, " "); } - return cdecl__emit(dst, dstlen, "*"); + return cdecl__emit(dst, "*"); } -static size_t declare_array(char **dst, size_t *dstlen, struct cdecl_array *a) +static size_t declare_array(struct output_state *dst, struct cdecl_array *a) { size_t ret; - ret = cdecl__emit(dst, dstlen, "["); + ret = cdecl__emit(dst, "["); if (a->vla) { const char *s = a->vla[0] ? a->vla : "*"; - ret += cdecl__emit(dst, dstlen, s); + ret += cdecl__emit(dst, s); } else { - size_t rc = snprintf(*dst, *dstlen, "%.0" PRIuMAX, a->length); - ret += cdecl__advance(dst, dstlen, rc); + size_t rc = snprintf(dst->dst, dst->dstlen, "%.0" PRIuMAX, a->length); + ret += cdecl__advance(dst, rc); } - return ret + cdecl__emit(dst, dstlen, "]"); + return ret + cdecl__emit(dst, "]"); } static size_t -declare_function(char **dst, size_t *dstlen, struct cdecl_function *f) +declare_function(struct output_state *dst, struct cdecl_function *f) { struct cdecl *p; size_t ret; - ret = cdecl__emit(dst, dstlen, "("); + ret = cdecl__emit(dst, "("); for (p = f->parameters; p; p = p->next) { - ret += declare_decl(dst, dstlen, p); + ret += declare_decl(dst, p); if (p->next) - ret += cdecl__emit(dst, dstlen, ", "); + ret += cdecl__emit(dst, ", "); else if (f->variadic) - ret += cdecl__emit(dst, dstlen, ", ..."); + ret += cdecl__emit(dst, ", ..."); } - return ret + cdecl__emit(dst, dstlen, ")"); + return ret + cdecl__emit(dst, ")"); } static size_t -declare_declarator(char **dst, size_t *dstlen, struct cdecl_declarator *d) +declare_declarator(struct output_state *dst, struct cdecl_declarator *d) { size_t ret = 0; @@ -118,10 +118,10 @@ declare_declarator(char **dst, size_t *dstlen, struct cdecl_declarator *d) case CDECL_DECL_NULL: break; case CDECL_DECL_IDENT: - ret += cdecl__emit(dst, dstlen, d->u.ident); + ret += cdecl__emit(dst, d->u.ident); break; case CDECL_DECL_POINTER: - ret += declare_pointer(dst, dstlen, &d->u.pointer); + ret += declare_pointer(dst, &d->u.pointer); break; /* * Arrays and functions are special: since they are postfix, @@ -129,11 +129,11 @@ declare_declarator(char **dst, size_t *dstlen, struct cdecl_declarator *d) * "bodies". */ case CDECL_DECL_ARRAY: - ret += declare_postfix_child(dst, dstlen, d->child); - return ret + declare_array(dst, dstlen, &d->u.array); + ret += declare_postfix_child(dst, d->child); + return ret + declare_array(dst, &d->u.array); case CDECL_DECL_FUNCTION: - ret += declare_postfix_child(dst, dstlen, d->child); - return ret + declare_function(dst, dstlen, &d->u.function); + ret += declare_postfix_child(dst, d->child); + return ret + declare_function(dst, &d->u.function); default: assert(0); } @@ -144,5 +144,7 @@ declare_declarator(char **dst, size_t *dstlen, struct cdecl_declarator *d) size_t cdecl_declare(char *buf, size_t n, struct cdecl *decl) { - return declare_decl(&buf, &n, decl); + struct output_state dst = { buf, n }; + + return declare_decl(&dst, decl); } diff --git a/src/explain.c b/src/explain.c index fa34095..e6b4f16 100644 --- a/src/explain.c +++ b/src/explain.c @@ -27,18 +27,18 @@ #define PRE_SPECS (CDECL_SPEC_FUNC|CDECL_SPEC_STOR) #define POST_SPECS (CDECL_SPEC_QUAL|CDECL_SPEC_TYPE) -static size_t explain_specs(char **dst, size_t *dstlen, struct cdecl_declspec *s, unsigned mask) +static size_t explain_specs(struct output_state *dst, struct cdecl_declspec *s, unsigned mask) { size_t ret; - ret = cdecl__emit_specs(dst, dstlen, s, mask); - return ret + cdecl__emit(dst, dstlen, " " + !ret); + ret = cdecl__emit_specs(dst, s, mask); + return ret + cdecl__emit(dst, " " + !ret); } static size_t -explain_specs_post(char **dst, size_t *dstlen, struct cdecl_declspec *s) +explain_specs_post(struct output_state *dst, struct cdecl_declspec *s) { - return cdecl__emit_specs(dst, dstlen, s, POST_SPECS); + return cdecl__emit_specs(dst, s, POST_SPECS); } /* @@ -46,7 +46,7 @@ explain_specs_post(char **dst, size_t *dstlen, struct cdecl_declspec *s) * emit nothing. */ static size_t -explain_name(char **dst, size_t *dstlen, struct cdecl_declarator *d) +explain_name(struct output_state *dst, struct cdecl_declarator *d) { size_t ret; @@ -56,8 +56,8 @@ explain_name(char **dst, size_t *dstlen, struct cdecl_declarator *d) if (d->type != CDECL_DECL_IDENT) return 0; - ret = cdecl__emit(dst, dstlen, d->u.ident); - return ret + cdecl__emit(dst, dstlen, " as "); + ret = cdecl__emit(dst, d->u.ident); + return ret + cdecl__emit(dst, " as "); } /* @@ -65,12 +65,12 @@ explain_name(char **dst, size_t *dstlen, struct cdecl_declarator *d) * QUAL is the (possibly empty) list of qualifiers. */ static size_t -explain_pointer(char **dst, size_t *dstlen, struct cdecl_pointer *p) +explain_pointer(struct output_state *dst, struct cdecl_pointer *p) { size_t ret; - ret = explain_specs(dst, dstlen, p->qualifiers, -1); - return ret + cdecl__emit(dst, dstlen, "pointer to "); + ret = explain_specs(dst, p->qualifiers, -1); + return ret + cdecl__emit(dst, "pointer to "); } /* @@ -79,36 +79,36 @@ explain_pointer(char **dst, size_t *dstlen, struct cdecl_pointer *p) * and for normal arrays X is the (possibly omitted) length. */ static size_t -explain_array(char **dst, size_t *dstlen, struct cdecl_array *a) +explain_array(struct output_state *dst, struct cdecl_array *a) { size_t ret = 0, rc = 0; if (a->vla) - ret += cdecl__emit(dst, dstlen, "variable-length "); - ret += cdecl__emit(dst, dstlen, "array "); + ret += cdecl__emit(dst, "variable-length "); + ret += cdecl__emit(dst, "array "); if (a->vla) { - rc = cdecl__emit(dst, dstlen, a->vla); + rc = cdecl__emit(dst, a->vla); ret += rc; } else { - rc = snprintf(*dst, *dstlen, "%.0" PRIuMAX, a->length); - ret += cdecl__advance(dst, dstlen, rc); + rc = snprintf(dst->dst, dst->dstlen, "%.0" PRIuMAX, a->length); + ret += cdecl__advance(dst, rc); } - return ret + cdecl__emit(dst, dstlen, " of " + !rc); + return ret + cdecl__emit(dst, " of " + !rc); } static size_t -explain_declarators(char **dst, size_t *dstlen, struct cdecl_declarator *decl); +explain_declarators(struct output_state *dst, struct cdecl_declarator *decl); -static size_t explain_decl(char **dst, size_t *dstlen, struct cdecl *decl) +static size_t explain_decl(struct output_state *dst, struct cdecl *decl) { size_t ret; - ret = explain_name(dst, dstlen, decl->declarators); - ret += explain_specs(dst, dstlen, decl->specifiers, PRE_SPECS); - ret += explain_declarators(dst, dstlen, decl->declarators); - ret += explain_specs_post(dst, dstlen, decl->specifiers); + 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; } @@ -119,49 +119,49 @@ static size_t explain_decl(char **dst, size_t *dstlen, struct cdecl *decl) * list) parameter or identifier lists enclosed in parentheses. */ static size_t -explain_function(char **dst, size_t *dstlen, struct cdecl_function *f) +explain_function(struct output_state *dst, struct cdecl_function *f) { size_t ret = 0; - ret += cdecl__emit(dst, dstlen, "function "); + ret += cdecl__emit(dst, "function "); if (f->parameters) { struct cdecl *p; - ret += cdecl__emit(dst, dstlen, "("); + ret += cdecl__emit(dst, "("); for (p = f->parameters; p; p = p->next) { - ret += explain_decl(dst, dstlen, p); + ret += explain_decl(dst, p); if (p->next) - ret += cdecl__emit(dst, dstlen, ", "); + ret += cdecl__emit(dst, ", "); } if (f->variadic) - ret += cdecl__emit(dst, dstlen, ", ...) "); + ret += cdecl__emit(dst, ", ...) "); else - ret += cdecl__emit(dst, dstlen, ") "); + ret += cdecl__emit(dst, ") "); } - return ret + cdecl__emit(dst, dstlen, "returning "); + return ret + cdecl__emit(dst, "returning "); } static size_t -explain_declarators(char **dst, size_t *dstlen, struct cdecl_declarator *d) +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; - ret = explain_declarators(dst, dstlen, d->child); + ret = explain_declarators(dst, d->child); switch (d->type) { case CDECL_DECL_POINTER: - return ret + explain_pointer(dst, dstlen, &d->u.pointer); + return ret + explain_pointer(dst, &d->u.pointer); case CDECL_DECL_ARRAY: - return ret + explain_array(dst, dstlen, &d->u.array); + return ret + explain_array(dst, &d->u.array); case CDECL_DECL_FUNCTION: - return ret + explain_function(dst, dstlen, &d->u.function); + return ret + explain_function(dst, &d->u.function); default: assert(0); } @@ -169,12 +169,13 @@ explain_declarators(char **dst, size_t *dstlen, 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(&buf, &n, "type "); + ret = cdecl__emit(&dst, "type "); else - ret = cdecl__emit(&buf, &n, "declare "); + ret = cdecl__emit(&dst, "declare "); - return ret + explain_decl(&buf, &n, decl); + return ret + explain_decl(&dst, decl); } diff --git a/src/output.c b/src/output.c index 0bc5023..27921ab 100644 --- a/src/output.c +++ b/src/output.c @@ -24,33 +24,33 @@ #include "specstr.h" -size_t cdecl__advance(char **buf, size_t *n, size_t amount) +size_t cdecl__advance(struct output_state *dst, size_t amount) { - if (amount >= *n) { - *n = 0; - *buf = 0; + if (amount >= dst->dstlen) { + dst->dstlen = 0; + dst->dst = 0; } else { - *buf += amount; - *n -= amount; + dst->dst += amount; + dst->dstlen -= amount; } return amount; } -size_t cdecl__emit(char **dst, size_t *dstlen, const char *src) +size_t cdecl__emit(struct output_state *dst, const char *src) { - size_t rc = snprintf(*dst, *dstlen, "%s", src); - return cdecl__advance(dst, dstlen, rc); + size_t rc = snprintf(dst->dst, dst->dstlen, "%s", src); + return cdecl__advance(dst, rc); } -static size_t explain_spec(char **dst, size_t *dstlen, struct cdecl_declspec *s) +static size_t explain_spec(struct output_state *dst, struct cdecl_declspec *s) { size_t ret; - ret = cdecl__emit(dst, dstlen, spec_string(s->type)); + ret = cdecl__emit(dst, spec_string(s->type)); if (s->ident) { - ret += cdecl__emit(dst, dstlen, " " + !ret); - ret += cdecl__emit(dst, dstlen, s->ident); + ret += cdecl__emit(dst, " " + !ret); + ret += cdecl__emit(dst, s->ident); } return ret; @@ -61,7 +61,7 @@ static size_t explain_spec(char **dst, size_t *dstlen, struct cdecl_declspec *s) * listed in mask, which is the bitwise OR of the desired specifier kinds, are * printed. */ -size_t cdecl__emit_specs(char **dst, size_t *dstlen, +size_t cdecl__emit_specs(struct output_state *dst, struct cdecl_declspec *s, unsigned mask) { @@ -71,8 +71,8 @@ size_t cdecl__emit_specs(char **dst, size_t *dstlen, if (!(s->type & mask)) continue; - ret += cdecl__emit(dst, dstlen, " " + !ret); - ret += explain_spec(dst, dstlen, s); + ret += cdecl__emit(dst, " " + !ret); + ret += explain_spec(dst, s); } return ret; diff --git a/t/normalize.c b/t/normalize.c index 9c54d02..dc4cd53 100644 --- a/t/normalize.c +++ b/t/normalize.c @@ -108,11 +108,10 @@ int do_normalize(char *line, size_t n) line = malloc_nofail(n); line[0] = 0; if (specs) { - char *tmp_line = line; - size_t tmp_n = n; + struct output_state dst = { line, n }; specs = cdecl__normalize_specs(specs); - cdecl__emit_specs(&tmp_line, &tmp_n, specs, -1); + cdecl__emit_specs(&dst, specs, -1); } printf("%s\n", line); free(line);