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 | static void macro_subst( | 2901 | static void macro_subst( |
| 2902 | TokenString *tok_str, | 2902 | TokenString *tok_str, |
| 2903 | Sym **nested_list, | 2903 | Sym **nested_list, |
| 2904 | const int *macro_str, | 2904 | const int *macro_str |
| 2905 | int can_read_stream | ||
| 2906 | ); | 2905 | ); |
| 2907 | 2906 | ||
| 2908 | /* substitute arguments in replacement lists in macro_str by the values in | 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 | } else { | 2992 | } else { |
| 2994 | add_var: | 2993 | add_var: |
| 2995 | /* NOTE: the stream cannot be read when macro | 2994 | macro_subst(&str, nested_list, st); |
| 2996 | substituting an argument */ | ||
| 2997 | macro_subst(&str, nested_list, st, 0); | ||
| 2998 | } | 2995 | } |
| 2999 | if (str.len == l0) /* expanded to empty string */ | 2996 | if (str.len == l0) /* expanded to empty string */ |
| 3000 | tok_str_add(&str, TOK_PLCHLDR); | 2997 | tok_str_add(&str, TOK_PLCHLDR); |
| @@ -3016,9 +3013,102 @@ static char const ab_month_name[12][4] = · 15 unmodified lines | |||
| 3016 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" | 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 | /* peek or read [ws_str == NULL] next token from function macro call, | 3109 | /* peek or read [ws_str == NULL] next token from function macro call, |
| 3020 | walking up macro levels up to the file if necessary */ | 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 | int t; | 3113 | int t; |
| 3024 | const int *p; | 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 | static int macro_subst_tok( | 3171 | static int macro_subst_tok( |
| 3082 | TokenString *tok_str, | 3172 | TokenString *tok_str, |
| 3083 | Sym **nested_list, | 3173 | Sym **nested_list, |
| 3084 | Sym *s, | 3174 | Sym *s) |
| 3085 | int can_read_stream) | ||
| 3086 | { | 3175 | { |
| 3087 | Sym *args, *sa, *sa1; | 3176 | Sym *args, *sa, *sa1; |
| 3088 | int parlevel, *mstr, t, t1, spc; | 3177 | int parlevel, *mstr, t, t1, spc; |
| @@ -3127,6 +3216,7 @@ static int macro_subst_tok( · 38 unmodified lines | |||
| 3127 | cstr_free(&cstr); | 3216 | cstr_free(&cstr); |
| 3128 | } else { | 3217 | } else { |
| 3129 | int saved_parse_flags = parse_flags; | 3218 | int saved_parse_flags = parse_flags; |
| 3219 | int *joined_str = NULL; | ||
| 3130 | 3220 | ||
| 3131 | mstr = s->d; | 3221 | mstr = s->d; |
| 3132 | if (s->type.t == MACRO_FUNC) { | 3222 | if (s->type.t == MACRO_FUNC) { |
| @@ -3139,7 +3229,7 @@ static int macro_subst_tok( · 6 unmodified lines | |||
| 3139 | | PARSE_FLAG_ACCEPT_STRAYS; | 3229 | | PARSE_FLAG_ACCEPT_STRAYS; |
| 3140 | 3230 | ||
| 3141 | /* get next token from argument stream */ | 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 | if (t != '(') { | 3233 | if (t != '(') { |
| 3144 | /* not a macro substitution after all, restore the | 3234 | /* not a macro substitution after all, restore the |
| 3145 | * macro token plus all whitespace we've read. | 3235 | * macro token plus all whitespace we've read. |
| @@ -3167,7 +3257,7 @@ static int macro_subst_tok( · 21 unmodified lines | |||
| 3167 | /* NOTE: empty args are allowed, except if no args */ | 3257 | /* NOTE: empty args are allowed, except if no args */ |
| 3168 | for(;;) { | 3258 | for(;;) { |
| 3169 | do { | 3259 | do { |
| 3170 | next_argstream(nested_list, can_read_stream, NULL); | 3260 | next_argstream(nested_list, NULL); |
| 3171 | } while (is_space(tok) || TOK_LINEFEED == tok); | 3261 | } while (is_space(tok) || TOK_LINEFEED == tok); |
| 3172 | empty_arg: | 3262 | empty_arg: |
| 3173 | /* handle '()' case */ | 3263 | /* handle '()' case */ |
| @@ -3192,7 +3282,7 @@ static int macro_subst_tok( · 18 unmodified lines | |||
| 3192 | tok = ' '; | 3282 | tok = ' '; |
| 3193 | if (!check_space(tok, &spc)) | 3283 | if (!check_space(tok, &spc)) |
| 3194 | tok_str_add2(&str, tok, &tokc); | 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 | if (parlevel) | 3287 | if (parlevel) |
| 3198 | expect(")"); | 3288 | expect(")"); |
| @@ -3233,140 +3323,38 @@ static int macro_subst_tok( · 34 unmodified lines | |||
| 3233 | 3323 | ||
| 3234 | sym_push2(nested_list, s->v, 0, 0); | 3324 | sym_push2(nested_list, s->v, 0, 0); |
| 3235 | parse_flags = saved_parse_flags; | 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 | /* pop nested defined symbol */ | 3329 | /* pop nested defined symbol */ |
| 3239 | sa1 = *nested_list; | 3330 | sa1 = *nested_list; |
| 3240 | *nested_list = sa1->prev; | 3331 | *nested_list = sa1->prev; |
| 3241 | sym_free(sa1); | 3332 | sym_free(sa1); |
| 3333 | if (joined_str) | ||
| 3334 | tok_str_free_str(joined_str); | ||
| 3242 | if (mstr != s->d) | 3335 | if (mstr != s->d) |
| 3243 | tok_str_free_str(mstr); | 3336 | tok_str_free_str(mstr); |
| 3244 | } | 3337 | } |
| 3245 | return 0; | 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 | /* do macro substitution of macro_str and add result to | 3341 | /* do macro substitution of macro_str and add result to |
| 3342 | (tok_str,tok_len). 'nested_list' is the list of all macros we got | 3342 | (tok_str,tok_len). 'nested_list' is the list of all macros we got |
| 3343 | inside to avoid recursing. */ | 3343 | inside to avoid recursing. */ |
| 3344 | static void macro_subst( | 3344 | static void macro_subst( |
| 3345 | TokenString *tok_str, | 3345 | TokenString *tok_str, |
| 3346 | Sym **nested_list, | 3346 | Sym **nested_list, |
| 3347 | const int *macro_str, | 3347 | const int *macro_str |
| 3348 | int can_read_stream | ||
| 3349 | ) | 3348 | ) |
| 3350 | { | 3349 | { |
| 3351 | Sym *s; | 3350 | Sym *s; |
| 3352 | const int *ptr; | ||
| 3353 | int t, spc, nosubst; | 3351 | int t, spc, nosubst; |
| 3354 | CValue cval; | 3352 | CValue cval; |
| 3355 | int *macro_str1 = NULL; | ||
| 3356 | 3353 | ||
| 3357 | /* first scan for '##' operator handling */ | ||
| 3358 | ptr = macro_str; | ||
| 3359 | spc = nosubst = 0; | 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 | while (1) { | 3356 | while (1) { |
| 3369 | TOK_GET(&t, &ptr, &cval); | 3357 | TOK_GET(&t, ¯o_str, &cval); |
| 3370 | if (t <= 0) | 3358 | if (t <= 0) |
| 3371 | break; | 3359 | break; |
| 3372 | 3360 | ||
| @@ -3384,18 +3372,18 @@ static void macro_subst( · 11 unmodified lines | |||
| 3384 | 3372 | ||
| 3385 | { | 3373 | { |
| 3386 | TokenString str; | 3374 | TokenString str; |
| 3387 | str.str = (int*)ptr; | 3375 | str.str = (int*)macro_str; |
| 3388 | begin_macro(&str, 2); | 3376 | begin_macro(&str, 2); |
| 3389 | 3377 | ||
| 3390 | tok = t; | 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 | if (str.alloc == 3) { | 3381 | if (str.alloc == 3) { |
| 3394 | /* already finished by reading function macro arguments */ | 3382 | /* already finished by reading function macro arguments */ |
| 3395 | break; | 3383 | break; |
| 3396 | } | 3384 | } |
| 3397 | 3385 | ||
| 3398 | ptr = macro_ptr; | 3386 | macro_str = macro_ptr; |
| 3399 | end_macro (); | 3387 | end_macro (); |
| 3400 | } | 3388 | } |
| 3401 | 3389 | ||
| @@ -3416,9 +3404,6 @@ no_subst: · 14 unmodified lines | |||
| 3416 | nosubst = 1; | 3404 | nosubst = 1; |
| 3417 | } | 3405 | } |
| 3418 | } | 3406 | } |
| 3419 | if (macro_str1) | ||
| 3420 | tok_str_free_str(macro_str1); | ||
| 3421 | |||
| 3422 | } | 3407 | } |
| 3423 | 3408 | ||
| 3424 | /* return next token with macro substitution */ | 3409 | /* return next token with macro substitution */ |
| @@ -3446,7 +3431,7 @@ ST_FUNC void next(void) · 21 unmodified lines | |||
| 3446 | if (s) { | 3431 | if (s) { |
| 3447 | Sym *nested_list = NULL; | 3432 | Sym *nested_list = NULL; |
| 3448 | tokstr_buf.len = 0; | 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 | tok_str_add(&tokstr_buf, 0); | 3435 | tok_str_add(&tokstr_buf, 0); |
| 3451 | begin_macro(&tokstr_buf, 2); | 3436 | begin_macro(&tokstr_buf, 2); |
| 3452 | goto redo; | 3437 | goto redo; |