Hmm, this is trickier than I thought at first. The attached patch
passes tests and works for the case I described in my last mail, but
fails for

#define A(a,b...) g(a,##b,##b)
A(a,)

which should produce g(a). Probably. I mean, it's pretty weird to use
variadic macros like that, though someone might have a

#define double_printf(fmt, args...) printf(fmt##fmt,##args,##args)

macro. But I just checked and mob tcc does support the double-varargs example.

On Fri, May 1, 2015 at 4:39 AM, Sergey Korshunoff <[email protected]> wrote:
> Hi! tcc-macro-002.diff don't break anything for me.
>
> _______________________________________________
> Tinycc-devel mailing list
> [email protected]
> https://lists.nongnu.org/mailman/listinfo/tinycc-devel
diff --git a/tcc.h b/tcc.h
index 384e8de..aeb44fc 100644
--- a/tcc.h
+++ b/tcc.h
@@ -880,6 +880,7 @@ struct TCCState {
 #define TOK_DOTS     0xcc /* three dots */
 #define TOK_SHR      0xcd /* unsigned shift right */
 #define TOK_NOSUBST  0xcf /* means following token has already been pp'd */
+#define TOK_GNUCOMMA 0xd0 /* ,## preprocessing token */
 
 #define TOK_SHL   0x01 /* shift left */
 #define TOK_SAR   0x02 /* signed shift right */
diff --git a/tccpp.c b/tccpp.c
index 0a99832..f884b37 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -2771,14 +2771,11 @@ 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 == TOK_PLCHLDR) {
-                            /* suppress ',' '##' */
-                            str.len -= 2;
-                        } else {
-                            /* suppress '##' and add variable */
-                            str.len--;
-                            goto add_var;
-                        }
+                        str.len -= 2;
+                        tok_str_add(&str, TOK_GNUCOMMA);
+                        str.str[str.len] = 0;
+
+                        goto add_var;
                     } else {
                         int t1;
                     add_var:
@@ -2789,7 +2786,7 @@ static int *macro_arg_subst(Sym **nested_list, const int 
*macro_str, Sym *args)
                             tok_str_add2(&str, t1, &cval);
                         }
                     }
-                } else if (*st != TOK_PLCHLDR) {
+                } else {
                     /* NOTE: the stream cannot be read when macro
                        substituing an argument */
                     macro_subst(&str, nested_list, st, NULL);
@@ -2802,6 +2799,8 @@ static int *macro_arg_subst(Sym **nested_list, const int 
*macro_str, Sym *args)
         }
         last_tok = t;
     }
+    if (str.len == 0)
+        tok_str_add(&str, TOK_PLCHLDR);
     tok_str_add(&str, 0);
     return str.str;
 }
@@ -2942,9 +2941,9 @@ 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;
+                if (str.len == 0)
+                    tok_str_add(&str, TOK_PLCHLDR);
                 tok_str_add(&str, 0);
                 sa1 = sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, 0);
                 sa1->d = str.str;
@@ -3039,13 +3038,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;
@@ -3082,6 +3083,7 @@ static void macro_subst(TokenString *tok_str, Sym 
**nested_list,
     CValue cval;
     struct macro_level ml;
     int force_blank;
+    int gnucomma_index = -1;
     
     /* first scan for '##' operator handling */
     ptr = macro_str;
@@ -3106,8 +3108,16 @@ static void macro_subst(TokenString *tok_str, Sym 
**nested_list,
             TOK_GET(&t, &ptr, &cval);
             goto no_subst;
         }
+        if (t == TOK_GNUCOMMA) {
+            if (gnucomma_index != -1)
+                tcc_error("two GNU commas in the same macro");
+            gnucomma_index = tok_str->len;
+            tok_str_add(tok_str, ',');
+            TOK_GET(&t, &ptr, &cval);
+        }
         s = define_find(t);
         if (s != NULL) {
+            int old_length = tok_str->len;
             /* if nested substitution, do nothing */
             if (sym_find2(*nested_list, t)) {
                 /* and mark it as TOK_NOSUBST, so it doesn't get subst'd again 
*/
@@ -3120,6 +3130,8 @@ static void macro_subst(TokenString *tok_str, Sym 
**nested_list,
             macro_ptr = (int *)ptr;
             tok = t;
             ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
+            if (old_length == tok_str->len)
+                tok_str_add(tok_str, TOK_PLCHLDR);
             ptr = (int *)macro_ptr;
             macro_ptr = ml.p;
             if (can_read_stream && *can_read_stream == &ml)
@@ -3138,6 +3150,12 @@ static void macro_subst(TokenString *tok_str, Sym 
**nested_list,
             if (!check_space(t, &spc)) 
                 tok_str_add2(tok_str, t, &cval);
         }
+        if (gnucomma_index != -1 &&
+            tok_str->len >= gnucomma_index+2 &&
+            tok_str->str[gnucomma_index+1] == TOK_PLCHLDR)
+            tok_str->str[gnucomma_index] = ' ';
+        if (tok_str->len && tok_str->str[tok_str->len-1] == TOK_PLCHLDR)
+            tok_str->len--;
     }
     if (macro_str1)
         tok_str_free(macro_str1);
_______________________________________________
Tinycc-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to