This is a reattempt of
4291cc769a3eeef8b1c171e5479194733a4da6cd. The first
attempt introduced a bug where the separating `.` was not accounted for and
accidentally truncated. It was reverted in
8d662734b6a34709d9475b120e7ce3de872339e2. The present commit takes much the same
approach but ensures to account for the separating `.`.
Quoting
4291cc769a3eeef8b1c171e5479194733a4da6cd:
This block of code is scanning a string of `:`-separated entries and writing
them into `buf` in reverse order `.`-separated. We can rewrite it to avoid
dynamic allocation, thus avoiding certain failure cases and locking overhead.
Unfortunately there seems to be no variant of `strrchr` that takes a length.
So we need to write our own loop for locating the last `:` with a limit.
#include <ctype.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
static char *buf;
static size_t bufsz;
char gidx[100]; /* large enough for '.' plus any integer */
- char *fn, *p, *q;
+ char *fn;
size_t len;
if (job->graph_index)
strcpy(buf, fn);
strcat(buf, gidx);
strcat(buf, ".");
- p = strdup(job->output_langname);
- while ((q = strrchr(p, ':'))) {
- strcat(buf, q+1);
- strcat(buf, ".");
- *q = '\0';
+
+ {
+ char *dst = buf + strlen(buf);
+ const char *src = job->output_langname;
+ const char *src_end = src + strlen(src);
+ for (const char *q = src_end; ; --q) {
+ if (*q == ':') {
+ dst += sprintf(dst, "%.*s.", (int)(src_end - q - 1), q + 1);
+ src_end = q;
+ }
+ if (q == src) {
+ sprintf(dst, "%.*s", (int)(src_end - src), src);
+ break;
+ }
+ }
}
- strcat(buf, p);
- free(p);
job->output_filename = buf;
}