With last change the can_read_stream flag is unneeded, so tidy this a bit.
Unified · Split
| @@ -2901,8 +2901,7 @@ ST_FUNC void next_nomacro(void) · 2900 unmodified lines | ||
| 2901 | 2901 | static void macro_subst( |
| 2902 | 2902 | TokenString *tok_str, |
| 2903 | 2903 | Sym **nested_list, |
| 2904 | − const int *macro_str, | |
| 2905 | − int can_read_stream | |
| 2904 | + const int *macro_str | |
| 2906 | 2905 | ); |
| 2907 | 2906 | |
| 2908 | 2907 | /* substitute arguments in replacement lists in macro_str by the values in |
| @@ -2992,9 +2991,7 @@ static int *macro_arg_subst(Sym **nested_list, const int *macro_str, Sym *args) · 83 unmodified lines | ||
| 2992 | 2991 | } |
| 2993 | 2992 | } else { |
| 2994 | 2993 | add_var: |
| 2995 | − /* NOTE: the stream cannot be read when macro | |
| 2996 | − substituting an argument */ | |
| 2997 | − macro_subst(&str, nested_list, st, 0); | |
| 2994 | + macro_subst(&str, nested_list, st); | |
| 2998 | 2995 | } |
| 2999 | 2996 | if (str.len == l0) /* expanded to empty string */ |
| 3000 | 2997 | tok_str_add(&str, TOK_PLCHLDR); |
| @@ -3016,9 +3013,102 @@ static char const ab_month_name[12][4] = · 15 unmodified lines | ||
| 3016 | 3013 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" |
| 3017 | 3014 | }; |
| 3018 | 3015 | |
| 3016 | +static int paste_tokens(int t1, CValue *v1, int t2, CValue *v2) | |
| 3017 | +{ | |
| 3018 | + CString cstr; | |
| 3019 | + int n, ret = 1; | |
| 3020 | + | |
| 3021 | + cstr_new(&cstr); | |
| 3022 | + if (t1 != TOK_PLCHLDR) | |
| 3023 | + cstr_cat(&cstr, get_tok_str(t1, v1), -1); | |
| 3024 | + n = cstr.size; | |
| 3025 | + if (t2 != TOK_PLCHLDR) | |
| 3026 | + cstr_cat(&cstr, get_tok_str(t2, v2), -1); | |
| 3027 | + cstr_ccat(&cstr, '\0'); | |
| 3028 | + | |
| 3029 | + tcc_open_bf(tcc_state, ":paste:", cstr.size); | |
| 3030 | + memcpy(file->buffer, cstr.data, cstr.size); | |
| 3031 | + for (;;) { | |
| 3032 | + next_nomacro1(); | |
| 3033 | + if (0 == *file->buf_ptr) | |
| 3034 | + break; | |
| 3035 | + if (is_space(tok)) | |
| 3036 | + continue; | |
| 3037 | + tcc_warning("pasting \"%.*s\" and \"%s\" does not give a valid" | |
| 3038 | + " preprocessing token", n, cstr.data, (char*)cstr.data + n); | |
| 3039 | + ret = 0; | |
| 3040 | + break; | |
| 3041 | + } | |
| 3042 | + tcc_close(); | |
| 3043 | + //printf("paste <%s>\n", (char*)cstr.data); | |
| 3044 | + cstr_free(&cstr); | |
| 3045 | + return ret; | |
| 3046 | +} | |
| 3047 | + | |
| 3048 | +/* handle the '##' operator. Return NULL if no '##' seen. Otherwise | |
| 3049 | + return the resulting string (which must be freed). */ | |
| 3050 | +static inline int *macro_twosharps(const int *ptr0) | |
| 3051 | +{ | |
| 3052 | + int t; | |
| 3053 | + CValue cval; | |
| 3054 | + TokenString macro_str1; | |
| 3055 | + int start_of_nosubsts = -1; | |
| 3056 | + const int *ptr; | |
| 3057 | + | |
| 3058 | + /* we search the first '##' */ | |
| 3059 | + for (ptr = ptr0;;) { | |
| 3060 | + TOK_GET(&t, &ptr, &cval); | |
| 3061 | + if (t == TOK_PPJOIN) | |
| 3062 | + break; | |
| 3063 | + if (t == 0) | |
| 3064 | + return NULL; | |
| 3065 | + } | |
| 3066 | + | |
| 3067 | + tok_str_new(¯o_str1); | |
| 3068 | + | |
| 3069 | + //tok_print(" $$$", ptr0); | |
| 3070 | + for (ptr = ptr0;;) { | |
| 3071 | + TOK_GET(&t, &ptr, &cval); | |
| 3072 | + if (t == 0) | |
| 3073 | + break; | |
| 3074 | + if (t == TOK_PPJOIN) | |
| 3075 | + continue; | |
| 3076 | + while (*ptr == TOK_PPJOIN) { | |
| 3077 | + int t1; CValue cv1; | |
| 3078 | + /* given 'a##b', remove nosubsts preceding 'a' */ | |
| 3079 | + if (start_of_nosubsts >= 0) | |
| 3080 | + macro_str1.len = start_of_nosubsts; | |
| 3081 | + /* given 'a##b', remove nosubsts preceding 'b' */ | |
| 3082 | + while ((t1 = *++ptr) == TOK_NOSUBST) | |
| 3083 | + ; | |
| 3084 | + if (t1 && t1 != TOK_PPJOIN) { | |
| 3085 | + TOK_GET(&t1, &ptr, &cv1); | |
| 3086 | + if (t != TOK_PLCHLDR || t1 != TOK_PLCHLDR) { | |
| 3087 | + if (paste_tokens(t, &cval, t1, &cv1)) { | |
| 3088 | + t = tok, cval = tokc; | |
| 3089 | + } else { | |
| 3090 | + tok_str_add2(¯o_str1, t, &cval); | |
| 3091 | + t = t1, cval = cv1; | |
| 3092 | + } | |
| 3093 | + } | |
| 3094 | + } | |
| 3095 | + } | |
| 3096 | + if (t == TOK_NOSUBST) { | |
| 3097 | + if (start_of_nosubsts < 0) | |
| 3098 | + start_of_nosubsts = macro_str1.len; | |
| 3099 | + } else { | |
| 3100 | + start_of_nosubsts = -1; | |
| 3101 | + } | |
| 3102 | + tok_str_add2(¯o_str1, t, &cval); | |
| 3103 | + } | |
| 3104 | + tok_str_add(¯o_str1, 0); | |
| 3105 | + //tok_print(" ###", macro_str1.str); | |
| 3106 | + return macro_str1.str; | |
| 3107 | +} | |
| 3108 | + | |
| 3019 | 3109 | /* peek or read [ws_str == NULL] next token from function macro call, |
| 3020 | 3110 | walking up macro levels up to the file if necessary */ |
| 3021 | −static int next_argstream(Sym **nested_list, int can_read_stream, TokenString *ws_str) | |
| 3111 | +static int next_argstream(Sym **nested_list, TokenString *ws_str) | |
| 3022 | 3112 | { |
| 3023 | 3113 | int t; |
| 3024 | 3114 | const int *p; |
| @@ -3081,8 +3171,7 @@ static int next_argstream(Sym **nested_list, int can_read_stream, TokenString *w · 56 unmodified lines | ||
| 3081 | 3171 | static int macro_subst_tok( |
| 3082 | 3172 | TokenString *tok_str, |
| 3083 | 3173 | Sym **nested_list, |
| 3084 | − Sym *s, | |
| 3085 | − int can_read_stream) | |
| 3174 | + Sym *s) | |
| 3086 | 3175 | { |
| 3087 | 3176 | Sym *args, *sa, *sa1; |
| 3088 | 3177 | int parlevel, *mstr, t, t1, spc; |
| @@ -3127,6 +3216,7 @@ static int macro_subst_tok( · 38 unmodified lines | ||
| 3127 | 3216 | cstr_free(&cstr); |
| 3128 | 3217 | } else { |
| 3129 | 3218 | int saved_parse_flags = parse_flags; |
| 3219 | + int *joined_str = NULL; | |
| 3130 | 3220 | |
| 3131 | 3221 | mstr = s->d; |
| 3132 | 3222 | if (s->type.t == MACRO_FUNC) { |
| @@ -3139,7 +3229,7 @@ static int macro_subst_tok( · 6 unmodified lines | ||
| 3139 | 3229 | | PARSE_FLAG_ACCEPT_STRAYS; |
| 3140 | 3230 | |
| 3141 | 3231 | /* get next token from argument stream */ |
| 3142 | − t = next_argstream(nested_list, can_read_stream, &ws_str); | |
| 3232 | + t = next_argstream(nested_list, &ws_str); | |
| 3143 | 3233 | if (t != '(') { |
| 3144 | 3234 | /* not a macro substitution after all, restore the |
| 3145 | 3235 | * macro token plus all whitespace we've read. |
| @@ -3167,7 +3257,7 @@ static int macro_subst_tok( · 21 unmodified lines | ||
| 3167 | 3257 | /* NOTE: empty args are allowed, except if no args */ |
| 3168 | 3258 | for(;;) { |
| 3169 | 3259 | do { |
| 3170 | − next_argstream(nested_list, can_read_stream, NULL); | |
| 3260 | + next_argstream(nested_list, NULL); | |
| 3171 | 3261 | } while (is_space(tok) || TOK_LINEFEED == tok); |
| 3172 | 3262 | empty_arg: |
| 3173 | 3263 | /* handle '()' case */ |
| @@ -3192,7 +3282,7 @@ static int macro_subst_tok( · 18 unmodified lines | ||
| 3192 | 3282 | tok = ' '; |
| 3193 | 3283 | if (!check_space(tok, &spc)) |
| 3194 | 3284 | tok_str_add2(&str, tok, &tokc); |
| 3195 | − next_argstream(nested_list, can_read_stream, NULL); | |
| 3285 | + next_argstream(nested_list, NULL); | |
| 3196 | 3286 | } |
| 3197 | 3287 | if (parlevel) |
| 3198 | 3288 | expect(")"); |
| @@ -3233,140 +3323,38 @@ static int macro_subst_tok( · 34 unmodified lines | ||
| 3233 | 3323 | |
| 3234 | 3324 | sym_push2(nested_list, s->v, 0, 0); |
| 3235 | 3325 | parse_flags = saved_parse_flags; |
| 3236 | − macro_subst(tok_str, nested_list, mstr, can_read_stream | 2); | |
| 3326 | + joined_str = macro_twosharps(mstr); | |
| 3327 | + macro_subst(tok_str, nested_list, joined_str ? joined_str : mstr); | |
| 3237 | 3328 | |
| 3238 | 3329 | /* pop nested defined symbol */ |
| 3239 | 3330 | sa1 = *nested_list; |
| 3240 | 3331 | *nested_list = sa1->prev; |
| 3241 | 3332 | sym_free(sa1); |
| 3333 | + if (joined_str) | |
| 3334 | + tok_str_free_str(joined_str); | |
| 3242 | 3335 | if (mstr != s->d) |
| 3243 | 3336 | tok_str_free_str(mstr); |
| 3244 | 3337 | } |
| 3245 | 3338 | return 0; |
| 3246 | 3339 | } |
| 3247 | 3340 | |
| 3248 | −static int paste_tokens(int t1, CValue *v1, int t2, CValue *v2) | |
| 3249 | −{ | |
| 3250 | − CString cstr; | |
| 3251 | − int n, ret = 1; | |
| 3252 | − | |
| 3253 | − cstr_new(&cstr); | |
| 3254 | − if (t1 != TOK_PLCHLDR) | |
| 3255 | − cstr_cat(&cstr, get_tok_str(t1, v1), -1); | |
| 3256 | − n = cstr.size; | |
| 3257 | − if (t2 != TOK_PLCHLDR) | |
| 3258 | − cstr_cat(&cstr, get_tok_str(t2, v2), -1); | |
| 3259 | − cstr_ccat(&cstr, '\0'); | |
| 3260 | − | |
| 3261 | − tcc_open_bf(tcc_state, ":paste:", cstr.size); | |
| 3262 | − memcpy(file->buffer, cstr.data, cstr.size); | |
| 3263 | − for (;;) { | |
| 3264 | − next_nomacro1(); | |
| 3265 | − if (0 == *file->buf_ptr) | |
| 3266 | − break; | |
| 3267 | − if (is_space(tok)) | |
| 3268 | − continue; | |
| 3269 | − tcc_warning("pasting \"%.*s\" and \"%s\" does not give a valid" | |
| 3270 | − " preprocessing token", n, cstr.data, (char*)cstr.data + n); | |
| 3271 | − ret = 0; | |
| 3272 | − break; | |
| 3273 | − } | |
| 3274 | − tcc_close(); | |
| 3275 | − //printf("paste <%s>\n", (char*)cstr.data); | |
| 3276 | − cstr_free(&cstr); | |
| 3277 | − return ret; | |
| 3278 | −} | |
| 3279 | − | |
| 3280 | −/* handle the '##' operator. Return NULL if no '##' seen. Otherwise | |
| 3281 | − return the resulting string (which must be freed). */ | |
| 3282 | −static inline int *macro_twosharps(const int *ptr0) | |
| 3283 | −{ | |
| 3284 | − int t; | |
| 3285 | − CValue cval; | |
| 3286 | − TokenString macro_str1; | |
| 3287 | − int start_of_nosubsts = -1; | |
| 3288 | − const int *ptr; | |
| 3289 | − | |
| 3290 | − /* we search the first '##' */ | |
| 3291 | − for (ptr = ptr0;;) { | |
| 3292 | − TOK_GET(&t, &ptr, &cval); | |
| 3293 | − if (t == TOK_PPJOIN) | |
| 3294 | − break; | |
| 3295 | − if (t == 0) | |
| 3296 | − return NULL; | |
| 3297 | − } | |
| 3298 | − | |
| 3299 | − tok_str_new(¯o_str1); | |
| 3300 | − | |
| 3301 | − //tok_print(" $$$", ptr0); | |
| 3302 | − for (ptr = ptr0;;) { | |
| 3303 | − TOK_GET(&t, &ptr, &cval); | |
| 3304 | − if (t == 0) | |
| 3305 | − break; | |
| 3306 | − if (t == TOK_PPJOIN) | |
| 3307 | − continue; | |
| 3308 | − while (*ptr == TOK_PPJOIN) { | |
| 3309 | − int t1; CValue cv1; | |
| 3310 | − /* given 'a##b', remove nosubsts preceding 'a' */ | |
| 3311 | − if (start_of_nosubsts >= 0) | |
| 3312 | − macro_str1.len = start_of_nosubsts; | |
| 3313 | − /* given 'a##b', remove nosubsts preceding 'b' */ | |
| 3314 | − while ((t1 = *++ptr) == TOK_NOSUBST) | |
| 3315 | − ; | |
| 3316 | − if (t1 && t1 != TOK_PPJOIN) { | |
| 3317 | − TOK_GET(&t1, &ptr, &cv1); | |
| 3318 | − if (t != TOK_PLCHLDR || t1 != TOK_PLCHLDR) { | |
| 3319 | − if (paste_tokens(t, &cval, t1, &cv1)) { | |
| 3320 | − t = tok, cval = tokc; | |
| 3321 | − } else { | |
| 3322 | − tok_str_add2(¯o_str1, t, &cval); | |
| 3323 | − t = t1, cval = cv1; | |
| 3324 | − } | |
| 3325 | − } | |
| 3326 | − } | |
| 3327 | − } | |
| 3328 | − if (t == TOK_NOSUBST) { | |
| 3329 | − if (start_of_nosubsts < 0) | |
| 3330 | − start_of_nosubsts = macro_str1.len; | |
| 3331 | − } else { | |
| 3332 | − start_of_nosubsts = -1; | |
| 3333 | − } | |
| 3334 | − tok_str_add2(¯o_str1, t, &cval); | |
| 3335 | − } | |
| 3336 | − tok_str_add(¯o_str1, 0); | |
| 3337 | − //tok_print(" ###", macro_str1.str); | |
| 3338 | − return macro_str1.str; | |
| 3339 | −} | |
| 3340 | − | |
| 3341 | 3341 | /* do macro substitution of macro_str and add result to |
| 3342 | 3342 | (tok_str,tok_len). 'nested_list' is the list of all macros we got |
| 3343 | 3343 | inside to avoid recursing. */ |
| 3344 | 3344 | static void macro_subst( |
| 3345 | 3345 | TokenString *tok_str, |
| 3346 | 3346 | Sym **nested_list, |
| 3347 | − const int *macro_str, | |
| 3348 | − int can_read_stream | |
| 3347 | + const int *macro_str | |
| 3349 | 3348 | ) |
| 3350 | 3349 | { |
| 3351 | 3350 | Sym *s; |
| 3352 | − const int *ptr; | |
| 3353 | 3351 | int t, spc, nosubst; |
| 3354 | 3352 | CValue cval; |
| 3355 | − int *macro_str1 = NULL; | |
| 3356 | 3353 | |
| 3357 | − /* first scan for '##' operator handling */ | |
| 3358 | − ptr = macro_str; | |
| 3359 | 3354 | spc = nosubst = 0; |
| 3360 | 3355 | |
| 3361 | − /* first scan for '##' operator handling */ | |
| 3362 | − if (can_read_stream) { | |
| 3363 | − macro_str1 = macro_twosharps(ptr); | |
| 3364 | − if (macro_str1) | |
| 3365 | − ptr = macro_str1; | |
| 3366 | − } | |
| 3367 | − | |
| 3368 | 3356 | while (1) { |
| 3369 | − TOK_GET(&t, &ptr, &cval); | |
| 3357 | + TOK_GET(&t, ¯o_str, &cval); | |
| 3370 | 3358 | if (t <= 0) |
| 3371 | 3359 | break; |
| 3372 | 3360 | |
| @@ -3384,18 +3372,18 @@ static void macro_subst( · 11 unmodified lines | ||
| 3384 | 3372 | |
| 3385 | 3373 | { |
| 3386 | 3374 | TokenString str; |
| 3387 | − str.str = (int*)ptr; | |
| 3375 | + str.str = (int*)macro_str; | |
| 3388 | 3376 | begin_macro(&str, 2); |
| 3389 | 3377 | |
| 3390 | 3378 | tok = t; |
| 3391 | − macro_subst_tok(tok_str, nested_list, s, can_read_stream); | |
| 3379 | + macro_subst_tok(tok_str, nested_list, s); | |
| 3392 | 3380 | |
| 3393 | 3381 | if (str.alloc == 3) { |
| 3394 | 3382 | /* already finished by reading function macro arguments */ |
| 3395 | 3383 | break; |
| 3396 | 3384 | } |
| 3397 | 3385 | |
| 3398 | − ptr = macro_ptr; | |
| 3386 | + macro_str = macro_ptr; | |
| 3399 | 3387 | end_macro (); |
| 3400 | 3388 | } |
| 3401 | 3389 | |
| @@ -3416,9 +3404,6 @@ no_subst: · 14 unmodified lines | ||
| 3416 | 3404 | nosubst = 1; |
| 3417 | 3405 | } |
| 3418 | 3406 | } |
| 3419 | − if (macro_str1) | |
| 3420 | − tok_str_free_str(macro_str1); | |
| 3421 | − | |
| 3422 | 3407 | } |
| 3423 | 3408 | |
| 3424 | 3409 | /* return next token with macro substitution */ |
| @@ -3446,7 +3431,7 @@ ST_FUNC void next(void) · 21 unmodified lines | ||
| 3446 | 3431 | if (s) { |
| 3447 | 3432 | Sym *nested_list = NULL; |
| 3448 | 3433 | tokstr_buf.len = 0; |
| 3449 | − macro_subst_tok(&tokstr_buf, &nested_list, s, 1); | |
| 3434 | + macro_subst_tok(&tokstr_buf, &nested_list, s); | |
| 3450 | 3435 | tok_str_add(&tokstr_buf, 0); |
| 3451 | 3436 | begin_macro(&tokstr_buf, 2); |
| 3452 | 3437 | goto redo; |