summaryrefslogtreecommitdiff
path: root/src/util
diff options
context:
space:
mode:
authorDennis Camera <skonfig@dtnr.ch>2022-08-22 23:41:16 +0200
committerDennis Camera <skonfig@dtnr.ch>2022-08-22 23:41:16 +0200
commitb881b02a54e18d0897822044b48730eaa2c7bb9c (patch)
treef3df60acf1ea75bbac95b2ffdeaf1f52edbd3181 /src/util
parent2f425cb9e9d28c8e7f017a4fbe1203c7431e745b (diff)
downloadskonfig-c-b881b02a54e18d0897822044b48730eaa2c7bb9c.tar.gz
skonfig-c-b881b02a54e18d0897822044b48730eaa2c7bb9c.zip
Fix clang compile errors
Diffstat (limited to 'src/util')
-rw-r--r--src/util/string.c23
-rw-r--r--src/util/string.h10
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: