aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2026-01-12 19:22:06 +0100
committerlemon <lsof@mailbox.org>2026-01-12 19:22:06 +0100
commite13aba91f8668224e2de0977a0beebf52ec6d65d (patch)
tree421acaea455ef0fdc5abe8c44bca52ef1c463fe7
parent8202d977ba9950836d7e984c2c7e0aab859122b4 (diff)
driver: -iquote, -isystem, etc
With GCC-like search order
-rw-r--r--c/lex.c42
-rw-r--r--common.h17
-rw-r--r--main.c46
3 files changed, 74 insertions, 31 deletions
diff --git a/c/lex.c b/c/lex.c
index f1dab08..f1d29c9 100644
--- a/c/lex.c
+++ b/c/lex.c
@@ -1605,24 +1605,36 @@ ppinclude(struct lexer *lx, const struct span *span0)
path[end - base + tk.len] = 0;
if (tryinclude(lx, &span, path)) return;
}
- /* try embedded files pseudo-path */
- xbgrow(&path, tk.len + 3);
- path[0] = '@', path[1] = ':';
- memcpy(path+2, tk.s, tk.len);
- path[tk.len+2] = 0;
- if (tryinclude(lx, &span, path)) return;
- /* try system paths */
- for (struct inclpaths *p = cinclpaths; p; p = p->next) {
- int ndir = strlen(p->path);
- xbgrow(&path, ndir + tk.len + 2);
- memcpy(path, p->path, ndir);
- path[ndir++] = '/';
- memcpy(path + ndir, tk.s, tk.len);
- path[ndir + tk.len] = 0;
- if (tryinclude(lx, &span, path)) return;
+ /* try system paths. order:
+ * 1. -iquote
+ * 2. -I
+ * 3. -isystem
+ * 4. embedded include files
+ * 5. standard system includes
+ * 6. -idirafter
+ */
+ for (int i = (tk.t != TKPPHDRQ); i < countof(cinclpaths); ++i) {
+ for (struct inclpath *p = cinclpaths[i].list; p; p = p->next) {
+ if (i == CINCLsys) {
+ /* try embedded files pseudo-path */
+ xbgrow(&path, tk.len + 3);
+ path[0] = '@', path[1] = ':';
+ memcpy(path+2, tk.s, tk.len);
+ path[tk.len+2] = 0;
+ if (tryinclude(lx, &span, path)) return;
+ }
+ int ndir = strlen(p->path);
+ xbgrow(&path, ndir + tk.len + 2);
+ memcpy(path, p->path, ndir);
+ path[ndir++] = '/';
+ memcpy(path + ndir, tk.s, tk.len);
+ path[ndir + tk.len] = 0;
+ if (tryinclude(lx, &span, path)) return;
+ }
}
NotFound:
error(&tk.span, "file not found: %'S", tk.s, tk.len);
+ xbfree(path);
} else {
error(&tk.span, "expected \"header\" or <header>");
ppskipline(lx);
diff --git a/common.h b/common.h
index ac4bc88..81e34c5 100644
--- a/common.h
+++ b/common.h
@@ -153,10 +153,19 @@ struct option {
struct wbuf *dbgout;
};
extern struct option ccopt;
-extern struct inclpaths {
- struct inclpaths *next;
- const char *path;
-} *cinclpaths;
+extern struct cinclpaths {
+ struct inclpath {
+ struct inclpath *next;
+ const char *path;
+ } *list, **tail;
+} cinclpaths[5];
+enum { /* GCC include directory search order: https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html#Options-for-Directory-Search */
+ CINCL_iquote,
+ CINCL_I,
+ CINCL_isystem,
+ CINCLsys,
+ CINCL_idirafter,
+};
/**********/
/* Target */
diff --git a/main.c b/main.c
index ccfa1a4..74e61e4 100644
--- a/main.c
+++ b/main.c
@@ -11,15 +11,21 @@
#include <time.h>
struct option ccopt;
-struct inclpaths *cinclpaths;
+struct cinclpaths cinclpaths[5];
static void
-addinclpath(const char *path)
+addinclpath(int ord, const char *path)
{
- struct inclpaths *p = alloc(&globarena, sizeof *cinclpaths, 0);
- p->next = cinclpaths;
+ struct inclpath *p = alloc(&globarena, sizeof *p, 0);
+ assert((uint)ord < countof(cinclpaths));
p->path = path;
- cinclpaths = p;
+ p->next = NULL;
+ if (cinclpaths[ord].list) {
+ *cinclpaths[ord].tail = p;
+ } else {
+ cinclpaths[ord].list = p;
+ }
+ cinclpaths[ord].tail = &p->next;
}
/* parse an argument of the form 'opt=abcd'
@@ -130,6 +136,7 @@ optparse(char **args)
}
continue;
}
+ int cinclord;
if (!strcmp(arg, "help") || !strcmp(arg, "h") || !strcmp(arg, "-help")) {
prihelp();
exit(0);
@@ -190,7 +197,7 @@ optparse(char **args)
const char *s = *++args;
if (!s) fatal(NULL, "missing target name");
task.targ = s;
- } else if (*arg == 'l' || *arg == 'L') {
+ } else if (*arg == 'l' || *arg == 'L' || *arg == 'B') {
vpush(&task.linkargs, arg-1);
} else if (!strcmp(arg, "v") || !strcmp(arg, "-verbose")) {
task.verbose = 1;
@@ -211,7 +218,8 @@ optparse(char **args)
} else if (*arg == 'g') {
/* TODO debug info */
} else if (*arg == 'O') {
- if (!arg[1] || (uint)arg[1] - '1' < 9) ccopt.o = OPT1;
+ if (!arg[1]) ccopt.o = 0; /* default opts */
+ else if ((uint)arg[1] - '1' < 9) ccopt.o = OPT1;
else if (arg[1] == '0') ccopt.o = OPT0;
else goto Bad;
} else if (*arg == 'D' || *arg == 'U') {
@@ -221,10 +229,24 @@ optparse(char **args)
cpppredef(*arg == 'U', def);
} else if (*arg == 'O') {
/* TODO optimization level */
- } else if (*arg == 'I') {
- const char *p = arg[1] ? arg+1 : *++args;
- if (!p) fatal(NULL, "missing path after `-I`");
- else addinclpath(p);
+ } else if (*arg == 'I' || !strcmp(arg, "-include-directory")) {
+ const char *p;
+ cinclord = CINCL_I;
+ if (*arg == 'I' && arg[1]) p = arg+1;
+ else CIncl: p = *++args;
+ if (!p) fatal(NULL, "missing path after `%s`", arg-1);
+ addinclpath(cinclord, p);
+ } else if (!strcmp(arg, "iquote")) {
+ cinclord = CINCL_iquote;
+ goto CIncl;
+ } else if (!strcmp(arg, "isystem")) {
+ cinclord = CINCL_isystem;
+ goto CIncl;
+ } else if (!strcmp(arg, "idirafter")) {
+ cinclord = CINCL_idirafter;
+ goto CIncl;
+ } else if (!strcmp(arg, "nostdinc") || !strcmp(arg, "-no-standard-includes")) {
+ cinclpaths[CINCLsys].list = NULL;
} else if (*arg == 'M') {
++arg;
if (*arg == 'F' || *arg == 'T' || *arg == 'Q') {
@@ -616,7 +638,7 @@ sysinclpaths(void)
HOST_INCLUDE_DIRS
};
for (int i = 0; i < countof(paths); ++i)
- addinclpath(paths[i]);
+ addinclpath(CINCLsys, paths[i]);
}
static void