>From 701488bf60e9b51ffa5d9da5bb6d7869620da154 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 28 Sep 2018 16:05:51 -0700 Subject: [PATCH 1/2] uniqstr: avoid need for VLAs C11 no longer requires support for variable-length arrays, and VS2015 does not have them. Redo UNIQSTR_CONCAT to use a method that is simpler and better anyway. * src/uniqstr.c (uniqstr_vsprintf): Remove; no longer needed. * src/uniqstr.h (UNIQSTR_GEN_FORMAT, UNIQSTR_GEN_FORMAT_): * src/uniqstr.c (uniqstr_concat): New function. * src/uniqstr.h (UNIQSTR_CONCAT): Use it instead of using uniqstr_vsprintf. --- src/uniqstr.c | 33 +++++++++++++++++++++++++-------- src/uniqstr.h | 42 +++++------------------------------------- 2 files changed, 30 insertions(+), 45 deletions(-) diff --git a/src/uniqstr.c b/src/uniqstr.c index bfe1d172..b4f6e946 100644 --- a/src/uniqstr.c +++ b/src/uniqstr.c @@ -56,19 +56,36 @@ uniqstr_new (char const *str) } uniqstr -uniqstr_vsprintf (char const *format, ...) +uniqstr_concat (int nargs, ...) { va_list args; - size_t length; - va_start (args, format); - length = vsnprintf (NULL, 0, format, args); + + va_start (args, nargs); + size_t reslen = 0; + for (int i = 0; i < nargs; i++) + reslen += strlen (va_arg (args, char const *)); va_end (args); - char res[length + 1]; - va_start (args, format); - vsprintf (res, format, args); + char *str = xmalloc (reslen + 1); + char *p = str; + + va_start (args, nargs); + for (int i = 0; i < nargs; i++) + { + char const *arg = va_arg (args, char const *); + size_t arglen = strlen (arg); + memcpy (p, arg, arglen); + p += arglen; + } va_end (args); - return uniqstr_new (res); + + *p = '\0'; + uniqstr res = hash_insert (uniqstrs_table, str); + if (!res) + xalloc_die (); + if (res != str) + free (str); + return res; } /*------------------------------. diff --git a/src/uniqstr.h b/src/uniqstr.h index fe04cb79..52472421 100644 --- a/src/uniqstr.h +++ b/src/uniqstr.h @@ -32,12 +32,6 @@ typedef char const *uniqstr; /* Return the uniqstr for STR. */ uniqstr uniqstr_new (char const *str); -/* Return a uniqstr built by vsprintf. In order to simply concatenate - strings, use UNIQSTR_CONCAT, which is a convenient wrapper around - this function. */ -uniqstr uniqstr_vsprintf (char const *format, ...) - _GL_ATTRIBUTE_FORMAT_PRINTF (1, 2); - /* Two uniqstr values have the same value iff they are the same. */ # define UNIQSTR_EQ(Ustr1, Ustr2) (!!((Ustr1) == (Ustr2))) @@ -52,38 +46,12 @@ void uniqstr_assert (char const *str); | Concatenation. | `----------------*/ -/* Concatenate at most 20 strings and return a uniqstr. The goal of - this macro is to make the caller's code a little more succinct - without a trivial uniqstr_vsprintf format string to maintain - (for example, "%s%s%s") while still benefitting from gcc's type - checking. Unfortunately, because of the missing format string in the - macro invocation, the argument number reported by gcc for a bad - argument type is 1 too large. */ +/* Concatenate strings and return a uniqstr. The goal of + this macro is to make the caller's code a little more succinct. */ # define UNIQSTR_CONCAT(...) \ - uniqstr_vsprintf (UNIQSTR_GEN_FORMAT (__VA_ARGS__, \ - "%s", "%s", "%s", "%s", "%s", \ - "%s", "%s", "%s", "%s", "%s", \ - "%s", "%s", "%s", "%s", "%s", \ - "%s", "%s", "%s", "%s", "%s"), \ - __VA_ARGS__) - -# define UNIQSTR_GEN_FORMAT(F1, F2, F3, F4, F5, \ - F6, F7, F8, F9, F10, \ - F11, F12, F13, F14, F15, \ - F16, F17, F18, F19, F20, \ - ...) \ - UNIQSTR_GEN_FORMAT_ (__VA_ARGS__, \ - "", "", "", "", "", \ - "", "", "", "", "", \ - "", "", "", "", "", \ - "", "", "", "", "") - -# define UNIQSTR_GEN_FORMAT_(F1, F2, F3, F4, F5, \ - F6, F7, F8, F9, F10, \ - F11, F12, F13, F14, F15, \ - F16, F17, F18, F19, F20, ...) \ - F1 F2 F3 F4 F5 F6 F7 F8 F9 F10 \ - F11 F12 F13 F14 F15 F16 F17 F18 F19 F20 + uniqstr_concat (ARRAY_CARDINALITY (((char const *[]) {__VA_ARGS__})), \ + __VA_ARGS__) +uniqstr uniqstr_concat (int nargs, ...); /*--------------------. | Table of uniqstrs. | -- 2.17.1