This fixes test7 described in: http://lists.nongnu.org/archive/html/tinycc-devel/2015-05/msg00002.html Note that the current code still adds excessive forced blank characters to its output, so this patch might not change visible behaviour.
Unified · Split
| @@ -2877,19 +2877,26 @@ static int macro_subst_tok(TokenString *tok_str, · 2876 unmodified lines | ||
| 2877 | 2877 | tok_str_add2(tok_str, t1, &cval); |
| 2878 | 2878 | cstr_free(&cstr); |
| 2879 | 2879 | } else { |
| 2880 | + int mtok = tok; | |
| 2880 | 2881 | int saved_parse_flags = parse_flags; |
| 2881 | 2882 | parse_flags |= PARSE_FLAG_ACCEPT_STRAYS | PARSE_FLAG_SPACES | PARSE_FLAG_LINEFEED; |
| 2882 | 2883 | |
| 2883 | 2884 | mstr = s->d; |
| 2884 | 2885 | mstr_allocated = 0; |
| 2885 | 2886 | if (s->type.t == MACRO_FUNC) { |
| 2887 | + TokenString ws_str; /* whitespace between macro name and | |
| 2888 | + * argument list */ | |
| 2889 | + tok_str_new(&ws_str); | |
| 2890 | + spc = 0; | |
| 2886 | 2891 | /* NOTE: we do not use next_nomacro to avoid eating the |
| 2887 | 2892 | next token. XXX: find better solution */ |
| 2888 | 2893 | redo: |
| 2889 | 2894 | if (macro_ptr) { |
| 2890 | 2895 | p = macro_ptr; |
| 2891 | − while (is_space(t = *p) || TOK_LINEFEED == t) | |
| 2896 | + while (is_space(t = *p) || TOK_LINEFEED == t) { | |
| 2897 | + tok_str_add(&ws_str, t); | |
| 2892 | 2898 | ++p; |
| 2899 | + } | |
| 2893 | 2900 | if (t == 0 && can_read_stream) { |
| 2894 | 2901 | /* end of macro stream: we must look at the token |
| 2895 | 2902 | after in the file */ |
| @@ -2910,7 +2917,7 @@ static int macro_subst_tok(TokenString *tok_str, · 14 unmodified lines | ||
| 2910 | 2917 | while (is_space(ch) || ch == '\n' || ch == '/') |
| 2911 | 2918 | { |
| 2912 | 2919 | if (ch == '/') |
| 2913 | − { | |
| 2920 | + { | |
| 2914 | 2921 | int c; |
| 2915 | 2922 | uint8_t *p = file->buf_ptr; |
| 2916 | 2923 | PEEKC(c, p); |
| @@ -2921,18 +2928,29 @@ static int macro_subst_tok(TokenString *tok_str, · 4 unmodified lines | ||
| 2921 | 2928 | p = parse_line_comment(p); |
| 2922 | 2929 | file->buf_ptr = p - 1; |
| 2923 | 2930 | } else |
| 2924 | − break; | |
| 2925 | − } | |
| 2926 | − cinp(); | |
| 2927 | − } | |
| 2931 | + break; | |
| 2932 | + ch = ' '; | |
| 2933 | + } | |
| 2934 | + tok_str_add(&ws_str, ch); | |
| 2935 | + cinp(); | |
| 2936 | + } | |
| 2928 | 2937 | t = ch; |
| 2929 | 2938 | } |
| 2930 | 2939 | if (t != '(') { |
| 2931 | − /* no macro subst */ | |
| 2940 | + /* not a macro substitution after all, restore the | |
| 2941 | + * macro token plus all whitespace we've read. | |
| 2942 | + * whitespace is intentionally not merged to preserve | |
| 2943 | + * newlines. */ | |
| 2944 | + int i; | |
| 2945 | + tok_str_add(tok_str, mtok); | |
| 2946 | + for(i=0; i<ws_str.len; i++) | |
| 2947 | + tok_str_add(tok_str, ws_str.str[i]); | |
| 2948 | + tok_str_free(ws_str.str); | |
| 2932 | 2949 | parse_flags = saved_parse_flags; |
| 2933 | 2950 | return -1; |
| 2951 | + } else { | |
| 2952 | + tok_str_free(ws_str.str); | |
| 2934 | 2953 | } |
| 2935 | − | |
| 2936 | 2954 | /* argument macro */ |
| 2937 | 2955 | next_nomacro(); |
| 2938 | 2956 | next_nomacro(); |
| @@ -3101,7 +3119,7 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, · 162 unmodified lines | ||
| 3101 | 3119 | Sym *s; |
| 3102 | 3120 | int *macro_str1; |
| 3103 | 3121 | const int *ptr; |
| 3104 | − int t, ret, spc; | |
| 3122 | + int t, spc; | |
| 3105 | 3123 | CValue cval; |
| 3106 | 3124 | struct macro_level ml; |
| 3107 | 3125 | int force_blank; |
| @@ -3145,14 +3163,12 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, · 37 unmodified lines | ||
| 3145 | 3163 | ml.prev = *can_read_stream, *can_read_stream = &ml; |
| 3146 | 3164 | macro_ptr = (int *)ptr; |
| 3147 | 3165 | tok = t; |
| 3148 | − ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream); | |
| 3166 | + macro_subst_tok(tok_str, nested_list, s, can_read_stream); | |
| 3149 | 3167 | spc = tok_str->len && is_space(tok_str->str[tok_str->len-1]); |
| 3150 | 3168 | ptr = (int *)macro_ptr; |
| 3151 | 3169 | macro_ptr = ml.p; |
| 3152 | 3170 | if (can_read_stream && *can_read_stream == &ml) |
| 3153 | 3171 | *can_read_stream = ml.prev; |
| 3154 | − if (ret != 0) | |
| 3155 | − goto no_subst; | |
| 3156 | 3172 | if (parse_flags & PARSE_FLAG_SPACES) |
| 3157 | 3173 | force_blank = 1; |
| 3158 | 3174 | } else { |
| @@ -3199,6 +3215,13 @@ ST_FUNC void next(void) · 40 unmodified lines | ||
| 3199 | 3215 | macro_ptr = str.str; |
| 3200 | 3216 | macro_ptr_allocated = str.str; |
| 3201 | 3217 | goto redo; |
| 3218 | + } else { | |
| 3219 | + tok_str_add(&str, 0); | |
| 3220 | + if (str.len > 1) { | |
| 3221 | + macro_ptr = str.str + 1; | |
| 3222 | + macro_ptr_allocated = str.str; | |
| 3223 | + } | |
| 3224 | + tok = str.str[0]; | |
| 3202 | 3225 | } |
| 3203 | 3226 | } |
| 3204 | 3227 | } |