forked from Mirrors/tinycc
tccpp: allow "#define X defined Y ..."
That means: we do not macro-expand the argument of 'defined' Also: store the last token position into the TokenString structure in order to get rid of the tok_last function.master
parent
824dcebe59
commit
6c468c10f7
1
tcc.h
1
tcc.h
|
@ -561,6 +561,7 @@ typedef struct ParseState {
|
||||||
typedef struct TokenString {
|
typedef struct TokenString {
|
||||||
int *str;
|
int *str;
|
||||||
int len;
|
int len;
|
||||||
|
int lastlen;
|
||||||
int allocated_len;
|
int allocated_len;
|
||||||
int last_line_num;
|
int last_line_num;
|
||||||
/* used to chain token-strings with begin/end_macro() */
|
/* used to chain token-strings with begin/end_macro() */
|
||||||
|
|
50
tccpp.c
50
tccpp.c
|
@ -48,6 +48,7 @@ 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_once;
|
||||||
|
static int pp_expr;
|
||||||
static void tok_print(const char *msg, const int *str);
|
static void tok_print(const char *msg, const int *str);
|
||||||
|
|
||||||
static struct TinyAlloc *toksym_alloc;
|
static struct TinyAlloc *toksym_alloc;
|
||||||
|
@ -127,7 +128,7 @@ ST_FUNC void expect(const char *msg)
|
||||||
#define tal_free(al, p) tal_free_impl(al, p, __FILE__, __LINE__)
|
#define tal_free(al, p) tal_free_impl(al, p, __FILE__, __LINE__)
|
||||||
#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size, __FILE__, __LINE__)
|
#define tal_realloc(al, p, size) tal_realloc_impl(&al, p, size, __FILE__, __LINE__)
|
||||||
#define TAL_DEBUG_PARAMS , const char *file, int line
|
#define TAL_DEBUG_PARAMS , const char *file, int line
|
||||||
#define TAL_DEBUG_FILE_LEN 15
|
#define TAL_DEBUG_FILE_LEN 40
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define TOKSYM_TAL_SIZE (768 * 1024) /* allocator for tiny TokenSym in table_ident */
|
#define TOKSYM_TAL_SIZE (768 * 1024) /* allocator for tiny TokenSym in table_ident */
|
||||||
|
@ -1056,7 +1057,7 @@ static inline int tok_size(const int *p)
|
||||||
ST_INLN void tok_str_new(TokenString *s)
|
ST_INLN void tok_str_new(TokenString *s)
|
||||||
{
|
{
|
||||||
s->str = NULL;
|
s->str = NULL;
|
||||||
s->len = 0;
|
s->len = s->lastlen = 0;
|
||||||
s->allocated_len = 0;
|
s->allocated_len = 0;
|
||||||
s->last_line_num = -1;
|
s->last_line_num = -1;
|
||||||
}
|
}
|
||||||
|
@ -1142,7 +1143,7 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv)
|
||||||
{
|
{
|
||||||
int len, *str;
|
int len, *str;
|
||||||
|
|
||||||
len = s->len;
|
len = s->lastlen = s->len;
|
||||||
str = s->str;
|
str = s->str;
|
||||||
|
|
||||||
/* allocate space for worst case */
|
/* allocate space for worst case */
|
||||||
|
@ -1271,19 +1272,6 @@ static inline void TOK_GET(int *t, const int **pp, CValue *cv)
|
||||||
*pp = p;
|
*pp = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calling this function is expensive, but it is not possible
|
|
||||||
to read a token string backwards. */
|
|
||||||
static int tok_last(const int *str0, const int *str1)
|
|
||||||
{
|
|
||||||
const int *str = str0;
|
|
||||||
int tok = 0;
|
|
||||||
CValue cval;
|
|
||||||
|
|
||||||
while (str < str1)
|
|
||||||
TOK_GET(&tok, &str, &cval);
|
|
||||||
return tok;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int macro_is_equal(const int *a, const int *b)
|
static int macro_is_equal(const int *a, const int *b)
|
||||||
{
|
{
|
||||||
CValue cv;
|
CValue cv;
|
||||||
|
@ -1418,6 +1406,7 @@ static int expr_preprocess(void)
|
||||||
TokenString *str;
|
TokenString *str;
|
||||||
|
|
||||||
str = tok_str_alloc();
|
str = tok_str_alloc();
|
||||||
|
pp_expr = 1;
|
||||||
while (tok != TOK_LINEFEED && tok != TOK_EOF) {
|
while (tok != TOK_LINEFEED && tok != TOK_EOF) {
|
||||||
next(); /* do macro subst */
|
next(); /* do macro subst */
|
||||||
if (tok == TOK_DEFINED) {
|
if (tok == TOK_DEFINED) {
|
||||||
|
@ -1425,9 +1414,14 @@ static int expr_preprocess(void)
|
||||||
t = tok;
|
t = tok;
|
||||||
if (t == '(')
|
if (t == '(')
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
|
if (tok < TOK_IDENT)
|
||||||
|
expect("identifier");
|
||||||
c = define_find(tok) != 0;
|
c = define_find(tok) != 0;
|
||||||
if (t == '(')
|
if (t == '(') {
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
|
if (tok != ')')
|
||||||
|
expect("')'");
|
||||||
|
}
|
||||||
tok = TOK_CINT;
|
tok = TOK_CINT;
|
||||||
tokc.i = c;
|
tokc.i = c;
|
||||||
} else if (tok >= TOK_IDENT) {
|
} else if (tok >= TOK_IDENT) {
|
||||||
|
@ -1437,6 +1431,7 @@ static int expr_preprocess(void)
|
||||||
}
|
}
|
||||||
tok_str_add_tok(str);
|
tok_str_add_tok(str);
|
||||||
}
|
}
|
||||||
|
pp_expr = 0;
|
||||||
tok_str_add(str, -1); /* simulate end of file */
|
tok_str_add(str, -1); /* simulate end of file */
|
||||||
tok_str_add(str, 0);
|
tok_str_add(str, 0);
|
||||||
/* now evaluate C constant expression */
|
/* now evaluate C constant expression */
|
||||||
|
@ -1456,7 +1451,7 @@ ST_FUNC void parse_define(void)
|
||||||
int saved_parse_flags = parse_flags;
|
int saved_parse_flags = parse_flags;
|
||||||
|
|
||||||
v = tok;
|
v = tok;
|
||||||
if (v < TOK_IDENT)
|
if (v < TOK_IDENT || v == TOK_DEFINED)
|
||||||
tcc_error("invalid macro name '%s'", get_tok_str(tok, &tokc));
|
tcc_error("invalid macro name '%s'", get_tok_str(tok, &tokc));
|
||||||
/* XXX: should check if same macro (ANSI) */
|
/* XXX: should check if same macro (ANSI) */
|
||||||
first = NULL;
|
first = NULL;
|
||||||
|
@ -3403,23 +3398,26 @@ static void macro_subst(
|
||||||
macro_str = macro_ptr;
|
macro_str = macro_ptr;
|
||||||
end_macro ();
|
end_macro ();
|
||||||
}
|
}
|
||||||
|
if (tok_str->len)
|
||||||
spc = (tok_str->len &&
|
spc = is_space(t = tok_str->str[tok_str->lastlen]);
|
||||||
is_space(tok_last(tok_str->str,
|
|
||||||
tok_str->str + tok_str->len)));
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (t == '\\' && !(parse_flags & PARSE_FLAG_ACCEPT_STRAYS))
|
if (t == '\\' && !(parse_flags & PARSE_FLAG_ACCEPT_STRAYS))
|
||||||
tcc_error("stray '\\' in program");
|
tcc_error("stray '\\' in program");
|
||||||
|
|
||||||
no_subst:
|
no_subst:
|
||||||
if (!check_space(t, &spc))
|
if (!check_space(t, &spc))
|
||||||
tok_str_add2(tok_str, t, &cval);
|
tok_str_add2(tok_str, t, &cval);
|
||||||
nosubst = 0;
|
|
||||||
|
if (nosubst) {
|
||||||
|
if (nosubst > 1 && (spc || (++nosubst == 3 && t == '(')))
|
||||||
|
continue;
|
||||||
|
nosubst = 0;
|
||||||
|
}
|
||||||
if (t == TOK_NOSUBST)
|
if (t == TOK_NOSUBST)
|
||||||
nosubst = 1;
|
nosubst = 1;
|
||||||
}
|
}
|
||||||
|
/* GCC supports 'defined' as result of a macto substitution */
|
||||||
|
if (t == TOK_DEFINED && pp_expr)
|
||||||
|
nosubst = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/* accept 'defined' as result of substitution */
|
||||||
|
|
||||||
|
----- 1 ------
|
||||||
|
#define AAA 2
|
||||||
|
#define BBB
|
||||||
|
#define CCC (defined ( AAA ) && AAA > 1 && !defined BBB)
|
||||||
|
#if !CCC
|
||||||
|
OK
|
||||||
|
#else
|
||||||
|
NOT OK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
----- 2 ------
|
||||||
|
#undef BBB
|
||||||
|
#if CCC
|
||||||
|
OK
|
||||||
|
#else
|
||||||
|
NOT OK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
----- 3 ------
|
||||||
|
#define DEFINED defined
|
||||||
|
#define DDD (DEFINED ( AAA ) && AAA > 1 && !DEFINED BBB)
|
||||||
|
#if (DDD)
|
||||||
|
OK
|
||||||
|
#else
|
||||||
|
NOT OK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
----- 4 ------
|
||||||
|
#undef AAA
|
||||||
|
#if !(DDD)
|
||||||
|
OK
|
||||||
|
#else
|
||||||
|
NOT OK
|
||||||
|
#endif
|
|
@ -0,0 +1,8 @@
|
||||||
|
----- 1 ------
|
||||||
|
OK
|
||||||
|
----- 2 ------
|
||||||
|
OK
|
||||||
|
----- 3 ------
|
||||||
|
OK
|
||||||
|
----- 4 ------
|
||||||
|
OK
|
Loading…
Reference in New Issue