mirror of
https://github.com/mirror/tinycc.git
synced 2024-12-28 04:00:06 +08:00
tccpp: integrate __has_include() more nicely
- make only one function from previously four pieces - use parse_pp_string() for the normal cases "..." and <...> - use the sanity check for computed include as end-condition too. - use 's1' instead of 'tcc_state' when possible 117 insertions(+), 165 deletions(-), less 48 lines
This commit is contained in:
parent
0f72db09ab
commit
85c32ddd0b
262
tccpp.c
262
tccpp.c
@ -891,6 +891,7 @@ ST_FUNC int set_idnum(int c, int val)
|
|||||||
|
|
||||||
static inline void skip_spaces(void)
|
static inline void skip_spaces(void)
|
||||||
{
|
{
|
||||||
|
ch = file->buf_ptr[0];
|
||||||
while (isidnum_table[ch - CH_EOF] & IS_SPC)
|
while (isidnum_table[ch - CH_EOF] & IS_SPC)
|
||||||
cinp();
|
cinp();
|
||||||
}
|
}
|
||||||
@ -1495,94 +1496,113 @@ static void maybe_run_test(TCCState *s)
|
|||||||
define_push(tok, MACRO_OBJ, NULL, NULL);
|
define_push(tok, MACRO_OBJ, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parse_include(char *buf, size_t size_buf, int last)
|
static CachedInclude *
|
||||||
|
search_cached_include(TCCState *s1, const char *filename, int add);
|
||||||
|
|
||||||
|
static int parse_include(TCCState *s1, int do_next, int test)
|
||||||
{
|
{
|
||||||
int c;
|
int c, i;
|
||||||
|
CString cs;
|
||||||
|
char name[1024], buf[1024], *p;
|
||||||
|
CachedInclude *e;
|
||||||
|
|
||||||
skip_spaces();
|
cstr_new(&cs);
|
||||||
if (ch == '<') {
|
skip_spaces(), c = ch;
|
||||||
c = '>';
|
if (c == '<' || c == '\"') {
|
||||||
goto read_name;
|
file->buf_ptr = parse_pp_string(file->buf_ptr, c == '<' ? '>' : c, &cs);
|
||||||
} else if (ch == '\"') {
|
next_nomacro();
|
||||||
char *q;
|
|
||||||
|
|
||||||
c = ch;
|
|
||||||
read_name:
|
|
||||||
inp();
|
|
||||||
q = buf;
|
|
||||||
while (ch != c && ch != '\n' && ch != CH_EOF) {
|
|
||||||
if ((q - buf) < size_buf - 1)
|
|
||||||
*q++ = ch;
|
|
||||||
if (ch == '\\') {
|
|
||||||
if (handle_stray_noerror() == 0)
|
|
||||||
--q;
|
|
||||||
} else
|
|
||||||
inp();
|
|
||||||
}
|
|
||||||
if (ch != c)
|
|
||||||
goto error;
|
|
||||||
*q = '\0';
|
|
||||||
minp();
|
|
||||||
#if 0
|
|
||||||
/* eat all spaces and comments after include */
|
|
||||||
/* XXX: slightly incorrect */
|
|
||||||
while (ch1 != '\n' && ch1 != CH_EOF)
|
|
||||||
inp();
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
int len;
|
/* computed #include : concatenate tokens until result is one of
|
||||||
/* computed #include : concatenate everything up to linefeed,
|
the two accepted forms. Don't convert pp-tokens to tokens here. */
|
||||||
the result must be one of the two accepted forms.
|
parse_flags = PARSE_FLAG_PREPROCESS
|
||||||
Don't convert pp-tokens to tokens here. */
|
|
||||||
parse_flags = (PARSE_FLAG_PREPROCESS
|
|
||||||
| PARSE_FLAG_LINEFEED
|
| PARSE_FLAG_LINEFEED
|
||||||
| (parse_flags & PARSE_FLAG_ASM_FILE));
|
| (parse_flags & PARSE_FLAG_ASM_FILE);
|
||||||
|
for (;;) {
|
||||||
next();
|
next();
|
||||||
buf[0] = '\0';
|
p = cs.data, i = cs.size - 1;
|
||||||
while (tok != TOK_LINEFEED && tok != last) {
|
if (i > 0
|
||||||
pstrcat(buf, size_buf, get_tok_str(tok, &tokc));
|
&& ((p[0] == '"' && p[i] == '"')
|
||||||
next();
|
|| (p[0] == '<' && p[i] == '>')))
|
||||||
}
|
break;
|
||||||
len = strlen(buf);
|
if (tok == TOK_LINEFEED)
|
||||||
if (tok == last)
|
|
||||||
unget_tok(0);
|
|
||||||
/* check syntax and remove '<>|""' */
|
|
||||||
if ((len < 2 || ((buf[0] != '"' || buf[len-1] != '"') &&
|
|
||||||
(buf[0] != '<' || buf[len-1] != '>'))))
|
|
||||||
error:
|
|
||||||
tcc_error("'#include' expects \"FILENAME\" or <FILENAME>");
|
tcc_error("'#include' expects \"FILENAME\" or <FILENAME>");
|
||||||
c = buf[len-1];
|
cstr_cat(&cs, get_tok_str(tok, &tokc), -1);
|
||||||
memmove(buf, buf + 1, len - 2);
|
|
||||||
buf[len - 2] = '\0';
|
|
||||||
}
|
}
|
||||||
return c;
|
c = p[0];
|
||||||
|
/* remove '<>|""' */
|
||||||
|
memmove(p, p + 1, cs.size -= 2);
|
||||||
}
|
}
|
||||||
|
cstr_ccat(&cs, '\0');
|
||||||
|
pstrcpy(name, sizeof name, cs.data);
|
||||||
|
cstr_free(&cs);
|
||||||
|
|
||||||
static int get_include_file(TCCState *s1, int i, int c,
|
i = do_next ? file->include_next_index : -1;
|
||||||
char *buf, char *buf1, size_t size_buf1)
|
for (;;) {
|
||||||
{
|
++i;
|
||||||
const char *path;
|
|
||||||
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
/* check absolute include path */
|
/* check absolute include path */
|
||||||
if (!IS_ABSPATH(buf))
|
if (!IS_ABSPATH(name))
|
||||||
return -1;
|
continue;
|
||||||
buf1[0] = 0;
|
buf[0] = '\0';
|
||||||
} else if (i == 1) {
|
} else if (i == 1) {
|
||||||
/* search in file's dir if "header.h" */
|
/* search in file's dir if "header.h" */
|
||||||
if (c != '\"')
|
if (c != '\"')
|
||||||
return -1;
|
continue;
|
||||||
path = file->true_filename;
|
p = file->true_filename;
|
||||||
pstrncpy(buf1, path, tcc_basename(path) - path);
|
pstrncpy(buf, p, tcc_basename(p) - p);
|
||||||
} else {
|
} else {
|
||||||
/* search in all the include paths */
|
|
||||||
int j = i - 2, k = j - s1->nb_include_paths;
|
int j = i - 2, k = j - s1->nb_include_paths;
|
||||||
path = k < 0 ? s1->include_paths[j] : s1->sysinclude_paths[k];
|
if (k < 0)
|
||||||
pstrcpy(buf1, size_buf1, path);
|
p = s1->include_paths[j];
|
||||||
pstrcat(buf1, size_buf1, "/");
|
else if (k < s1->nb_sysinclude_paths)
|
||||||
}
|
p = s1->sysinclude_paths[k];
|
||||||
pstrcat(buf1, size_buf1, buf);
|
else if (test)
|
||||||
return 0;
|
return 0;
|
||||||
|
else
|
||||||
|
tcc_error("include file '%s' not found", name);
|
||||||
|
pstrcpy(buf, sizeof buf, p);
|
||||||
|
pstrcat(buf, sizeof buf, "/");
|
||||||
|
}
|
||||||
|
pstrcat(buf, sizeof buf, name);
|
||||||
|
e = search_cached_include(s1, buf, 0);
|
||||||
|
if (e && (define_find(e->ifndef_macro) || e->once == pp_once)) {
|
||||||
|
/* no need to parse the include because the 'ifndef macro'
|
||||||
|
is defined (or had #pragma once) */
|
||||||
|
#ifdef INC_DEBUG
|
||||||
|
printf("%s: skipping cached %s\n", file->filename, buf);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (tcc_open(s1, buf) >= 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (test) {
|
||||||
|
tcc_close();
|
||||||
|
} else {
|
||||||
|
if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
|
||||||
|
tcc_error("#include recursion too deep");
|
||||||
|
/* push previous file on stack */
|
||||||
|
*s1->include_stack_ptr++ = file->prev;
|
||||||
|
file->include_next_index = i;
|
||||||
|
#ifdef INC_DEBUG
|
||||||
|
printf("%s: including %s\n", file->prev->filename, file->filename);
|
||||||
|
#endif
|
||||||
|
/* update target deps */
|
||||||
|
if (s1->gen_deps) {
|
||||||
|
BufferedFile *bf = file;
|
||||||
|
while (i == 1 && (bf = bf->prev))
|
||||||
|
i = bf->include_next_index;
|
||||||
|
/* skip system include files */
|
||||||
|
if (s1->include_sys_deps || i - 2 < s1->nb_include_paths)
|
||||||
|
dynarray_add(&s1->target_deps, &s1->nb_target_deps,
|
||||||
|
tcc_strdup(buf));
|
||||||
|
}
|
||||||
|
/* add include file debug info */
|
||||||
|
tcc_debug_bincl(s1);
|
||||||
|
tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eval an expression for #if/#elif */
|
/* eval an expression for #if/#elif */
|
||||||
@ -1601,15 +1621,15 @@ static int expr_preprocess(TCCState *s1)
|
|||||||
t = tok;
|
t = tok;
|
||||||
if (t == '(')
|
if (t == '(')
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
if (tok == TOK___HAS_INCLUDE || tok == TOK___HAS_INCLUDE_NEXT)
|
|
||||||
c = 1;
|
|
||||||
else {
|
|
||||||
if (tok < TOK_IDENT)
|
if (tok < TOK_IDENT)
|
||||||
expect("identifier");
|
expect("identifier");
|
||||||
if (tcc_state->run_test)
|
if (s1->run_test)
|
||||||
maybe_run_test(tcc_state);
|
maybe_run_test(s1);
|
||||||
c = define_find(tok) != 0;
|
c = 0;
|
||||||
}
|
if (define_find(tok)
|
||||||
|
|| tok == TOK___HAS_INCLUDE
|
||||||
|
|| tok == TOK___HAS_INCLUDE_NEXT)
|
||||||
|
c = 1;
|
||||||
if (t == '(') {
|
if (t == '(') {
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
if (tok != ')')
|
if (tok != ')')
|
||||||
@ -1619,32 +1639,15 @@ static int expr_preprocess(TCCState *s1)
|
|||||||
tokc.i = c;
|
tokc.i = c;
|
||||||
} else if (tok == TOK___HAS_INCLUDE ||
|
} else if (tok == TOK___HAS_INCLUDE ||
|
||||||
tok == TOK___HAS_INCLUDE_NEXT) {
|
tok == TOK___HAS_INCLUDE_NEXT) {
|
||||||
int c, n, i, fd, save_tok = tok;
|
t = tok;
|
||||||
char buf[1024];
|
|
||||||
|
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
if (tok != '(')
|
if (tok != '(')
|
||||||
expect("(");
|
expect("(");
|
||||||
ch = file->buf_ptr[0];
|
c = parse_include(s1, t - TOK___HAS_INCLUDE, 1);
|
||||||
c = parse_include(buf, sizeof(buf), ')');
|
|
||||||
next_nomacro();
|
|
||||||
if (tok != ')')
|
if (tok != ')')
|
||||||
expect("')'");
|
expect("')'");
|
||||||
tok = TOK_CINT;
|
tok = TOK_CINT;
|
||||||
tokc.i = 0;
|
tokc.i = c;
|
||||||
i = save_tok == TOK___HAS_INCLUDE_NEXT ? file->include_next_index + 1 : 0;
|
|
||||||
n = 2 + s1->nb_include_paths + s1->nb_sysinclude_paths;
|
|
||||||
for (; i < n; i++) {
|
|
||||||
char buf1[sizeof file->filename];
|
|
||||||
|
|
||||||
if (get_include_file(s1, i, c, buf, buf1, sizeof(buf1)))
|
|
||||||
continue;
|
|
||||||
if ((fd = open(buf1, O_RDONLY | O_BINARY)) >= 0) {
|
|
||||||
close(fd);
|
|
||||||
tokc.i = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (tok >= TOK_IDENT) {
|
} else if (tok >= TOK_IDENT) {
|
||||||
/* if undefined macro, replace with zero, check for func-like */
|
/* if undefined macro, replace with zero, check for func-like */
|
||||||
t = tok;
|
t = tok;
|
||||||
@ -1922,7 +1925,7 @@ pragma_err:
|
|||||||
ST_FUNC void preprocess(int is_bof)
|
ST_FUNC void preprocess(int is_bof)
|
||||||
{
|
{
|
||||||
TCCState *s1 = tcc_state;
|
TCCState *s1 = tcc_state;
|
||||||
int i, c, n, saved_parse_flags;
|
int c, n, saved_parse_flags;
|
||||||
char buf[1024], *q;
|
char buf[1024], *q;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
|
|
||||||
@ -1954,57 +1957,7 @@ ST_FUNC void preprocess(int is_bof)
|
|||||||
break;
|
break;
|
||||||
case TOK_INCLUDE:
|
case TOK_INCLUDE:
|
||||||
case TOK_INCLUDE_NEXT:
|
case TOK_INCLUDE_NEXT:
|
||||||
ch = file->buf_ptr[0];
|
parse_include(s1, tok - TOK_INCLUDE, 0);
|
||||||
/* XXX: incorrect if comments : use next_nomacro with a special mode */
|
|
||||||
|
|
||||||
c = parse_include(buf, sizeof(buf), 0);
|
|
||||||
|
|
||||||
if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
|
|
||||||
tcc_error("#include recursion too deep");
|
|
||||||
i = tok == TOK_INCLUDE_NEXT ? file->include_next_index + 1 : 0;
|
|
||||||
n = 2 + s1->nb_include_paths + s1->nb_sysinclude_paths;
|
|
||||||
for (; i < n; ++i) {
|
|
||||||
char buf1[sizeof file->filename];
|
|
||||||
CachedInclude *e;
|
|
||||||
|
|
||||||
if (get_include_file(s1, i, c, buf, buf1, sizeof(buf1)))
|
|
||||||
continue;
|
|
||||||
e = search_cached_include(s1, buf1, 0);
|
|
||||||
if (e && (define_find(e->ifndef_macro) || e->once == pp_once)) {
|
|
||||||
/* no need to parse the include because the 'ifndef macro'
|
|
||||||
is defined (or had #pragma once) */
|
|
||||||
#ifdef INC_DEBUG
|
|
||||||
printf("%s: skipping cached %s\n", file->filename, buf1);
|
|
||||||
#endif
|
|
||||||
goto include_done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tcc_open(s1, buf1) < 0)
|
|
||||||
continue;
|
|
||||||
/* push previous file on stack */
|
|
||||||
*s1->include_stack_ptr++ = file->prev;
|
|
||||||
file->include_next_index = i;
|
|
||||||
#ifdef INC_DEBUG
|
|
||||||
printf("%s: including %s\n", file->prev->filename, file->filename);
|
|
||||||
#endif
|
|
||||||
/* update target deps */
|
|
||||||
if (s1->gen_deps) {
|
|
||||||
BufferedFile *bf = file;
|
|
||||||
while (i == 1 && (bf = bf->prev))
|
|
||||||
i = bf->include_next_index;
|
|
||||||
/* skip system include files */
|
|
||||||
if (s1->include_sys_deps || n - i > s1->nb_sysinclude_paths)
|
|
||||||
dynarray_add(&s1->target_deps, &s1->nb_target_deps,
|
|
||||||
tcc_strdup(buf1));
|
|
||||||
}
|
|
||||||
/* add include file debug info */
|
|
||||||
tcc_debug_bincl(tcc_state);
|
|
||||||
tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
|
|
||||||
ch = file->buf_ptr[0];
|
|
||||||
goto the_end;
|
|
||||||
}
|
|
||||||
tcc_error("include file '%s' not found", buf);
|
|
||||||
include_done:
|
|
||||||
break;
|
break;
|
||||||
case TOK_IFNDEF:
|
case TOK_IFNDEF:
|
||||||
c = 1;
|
c = 1;
|
||||||
@ -2026,10 +1979,10 @@ include_done:
|
|||||||
file->ifndef_macro = tok;
|
file->ifndef_macro = tok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tok == TOK___HAS_INCLUDE || tok == TOK___HAS_INCLUDE_NEXT)
|
if (define_find(tok)
|
||||||
c = 1 ^ c;
|
|| tok == TOK___HAS_INCLUDE
|
||||||
else
|
|| tok == TOK___HAS_INCLUDE_NEXT)
|
||||||
c = (define_find(tok) != 0) ^ c;
|
c ^= 1;
|
||||||
do_if:
|
do_if:
|
||||||
if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
|
if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
|
||||||
tcc_error("memory full (ifdef)");
|
tcc_error("memory full (ifdef)");
|
||||||
@ -2120,7 +2073,6 @@ include_done:
|
|||||||
case TOK_ERROR:
|
case TOK_ERROR:
|
||||||
case TOK_WARNING:
|
case TOK_WARNING:
|
||||||
c = tok;
|
c = tok;
|
||||||
ch = file->buf_ptr[0];
|
|
||||||
skip_spaces();
|
skip_spaces();
|
||||||
q = buf;
|
q = buf;
|
||||||
while (ch != '\n' && ch != CH_EOF) {
|
while (ch != '\n' && ch != CH_EOF) {
|
||||||
|
Loading…
Reference in New Issue
Block a user