Hi Linus - please apply.
I had mixed up -isystem, and -dirafter in my original explanation.
They add a path in either end of the chain - implementation is OK.
Added a bit of a comment also - may be helpful for the next poor soul to
look into this area.



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.

        Sam
        
===== lib.c 1.112 vs edited =====
--- 1.112/lib.c 2005-01-14 23:11:01 +01:00
+++ edited/lib.c        2005-01-18 21:21:17 +01:00
@@ -428,16 +428,8 @@
 
        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 *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 @@
        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 **rc = next;
        static struct switches cmd[] = {
                { "nostdinc", handle_nostdinc },
+               { "dirafter", handle_dirafter },
                { NULL, NULL }
        };
        struct switches *s;
===== pre-process.c 1.123 vs edited =====
--- 1.123/pre-process.c 2004-12-09 19:55:29 +01:00
+++ edited/pre-process.c        2005-01-18 21:20:49 +01:00
@@ -38,14 +38,16 @@
 
 #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 @@
        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 @@
        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 @@
 
        /* 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;
-
-               path = stream->name;
-               slash = strrchr(path, '/');
-               plen = slash ? slash - path : 0;
+       /* Dir of inputfile is first dir to search for quoted includes */
+       set_stream_include_path(stream);
 
-               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(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_nostdinc(struct stream *stream, struct token **line, struct 
token *token)
 {
-       int stdinc;
-
        if (false_nesting)
                return free_preprocessor_line(token);
 
@@ -1337,22 +1382,11 @@
         * 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 @@
        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 @@
                        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 @@
                { "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++) {
===== token.h 1.50 vs edited =====
--- 1.50/token.h        2004-12-09 19:55:29 +01:00
+++ edited/token.h      2005-01-18 20:24:47 +01:00
@@ -35,6 +35,7 @@
 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" */
===== tokenize.c 1.64 vs edited =====
--- 1.64/tokenize.c     2004-12-09 19:55:29 +01:00
+++ edited/tokenize.c   2005-01-18 20:26:14 +01:00
@@ -185,6 +185,7 @@
        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;
-
To unsubscribe from this list: send the line "unsubscribe linux-sparse" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to