tccpp: alternative fix for #include_next infinite loop bug
authorgrischka <grischka>
Sun, 6 Jan 2013 16:20:44 +0000 (6 17:20 +0100)
committergrischka <grischka>
Sun, 6 Jan 2013 16:20:44 +0000 (6 17:20 +0100)
This replaces commit 3d409b08893873b917ccb8c34398bc41a4e84d7c

- revert old fix in libtcc.c
- #include_next: look up the file in the include stack to see
  if it is already included.
Also:
- streamline include code
- remove 'type' from struct CachedInclude (obsolete because we check
  full filename anyway)
- remove inc_type & inc_filename from struct Bufferedfile (obsolete)
- fix bug with TOK_FLAG_ENDIF not being reset
- unrelated: get rid of an 'variable potentially uninitialized' warning

libtcc.c
tcc.h
tccgen.c
tccpp.c

index 6c04caa..b0a9b1a 100644 (file)
--- a/libtcc.c
+++ b/libtcc.c
@@ -34,10 +34,6 @@ ST_DATA struct TCCState *tcc_state;
 
 /********************************************************/
 
-#ifndef _WIN32
-#include <limits.h>
-#endif
-
 #ifdef ONE_SOURCE
 #include "tccpp.c"
 #include "tccgen.c"
@@ -322,30 +318,7 @@ static void tcc_split_path(TCCState *s, void ***p_ary, int *p_nb_ary, const char
             }
         }
         cstr_ccat(&str, '\0');
-#ifndef _WIN32
-        {
-            int i, do_include;
-            char tmp[PATH_MAX];
-
-            if (realpath(str.data, tmp)) {
-                str.size = 0;
-                cstr_cat(&str, tmp);
-                cstr_ccat(&str, '\0');
-            }
-
-            do_include = 1;
-            for (i = 0; i < *p_nb_ary && do_include; i++) {
-                do_include = do_include &&
-                    strcmp((char*)str.data, (char*)(*p_ary)[i]);
-            }
-
-            if (do_include) {
-                dynarray_add(p_ary, p_nb_ary, str.data);
-            }
-        }
-#else
         dynarray_add(p_ary, p_nb_ary, str.data);
-#endif
         in = p+1;
     } while (*p);
 }
diff --git a/tcc.h b/tcc.h
index 8e79430..5489b49 100644 (file)
--- a/tcc.h
+++ b/tcc.h
@@ -422,9 +422,7 @@ typedef struct BufferedFile {
     int ifndef_macro;  /* #ifndef macro / #endif search */
     int ifndef_macro_saved; /* saved ifndef_macro */
     int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
-    char inc_type;          /* type of include */
-    char inc_filename[512]; /* filename specified by the user */
-    char filename[1024];    /* current filename - here to simplify code */
+    char filename[1024];    /* filename */
     unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
 } BufferedFile;
 
@@ -460,7 +458,6 @@ typedef struct InlineFunc {
 typedef struct CachedInclude {
     int ifndef_macro;
     int hash_next; /* -1 if none */
-    char type; /* '"' or '>' to give include type */
     char filename[1]; /* path specified in #include */
 } CachedInclude;
 
index 5a79f49..71555cd 100644 (file)
--- a/tccgen.c
+++ b/tccgen.c
@@ -3284,8 +3284,8 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
 {
     Sym *s;
     CType type1, *type2;
-    int qualifiers, storage, saved_nocode_wanted;
-    
+    int qualifiers, storage;
+
     while (tok == '*') {
         qualifiers = 0;
     redo:
@@ -3339,12 +3339,12 @@ static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
     storage = type->t & VT_STORAGE;
     type->t &= ~VT_STORAGE;
     if (storage & VT_STATIC) {
-        saved_nocode_wanted = nocode_wanted;
+        int saved_nocode_wanted = nocode_wanted;
         nocode_wanted = 1;
-    }
-    post_type(type, ad);
-    if (storage & VT_STATIC)
+        post_type(type, ad);
         nocode_wanted = saved_nocode_wanted;
+    } else
+        post_type(type, ad);
     type->t |= storage;
     if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
         parse_attribute(ad);
diff --git a/tccpp.c b/tccpp.c
index 4b7b4fa..05098e1 100644 (file)
--- a/tccpp.c
+++ b/tccpp.c
@@ -1242,13 +1242,12 @@ ST_FUNC void parse_define(void)
     define_push(v, t, str.str, first);
 }
 
-static inline int hash_cached_include(int type, const char *filename)
+static inline int hash_cached_include(const char *filename)
 {
     const unsigned char *s;
     unsigned int h;
 
     h = TOK_HASH_INIT;
-    h = TOK_HASH_FUNC(h, type);
     s = filename;
     while (*s) {
         h = TOK_HASH_FUNC(h, *s);
@@ -1258,45 +1257,39 @@ static inline int hash_cached_include(int type, const char *filename)
     return h;
 }
 
-/* XXX: use a token or a hash table to accelerate matching ? */
-static CachedInclude *search_cached_include(TCCState *s1,
-                                            int type, const char *filename)
+static CachedInclude *search_cached_include(TCCState *s1, const char *filename)
 {
     CachedInclude *e;
     int i, h;
-    h = hash_cached_include(type, filename);
+    h = hash_cached_include(filename);
     i = s1->cached_includes_hash[h];
     for(;;) {
         if (i == 0)
             break;
         e = s1->cached_includes[i - 1];
-        if (e->type == type && !PATHCMP(e->filename, filename))
+        if (0 == PATHCMP(e->filename, filename))
             return e;
         i = e->hash_next;
     }
     return NULL;
 }
 
-static inline void add_cached_include(TCCState *s1, int type, 
-                                      const char *filename, int ifndef_macro)
+static inline void add_cached_include(TCCState *s1, const char *filename, int ifndef_macro)
 {
     CachedInclude *e;
     int h;
 
-    if (search_cached_include(s1, type, filename))
+    if (search_cached_include(s1, filename))
         return;
 #ifdef INC_DEBUG
     printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
 #endif
     e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
-    if (!e)
-        return;
-    e->type = type;
     strcpy(e->filename, filename);
     e->ifndef_macro = ifndef_macro;
     dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
     /* add in hash table */
-    h = hash_cached_include(type, filename);
+    h = hash_cached_include(filename);
     e->hash_next = s1->cached_includes_hash[h];
     s1->cached_includes_hash[h] = s1->nb_cached_includes;
 }
@@ -1436,27 +1429,29 @@ ST_FUNC void preprocess(int is_bof)
 
         if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
             tcc_error("#include recursion too deep");
+        /* store current file in stack, but increment stack later below */
+        *s1->include_stack_ptr = file;
 
         n = s1->nb_include_paths + s1->nb_sysinclude_paths;
         for (i = -2; i < n; ++i) {
             char buf1[sizeof file->filename];
             CachedInclude *e;
+            BufferedFile **f;
             const char *path;
-            int size, fd;
 
             if (i == -2) {
                 /* check absolute include path */
                 if (!IS_ABSPATH(buf))
                     continue;
                 buf1[0] = 0;
+                i = n; /* force end loop */
 
             } else if (i == -1) {
                 /* search in current dir if "header.h" */
                 if (c != '\"')
                     continue;
-                size = tcc_basename(file->filename) - file->filename;
-                memcpy(buf1, file->filename, size);
-                buf1[size] = '\0';
+                path = file->filename;
+                pstrncpy(buf1, path, tcc_basename(path) - path);
 
             } else {
                 /* search in all the include paths */
@@ -1470,41 +1465,37 @@ ST_FUNC void preprocess(int is_bof)
 
             pstrcat(buf1, sizeof(buf1), buf);
 
-            e = search_cached_include(s1, c, buf1);
+            if (tok == TOK_INCLUDE_NEXT)
+                for (f = s1->include_stack_ptr; f >= s1->include_stack; --f)
+                    if (0 == PATHCMP((*f)->filename, buf1)) {
+#ifdef INC_DEBUG
+                        printf("%s: #include_next skipping %s\n", file->filename, buf1);
+#endif
+                        goto include_trynext;
+                    }
+
+            e = search_cached_include(s1, buf1);
             if (e && define_find(e->ifndef_macro)) {
                 /* no need to parse the include because the 'ifndef macro'
                    is defined */
 #ifdef INC_DEBUG
-                printf("%s: skipping %s\n", file->filename, buf);
+                printf("%s: skipping cached %s\n", file->filename, buf1);
 #endif
-                fd = 0;
-            } else {
-                fd = tcc_open(s1, buf1);
-                if (fd < 0)
-                    continue;
+                goto include_done;
             }
 
-            if (tok == TOK_INCLUDE_NEXT) {
-                tok = TOK_INCLUDE;
-                if (fd)
-                    tcc_close();
+            if (tcc_open(s1, buf1) < 0)
+include_trynext:
                 continue;
-            }
-
-            if (0 == fd)
-                goto include_done;
 
 #ifdef INC_DEBUG
-            printf("%s: including %s\n", file->filename, buf1);
+            printf("%s: including %s\n", file->prev->filename, file->filename);
 #endif
             /* update target deps */
             dynarray_add((void ***)&s1->target_deps, &s1->nb_target_deps,
                     tcc_strdup(buf1));
-           /* XXX: fix current line init */
-           /* push current file in stack */
-            *s1->include_stack_ptr++ = file->prev;
-            file->inc_type = c;
-            pstrcpy(file->inc_filename, sizeof(file->inc_filename), buf1);
+            /* push current file in stack */
+            ++s1->include_stack_ptr;
             /* add include file debug info */
             if (s1->do_debug)
                 put_stabs(file->filename, N_BINCL, 0, 0, 0);
@@ -2137,8 +2128,8 @@ static inline void next_nomacro1(void)
 #ifdef INC_DEBUG
                     printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
 #endif
-                    add_cached_include(s1, file->inc_type, file->inc_filename,
-                                       file->ifndef_macro_saved);
+                    add_cached_include(s1, file->filename, file->ifndef_macro_saved);
+                    tok_flags &= ~TOK_FLAG_ENDIF;
                 }
 
                 /* add end of include file debug info */