tccpp: #pragma once normalized
In order to detect a "same file" faster, this makes one restriction to the feature: the basenames are required to match at least (as in "test.h" and "dir/../test.h") Also remove obsolete 'pp_once' (cached includes do not persist across compilations anymore anyway) This rewrites commits30fd24abd4
4e363a1728
3 files changed, 38 insertions(+), 74 deletions(-)
This commit is contained in:
parent
fd6d2180c5
commit
022fb4293b
3 changed files with 49 additions and 81 deletions
20
libtcc.c
20
libtcc.c
|
@ -504,8 +504,28 @@ PUB_FUNC void tcc_memcheck(int d)
|
||||||
}
|
}
|
||||||
POST_SEM(&mem_sem);
|
POST_SEM(&mem_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* MEM_DEBUG */
|
#endif /* MEM_DEBUG */
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
# define realpath(file, buf) _fullpath(buf, file, 260)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* for #pragma once */
|
||||||
|
ST_FUNC int normalized_PATHCMP(const char *f1, const char *f2)
|
||||||
|
{
|
||||||
|
char *p1, *p2;
|
||||||
|
int ret = 1;
|
||||||
|
if (!!(p1 = realpath(f1, NULL))) {
|
||||||
|
if (!!(p2 = realpath(f2, NULL))) {
|
||||||
|
ret = PATHCMP(p1, p2);
|
||||||
|
free(p2); /* using original free */
|
||||||
|
}
|
||||||
|
free(p1);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
#define free(p) use_tcc_free(p)
|
#define free(p) use_tcc_free(p)
|
||||||
#define malloc(s) use_tcc_malloc(s)
|
#define malloc(s) use_tcc_malloc(s)
|
||||||
#define realloc(p, s) use_tcc_realloc(p, s)
|
#define realloc(p, s) use_tcc_realloc(p, s)
|
||||||
|
|
7
tcc.h
7
tcc.h
|
@ -38,7 +38,6 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <setjmp.h>
|
#include <setjmp.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
|
@ -717,10 +716,6 @@ typedef struct InlineFunc {
|
||||||
/* include file cache, used to find files faster and also to eliminate
|
/* include file cache, used to find files faster and also to eliminate
|
||||||
inclusion if the include file is protected by #ifndef ... #endif */
|
inclusion if the include file is protected by #ifndef ... #endif */
|
||||||
typedef struct CachedInclude {
|
typedef struct CachedInclude {
|
||||||
struct stat st;
|
|
||||||
#ifdef _WIN32
|
|
||||||
unsigned long long hash;
|
|
||||||
#endif
|
|
||||||
int ifndef_macro;
|
int ifndef_macro;
|
||||||
int once;
|
int once;
|
||||||
int hash_next; /* -1 if none */
|
int hash_next; /* -1 if none */
|
||||||
|
@ -1315,6 +1310,8 @@ ST_FUNC char *normalize_slashes(char *path);
|
||||||
#endif
|
#endif
|
||||||
ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname, int level);
|
ST_FUNC DLLReference *tcc_add_dllref(TCCState *s1, const char *dllname, int level);
|
||||||
ST_FUNC char *tcc_load_text(int fd);
|
ST_FUNC char *tcc_load_text(int fd);
|
||||||
|
/* for #pragma once */
|
||||||
|
ST_FUNC int normalized_PATHCMP(const char *f1, const char *f2);
|
||||||
|
|
||||||
/* tcc_parse_args return codes: */
|
/* tcc_parse_args return codes: */
|
||||||
#define OPT_HELP 1
|
#define OPT_HELP 1
|
||||||
|
|
103
tccpp.c
103
tccpp.c
|
@ -48,7 +48,6 @@ static CString cstr_buf;
|
||||||
static TokenString tokstr_buf;
|
static TokenString tokstr_buf;
|
||||||
static unsigned char isidnum_table[256 - CH_EOF];
|
static unsigned char isidnum_table[256 - CH_EOF];
|
||||||
static int pp_debug_tok, pp_debug_symv;
|
static int pp_debug_tok, pp_debug_symv;
|
||||||
static int pp_once;
|
|
||||||
static int pp_expr;
|
static int pp_expr;
|
||||||
static int pp_counter;
|
static int pp_counter;
|
||||||
static void tok_print(const char *msg, const int *str);
|
static void tok_print(const char *msg, const int *str);
|
||||||
|
@ -1407,7 +1406,7 @@ static int parse_include(TCCState *s1, int do_next, int test)
|
||||||
}
|
}
|
||||||
pstrcat(buf, sizeof buf, name);
|
pstrcat(buf, sizeof buf, name);
|
||||||
e = search_cached_include(s1, buf, 0);
|
e = search_cached_include(s1, buf, 0);
|
||||||
if (e && (define_find(e->ifndef_macro) || e->once == pp_once)) {
|
if (e && (define_find(e->ifndef_macro) || e->once)) {
|
||||||
/* no need to parse the include because the 'ifndef macro'
|
/* no need to parse the include because the 'ifndef macro'
|
||||||
is defined (or had #pragma once) */
|
is defined (or had #pragma once) */
|
||||||
#ifdef INC_DEBUG
|
#ifdef INC_DEBUG
|
||||||
|
@ -1607,91 +1606,44 @@ bad_twosharp:
|
||||||
define_push(v, t, tok_str_dup(&tokstr_buf), first);
|
define_push(v, t, tok_str_dup(&tokstr_buf), first);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
static unsigned long long calc_file_hash(const char *filename)
|
|
||||||
{
|
|
||||||
unsigned long long hash = 14695981039346656037ull; // FNV_offset_basis;
|
|
||||||
int fd = open (filename, O_RDONLY | O_BINARY);
|
|
||||||
|
|
||||||
if (fd < 0)
|
|
||||||
return 0;
|
|
||||||
for (;;) {
|
|
||||||
unsigned char temp[IO_BUF_SIZE];
|
|
||||||
int i, n = read(fd, temp, sizeof(temp));
|
|
||||||
|
|
||||||
if (n <= 0)
|
|
||||||
break;
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
hash = hash * 1099511628211ull ^ temp[i]; // FNV_prime
|
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
return hash ? hash : 1ull;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static CachedInclude *search_cached_include(TCCState *s1, const char *filename, int add)
|
static CachedInclude *search_cached_include(TCCState *s1, const char *filename, int add)
|
||||||
{
|
{
|
||||||
unsigned int h = 0;
|
const char *s, *basename;
|
||||||
|
unsigned int h;
|
||||||
CachedInclude *e;
|
CachedInclude *e;
|
||||||
int i;
|
int c, i, len;
|
||||||
struct stat st;
|
|
||||||
#ifdef _WIN32
|
|
||||||
unsigned long long hash = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* This is needed for #pragmae once
|
s = basename = tcc_basename(filename);
|
||||||
* We cannot use stat on windows because st_ino is not set correctly
|
h = TOK_HASH_INIT;
|
||||||
* so we calculate a hash of file contents.
|
while ((c = (unsigned char)*s) != 0) {
|
||||||
* 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);
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
/* Only calculate file hash if file size same. */
|
h = TOK_HASH_FUNC(h, toup(c));
|
||||||
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;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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
|
#else
|
||||||
if (st.st_dev == e->st.st_dev && st.st_ino == e->st.st_ino)
|
h = TOK_HASH_FUNC(h, c);
|
||||||
#endif
|
#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];
|
||||||
|
if (0 == PATHCMP(filename, e->filename))
|
||||||
|
return e;
|
||||||
|
if (e->once
|
||||||
|
&& 0 == PATHCMP(basename, tcc_basename(e->filename))
|
||||||
|
&& 0 == normalized_PATHCMP(filename, e->filename)
|
||||||
|
)
|
||||||
return e;
|
return e;
|
||||||
i = e->hash_next;
|
i = e->hash_next;
|
||||||
}
|
}
|
||||||
skip:
|
|
||||||
if (!add)
|
if (!add)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
|
e = tcc_malloc(sizeof(CachedInclude) + (len = strlen(filename)));
|
||||||
e->st = st;
|
memcpy(e->filename, filename, len + 1);
|
||||||
#ifdef _WIN32
|
|
||||||
e->hash = hash;
|
|
||||||
#endif
|
|
||||||
strcpy(e->filename, filename);
|
|
||||||
e->ifndef_macro = e->once = 0;
|
e->ifndef_macro = e->once = 0;
|
||||||
dynarray_add(&s1->cached_includes, &s1->nb_cached_includes, e);
|
dynarray_add(&s1->cached_includes, &s1->nb_cached_includes, e);
|
||||||
/* add in hash table */
|
/* add in hash table */
|
||||||
|
@ -1735,7 +1687,7 @@ static void pragma_parse(TCCState *s1)
|
||||||
pp_debug_tok = t, pp_debug_symv = v;
|
pp_debug_tok = t, pp_debug_symv = v;
|
||||||
|
|
||||||
} else if (tok == TOK_once) {
|
} else if (tok == TOK_once) {
|
||||||
search_cached_include(s1, file->filename, 1)->once = pp_once;
|
search_cached_include(s1, file->filename, 1)->once = 1;
|
||||||
|
|
||||||
} else if (s1->output_type == TCC_OUTPUT_PREPROCESS) {
|
} else if (s1->output_type == TCC_OUTPUT_PREPROCESS) {
|
||||||
/* tcc -E: keep pragmas below unchanged */
|
/* tcc -E: keep pragmas below unchanged */
|
||||||
|
@ -3685,7 +3637,6 @@ ST_FUNC void preprocess_start(TCCState *s1, int filetype)
|
||||||
pp_expr = 0;
|
pp_expr = 0;
|
||||||
pp_counter = 0;
|
pp_counter = 0;
|
||||||
pp_debug_tok = pp_debug_symv = 0;
|
pp_debug_tok = pp_debug_symv = 0;
|
||||||
pp_once++;
|
|
||||||
s1->pack_stack[0] = 0;
|
s1->pack_stack[0] = 0;
|
||||||
s1->pack_stack_ptr = s1->pack_stack;
|
s1->pack_stack_ptr = s1->pack_stack;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue