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
Unified · Split
| @@ -1254,6 +1254,7 @@ ST_FUNC void parse_define(void) · 1253 unmodified lines | ||
| 1254 | 1254 | { |
| 1255 | 1255 | Sym *s, *first, **ps; |
| 1256 | 1256 | int v, t, varg, is_vaargs, spc, ptok, macro_list_start; |
| 1257 | + int saved_parse_flags; | |
| 1257 | 1258 | TokenString str; |
| 1258 | 1259 | |
| 1259 | 1260 | v = tok; |
| @@ -1295,6 +1296,8 @@ ST_FUNC void parse_define(void) · 35 unmodified lines | ||
| 1295 | 1296 | /* EOF testing necessary for '-D' handling */ |
| 1296 | 1297 | ptok = 0; |
| 1297 | 1298 | macro_list_start = 1; |
| 1299 | + saved_parse_flags = parse_flags; | |
| 1300 | + parse_flags |= PARSE_FLAG_ACCEPT_STRAYS | PARSE_FLAG_SPACES | PARSE_FLAG_LINEFEED; | |
| 1298 | 1301 | while (tok != TOK_LINEFEED && tok != TOK_EOF) { |
| 1299 | 1302 | if (macro_list_start && spc == 2 && tok == TOK_TWOSHARPS) |
| 1300 | 1303 | tcc_error("'##' invalid at start of macro"); |
| @@ -1314,6 +1317,7 @@ ST_FUNC void parse_define(void) · 13 unmodified lines | ||
| 1314 | 1317 | skip: |
| 1315 | 1318 | next_nomacro_spc(); |
| 1316 | 1319 | } |
| 1320 | + parse_flags = saved_parse_flags; | |
| 1317 | 1321 | if (ptok == TOK_TWOSHARPS) |
| 1318 | 1322 | tcc_error("'##' invalid at end of macro"); |
| 1319 | 1323 | if (spc == 1) |
| @@ -2729,6 +2733,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) · 1409 unmodified lines | ||
| 2729 | 2733 | CValue cval; |
| 2730 | 2734 | TokenString str; |
| 2731 | 2735 | CString cstr; |
| 2736 | + CString cstr2; | |
| 2732 | 2737 | |
| 2733 | 2738 | tok_str_new(&str); |
| 2734 | 2739 | last_tok = 0; |
| @@ -2757,9 +2762,13 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) · 22 unmodified lines | ||
| 2757 | 2762 | printf("stringize: %s\n", (char *)cstr.data); |
| 2758 | 2763 | #endif |
| 2759 | 2764 | /* add string */ |
| 2760 | − cval.cstr = &cstr; | |
| 2761 | − tok_str_add2(&str, TOK_STR, &cval); | |
| 2765 | + cstr_new(&cstr2); | |
| 2766 | + /* emulate GCC behaviour and parse escapes in the token string */ | |
| 2767 | + parse_escape_string(&cstr2, cstr.data, 0); | |
| 2762 | 2768 | cstr_free(&cstr); |
| 2769 | + cval.cstr = &cstr2; | |
| 2770 | + tok_str_add2(&str, TOK_STR, &cval); | |
| 2771 | + cstr_free(cval.cstr); | |
| 2763 | 2772 | } else { |
| 2764 | 2773 | tok_str_add2(&str, t, &cval); |
| 2765 | 2774 | } |
| @@ -2868,6 +2877,9 @@ static int macro_subst_tok(TokenString *tok_str, · 102 unmodified lines | ||
| 2868 | 2877 | tok_str_add2(tok_str, t1, &cval); |
| 2869 | 2878 | cstr_free(&cstr); |
| 2870 | 2879 | } else { |
| 2880 | + int saved_parse_flags = parse_flags; | |
| 2881 | + parse_flags |= PARSE_FLAG_ACCEPT_STRAYS | PARSE_FLAG_SPACES | PARSE_FLAG_LINEFEED; | |
| 2882 | + | |
| 2871 | 2883 | mstr = s->d; |
| 2872 | 2884 | mstr_allocated = 0; |
| 2873 | 2885 | if (s->type.t == MACRO_FUNC) { |
| @@ -2915,9 +2927,12 @@ static int macro_subst_tok(TokenString *tok_str, · 41 unmodified lines | ||
| 2915 | 2927 | } |
| 2916 | 2928 | t = ch; |
| 2917 | 2929 | } |
| 2918 | − if (t != '(') /* no macro subst */ | |
| 2930 | + if (t != '(') { | |
| 2931 | + /* no macro subst */ | |
| 2932 | + parse_flags = saved_parse_flags; | |
| 2919 | 2933 | return -1; |
| 2920 | − | |
| 2934 | + } | |
| 2935 | + | |
| 2921 | 2936 | /* argument macro */ |
| 2922 | 2937 | next_nomacro(); |
| 2923 | 2938 | next_nomacro(); |
| @@ -2986,6 +3001,7 @@ static int macro_subst_tok(TokenString *tok_str, · 62 unmodified lines | ||
| 2986 | 3001 | mstr_allocated = 1; |
| 2987 | 3002 | } |
| 2988 | 3003 | sym_push2(nested_list, s->v, 0, 0); |
| 3004 | + parse_flags = saved_parse_flags; | |
| 2989 | 3005 | macro_subst(tok_str, nested_list, mstr, can_read_stream); |
| 2990 | 3006 | /* pop nested defined symbol */ |
| 2991 | 3007 | sa1 = *nested_list; |
| @@ -3107,6 +3123,9 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, · 115 unmodified lines | ||
| 3107 | 3123 | TOK_GET(&t, &ptr, &cval); |
| 3108 | 3124 | if (t == 0) |
| 3109 | 3125 | break; |
| 3126 | + if (t == '\\' && !(parse_flags & PARSE_FLAG_ACCEPT_STRAYS)) { | |
| 3127 | + tcc_error("stray '\\' in program"); | |
| 3128 | + } | |
| 3110 | 3129 | if (t == TOK_NOSUBST) { |
| 3111 | 3130 | /* following token has already been subst'd. just copy it on */ |
| 3112 | 3131 | tok_str_add2(tok_str, TOK_NOSUBST, NULL); |