From a6e6a954f5fb70c12e2f40e99281219c720de71b Mon Sep 17 00:00:00 2001 From: Philip Date: Sat, 2 May 2015 13:19:14 +0000 Subject: [PATCH] tccpp.c: correct # stringification Fix handling of escape characters, spaces, and line feeds in macros or macro arguments that might yet be subject to # stringification. Should this be an -f option? I think memory usage increases only very slightly (in particular, while line feeds, stray \s, and spaces are preserved, comments are not), so it's probably not worth it to make it one. Note that macro_subst now checks for stray \s which are still left in the input stream after macro substitution, if desired. This patch depends on the previous patch, so if you revert that, please revert this patch, too. See http://lists.nongnu.org/archive/html/tinycc-devel/2015-05/msg00002.html --- tccpp.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/tccpp.c b/tccpp.c index ed3168f..dc79d20 100644 --- a/tccpp.c +++ b/tccpp.c @@ -1254,6 +1254,7 @@ ST_FUNC void parse_define(void) { Sym *s, *first, **ps; int v, t, varg, is_vaargs, spc, ptok, macro_list_start; + int saved_parse_flags; TokenString str; v = tok; @@ -1295,6 +1296,8 @@ ST_FUNC void parse_define(void) /* EOF testing necessary for '-D' handling */ ptok = 0; macro_list_start = 1; + saved_parse_flags = parse_flags; + parse_flags |= PARSE_FLAG_ACCEPT_STRAYS | PARSE_FLAG_SPACES | PARSE_FLAG_LINEFEED; while (tok != TOK_LINEFEED && tok != TOK_EOF) { if (macro_list_start && spc == 2 && tok == TOK_TWOSHARPS) tcc_error("'##' invalid at start of macro"); @@ -1314,6 +1317,7 @@ ST_FUNC void parse_define(void) skip: next_nomacro_spc(); } + parse_flags = saved_parse_flags; if (ptok == TOK_TWOSHARPS) tcc_error("'##' invalid at end of macro"); if (spc == 1) @@ -2729,6 +2733,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) CValue cval; TokenString str; CString cstr; + CString cstr2; tok_str_new(&str); last_tok = 0; @@ -2757,9 +2762,13 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) printf("stringize: %s\n", (char *)cstr.data); #endif /* add string */ - cval.cstr = &cstr; - tok_str_add2(&str, TOK_STR, &cval); + cstr_new(&cstr2); + /* emulate GCC behaviour and parse escapes in the token string */ + parse_escape_string(&cstr2, cstr.data, 0); cstr_free(&cstr); + cval.cstr = &cstr2; + tok_str_add2(&str, TOK_STR, &cval); + cstr_free(cval.cstr); } else { tok_str_add2(&str, t, &cval); } @@ -2868,6 +2877,9 @@ static int macro_subst_tok(TokenString *tok_str, tok_str_add2(tok_str, t1, &cval); cstr_free(&cstr); } else { + int saved_parse_flags = parse_flags; + parse_flags |= PARSE_FLAG_ACCEPT_STRAYS | PARSE_FLAG_SPACES | PARSE_FLAG_LINEFEED; + mstr = s->d; mstr_allocated = 0; if (s->type.t == MACRO_FUNC) { @@ -2915,9 +2927,12 @@ static int macro_subst_tok(TokenString *tok_str, } t = ch; } - if (t != '(') /* no macro subst */ + if (t != '(') { + /* no macro subst */ + parse_flags = saved_parse_flags; return -1; - + } + /* argument macro */ next_nomacro(); next_nomacro(); @@ -2986,6 +3001,7 @@ static int macro_subst_tok(TokenString *tok_str, mstr_allocated = 1; } sym_push2(nested_list, s->v, 0, 0); + parse_flags = saved_parse_flags; macro_subst(tok_str, nested_list, mstr, can_read_stream); /* pop nested defined symbol */ sa1 = *nested_list; @@ -3107,6 +3123,9 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, TOK_GET(&t, &ptr, &cval); if (t == 0) break; + if (t == '\\' && !(parse_flags & PARSE_FLAG_ACCEPT_STRAYS)) { + tcc_error("stray '\\' in program"); + } if (t == TOK_NOSUBST) { /* following token has already been subst'd. just copy it on */ tok_str_add2(tok_str, TOK_NOSUBST, NULL);