From: Nick Bowler Date: Fri, 23 Jun 2023 05:11:15 +0000 (-0400) Subject: libcdecl: Avoid vsnprintf for error reporting. X-Git-Tag: v1.3~147 X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/commitdiff_plain/655528745c72b4a7d50aee1688c359dc069ee546 libcdecl: Avoid vsnprintf for error reporting. Using vsnprintf is overkill here. We only need to handle a single %s conversion, which can be done by direct call to snprintf. As this is the only caller of vsnprintf, dropping it means we can drop the vsnprintf gnulib module. Also, at least with gcc, using va_start and such is fairly expensive. The direct-snprintf version is quite a bit more compact. --- diff --git a/bootstrap b/bootstrap index 8b6bf0b..5ec2dc4 100755 --- a/bootstrap +++ b/bootstrap @@ -33,7 +33,7 @@ if test -x $GNULIB/gnulib-tool; then exec 3>lib/symfiles.tmp 4&3 ) || die "gnulib-tool failed" shared_modules=`LC_ALL=C sort -u <&4` diff --git a/m4/gnulib-cache.m4 b/m4/gnulib-cache.m4 index 6113698..2b29495 100644 --- a/m4/gnulib-cache.m4 +++ b/m4/gnulib-cache.m4 @@ -50,8 +50,7 @@ # mbswidth \ # readline \ # snprintf \ -# tls \ -# vsnprintf +# tls # Specification in the form of a few gnulib-tool.m4 macro invocations: gl_LOCAL_DIR([]) @@ -66,7 +65,6 @@ gl_MODULES([ readline snprintf tls - vsnprintf ]) gl_AVOID([gperf std-gnu11]) gl_SOURCE_BASE([lib]) diff --git a/src/cdecl-internal.h b/src/cdecl-internal.h index ab62725..74c2654 100644 --- a/src/cdecl-internal.h +++ b/src/cdecl-internal.h @@ -35,7 +35,7 @@ static inline void cdecl__init_i18n(void) } #endif -void cdecl__err(unsigned code, const char *fmt, ...); +void cdecl__err(unsigned code, const char *fmt, const char *arg); void cdecl__errmsg(unsigned msg); struct cdecl_declspec *cdecl__normalize_specs(struct cdecl_declspec *specs); diff --git a/src/error.c b/src/error.c index 5466d39..36e6366 100644 --- a/src/error.c +++ b/src/error.c @@ -19,9 +19,7 @@ #include #include #include -#include #include -#include #include "cdecl.h" #include "cdecl-internal.h" @@ -124,23 +122,20 @@ void cdecl__errmsg(unsigned msg) } /* - * Sets the library error to code, with a printf-style error string. + * Sets the library error to code; fmt is a printf-style string that may use + * up to one %s directive, to refer to arg. */ -void cdecl__err(unsigned code, const char *fmt, ...) +void cdecl__err(unsigned code, const char *fmt, const char *arg) { struct err_state *state; int rc, try = 0; - va_list ap; state = get_err_state(); if (!state) return; retry: - va_start(ap, fmt); - rc = vsnprintf(state->str, state->nstr, fmt, ap); - va_end(ap); - + rc = snprintf(state->str, state->nstr, fmt, arg); if (rc > 0 && rc >= state->nstr) { assert(try++ == 0 && rc < SIZE_MAX / 4); state = alloc_err_state(state, (size_t)(rc+1u) * 3 / 2); diff --git a/t/cdeclerr.c b/t/cdeclerr.c index 16ba1be..b8a9a74 100644 --- a/t/cdeclerr.c +++ b/t/cdeclerr.c @@ -73,7 +73,7 @@ static void check_fixed_string(size_t len) memset(work2, 'X', len - 1); tap_diag("cdecl__err w/ %lu-byte string", (unsigned long)len); - cdecl__err(1234, work1); + cdecl__err(1234, work1, ""); memset(work1, 0, len); err = cdecl_get_error();