aboutsummaryrefslogtreecommitdiff
path: root/vendor/librune
diff options
context:
space:
mode:
authorThomas Voss <mail@thomasvoss.com> 2024-01-23 16:06:31 +0100
committerThomas Voss <mail@thomasvoss.com> 2024-01-23 16:06:31 +0100
commit0a9060e335d59f0ccaf5d9600abbcb938db30928 (patch)
tree874deccfe6c9b5a0d225cd892b06229378761b2f /vendor/librune
parent851ca8da9d72fbc438420eab4a7de4d84fb5bc5d (diff)
Bump librune version
Diffstat (limited to 'vendor/librune')
-rw-r--r--vendor/librune/README.md1
-rw-r--r--vendor/librune/cbs.h144
-rwxr-xr-xvendor/librune/gen/gbrk1
-rw-r--r--vendor/librune/include/builder.h31
-rw-r--r--vendor/librune/include/internal/common.h2
-rw-r--r--vendor/librune/include/internal/gbrk_lookup.h1
-rw-r--r--vendor/librune/include/internal/types.h8
-rw-r--r--vendor/librune/include/utf8.h2
-rw-r--r--vendor/librune/lib/builder/u8strfit.c11
-rw-r--r--vendor/librune/lib/builder/u8strfree.c9
-rw-r--r--vendor/librune/lib/builder/u8strgrow.c41
-rw-r--r--vendor/librune/lib/builder/u8strinit.c17
-rw-r--r--vendor/librune/lib/builder/u8strpushr.c13
-rw-r--r--vendor/librune/lib/builder/u8strpushstr.c17
-rw-r--r--vendor/librune/lib/builder/u8strpushu8.c16
-rw-r--r--vendor/librune/make.c86
16 files changed, 294 insertions, 106 deletions
diff --git a/vendor/librune/README.md b/vendor/librune/README.md
index fa98774..5431551 100644
--- a/vendor/librune/README.md
+++ b/vendor/librune/README.md
@@ -22,6 +22,7 @@ This library contains the following headers:
1. `gbrk.h` — grapheme-iteration functions
2. `rune.h` — rune-constants, -macros, and -functions
3. `utf8.h` — UTF-8 encoding, decoding, iteration, etc.
+4. `builder.h` — string building functions
## Installation
diff --git a/vendor/librune/cbs.h b/vendor/librune/cbs.h
index bcf82df..b8b7ece 100644
--- a/vendor/librune/cbs.h
+++ b/vendor/librune/cbs.h
@@ -30,6 +30,9 @@
the program on error. If this is undesired behavior, feel free to edit the
functions to return errors.
+ IMPORTANT NOTE: This library is built with the assumption that the source
+ file for your build script and your build script are in the SAME DIRECTORY.
+
There are a few exceptions to the above rule, and they are documented.
This library does not aim to ever support Windows */
@@ -40,6 +43,7 @@
#ifdef __GNUC__
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-function"
+# pragma GCC diagnostic ignored "-Wparentheses"
#endif
/* Assert that the user is building for a supported platform. The only portable
@@ -87,7 +91,9 @@
# define noreturn [[noreturn]]
#else
# include <stdbool.h>
+# include <stddef.h>
# include <stdnoreturn.h>
+# define nullptr NULL
#endif
/* Give helpful diagnostics when people use die() incorrectly on GCC. C23
@@ -147,7 +153,8 @@ ATTR_FMT noreturn static void die(const char *_Nullable, ...);
ATTR_FMT noreturn static void diex(const char *, ...);
/* Initializes some data required for this header to work properly. This should
- be the first thing called in main() with argc and argv passed. */
+ be the first thing called in main() with argc and argv passed. It also
+ chdir()s into the directory where the build script is located. */
static void cbsinit(int, char **);
/* Get the number of items in the array a */
@@ -253,7 +260,10 @@ static bool foutdatedv(const char *base, const char **p, size_t n);
/* Rebuild the build script if it has been modified, and execute the newly built
script. You should call the rebuild() macro at the very beginning of main(),
but right after cbsinit(). You probably don’t want to call _rebuild()
- directly. */
+ directly.
+
+ NOTE: This function/macro REQUIRES that the source for the build script and
+ the compiled build script are in the SAME DIRECTORY. */
static void _rebuild(char *);
#define rebuild() _rebuild(__FILE__)
@@ -339,7 +349,7 @@ void
strvfree(struct strv *v)
{
free(v->buf);
- *v = (struct strv){0};
+ memset(v, 0, sizeof(*v));
}
void *
@@ -388,8 +398,10 @@ diex(const char *fmt, ...)
void
cbsinit(int argc, char **argv)
{
+ char *s;
+
_cbs_argc = argc;
- _cbs_argv = bufalloc(NULL, argc, sizeof(char *));
+ _cbs_argv = bufalloc(nullptr, argc, sizeof(char *));
for (int i = 0; i < argc; i++) {
if (!(_cbs_argv[i] = strdup(argv[i]))) {
/* We might not have set _cbs_argv[0] yet, so we can’t use die() */
@@ -397,18 +409,38 @@ cbsinit(int argc, char **argv)
exit(EXIT_FAILURE);
}
}
+
+ /* Cd to dirname(argv[0]). We can’t use dirname(3) because it may modify
+ the source string. */
+ if (s = strrchr(_cbs_argv[0], '/')) {
+ s[0] = '\0';
+ if (chdir(_cbs_argv[0]) == -1)
+ die("chdir: %s", s);
+ s[0] = '/';
+ }
}
static size_t
-_next_powerof2(size_t n)
+_next_powerof2(size_t x)
{
- if (n && !(n & (n - 1)))
- return n;
+#if defined(__has_builtin) && __has_builtin(__builtin_clzl)
+ x = x <= 1 ? 1 : 1 << (64 - __builtin_clzl(x - 1));
+#else
+ if (x) {
+ x--;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ if (sizeof(size_t) >= 4)
+ x |= x >> 16;
+ if (sizeof(size_t) >= 8)
+ x |= x >> 32;
+ }
+ x++;
+#endif
- n--;
- for (size_t i = 1; i < sizeof(size_t); i <<= 1)
- n |= n >> i;
- return n + 1;
+ return x;
}
bool
@@ -430,7 +462,7 @@ binexists(const char *name)
return true;
}
- p = strtok(NULL, ":");
+ p = strtok(nullptr, ":");
}
free(path);
@@ -447,14 +479,14 @@ cmdaddv(cmd_t *cmd, char **xs, size_t n)
memcpy(cmd->_argv + cmd->_len, xs, n * sizeof(*xs));
cmd->_len += n;
- cmd->_argv[cmd->_len] = NULL;
+ cmd->_argv[cmd->_len] = nullptr;
}
void
cmdclr(cmd_t *c)
{
c->_len = 0;
- *c->_argv = NULL;
+ *c->_argv = nullptr;
}
int
@@ -508,7 +540,7 @@ cmdexecb(cmd_t c, char **p, size_t *n)
close(fds[FD_W]);
- buf = NULL;
+ buf = nullptr;
len = 0;
blksize = fstat(fds[FD_R], &sb) == -1 ? BUFSIZ : sb.st_blksize;
@@ -679,62 +711,44 @@ foutdatedv(const char *src, const char **deps, size_t n)
return false;
}
-static char *
-_getcwd(void)
-{
- char *buf = NULL;
- size_t n = 0;
-
- for (;;) {
- n += PATH_MAX;
- buf = bufalloc(buf, n, sizeof(char));
- if (getcwd(buf, n))
- break;
- if (errno != ERANGE)
- die("getcwd");
- }
-
- return buf;
-}
-
void
_rebuild(char *src)
{
- char *cwd, *cpy1, *cpy2, *dn, *bn;
+ char *bbn, *sbn, *argv0;
cmd_t cmd = {0};
-
- cwd = _getcwd();
- if (!(cpy1 = strdup(*_cbs_argv)))
- die("strdup");
- if (!(cpy2 = strdup(*_cbs_argv)))
- die("strdup");
- dn = dirname(cpy1);
- bn = basename(cpy2);
-
- if (chdir(dn) == -1)
- die("chdir: %s", dn);
- if (!foutdated(bn, src)) {
- if (chdir(cwd) == -1)
- die("chdir: %s", cwd);
- free(cpy1);
- free(cpy2);
- free(cwd);
+ size_t bufsiz;
+
+ /* We assume that the compiled binary and the source file are in the same
+ directory. */
+ if (sbn = strrchr(src, '/'))
+ sbn++;
+ else
+ sbn = src;
+ if (bbn = strrchr(*_cbs_argv, '/'))
+ bbn++;
+ else
+ bbn = src;
+
+ if (!foutdated(bbn, sbn))
return;
- }
cmdadd(&cmd, "cc");
#ifdef CBS_PTHREAD
cmdadd(&cmd, "-lpthread");
#endif
- cmdadd(&cmd, "-o", bn, src);
+ cmdadd(&cmd, "-o", bbn, sbn);
cmdput(cmd);
if (cmdexec(cmd))
diex("Compilation of build script failed");
cmdclr(&cmd);
- if (chdir(cwd) == -1)
- die("chdir: %s", cwd);
+ argv0 = bufalloc(nullptr, strlen(bbn) + 3, 1);
+ *_cbs_argv = argv0;
+
+ *argv0++ = '.';
+ *argv0++ = '/';
+ strcpy(argv0, bbn);
cmdaddv(&cmd, _cbs_argv, _cbs_argc);
execvp(*cmd._argv, cmd._argv);
@@ -761,7 +775,7 @@ pcquery(struct strv *vec, char *lib, int flags)
cmd_t c = {0};
wordexp_t we;
- p = NULL;
+ p = nullptr;
cmdadd(&c, "pkg-config");
if (flags & PKGC_LIBS)
@@ -840,7 +854,7 @@ _tpwork(void *arg)
pthread_mutex_unlock(&tp->_mtx);
}
- return NULL;
+ return nullptr;
}
void
@@ -849,13 +863,13 @@ tpinit(tpool_t *tp, size_t n)
tp->_tcnt = n;
tp->_stop = false;
tp->_left = 0;
- tp->_head = tp->_tail = NULL;
- tp->_thrds = bufalloc(NULL, n, sizeof(pthread_t));
- pthread_cond_init(&tp->_cnd, NULL);
- pthread_mutex_init(&tp->_mtx, NULL);
+ tp->_head = tp->_tail = nullptr;
+ tp->_thrds = bufalloc(nullptr, n, sizeof(pthread_t));
+ pthread_cond_init(&tp->_cnd, nullptr);
+ pthread_mutex_init(&tp->_mtx, nullptr);
for (size_t i = 0; i < n; i++)
- pthread_create(tp->_thrds + i, NULL, _tpwork, tp);
+ pthread_create(tp->_thrds + i, nullptr, _tpwork, tp);
}
void
@@ -868,7 +882,7 @@ tpfree(tpool_t *tp)
pthread_mutex_unlock(&tp->_mtx);
for (size_t i = 0; i < tp->_tcnt; i++)
- pthread_join(tp->_thrds[i], NULL);
+ pthread_join(tp->_thrds[i], nullptr);
free(tp->_thrds);
while (tp->_head) {
@@ -890,7 +904,7 @@ _tpdeq(tpool_t *tp)
if (j) {
tp->_head = tp->_head->next;
if (!tp->_head)
- tp->_tail = NULL;
+ tp->_tail = nullptr;
}
return j;
@@ -899,7 +913,7 @@ _tpdeq(tpool_t *tp)
void
tpenq(tpool_t *tp, tfunc_t fn, void *arg, tfree_func_t free)
{
- struct _tjob *j = bufalloc(NULL, 1, sizeof(struct _tjob));
+ struct _tjob *j = bufalloc(nullptr, 1, sizeof(struct _tjob));
*j = (struct _tjob){
.fn = fn,
.arg = arg,
diff --git a/vendor/librune/gen/gbrk b/vendor/librune/gen/gbrk
index 5cbd87f..58e47b4 100755
--- a/vendor/librune/gen/gbrk
+++ b/vendor/librune/gen/gbrk
@@ -31,6 +31,7 @@ cat <<C
#ifndef RUNE_INTERNAL_GBRK_LOOKUP_H
#define RUNE_INTERNAL_GBRK_LOOKUP_H
+/* IWYU pragma: private */
/* clang-format off */
#include "types.h"
diff --git a/vendor/librune/include/builder.h b/vendor/librune/include/builder.h
new file mode 100644
index 0000000..b711f97
--- /dev/null
+++ b/vendor/librune/include/builder.h
@@ -0,0 +1,31 @@
+#ifndef RUNE_BUILDER_H
+#define RUNE_BUILDER_H
+
+#define _RUNE_NEEDS_U8VIEW 1
+#include "internal/types.h" /* IWYU pragma: export */
+
+struct u8buf {
+ char8_t *p;
+ size_t len, cap;
+};
+
+struct u8buf *u8strinit(struct u8buf *, size_t);
+struct u8buf *u8strgrow(struct u8buf *, size_t);
+struct u8buf *u8strfit(struct u8buf *);
+void u8strfree(struct u8buf);
+
+struct u8buf *u8strpushr(struct u8buf *, rune);
+struct u8buf *u8strpushstr(struct u8buf *, const char *);
+struct u8buf *u8strpushu8(struct u8buf *, struct u8view);
+
+#if __STDC_VERSION__ >= 201112L
+# define u8strpush(b, x) \
+ _Generic((x), \
+ char: u8strpushr, \
+ int: u8strpushr, \
+ rune: u8strpushr, \
+ char *: u8strpushstr, \
+ struct u8view: u8strpushu8)((b), (x))
+#endif
+
+#endif /* !RUNE_BUILDER_H */
diff --git a/vendor/librune/include/internal/common.h b/vendor/librune/include/internal/common.h
index 7107528..af490d3 100644
--- a/vendor/librune/include/internal/common.h
+++ b/vendor/librune/include/internal/common.h
@@ -1,6 +1,8 @@
#ifndef RUNE_INTERNAL_COMMON_H
#define RUNE_INTERNAL_COMMON_H
+/* IWYU pragma: private */
+
#if __STDC_VERSION__ >= 202311L
# define RUNE_IS_23 1
#endif
diff --git a/vendor/librune/include/internal/gbrk_lookup.h b/vendor/librune/include/internal/gbrk_lookup.h
index 39dfa8e..043be97 100644
--- a/vendor/librune/include/internal/gbrk_lookup.h
+++ b/vendor/librune/include/internal/gbrk_lookup.h
@@ -5,6 +5,7 @@
#ifndef RUNE_INTERNAL_GBRK_LOOKUP_H
#define RUNE_INTERNAL_GBRK_LOOKUP_H
+/* IWYU pragma: private */
/* clang-format off */
#include "types.h"
diff --git a/vendor/librune/include/internal/types.h b/vendor/librune/include/internal/types.h
index b2fa34c..b7ce6f1 100644
--- a/vendor/librune/include/internal/types.h
+++ b/vendor/librune/include/internal/types.h
@@ -1,5 +1,4 @@
-#ifndef RUNE_INTERNAL_TYPES_H
-#define RUNE_INTERNAL_TYPES_H
+/* IWYU pragma: private */
#include <stddef.h> /* IWYU pragma: export */
#include <stdint.h>
@@ -8,10 +7,11 @@ typedef unsigned char char8_t;
typedef uint_least32_t rune;
#if _RUNE_NEEDS_U8VIEW
+# if !_RUNE_HAS_U8VIEW
struct u8view {
const char8_t *p;
size_t len;
};
+# define _RUNE_HAS_U8VIEW 1
+# endif
#endif
-
-#endif /* !RUNE_INTERNAL_TYPES_H */
diff --git a/vendor/librune/include/utf8.h b/vendor/librune/include/utf8.h
index 0ebd745..1a91c24 100644
--- a/vendor/librune/include/utf8.h
+++ b/vendor/librune/include/utf8.h
@@ -18,7 +18,7 @@ int u8tor(rune *, const char8_t *);
int u8tor_uc(rune *, const char8_t *);
const char8_t *u8chk(const char8_t *, size_t);
-bool u8chkr(rune);
+_RUNE_UNSEQUENCED bool u8chkr(rune);
_RUNE_UNSEQUENCED int u8wdth(rune);
diff --git a/vendor/librune/lib/builder/u8strfit.c b/vendor/librune/lib/builder/u8strfit.c
new file mode 100644
index 0000000..c59b4b0
--- /dev/null
+++ b/vendor/librune/lib/builder/u8strfit.c
@@ -0,0 +1,11 @@
+#include <stdlib.h>
+
+#include "builder.h"
+
+#include "internal/common.h"
+
+struct u8buf *
+u8strfit(struct u8buf *b)
+{
+ return (b->p = realloc(b->p, b->len)) ? b : nullptr;
+}
diff --git a/vendor/librune/lib/builder/u8strfree.c b/vendor/librune/lib/builder/u8strfree.c
new file mode 100644
index 0000000..f425691
--- /dev/null
+++ b/vendor/librune/lib/builder/u8strfree.c
@@ -0,0 +1,9 @@
+#include <stdlib.h>
+
+#include "builder.h"
+
+void
+u8strfree(struct u8buf b)
+{
+ free(b.p);
+}
diff --git a/vendor/librune/lib/builder/u8strgrow.c b/vendor/librune/lib/builder/u8strgrow.c
new file mode 100644
index 0000000..253fcfc
--- /dev/null
+++ b/vendor/librune/lib/builder/u8strgrow.c
@@ -0,0 +1,41 @@
+#include <stdlib.h>
+
+#include "builder.h"
+
+#include "internal/common.h"
+
+static size_t nextpow2(size_t);
+
+struct u8buf *
+u8strgrow(struct u8buf *b, size_t n)
+{
+ if (n > b->cap) {
+ b->cap = nextpow2(n);
+ if (!(b->p = realloc(b->p, b->cap)))
+ return nullptr;
+ }
+ return b;
+}
+
+size_t
+nextpow2(size_t x)
+{
+#if defined(__has_builtin) && __has_builtin(__builtin_clzl)
+ x = x <= 1 ? 1 : 1 << (64 - __builtin_clzl(x - 1));
+#else
+ if (x) {
+ x--;
+ x |= x >> 1;
+ x |= x >> 2;
+ x |= x >> 4;
+ x |= x >> 8;
+ if (sizeof(size_t) >= 4)
+ x |= x >> 16;
+ if (sizeof(size_t) >= 8)
+ x |= x >> 32;
+ }
+ x++;
+#endif
+
+ return x;
+}
diff --git a/vendor/librune/lib/builder/u8strinit.c b/vendor/librune/lib/builder/u8strinit.c
new file mode 100644
index 0000000..caf061e
--- /dev/null
+++ b/vendor/librune/lib/builder/u8strinit.c
@@ -0,0 +1,17 @@
+#include <stdlib.h>
+
+#include "builder.h"
+
+#include "internal/common.h"
+
+struct u8buf *
+u8strinit(struct u8buf *b, size_t n)
+{
+ if (n && !(b->p = malloc(n)))
+ return nullptr;
+ else
+ b->p = nullptr;
+ b->len = 0;
+ b->cap = n;
+ return b;
+}
diff --git a/vendor/librune/lib/builder/u8strpushr.c b/vendor/librune/lib/builder/u8strpushr.c
new file mode 100644
index 0000000..89bb64f
--- /dev/null
+++ b/vendor/librune/lib/builder/u8strpushr.c
@@ -0,0 +1,13 @@
+#include "builder.h"
+#include "utf8.h"
+
+#include "internal/common.h"
+
+struct u8buf *
+u8strpushr(struct u8buf *b, rune ch)
+{
+ if (!u8strgrow(b, b->len + u8wdth(ch)))
+ return nullptr;
+ b->len += rtou8(b->p + b->len, ch, b->cap - b->len);
+ return b;
+}
diff --git a/vendor/librune/lib/builder/u8strpushstr.c b/vendor/librune/lib/builder/u8strpushstr.c
new file mode 100644
index 0000000..b80ad35
--- /dev/null
+++ b/vendor/librune/lib/builder/u8strpushstr.c
@@ -0,0 +1,17 @@
+#include <string.h>
+
+#include "builder.h"
+#include "utf8.h"
+
+#include "internal/common.h"
+
+struct u8buf *
+u8strpushstr(struct u8buf *b, const char *s)
+{
+ size_t n = strlen(s);
+ if (!u8strgrow(b, b->len + n))
+ return nullptr;
+ memcpy(b->p + b->len, s, n);
+ b->len += n;
+ return b;
+}
diff --git a/vendor/librune/lib/builder/u8strpushu8.c b/vendor/librune/lib/builder/u8strpushu8.c
new file mode 100644
index 0000000..0bcf9fc
--- /dev/null
+++ b/vendor/librune/lib/builder/u8strpushu8.c
@@ -0,0 +1,16 @@
+#include <string.h>
+
+#include "builder.h"
+#include "utf8.h"
+
+#include "internal/common.h"
+
+struct u8buf *
+u8strpushu8(struct u8buf *b, struct u8view v)
+{
+ if (!u8strgrow(b, b->len + v.len))
+ return nullptr;
+ memcpy(b->p + b->len, v.p, v.len);
+ b->len += v.len;
+ return b;
+}
diff --git a/vendor/librune/make.c b/vendor/librune/make.c
index c8a2d4d..a7227c9 100644
--- a/vendor/librune/make.c
+++ b/vendor/librune/make.c
@@ -1,6 +1,7 @@
#include <errno.h>
#include <glob.h>
#include <libgen.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -26,48 +27,59 @@
cmdclr(&c); \
} while (0)
+#define streq(a, b) (!strcmp(a, b))
+
static void work(void *);
static int globerr(const char *, int);
int
main(int argc, char **argv)
{
- cmd_t c = {0};
- size_t n;
- glob_t g;
- tpool_t tp;
-
cbsinit(argc, argv);
rebuild();
- if (chdir(dirname(*argv)) == -1)
- die("chdir");
-
- if (glob("lib/utf8/*.c", 0, globerr, &g)
- || glob("lib/gbrk/*.c", GLOB_APPEND, globerr, &g))
- {
- die("glob");
+ if (argc > 1) {
+ if (streq(argv[1], "clean")) {
+ cmd_t c = {0};
+ cmdadd(&c, "find", ".", "-name", "*.[ao]", "-delete");
+ cmdprc(c);
+ } else {
+ diex("invalid subcommand -- '%s'", argv[1]);
+ exit(EXIT_FAILURE);
+ }
+ } else {
+ cmd_t c = {0};
+ size_t n;
+ glob_t g;
+ tpool_t tp;
+
+ if (glob("lib/*/*.c", 0, globerr, &g))
+ die("glob");
+
+ if ((n = nproc()) == -1) {
+ if (errno)
+ die("nproc");
+ n = 8;
+ }
+
+ tpinit(&tp, n);
+ for (size_t i = 0; i < g.gl_pathc; i++)
+ tpenq(&tp, work, g.gl_pathv[i], NULL);
+ tpwait(&tp);
+ tpfree(&tp);
+
+ for (size_t i = 0; i < g.gl_pathc; i++)
+ g.gl_pathv[i][strlen(g.gl_pathv[i]) - 1] = 'o';
+
+ if (foutdatedv("librune.a", (const char **)g.gl_pathv, g.gl_pathc)) {
+ cmdadd(&c, "ar", "rcs", "librune.a");
+ cmdaddv(&c, g.gl_pathv, g.gl_pathc);
+ cmdprc(c);
+ }
+
+ globfree(&g);
}
- if ((n = nproc()) == -1) {
- if (errno)
- die("nproc");
- n = 8;
- }
-
- tpinit(&tp, n);
- for (size_t i = 0; i < g.gl_pathc; i++)
- tpenq(&tp, work, g.gl_pathv[i], NULL);
- tpwait(&tp);
- tpfree(&tp);
-
- cmdadd(&c, "ar", "rcs", "librune.a");
- for (size_t i = 0; i < g.gl_pathc; i++)
- g.gl_pathv[i][strlen(g.gl_pathv[i]) - 1] = 'o';
- cmdaddv(&c, g.gl_pathv, g.gl_pathc);
- cmdprc(c);
-
- globfree(&g);
return EXIT_SUCCESS;
}
@@ -82,11 +94,13 @@ work(void *p)
die("strdup");
dst[strlen(dst) - 1] = 'o';
- env_or_default(&sv, "CC", CC);
- env_or_default(&sv, "CFLAGS", CFLAGS);
- cmdaddv(&c, sv.buf, sv.len);
- cmdadd(&c, "-Iinclude", "-fPIC", "-o", dst, "-c", src);
- cmdprc(c);
+ if (foutdated(dst, src)) {
+ env_or_default(&sv, "CC", CC);
+ env_or_default(&sv, "CFLAGS", CFLAGS);
+ cmdaddv(&c, sv.buf, sv.len);
+ cmdadd(&c, "-Iinclude", "-fPIC", "-o", dst, "-c", src);
+ cmdprc(c);
+ }
free(dst);
}