aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tcc.h1
-rw-r--r--tccpp.c42
-rw-r--r--tests/tests2/67_macro_concat.c14
-rw-r--r--tests/tests2/67_macro_concat.expect2
-rw-r--r--tests/tests2/Makefile3
5 files changed, 56 insertions, 6 deletions
diff --git a/tcc.h b/tcc.h
index 9955839..dda2fc1 100644
--- a/tcc.h
+++ b/tcc.h
@@ -836,6 +836,7 @@ struct TCCState {
/* <-- */
#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_ADDC1 0xc3 /* add with carry generation */
#define TOK_ADDC2 0xc4 /* add with carry use */
diff --git a/tccpp.c b/tccpp.c
index c8beec5..dfdee50 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -2565,7 +2565,8 @@ ST_FUNC void next_nomacro(void)
} 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)
{
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 &&
last_tok == TOK_TWOSHARPS &&
str.len >= 2 && str.str[str.len - 2] == ',') {
- if (*st == 0) {
+ if (*st == TOK_PLCHLDR) {
/* suppress ',' '##' */
str.len -= 2;
} else {
@@ -2793,6 +2794,8 @@ static int macro_subst_tok(TokenString *tok_str,
tok_str_add2(&str, tok, &tokc);
next_nomacro_spc();
}
+ if (!str.len)
+ tok_str_add(&str, TOK_PLCHLDR);
str.len -= spc;
tok_str_add(&str, 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);
/* We concatenate the two tokens */
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;
- 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');
tcc_open_bf(tcc_state, ":paste:", cstr.size);
@@ -2904,8 +2909,35 @@ static inline int *macro_twosharps(const int *macro_str)
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(&macro_str1, t, &cval);
+ tok = ' ';
+ }
+ tcc_close();
+ cstr_free(&cstr);
+
start_of_nosubsts = -1;
+ }
tok_str_add2(&macro_str1, tok, &tokc);
}
tok_str_add(&macro_str1, 0);
diff --git a/tests/tests2/67_macro_concat.c b/tests/tests2/67_macro_concat.c
new file mode 100644
index 0000000..c580d3a
--- /dev/null
+++ b/tests/tests2/67_macro_concat.c
@@ -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;
+}
diff --git a/tests/tests2/67_macro_concat.expect b/tests/tests2/67_macro_concat.expect
new file mode 100644
index 0000000..8386c2d
--- /dev/null
+++ b/tests/tests2/67_macro_concat.expect
@@ -0,0 +1,2 @@
+jim: 21, bob: 42
+jim: 63
diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile
index 41adb2d..a7c8a2f 100644
--- a/tests/tests2/Makefile
+++ b/tests/tests2/Makefile
@@ -81,7 +81,8 @@ TESTS = \
63_local_enumerator_redefinition.test \
64_macro_nesting.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
# 34_array_assignment.test -- array assignment is not in C standard