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