X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/0c61f9637a469ac7a28b5a329551b03e6ad14d62..ccab8e9fa4419c944f831612d5b5474c847485fa:/src/declare.c diff --git a/src/declare.c b/src/declare.c index 4fc9fee..0ee9640 100644 --- a/src/declare.c +++ b/src/declare.c @@ -1,6 +1,6 @@ /* * Render C declarations. - * Copyright © 2011, 2021 Nick Bowler + * Copyright © 2011, 2021, 2023 Nick Bowler * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,143 +19,95 @@ #include #include #include +#include #include #include "cdecl.h" #include "cdecl-internal.h" -static size_t declare_specs(char *buf, size_t n, struct cdecl_declspec *s) -{ - size_t ret = 0, rc; - - if (!s) - return 0; +static void +declare_declarator(struct output_state *dst, struct cdecl_declarator *d); - rc = cdecl__explain_pre_specs(buf, n, s); - ret += cdecl__advance(&buf, &n, rc); - - rc = cdecl__explain_post_specs(buf, n, s); - return ret + rc; -} - -static size_t -declare_declarator(char *buf, size_t n, struct cdecl_declarator *d); - -static size_t declare_decl(char *buf, size_t n, struct cdecl *decl) +static void declare_decl(struct output_state *dst, struct cdecl *decl) { - size_t ret = 0, rc; - - rc = declare_specs(buf, n, decl->specifiers); + cdecl__emit_specs(dst, decl->specifiers, -1); if (decl->declarators->type != CDECL_DECL_NULL) - ret += cdecl__advance(&buf, &n, rc); - else - ret += cdecl__advance_(&buf, &n, rc); - - return ret + declare_declarator(buf, n, decl->declarators); -} - -static size_t -declare_postfix_child(char *buf, size_t n, struct cdecl_declarator *d) -{ - size_t ret = 0, rc; - - if (d->type == CDECL_DECL_POINTER) { - rc = snprintf(buf, n, "("); - ret += cdecl__advance_(&buf, &n, rc); - } + cdecl__emit(dst, " "); - rc = declare_declarator(buf, n, d); - ret += cdecl__advance_(&buf, &n, rc); - - if (d->type == CDECL_DECL_POINTER) { - rc = snprintf(buf, n, ")"); - ret += cdecl__advance_(&buf, &n, rc); - } - - return ret; + declare_declarator(dst, decl->declarators); } -static size_t declare_pointer(char *buf, size_t n, struct cdecl_pointer *p) +static void +declare_postfix_child(struct output_state *dst, struct cdecl_declarator *d) { - size_t ret = 0, rc; + if (d->type == CDECL_DECL_POINTER) + cdecl__emit(dst, "("); - rc = snprintf(buf, n, "*"); - if (p->qualifiers) - ret += cdecl__advance(&buf, &n, rc); - else - ret += cdecl__advance_(&buf, &n, rc); + declare_declarator(dst, d); - rc = cdecl__explain_specs(buf, n, p->qualifiers, CDECL_SPEC_QUAL); - return ret + rc; + if (d->type == CDECL_DECL_POINTER) + cdecl__emit(dst, ")"); } -static bool pointer_needs_space(struct cdecl_declarator *d) +static void declare_pointer(struct output_state *dst, struct cdecl_pointer *p) { - assert(d->type == CDECL_DECL_POINTER); - - if (d->u.pointer.qualifiers) - return d->child->type != CDECL_DECL_NULL; - - return false; + struct cdecl_declspec *q = p->qualifiers; + + if (q) { + cdecl__emit(dst, "* "); + cdecl__emit_specs(dst, q, -1); + cdecl__emit(dst, " "); + } else { + cdecl__emit(dst, "*"); + } } -static size_t declare_array(char *buf, size_t n, struct cdecl_array *a) +static void declare_array(struct output_state *dst, struct cdecl_array *a) { - size_t ret = 0, rc; - - rc = snprintf(buf, n, "["); - ret += cdecl__advance_(&buf, &n, rc); - - 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); + cdecl__emit(dst, "["); + + if (a->vla) { + const char *s = a->vla[0] ? a->vla : "*"; + cdecl__emit(dst, s); + } else { + size_t rc = snprintf(dst->dst, dst->dstlen, "%.0" PRIuMAX, a->length); + cdecl__advance(dst, rc); + } - return ret + snprintf(buf, n, "]"); + cdecl__emit(dst, "]"); } -static size_t declare_function(char *buf, size_t n, struct cdecl_function *f) +static void +declare_function(struct output_state *dst, struct cdecl_function *f) { - size_t ret = 0, rc; + struct cdecl *p; - rc = snprintf(buf, n, "("); - ret += cdecl__advance_(&buf, &n, rc); + cdecl__emit(dst, "("); - 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) { + declare_decl(dst, p); - rc = 0; if (p->next) - rc = snprintf(buf, n, ", "); + cdecl__emit(dst, ", "); else if (f->variadic) - rc = snprintf(buf, n, ", ..."); - ret += cdecl__advance_(&buf, &n, rc); + cdecl__emit(dst, ", ..."); } - return ret + snprintf(buf, n, ")"); + cdecl__emit(dst, ")"); } -static size_t -declare_declarator(char *buf, size_t n, struct cdecl_declarator *d) +static void +declare_declarator(struct output_state *dst, struct cdecl_declarator *d) { - size_t ret = 0, rc; - 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); + cdecl__emit(dst, 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); + declare_pointer(dst, &d->u.pointer); break; /* * Arrays and functions are special: since they are postfix, @@ -163,22 +115,24 @@ 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); + declare_postfix_child(dst, d->child); + declare_array(dst, &d->u.array); + return; 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); + 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) { - return declare_decl(buf, n, decl); + struct output_state dst = { buf, n }; + + declare_decl(&dst, decl); + + return dst.accum; }