forked from Mirrors/tinycc
Fix preprocessor concat with empty arg
parent
9714d2e75f
commit
6e56bb387d
1
tcc.h
1
tcc.h
|
@ -836,6 +836,7 @@ struct TCCState {
|
||||||
/* <-- */
|
/* <-- */
|
||||||
|
|
||||||
#define TOK_TWOSHARPS 0xc0 /* ## preprocessing token */
|
#define TOK_TWOSHARPS 0xc0 /* ## preprocessing token */
|
||||||
|
#define TOK_PLCHLDR 0xc1 /* placeholder token as defined in C99 */
|
||||||
#define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
|
#define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
|
||||||
#define TOK_ADDC1 0xc3 /* add with carry generation */
|
#define TOK_ADDC1 0xc3 /* add with carry generation */
|
||||||
#define TOK_ADDC2 0xc4 /* add with carry use */
|
#define TOK_ADDC2 0xc4 /* add with carry use */
|
||||||
|
|
42
tccpp.c
42
tccpp.c
|
@ -2565,7 +2565,8 @@ ST_FUNC void next_nomacro(void)
|
||||||
} while (is_space(tok));
|
} while (is_space(tok));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* substitute args in macro_str and return allocated string */
|
/* substitute arguments in replacement lists in macro_str by the values in
|
||||||
|
args (field d) and return allocated string */
|
||||||
static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
||||||
{
|
{
|
||||||
int last_tok, t, spc;
|
int last_tok, t, spc;
|
||||||
|
@ -2622,7 +2623,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args)
|
||||||
if (gnu_ext && s->type.t &&
|
if (gnu_ext && s->type.t &&
|
||||||
last_tok == TOK_TWOSHARPS &&
|
last_tok == TOK_TWOSHARPS &&
|
||||||
str.len >= 2 && str.str[str.len - 2] == ',') {
|
str.len >= 2 && str.str[str.len - 2] == ',') {
|
||||||
if (*st == 0) {
|
if (*st == TOK_PLCHLDR) {
|
||||||
/* suppress ',' '##' */
|
/* suppress ',' '##' */
|
||||||
str.len -= 2;
|
str.len -= 2;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2793,6 +2794,8 @@ static int macro_subst_tok(TokenString *tok_str,
|
||||||
tok_str_add2(&str, tok, &tokc);
|
tok_str_add2(&str, tok, &tokc);
|
||||||
next_nomacro_spc();
|
next_nomacro_spc();
|
||||||
}
|
}
|
||||||
|
if (!str.len)
|
||||||
|
tok_str_add(&str, TOK_PLCHLDR);
|
||||||
str.len -= spc;
|
str.len -= spc;
|
||||||
tok_str_add(&str, 0);
|
tok_str_add(&str, 0);
|
||||||
sa1 = sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, 0);
|
sa1 = sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, 0);
|
||||||
|
@ -2885,9 +2888,11 @@ static inline int *macro_twosharps(const int *macro_str)
|
||||||
TOK_GET(&t, &ptr, &cval);
|
TOK_GET(&t, &ptr, &cval);
|
||||||
/* We concatenate the two tokens */
|
/* We concatenate the two tokens */
|
||||||
cstr_new(&cstr);
|
cstr_new(&cstr);
|
||||||
cstr_cat(&cstr, get_tok_str(tok, &tokc));
|
if (tok != TOK_PLCHLDR)
|
||||||
|
cstr_cat(&cstr, get_tok_str(tok, &tokc));
|
||||||
n = cstr.size;
|
n = cstr.size;
|
||||||
cstr_cat(&cstr, get_tok_str(t, &cval));
|
if (t != TOK_PLCHLDR || tok == TOK_PLCHLDR)
|
||||||
|
cstr_cat(&cstr, get_tok_str(t, &cval));
|
||||||
cstr_ccat(&cstr, '\0');
|
cstr_ccat(&cstr, '\0');
|
||||||
|
|
||||||
tcc_open_bf(tcc_state, ":paste:", cstr.size);
|
tcc_open_bf(tcc_state, ":paste:", cstr.size);
|
||||||
|
@ -2904,8 +2909,35 @@ static inline int *macro_twosharps(const int *macro_str)
|
||||||
cstr_free(&cstr);
|
cstr_free(&cstr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (tok != TOK_NOSUBST)
|
if (tok != TOK_NOSUBST) {
|
||||||
|
const int *oldptr;
|
||||||
|
CValue cval;
|
||||||
|
|
||||||
|
/* Check if a space need to be added after ## concatenation in
|
||||||
|
order to avoid misinterpreting the newly formed token
|
||||||
|
followed by the next token as being a single token (see
|
||||||
|
macro_concat test) */
|
||||||
|
cstr_new(&cstr);
|
||||||
|
cstr_cat(&cstr, get_tok_str(tok, &tokc));
|
||||||
|
oldptr = ptr;
|
||||||
|
TOK_GET(&t, &ptr, &cval);
|
||||||
|
ptr = oldptr;
|
||||||
|
cstr_cat(&cstr, get_tok_str(t, &cval));
|
||||||
|
cstr_ccat(&cstr, '\0');
|
||||||
|
t = tok;
|
||||||
|
cval = tokc;
|
||||||
|
tcc_open_bf(tcc_state, ":paste:", cstr.size);
|
||||||
|
memcpy(file->buffer, cstr.data, cstr.size);
|
||||||
|
next_nomacro1();
|
||||||
|
if (!*file->buf_ptr) {
|
||||||
|
tok_str_add2(¯o_str1, t, &cval);
|
||||||
|
tok = ' ';
|
||||||
|
}
|
||||||
|
tcc_close();
|
||||||
|
cstr_free(&cstr);
|
||||||
|
|
||||||
start_of_nosubsts = -1;
|
start_of_nosubsts = -1;
|
||||||
|
}
|
||||||
tok_str_add2(¯o_str1, tok, &tokc);
|
tok_str_add2(¯o_str1, tok, &tokc);
|
||||||
}
|
}
|
||||||
tok_str_add(¯o_str1, 0);
|
tok_str_add(¯o_str1, 0);
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define P(A,B) A ## B ; bob
|
||||||
|
#define Q(A,B) A ## B+
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
int bob, jim = 21;
|
||||||
|
bob = P(jim,) *= 2;
|
||||||
|
printf("jim: %d, bob: %d\n", jim, bob);
|
||||||
|
jim = 60 Q(+,)3;
|
||||||
|
printf("jim: %d\n", jim);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
jim: 21, bob: 42
|
||||||
|
jim: 63
|
|
@ -81,7 +81,8 @@ TESTS = \
|
||||||
63_local_enumerator_redefinition.test \
|
63_local_enumerator_redefinition.test \
|
||||||
64_macro_nesting.test \
|
64_macro_nesting.test \
|
||||||
65_macro_concat_start.test \
|
65_macro_concat_start.test \
|
||||||
66_macro_concat_end.test
|
66_macro_concat_end.test \
|
||||||
|
67_macro_concat.test
|
||||||
|
|
||||||
# 30_hanoi.test -- seg fault in the code, gcc as well
|
# 30_hanoi.test -- seg fault in the code, gcc as well
|
||||||
# 34_array_assignment.test -- array assignment is not in C standard
|
# 34_array_assignment.test -- array assignment is not in C standard
|
||||||
|
|
Loading…
Reference in New Issue