diff options
| author | Dennis Camera <skonfig@dtnr.ch> | 2022-08-22 23:41:16 +0200 |
|---|---|---|
| committer | Dennis Camera <skonfig@dtnr.ch> | 2022-08-22 23:41:16 +0200 |
| commit | b881b02a54e18d0897822044b48730eaa2c7bb9c (patch) | |
| tree | f3df60acf1ea75bbac95b2ffdeaf1f52edbd3181 /src/util | |
| parent | 2f425cb9e9d28c8e7f017a4fbe1203c7431e745b (diff) | |
| download | skonfig-c-b881b02a54e18d0897822044b48730eaa2c7bb9c.tar.gz skonfig-c-b881b02a54e18d0897822044b48730eaa2c7bb9c.zip | |
Fix clang compile errors
Diffstat (limited to 'src/util')
| -rw-r--r-- | src/util/string.c | 23 | ||||
| -rw-r--r-- | src/util/string.h | 10 |
2 files changed, 23 insertions, 10 deletions
diff --git a/src/util/string.c b/src/util/string.c index c760b06..b17823e 100644 --- a/src/util/string.c +++ b/src/util/string.c @@ -68,6 +68,8 @@ size_t _vstrjoin_r(char *restrict buf, size_t buflen, char sep, va_list ap) { const char *s; size_t len = 0; + buflen /= sizeof(*buf); /* convert buflen to an "array length limit" */ + if (NULL != buf && 0 < buflen) { /* clear buf string */ *buf = '\0'; @@ -82,37 +84,48 @@ size_t _vstrjoin_r(char *restrict buf, size_t buflen, char sep, va_list ap) { ++len; } - if (NULL != buf) { + if (NULL != buf && 0 < (buflen - len)) { /* append element */ strncpy(buf+len, s, (buflen - len)); } len += strlen(s); } + if (NULL != buf && 0 < buflen) *(buf + buflen-1) = '\0'; + return len; } size_t _strjoin_r( - char *restrict buf, size_t buflen, char sep, /* const char *restrict */...) { + char sep, char *restrict buf, size_t buflen, /* const char *restrict */...) { va_list ap; - va_start(ap, sep); + va_start(ap, buflen); size_t len = _vstrjoin_r(buf, buflen, sep, ap); va_end(ap); return len; } -char *_strjoin(char sep, /* const char *restrict */...) { +/** NOTE: the _ argument is added to "hack" around undefined behaviour if the + * last non-variadic argument undergoes argument promotion. + * This results in a compile error on (at least) clang: + * + * src/util/string.c:130:16: error: passing an object that undergoes default + * argument promotion to 'va_start' has undefined behavior [-Werror,-Wvarargs] + */ +char *_strjoin(char sep, void *_, /* const char *restrict */...) { va_list ap; /* determine length of result string */ - va_start(ap, sep); + va_start(ap, _); size_t len = _vstrjoin_r(NULL, 0, sep, ap); va_end(ap); /* allocate destination buffer */ char *dest = malloc(len+1); if (NULL != dest) { + va_start(ap, _); (void)_vstrjoin_r(dest, len+1, sep, ap); + va_end(ap); } return dest; diff --git a/src/util/string.h b/src/util/string.h index b75e783..5e31e21 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -132,9 +132,9 @@ size_t stranjoin_r( char *_strjoin( /* internal */ - char sep, /* const char * */...); + char sep, void *_, /* const char * */...); size_t _strjoin_r( /* internal */ - char *restrict buf, size_t buflen, char sep, /* const char * */...); + char sep, char *restrict buf, size_t buflen, /* const char * */...); /** * strjoin: @@ -146,20 +146,20 @@ size_t _strjoin_r( /* internal */ * @param ...: a list of strings to join * @return a newly-allocated string containing all of the strings joined */ -#define strjoin(sep, ...) _strjoin(sep, __VA_ARGS__, NULL) +#define strjoin(sep, ...) _strjoin(sep, NULL, __VA_ARGS__, NULL) /** * strjoin_r: * Joins a number of strings together to form one long string stored in a * caller-allocated buffer with the @separator inserted betwween each of them. * + * @param sep: a char to insert between each of the strings * @param buf: the destination buffer (nothing will be written to it if NULL) * @param buflen: the length of @buf - * @param sep: a char to insert between each of the strings * @param ...: a list of strings to join * @return the length of the untruncated joined string */ -#define strjoin_r(sep, ...) _strjoin_r(sep, __VA_ARGS__, NULL) +#define strjoin_r(buf, buflen, sep, ...) _strjoin_r(sep, buf, buflen, __VA_ARGS__, NULL) /** * pathjoin: |
