diff options
| author | 2026-01-12 19:22:06 +0100 | |
|---|---|---|
| committer | 2026-01-12 19:22:06 +0100 | |
| commit | e13aba91f8668224e2de0977a0beebf52ec6d65d (patch) | |
| tree | 421acaea455ef0fdc5abe8c44bca52ef1c463fe7 | |
| parent | 8202d977ba9950836d7e984c2c7e0aab859122b4 (diff) | |
driver: -iquote, -isystem, etc
With GCC-like search order
| -rw-r--r-- | c/lex.c | 42 | ||||
| -rw-r--r-- | common.h | 17 | ||||
| -rw-r--r-- | main.c | 46 |
3 files changed, 74 insertions, 31 deletions
@@ -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); @@ -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 */ @@ -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 |