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