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(&macro_str1, '#');
+                tok = '#';
+            }
         }
         if (tok != TOK_NOSUBST) {
             tok_str_add2(&macro_str1, tok, &tokc);
             tok = ' ';
             start_of_nosubsts = -1;
-        }
-        tok_str_add2(&macro_str1, tok, &tokc);
+        } else
+            tok_str_add2(&macro_str1, tok, &tokc);
     }
     tok_str_add(&macro_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

Reply via email to