Concerning the #pragma once case, I tried to setup a cleaner patch on
tccpp.c. I just extracted the path normalisation from
search_cached_include and adjust some smaller things necessary. I diffed
this against latest mob 5b28165.

It's the simplest solution, just normalizing slashes and . .. upon
current working directory. This should master msot regular cases without
symlinks. But it means the identical files at two different paths in the
filesystem will not be seens as identical, but be included twice.

I don't wont to push it to the mob without feedback.

Regards

Michael

--- tccpp.c     2023-07-05 19:28:58.000000000 +0200
+++ tccpp_patched.c     2023-07-29 15:48:08.919820600 +0200
@@ -51,6 +51,7 @@
 static int pp_once;
 static int pp_expr;
 static int pp_counter;
+static char pp_wd[1024];
 static void tok_print(const char *msg, const int *str);
 
 static struct TinyAlloc *toksym_alloc;
@@ -1629,77 +1630,98 @@
 }
 #endif
 
+unsigned char* normlizepath (const char *filename) {
+    //
+    char fullname[sizeof(pp_wd)];
+    unsigned char *s, *t, *f, *e;
+
+    if (IS_DIRSEP (filename[0]))
+       pstrcpy (fullname, sizeof(fullname), filename);
+    else {
+       pstrcpy (fullname, sizeof(fullname), pp_wd);
+       pstrcat (fullname, sizeof(fullname), "/");
+       pstrcat (fullname, sizeof(fullname), filename);
+    }
+#ifdef _WIN32
+    normalize_slashes(fullname);
+#endif
+    /* Skip possible drive letter */
+    f = (unsigned char *) fullname;
+    while (*f != '/')
+       f++;
+    s = f;
+    t = f;
+    while (*s) {
+       if (*s == '/') {
+           *t++ = *s++;
+           while (*s == '/') {
+               s++;
+           }
+       }
+       if (s[0] == '.' && s[1] == '/')
+           s += 2;
+       else if (s[0] == '.' && s[1] == '.' && s[2] == '/') {
+           s += 3;
+           if (t > (f + 1) && t[-1] == '/')
+               t--;
+           while (t > (f + 1) && t[-1] != '/')
+               t--;
+       }
+       else
+           while (*s && *s != '/') {
+               *t++ = *s++;
+           }
+    }
+    *t = '\0';
+    e = tcc_malloc(sizeof(fullname));
+    strcpy(e, fullname);
+    return e;
+}
+
 static CachedInclude *search_cached_include(TCCState *s1, const char 
*filename, int add)
 {
     unsigned int h = 0;
     CachedInclude *e;
     int i;
-    struct stat st;
-#ifdef _WIN32
-    unsigned long long hash = 0;
-#endif
+    unsigned char *s0, *s;
 
-    /* This is needed for #pragmae once
-     * We cannot use stat on windows because st_ino is not set correctly
-     * so we calculate a hash of file contents.
-     * This also works for hard/soft links as in gcc/clang.
-     */
-    memset (&st, 0, sizeof(st));
-    if (stat (filename, &st))
-       goto  skip;
-    h = st.st_size & (CACHED_INCLUDES_HASH_SIZE - 1);
+    h = TOK_HASH_INIT;
+    //s = (unsigned char *) fullname;
+    s=s0= normlizepath(filename);
+    //printf("filename %s fullname %s\n",filename,s);
+    while (*s) {
 #ifdef _WIN32
-    /* Only calculate file hash if file size same. */
-    i = s1->cached_includes_hash[h];
-    for(;;) {
-        if (i == 0)
-            break;
-        e = s1->cached_includes[i - 1];
-       if (e->st.st_size == st.st_size) {
-           if (0 == PATHCMP(e->filename, filename)) {
-               hash = e->hash;
-               break;
-           }
-           if (e->hash == 0)
-               e->hash = calc_file_hash(e->filename);
-           if (hash == 0)
-               hash = calc_file_hash(filename);
-       }
-        i = e->hash_next;
-    }
+        h = TOK_HASH_FUNC(h, toup(*s));
+#else
+        h = TOK_HASH_FUNC(h, *s);
 #endif
+        s++;
+    }
+    h &= (CACHED_INCLUDES_HASH_SIZE - 1);
 
     i = s1->cached_includes_hash[h];
     for(;;) {
         if (i == 0)
             break;
         e = s1->cached_includes[i - 1];
-#ifdef _WIN32
-        if (e->st.st_size == st.st_size && e->hash == hash)
-#else
-        if (st.st_dev == e->st.st_dev && st.st_ino == e->st.st_ino)
-#endif
+        if (0 == PATHCMP(e->filename, s0))
             return e;
         i = e->hash_next;
     }
-skip:
     if (!add)
         return NULL;
 
-    e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
-    e->st = st;
-#ifdef _WIN32
-    e->hash = hash;
-#endif
-    strcpy(e->filename, filename);
+    e = tcc_malloc(sizeof(CachedInclude) + strlen(s0));
+    strcpy(e->filename, s0);
     e->ifndef_macro = e->once = 0;
     dynarray_add(&s1->cached_includes, &s1->nb_cached_includes, e);
     /* add in hash table */
     e->hash_next = s1->cached_includes_hash[h];
     s1->cached_includes_hash[h] = s1->nb_cached_includes;
-#ifdef INC_DEBUG
-    printf("adding cached '%s'\n", filename);
+#ifdef INC_DEBUG
+    printf("adding cached '%s' hash %d\n", e->filename,h);
 #endif
+    tcc_free(s0);
     return e;
 }
 
@@ -3709,6 +3731,7 @@
 
     parse_flags = is_asm ? PARSE_FLAG_ASM_FILE : 0;
     tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
+    getcwd(pp_wd, sizeof(pp_wd));
 }
 
 /* cleanup from error/setjmp */
_______________________________________________
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to