I've applied some of the changes to mob, and I'm attaching a diff with
the remaining changes. Feel free to revert some or all of those if you
think they need further discussion or shouldn't go in at all.
I'm not sure I have handling of placeholders and GNU commas right; the
problem is I can't compare to gcc as gcc has stopped supporting them
in most cases.
On Sat, May 2, 2015 at 11:50 AM, Pip Cet <[email protected]> wrote:
> I think everything is working now, with one exception that I think is fine:
>
> #define STRINGIFY2(x) #x
> #define STRINGIFY(x) STRINGIFY2(x)
> #define a \4
>
> int main (void)
> {
> printf("%s\n", STRINGIFY(a));
> }
>
> produces "\004", not "\4". They're equivalent, though.
>
> I'd appreciate it very much if people found things that are still
> broken with this patch, though I have my suspicions about a few cases
> that I'm going to try reproducing and fixing next (and then the memory
> leak and various cleanups).
>
> Thanks again for finding the test cases!
>
> On Fri, May 1, 2015 at 6:15 PM, Pip Cet <[email protected]> wrote:
>> Ooh, those are excellent. Thanks for finding them!
>>
>> Here's a preliminary patch that should fix all but tests 1 and 3,
>> which I'm still working on. Needs more testing and cleanup and all
>> that, but it would be great if someone could verify that the other
>> tests are indeed fixed by the patch.
>>
>>> /* ---- TEST 1 ---------------------------------- */
>>> #define hash_hash # ## #
>>> #define mkstr(a) # a
>>> #define in_between(a) mkstr(a)
>>> #define join(c, d) in_between(c hash_hash d)
>>> char p[] = join(x, y); // equivalent to
>>> // char p[] = "x ## y";
>>> /* --- EXPECT 1 --------------------------------- */
>>> char p[] = "x ## y";
>>
>> This one's difficult. It seems we stringify in the wrong place, or
>> places. Closely related to test 3.
>>
>>> /* ---- TEST 2 ---------------------------------- */
>>> #define x 3
>>> #define f(a) f(x * (a))
>>> #undef x
>>> #define x 2
>>> #define g f
>>> #define z z[0]
>>> #define h g(~
>>> #define m(a) a(w)
>>> #define w 0,1
>>> #define t(a) a
>>> #define p() int
>>> #define q(x) x
>>> #define r(x,y) x ## y
>>> #define str(x) # x
>>> f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);
>>> g(x+(3,4)-w) | h 5) & m
>>> (f)^m(m);
>>> p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };
>>> char c[2][6] = { str(hello), str() };
>>> /*
>>> * f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);
>>> * f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);
>>> * int i[] = { 1, 23, 4, 5, };
>>> * char c[2][6] = { "hello", "" };
>>> */
>>
>> fixed this one, though the fix isn't pretty and leaks memory at present.
>>
>> (will get back to test 3 later)
>>
>>> /* ---- TEST 5 ---------------------------------- */
>>> #define t(x,y,z) x ## y ## z
>>> int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,),
>>> t(10,,), t(,11,), t(,,12), t(,,) };
>>
>> This one appears to be fixed by my other patches.
>>
>>> /* ---- TEST 7 ---------------------------------- */
>>> #define a() YES
>>> #define b() a
>>> b()
>>> b()()
>>> /* --- EXPECT 7 --------------------------------- */
>>> a
>>> YES
>>
>> Fixed this one. Actually found a bug in my previous patch, so that's great.
>>
>> The rest, I think, already are passing?
diff --git a/tccpp.c b/tccpp.c
index fa29ca9..59e3603 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -2994,8 +2994,30 @@ static int macro_subst_tok(TokenString *tok_str,
else
break;
}
- if (tok != ',')
- expect(",");
+ /*
+ * #define f(a) f(a)
+ * #define h f(r
+ * h 5)
+ */
+ if (tok != ',') {
+ /* Argh! Not a macro invocation after all, at this
+ * point, so put everything back onto mstr that's
+ * been skipped since we saw the '(' )*/
+ tok_str_new(&str);
+ tok_str_add(&str, mtok);
+ tok_str_add(&str, '(');
+ for (sa = s->next; sa; sa = sa->next) {
+ int *p = sa->d;
+ while (p && *p) {
+ tok_str_add(&str, *p);
+ p++;
+ }
+ mstr = str.str;
+ /* leak memory */;
+ mstr_allocated = 0;
+ goto free_memory;
+ }
+ }
next_nomacro();
}
if (sa) {
@@ -3005,6 +3027,7 @@ static int macro_subst_tok(TokenString *tok_str,
/* now subst each arg */
mstr = macro_arg_subst(nested_list, mstr, args);
+ free_memory:
/* free memory */
sa = args;
while (sa) {
@@ -3056,8 +3079,6 @@ static inline int *macro_twosharps(const int *macro_str)
TOK_GET(&tok, &ptr, &tokc);
if (tok == 0)
break;
- if (tok == TOK_TWOSHARPS)
- continue;
if (tok == TOK_NOSUBST && start_of_nosubsts < 0)
start_of_nosubsts = macro_str1.len;
while (*ptr == TOK_TWOSHARPS) {
@@ -3077,13 +3098,15 @@ static inline int *macro_twosharps(const int *macro_str)
if (tok != TOK_PLCHLDR)
cstr_cat(&cstr, get_tok_str(tok, &tokc));
n = cstr.size;
- if (t != TOK_PLCHLDR || tok == TOK_PLCHLDR)
+ if (t != TOK_PLCHLDR)
cstr_cat(&cstr, get_tok_str(t, &cval));
cstr_ccat(&cstr, '\0');
tcc_open_bf(tcc_state, ":paste:", cstr.size);
memcpy(file->buffer, cstr.data, cstr.size);
for (;;) {
+ if (0 == *file->buf_ptr)
+ break;
next_nomacro1();
if (0 == *file->buf_ptr)
break;
@@ -3094,13 +3117,22 @@ static inline int *macro_twosharps(const int *macro_str)
tcc_close();
cstr_free(&cstr);
}
+ if (tok == TOK_TWOSHARPS) {
+ /* two sharps twosharped together tokenize to two
+ * sharp tokens, not a twosharp token. */
+ /* That's fun to say, but is it actually true? GCC
+ * stringifies #define a # ## # ## # to "## #" (and a
+ * warning), while we produce "###" (no warning) */
+ tok_str_add(¯o_str1, '#');
+ tok = '#';
+ }
}
if (tok != TOK_NOSUBST) {
tok_str_add2(¯o_str1, tok, &tokc);
tok = ' ';
start_of_nosubsts = -1;
- }
- tok_str_add2(¯o_str1, tok, &tokc);
+ } else
+ tok_str_add2(¯o_str1, tok, &tokc);
}
tok_str_add(¯o_str1, 0);
return macro_str1.str;
@@ -3119,7 +3151,6 @@ static void macro_subst(TokenString *tok_str, Sym
**nested_list,
int t, spc;
CValue cval;
struct macro_level ml;
- int force_blank;
int gnucomma_index = -1;
/* first scan for '##' operator handling */
@@ -3129,7 +3160,6 @@ static void macro_subst(TokenString *tok_str, Sym
**nested_list,
if (macro_str1)
ptr = macro_str1;
spc = 0;
- force_blank = 0;
while (1) {
/* NOTE: ptr == NULL can only happen if tokens are read from
@@ -3175,18 +3205,11 @@ static void macro_subst(TokenString *tok_str, Sym
**nested_list,
macro_ptr = ml.p;
if (can_read_stream && *can_read_stream == &ml)
*can_read_stream = ml.prev;
- if (parse_flags & PARSE_FLAG_SPACES)
- force_blank = 1;
if (old_len == tok_str->len)
tok_str_add(tok_str, TOK_PLCHLDR);
} else {
no_subst:
- if (force_blank) {
- tok_str_add(tok_str, ' ');
- spc = 1;
- force_blank = 0;
- }
- if (!check_space(t, &spc))
+ if (!check_space(t, &spc))
tok_str_add2(tok_str, t, &cval);
}
if (gnucomma_index != -1) {
diff --git a/tests/tests2/80_macros.c b/tests/tests2/80_macros.c
new file mode 100644
index 0000000..4db2650
--- /dev/null
+++ b/tests/tests2/80_macros.c
@@ -0,0 +1,46 @@
+#include <stdio.h>
+
+#define A(a,b...) g(a,##b,##b)
+#define B(x...) x
+#define C \
+
+#define D(x,y) x ## y
+#define E(x,y,z) x ## y ## z
+#define F(x) x
+#define G C
+#define H() F
+
+#define STRINGIFY2(x) #x
+#define STRINGIFY(x) STRINGIFY2(x)
+
+int main(void)
+{
+ printf("%s\n", STRINGIFY()); // should produce the empty string
+ printf("%s\n", STRINGIFY(C)); // should produce the empty string
+ printf("%s\n", STRINGIFY(
+ A(a,)
+ A(a,b)
+ A(a,b,c)
+ )); // should produce g(a ) g(a,b,b)g(a,b,c,b,c)
+ printf("%s\n", STRINGIFY(B())); // should produce the empty string
+ printf("%s\n", STRINGIFY(B(C))); // should produce the empty string
+ printf("%s\n", STRINGIFY(D(,))); // should produce the empty string
+ printf("%s\n", STRINGIFY(E(1,,))); // should produce 1
+ printf("%s\n", STRINGIFY(E(,2,))); // should produce 2
+ printf("%s\n", STRINGIFY(E(,,3))); // should produce 3
+ printf("%s\n", STRINGIFY(E(1,2,3))); // should produce 123
+
+ // should produce g(a ) g(a )g(a )g(a )g(a )
+ printf("%s\n", STRINGIFY(A(a,F()) A(a,C) A(a,G) A(a,) A(a)));
+ printf("%s\n", STRINGIFY(H()x));
+
+ // should produce F x, not Fx
+ printf("%s\n", STRINGIFY(H()
+x));
+
+ printf("%s\n", STRINGIFY(I x));
+ printf("%s\n", STRINGIFY(I
+x));
+
+ return 0;
+}
diff --git a/tests/tests2/80_macros.expect b/tests/tests2/80_macros.expect
new file mode 100644
index 0000000..0394cd3
--- /dev/null
+++ b/tests/tests2/80_macros.expect
@@ -0,0 +1,15 @@
+
+
+g(a) g(a,b,b) g(a,b,c,b,c)
+
+
+
+1
+2
+3
+123
+g(a) g(a) g(a) g(a) g(a)
+Fx
+F x
+I x
+I x
diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile
index a441674..97c22dc 100644
--- a/tests/tests2/Makefile
+++ b/tests/tests2/Makefile
@@ -98,7 +98,8 @@ TESTS = \
76_dollars_in_identifiers.test \
77_push_pop_macro.test \
78_vla_label.test \
- 79_vla_continue.test
+ 79_vla_continue.test \
+ 80_macros.test
# 34_array_assignment.test -- array assignment is not in C standard
_______________________________________________
Tinycc-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel