20060428 Dave Dodge There's a bug in the macro_twosharps() function, where a pp-number is not created properly when multiple token pastings are involved. The sample code below from jun.lambda@gmail.com demonstrates the problem; FLAGS(0) should evaluate to 0 but ends up evaluating to 1: #define SQUISH(n) (!!((n) & 0xF)) #define HEX2BIN(n) (SQUISH(n)) #define FLAGS(f) HEX2BIN(0x##f##U) int main () { return FLAGS(0); } What happens internally is that the first pasting of "0x"+"0" creates the pp-number "0x0". The buffer containing that result is then used directly as the current token string. When the second pasting begins, the buffer is reset, destroying the current token string before the pasting operation. So instead of pasting "0x0"+"U", it ends up with ""+"U". A solution is to use a different buffer to hold the current token contents, so that concatenation won't damage it. The global tokcstr is normally used alongside tok and tokc when parsing, so I just used that. Index: tcc-0.9.23/tcc.c =================================================================== --- tcc-0.9.23.orig/tcc.c 2006-04-28 03:40:30.000000000 -0400 +++ tcc-0.9.23/tcc.c 2006-04-28 03:43:41.000000000 -0400 @@ -4214,9 +4214,14 @@ (t >= TOK_IDENT || t == TOK_PPNUM)) { if (tok == TOK_PPNUM) { /* if number, then create a number token */ - /* NOTE: no need to allocate because - tok_str_add2() does it */ - tokc.cstr = &cstr; + /* NOTE: we cannot use cstr directly for this + because if there are multiple token pastings + in a sequence the concatenation will reset + cstr before the final token is ready. */ + cstr_reset(&tokcstr); + cstr_cat(&tokcstr, cstr.data); + cstr_ccat(&tokcstr, '\0'); + tokc.cstr = &tokcstr; } else { /* if identifier, we must do a test to validate we have a correct identifier */