diff options
| author | Sam Ravnborg <sam@ravnborg.org> | 2005-01-18 16:15:25 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-07 21:06:15 -0700 |
| commit | 99efcabf79a1d6c5c48fa29abc8a895009b4aa72 (patch) | |
| tree | 0350282f9f05435c3c7417bb63090a205be4e571 | |
| parent | 423e91dbdcd2ee723ea8955ace6cf8749525f21a (diff) | |
| download | sparse-dev-99efcabf79a1d6c5c48fa29abc8a895009b4aa72.tar.gz | |
[PATCH] make include path handling gcc compatible
Search include paths in same order as gcc does.
In other words search directories specified with -I before system
directories.
This fixes a bug reported by a few persons after the kernel switched
over to use -isystem to specify where to find compiler specific include files.
Sparse now supports the following include path relevant options:
-I dir Add dir to list of directories to search for. Search dir
before system dirs. Used for both <> and "" includes.
-I- Split include path - previous -I dir paths only used for
include "".
Also disable searching same dir as input file.
-isystem dir Add dir first in row of system dirs to search.
-dirafter dir Add dir in end of system dirs to search.
-nostdinc Discard all defined system dirs
The -iwithprefix, -iprefix and -iwithprefixbefore options are not not
supported and silently ignored. gcc discourage use of these options.
| -rw-r--r-- | lib.c | 24 | ||||
| -rw-r--r-- | pre-process.c | 192 | ||||
| -rw-r--r-- | token.h | 1 | ||||
| -rw-r--r-- | tokenize.c | 1 |
4 files changed, 166 insertions, 52 deletions
@@ -428,16 +428,8 @@ char **handle_switch_I(char *arg, char **next) switch (arg[1]) { case '-': - /* Explaining '-I-' with a google search: - * - * "Specifying -I after -I- searches for #include directories. - * If -I- is specified before, it searches for #include "file" - * and not #include ." - * - * Which didn't explain it at all to me. Maybe somebody else can - * explain it properly. We ignore it for now. - */ - return next; + add_pre_buffer("#split_include\n"); + break; case '\0': /* Plain "-I" */ path = *++next; @@ -465,7 +457,7 @@ char **handle_switch_i(char *arg, char **next) char *path = *++next; if (!path) die("missing argument for -isystem option"); - add_pre_buffer("#add_include \"%s/\"\n", path); + add_pre_buffer("#add_isystem \"%s/\"\n", path); } return next; } @@ -559,6 +551,15 @@ char **handle_nostdinc(char *arg, char **next) return next; } +char **handle_dirafter(char *arg, char **next) +{ + char *path = *++next; + if (!path) + die("missing argument for -dirafter option"); + add_pre_buffer("#add_dirafter \"%s/\"\n", path); + return next; +} + struct switches { const char *name; char **(*fn)(char *, char**); @@ -569,6 +570,7 @@ char **handle_switch(char *arg, char **next) char **rc = next; static struct switches cmd[] = { { "nostdinc", handle_nostdinc }, + { "dirafter", handle_dirafter }, { NULL, NULL } }; struct switches *s; diff --git a/pre-process.c b/pre-process.c index c502074d..ebc68910 100644 --- a/pre-process.c +++ b/pre-process.c @@ -38,14 +38,16 @@ enum { ELIF_IGNORE = 1, ELIF_SEEN_ELSE = 2 }; #define INCLUDEPATHS 300 const char *includepath[INCLUDEPATHS+1] = { + "", "/usr/include", "/usr/local/include", GCC_INTERNAL_INCLUDE, NULL }; -static const char **sys_includepath = includepath + 0; -static const char **gcc_includepath = includepath + 2; +static const char **quote_includepath = includepath; +static const char **angle_includepath = includepath + 1; +static const char **sys_includepath = includepath + 1; #define MARK_STREAM_NONCONST(pos) do { \ if (stream->constant != CONSTANT_FILE_NOPE) { \ @@ -613,9 +615,62 @@ static int already_tokenized(const char *path) return 0; } -static int try_include(const char *path, int plen, const char *filename, int flen, struct token **where, const char **next_path) +/* Hande include of header files. + * The relevant options are made compatible with gcc. The only options that + * are not supported is -withprefix and friends. + * + * Three set of include paths are known: + * quote_includepath: Path to search when using #include "file.h" + * angle_includepath: Path to search when using #include <file.h> + * sys_includepath: Built-in include paths + * + * The above is implmented as one array with pointes + * +--------------+ + * quote_includepath ---> | | + * +--------------+ + * | | + * +--------------+ + * angle_includepath ---> | | + * +--------------+ + * sys_includepath ---> | | + * +--------------+ + * | | + * +--------------+ + * + * -I dir insert dir just before sys_includepath and move the rest + * -I- makes all dirs specified with -I before to quote dirs only and + * angle_includepath is set equal to sys_includepath. + * -nostdinc removes all sys dirs be storing NULL in entry pointed + * to by * sys_includepath. Note this will reset all dirs built-in and added + * before -nostdinc by -isystem and -dirafter + * -isystem dir adds dir where sys_includepath points adding this dir as + * first systemdir + * -dirafter dir adds dir to the end of the list + **/ + +static void set_stream_include_path(struct stream *stream) +{ + const char *path = stream->path; + if (!path) { + const char *p = strrchr(stream->name, '/'); + path = ""; + if (p) { + int len = p - stream->name + 1; + char *m = malloc(len+1); + /* This includes the final "/" */ + memcpy(m, stream->name, len); + m[len] = 0; + path = m; + } + stream->path = path; + } + includepath[0] = path; +} + +static int try_include(const char *path, const char *filename, int flen, struct token **where, const char **next_path) { int fd; + int plen = strlen(path); static char fullname[PATH_MAX]; memcpy(fullname, path, plen); @@ -642,13 +697,12 @@ static int do_include_path(const char **pptr, struct token **list, struct token const char *path; while ((path = *pptr++) != NULL) { - if (!try_include(path, strlen(path), filename, flen, list, pptr)) + if (!try_include(path, filename, flen, list, pptr)) continue; return 1; } return 0; } - static void do_include(int local, struct stream *stream, struct token **list, struct token *token, const char *filename, const char **path) { @@ -656,24 +710,17 @@ static void do_include(int local, struct stream *stream, struct token **list, st /* Absolute path? */ if (filename[0] == '/') { - if (try_include("", 0, filename, flen, list, includepath)) + if (try_include("", filename, flen, list, includepath)) return; goto out; } - /* Same directory as current stream? */ - if (local) { - const char *path; - char *slash; - int plen; + /* Dir of inputfile is first dir to search for quoted includes */ + set_stream_include_path(stream); - path = stream->name; - slash = strrchr(path, '/'); - plen = slash ? slash - path : 0; - - if (try_include(path, plen, filename, flen, list, includepath)) - return; - } + if (!path) + /* Do not search quote include if <> is in use */ + path = local ? quote_includepath : angle_includepath; /* Check the standard include paths.. */ if (do_include_path(path, list, token, filename, flen)) @@ -723,7 +770,7 @@ static int handle_include_path(struct stream *stream, struct token **list, struc static int handle_include(struct stream *stream, struct token **list, struct token *token) { - return handle_include_path(stream, list, token, includepath); + return handle_include_path(stream, list, token, NULL); } static int handle_include_next(struct stream *stream, struct token **list, struct token *token) @@ -1328,8 +1375,6 @@ static int handle_error(struct stream *stream, struct token **line, struct token static int handle_nostdinc(struct stream *stream, struct token **line, struct token *token) { - int stdinc; - if (false_nesting) return free_preprocessor_line(token); @@ -1337,22 +1382,11 @@ static int handle_nostdinc(struct stream *stream, struct token **line, struct to * Do we have any non-system includes? * Clear them out if so.. */ - stdinc = gcc_includepath - sys_includepath; - if (stdinc) { - const char **src = gcc_includepath; - const char **dst = sys_includepath; - for (;;) { - if (!(*dst = *src)) - break; - dst++; - src++; - } - gcc_includepath -= stdinc; - } + *sys_includepath = NULL; return free_preprocessor_line(token); } -static void add_path_entry(struct token *token, const char *path) +static void add_path_entry(struct token *token, const char *path, const char ***where, const char **new_path) { const char **dst; const char *next; @@ -1361,13 +1395,19 @@ static void add_path_entry(struct token *token, const char *path) if (includepath[INCLUDEPATHS-2]) error_die(token->pos, "too many include path entries"); + /* check that this is not a duplicate */ + dst = includepath; + while (*dst) { + if (strcmp(*dst, path) == 0) + return; + dst++; + } next = path; - dst = sys_includepath; - sys_includepath++; - gcc_includepath++; + dst = *where; + *where = new_path; /* - * Move them all up starting at "sys_includepath", + * Move them all up starting at dst, * insert the new entry.. */ for (;;) { @@ -1390,10 +1430,77 @@ static int handle_add_include(struct stream *stream, struct token **line, struct warning(token->pos, "expected path string"); return 1; } - add_path_entry(token, token->string->data); + add_path_entry(token, token->string->data, &sys_includepath, sys_includepath + 1); + } +} + +static int handle_add_isystem(struct stream *stream, struct token **line, struct token *token) +{ + for (;;) { + token = token->next; + if (eof_token(token)) + return 1; + if (token_type(token) != TOKEN_STRING) { + warning(token->pos, "expected path string"); + return 1; + } + add_path_entry(token, token->string->data, &sys_includepath, sys_includepath); } } +/* Add to end on includepath list - no pointer updates */ +static void add_dirafter_entry(struct token *token, const char *path) +{ + const char **dst = includepath; + + /* Need one free entry.. */ + if (includepath[INCLUDEPATHS-2]) + error_die(token->pos, "too many include path entries"); + + /* Add to the end */ + while (*dst) + dst++; + *dst = path; + dst++; + *dst = NULL; +} + +static int handle_add_dirafter(struct stream *stream, struct token **line, struct token *token) +{ + for (;;) { + token = token->next; + if (eof_token(token)) + return 1; + if (token_type(token) != TOKEN_STRING) { + warning(token->pos, "expected path string"); + return 1; + } + add_dirafter_entry(token, token->string->data); + } +} + +static int handle_split_include(struct stream *stream, struct token **line, struct token *token) +{ + if (false_nesting) + return free_preprocessor_line(token); + + /* + * -I- + * From info gcc: + * Split the include path. Any directories specified with `-I' + * options before `-I-' are searched only for headers requested with + * `#include "FILE"'; they are not searched for `#include <FILE>'. + * If additional directories are specified with `-I' options after + * the `-I-', those directories are searched for all `#include' + * directives. + * In addition, `-I-' inhibits the use of the directory of the current + * file directory as the first search directory for `#include "FILE"'. + */ + quote_includepath = includepath+1; + angle_includepath = sys_includepath; + return free_preprocessor_line(token); +} + /* * We replace "#pragma xxx" with "__pragma__" in the token * stream. Just as an example. @@ -1453,8 +1560,11 @@ void init_preprocessor(void) { "line", handle_line }, // our internal preprocessor tokens - { "nostdinc", handle_nostdinc }, - { "add_include", handle_add_include }, + { "nostdinc", handle_nostdinc }, + { "add_include", handle_add_include }, + { "add_isystem", handle_add_isystem }, + { "add_dirafter", handle_add_dirafter }, + { "split_include", handle_split_include }, }; for (i = 0; i < (sizeof (handlers) / sizeof (handlers[0])); i++) { @@ -35,6 +35,7 @@ extern const char *includepath[]; struct stream { int fd; const char *name; + const char *path; // inputfile path - see set_stream_include_path() const char **next_path; /* Use these to check for "already parsed" */ @@ -185,6 +185,7 @@ int init_stream(const char *name, int fd, const char **next_path) current->name = name; current->fd = fd; current->next_path = next_path; + current->path = NULL; current->constant = CONSTANT_FILE_MAYBE; input_stream_nr = stream+1; return stream; |
