tccpp: #pragma once: make it work

after several "fixes" and "improvements"
   b3782c3cf5
   5fb57bead4
feature did not work at all

- Use 'once' flag, not 'ifndef_macro'
- Ignore filename letter case on _WIN32
- Increment global pp_once for each compilation
master
grischka 2016-10-01 20:03:48 +02:00
parent 07e47b3dd6
commit 3ddbfe1a82
2 changed files with 25 additions and 37 deletions

4
tcc.h
View File

@ -101,7 +101,6 @@
# define IS_DIRSEP(c) (c == '/' || c == '\\') # define IS_DIRSEP(c) (c == '/' || c == '\\')
# define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2]))) # define IS_ABSPATH(p) (IS_DIRSEP(p[0]) || (p[0] && p[1] == ':' && IS_DIRSEP(p[2])))
# define PATHCMP stricmp # define PATHCMP stricmp
# define PATH_NOCASE
#else #else
# define IS_DIRSEP(c) (c == '/') # define IS_DIRSEP(c) (c == '/')
# define IS_ABSPATH(p) IS_DIRSEP(p[0]) # define IS_ABSPATH(p) IS_DIRSEP(p[0])
@ -602,11 +601,12 @@ typedef struct InlineFunc {
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 {
int ifndef_macro; int ifndef_macro;
int once;
int hash_next; /* -1 if none */ int hash_next; /* -1 if none */
char filename[1]; /* path specified in #include */ char filename[1]; /* path specified in #include */
} CachedInclude; } CachedInclude;
#define CACHED_INCLUDES_HASH_SIZE 512 #define CACHED_INCLUDES_HASH_SIZE 32
#ifdef CONFIG_TCC_ASM #ifdef CONFIG_TCC_ASM
typedef struct ExprValue { typedef struct ExprValue {

58
tccpp.c
View File

@ -50,6 +50,7 @@ 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 void tok_print(const char *msg, const int *str); static void tok_print(const char *msg, const int *str);
/* isidnum_table flags: */ /* isidnum_table flags: */
@ -1474,26 +1475,25 @@ bad_twosharp:
define_push(v, t, &tokstr_buf, first); define_push(v, t, &tokstr_buf, first);
} }
static inline int hash_cached_include(const char *filename) static CachedInclude *search_cached_include(TCCState *s1, const char *filename, int add)
{ {
const unsigned char *s; const unsigned char *s;
unsigned int h; unsigned int h;
CachedInclude *e;
int i;
h = TOK_HASH_INIT; h = TOK_HASH_INIT;
s = (unsigned char *) filename; s = (unsigned char *) filename;
while (*s) { while (*s) {
#ifdef _WIN32
h = TOK_HASH_FUNC(h, toup(*s));
#else
h = TOK_HASH_FUNC(h, *s); h = TOK_HASH_FUNC(h, *s);
#endif
s++; s++;
} }
h &= (CACHED_INCLUDES_HASH_SIZE - 1); h &= (CACHED_INCLUDES_HASH_SIZE - 1);
return h;
}
static CachedInclude *search_cached_include(TCCState *s1, const char *filename)
{
CachedInclude *e;
int i, h;
h = hash_cached_include(filename);
i = s1->cached_includes_hash[h]; i = s1->cached_includes_hash[h];
for(;;) { for(;;) {
if (i == 0) if (i == 0)
@ -1503,31 +1503,22 @@ static CachedInclude *search_cached_include(TCCState *s1, const char *filename)
return e; return e;
i = e->hash_next; i = e->hash_next;
} }
return NULL; if (!add)
} return NULL;
static inline void add_cached_include(TCCState *s1, const char *filename, int ifndef_macro)
{
CachedInclude *e;
int h;
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)); e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
strcpy(e->filename, filename); strcpy(e->filename, filename);
e->ifndef_macro = ifndef_macro; e->ifndef_macro = e->once = 0;
dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e); dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
/* add in hash table */ /* add in hash table */
h = hash_cached_include(filename);
e->hash_next = s1->cached_includes_hash[h]; e->hash_next = s1->cached_includes_hash[h];
s1->cached_includes_hash[h] = s1->nb_cached_includes; s1->cached_includes_hash[h] = s1->nb_cached_includes;
#ifdef INC_DEBUG
printf("adding cached '%s'\n", filename);
#endif
return e;
} }
#define ONCE_PREFIX "#ONCE#"
static void pragma_parse(TCCState *s1) static void pragma_parse(TCCState *s1)
{ {
next_nomacro(); next_nomacro();
@ -1560,13 +1551,8 @@ 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) {
char buf1[sizeof(file->filename) + sizeof(ONCE_PREFIX)]; search_cached_include(s1, file->filename, 1)->once = pp_once;
strcpy(buf1, ONCE_PREFIX);
strcat(buf1, file->filename);
#ifdef PATH_NOCASE
strupr(buf1);
#endif
add_cached_include(s1, file->filename, tok_alloc(buf1, strlen(buf1))->tok);
} else if (s1->ppfp) { } else if (s1->ppfp) {
/* tcc -E: keep pragmas below unchanged */ /* tcc -E: keep pragmas below unchanged */
unget_tok(' '); unget_tok(' ');
@ -1767,10 +1753,10 @@ ST_FUNC void preprocess(int is_bof)
} }
pstrcat(buf1, sizeof(buf1), buf); pstrcat(buf1, sizeof(buf1), buf);
e = search_cached_include(s1, buf1); e = search_cached_include(s1, buf1, 0);
if (e && define_find(e->ifndef_macro)) { if (e && (define_find(e->ifndef_macro) || e->once == pp_once)) {
/* no need to parse the include because the 'ifndef macro' /* no need to parse the include because the 'ifndef macro'
is defined */ is defined (or had #pragma once) */
#ifdef INC_DEBUG #ifdef INC_DEBUG
printf("%s: skipping cached %s\n", file->filename, buf1); printf("%s: skipping cached %s\n", file->filename, buf1);
#endif #endif
@ -2484,7 +2470,8 @@ static inline void next_nomacro1(void)
#ifdef INC_DEBUG #ifdef INC_DEBUG
printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL)); printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
#endif #endif
add_cached_include(s1, file->filename, file->ifndef_macro_saved); search_cached_include(s1, file->filename, 1)
->ifndef_macro = file->ifndef_macro_saved;
tok_flags &= ~TOK_FLAG_ENDIF; tok_flags &= ~TOK_FLAG_ENDIF;
} }
@ -3445,6 +3432,7 @@ ST_FUNC void preprocess_init(TCCState *s1)
file->ifdef_stack_ptr ? */ file->ifdef_stack_ptr ? */
s1->ifdef_stack_ptr = s1->ifdef_stack; s1->ifdef_stack_ptr = s1->ifdef_stack;
file->ifdef_stack_ptr = s1->ifdef_stack_ptr; file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
pp_once++;
pvtop = vtop = vstack - 1; pvtop = vtop = vstack - 1;
s1->pack_stack[0] = 0; s1->pack_stack[0] = 0;