/* test case */ #define STR(x) #x #define MKSTR(x) STR(x) MKSTR(-A-) MKSTR(+ B +) tcc -E: expected result: "-A-" "+ B +"
Unified · Split
| @@ -336,7 +336,6 @@ typedef struct CachedInclude { · 335 unmodified lines | |||
| 336 | /* parser */ | 336 | /* parser */ |
| 337 | static struct BufferedFile *file; | 337 | static struct BufferedFile *file; |
| 338 | static int ch, tok; | 338 | static int ch, tok; |
| 339 | static CString tok_spaces; /* spaces before current token */ | ||
| 340 | static CValue tokc; | 339 | static CValue tokc; |
| 341 | static CString tokcstr; /* current parsed string, if any */ | 340 | static CString tokcstr; /* current parsed string, if any */ |
| 342 | /* additional informations about token */ | 341 | /* additional informations about token */ |
| @@ -357,6 +356,7 @@ static int parse_flags; · 14 unmodified lines | |||
| 357 | token. line feed is also | 356 | token. line feed is also |
| 358 | returned at eof */ | 357 | returned at eof */ |
| 359 | #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */ | 358 | #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */ |
| 359 | #define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */ | ||
| 360 | 360 | ||
| 361 | static Section *text_section, *data_section, *bss_section; /* predefined sections */ | 361 | static Section *text_section, *data_section, *bss_section; /* predefined sections */ |
| 362 | static Section *cur_text_section; /* current section where function code is | 362 | static Section *cur_text_section; /* current section where function code is |
| @@ -797,6 +797,7 @@ static char *tcc_fileextension (const char *p); · 434 unmodified lines | |||
| 797 | 797 | ||
| 798 | static void next(void); | 798 | static void next(void); |
| 799 | static void next_nomacro(void); | 799 | static void next_nomacro(void); |
| 800 | static void next_nomacro_spc(void); | ||
| 800 | static void parse_expr_type(CType *type); | 801 | static void parse_expr_type(CType *type); |
| 801 | static void expr_type(CType *type); | 802 | static void expr_type(CType *type); |
| 802 | static void unary_type(CType *type); | 803 | static void unary_type(CType *type); |
| @@ -2290,6 +2291,17 @@ static inline void skip_spaces(void) · 1487 unmodified lines | |||
| 2290 | cinp(); | 2291 | cinp(); |
| 2291 | } | 2292 | } |
| 2292 | 2293 | ||
| 2294 | static inline int check_space(int t, int *spc) | ||
| 2295 | { | ||
| 2296 | if (is_space(t)) { | ||
| 2297 | if (*spc) | ||
| 2298 | return 1; | ||
| 2299 | *spc = 1; | ||
| 2300 | } else | ||
| 2301 | *spc = 0; | ||
| 2302 | return 0; | ||
| 2303 | } | ||
| 2304 | |||
| 2293 | /* parse a string without interpreting escapes */ | 2305 | /* parse a string without interpreting escapes */ |
| 2294 | static uint8_t *parse_pp_string(uint8_t *p, | 2306 | static uint8_t *parse_pp_string(uint8_t *p, |
| 2295 | int sep, CString *str) | 2307 | int sep, CString *str) |
| @@ -2822,13 +2834,14 @@ static void tok_print(int *str) · 526 unmodified lines | |||
| 2822 | int t; | 2834 | int t; |
| 2823 | CValue cval; | 2835 | CValue cval; |
| 2824 | 2836 | ||
| 2837 | printf("<"); | ||
| 2825 | while (1) { | 2838 | while (1) { |
| 2826 | TOK_GET(t, str, cval); | 2839 | TOK_GET(t, str, cval); |
| 2827 | if (!t) | 2840 | if (!t) |
| 2828 | break; | 2841 | break; |
| 2829 | printf(" %s", get_tok_str(t, &cval)); | 2842 | printf("%s", get_tok_str(t, &cval)); |
| 2830 | } | 2843 | } |
| 2831 | printf("\n"); | 2844 | printf(">\n"); |
| 2832 | } | 2845 | } |
| 2833 | #endif | 2846 | #endif |
| 2834 | 2847 | ||
| @@ -2836,7 +2849,7 @@ static void tok_print(int *str) · 1 unmodified line | |||
| 2836 | static void parse_define(void) | 2849 | static void parse_define(void) |
| 2837 | { | 2850 | { |
| 2838 | Sym *s, *first, **ps; | 2851 | Sym *s, *first, **ps; |
| 2839 | int v, t, varg, is_vaargs, c; | 2852 | int v, t, varg, is_vaargs, spc; |
| 2840 | TokenString str; | 2853 | TokenString str; |
| 2841 | 2854 | ||
| 2842 | v = tok; | 2855 | v = tok; |
| @@ -2846,11 +2859,8 @@ static void parse_define(void) · 3 unmodified lines | |||
| 2846 | first = NULL; | 2859 | first = NULL; |
| 2847 | t = MACRO_OBJ; | 2860 | t = MACRO_OBJ; |
| 2848 | /* '(' must be just after macro definition for MACRO_FUNC */ | 2861 | /* '(' must be just after macro definition for MACRO_FUNC */ |
| 2849 | c = file->buf_ptr[0]; | 2862 | next_nomacro_spc(); |
| 2850 | if (c == '\\') | 2863 | if (tok == '(') { |
| 2851 | c = handle_stray1(file->buf_ptr); | ||
| 2852 | if (c == '(') { | ||
| 2853 | next_nomacro(); | ||
| 2854 | next_nomacro(); | 2864 | next_nomacro(); |
| 2855 | ps = &first; | 2865 | ps = &first; |
| 2856 | while (tok != ')') { | 2866 | while (tok != ')') { |
| @@ -2873,15 +2883,30 @@ static void parse_define(void) · 16 unmodified lines | |||
| 2873 | break; | 2883 | break; |
| 2874 | next_nomacro(); | 2884 | next_nomacro(); |
| 2875 | } | 2885 | } |
| 2886 | if (tok == ')') | ||
| 2887 | next_nomacro_spc(); | ||
| 2876 | t = MACRO_FUNC; | 2888 | t = MACRO_FUNC; |
| 2877 | } | 2889 | } |
| 2878 | tok_str_new(&str); | 2890 | tok_str_new(&str); |
| 2879 | next_nomacro(); | 2891 | spc = 2; |
| 2880 | /* EOF testing necessary for '-D' handling */ | 2892 | /* EOF testing necessary for '-D' handling */ |
| 2881 | while (tok != TOK_LINEFEED && tok != TOK_EOF) { | 2893 | while (tok != TOK_LINEFEED && tok != TOK_EOF) { |
| 2894 | /* remove spaces around ## and after '#' */ | ||
| 2895 | if (TOK_TWOSHARPS == tok) { | ||
| 2896 | if (1 == spc) | ||
| 2897 | --str.len; | ||
| 2898 | spc = 2; | ||
| 2899 | } else if ('#' == tok) { | ||
| 2900 | spc = 2; | ||
| 2901 | } else if (check_space(tok, &spc)) { | ||
| 2902 | goto skip; | ||
| 2903 | } | ||
| 2882 | tok_str_add2(&str, tok, &tokc); | 2904 | tok_str_add2(&str, tok, &tokc); |
| 2883 | next_nomacro(); | 2905 | skip: |
| 2906 | next_nomacro_spc(); | ||
| 2884 | } | 2907 | } |
| 2908 | if (spc == 1) | ||
| 2909 | --str.len; /* remove trailing space */ | ||
| 2885 | tok_str_add(&str, 0); | 2910 | tok_str_add(&str, 0); |
| 2886 | #ifdef PP_DEBUG | 2911 | #ifdef PP_DEBUG |
| 2887 | printf("define %s %d: ", get_tok_str(v, NULL), t); | 2912 | printf("define %s %d: ", get_tok_str(v, NULL), t); |
| @@ -3703,20 +3728,20 @@ static inline void next_nomacro1(void) · 815 unmodified lines | |||
| 3703 | uint8_t *p, *p1; | 3728 | uint8_t *p, *p1; |
| 3704 | unsigned int h; | 3729 | unsigned int h; |
| 3705 | 3730 | ||
| 3706 | cstr_reset(&tok_spaces); | ||
| 3707 | p = file->buf_ptr; | 3731 | p = file->buf_ptr; |
| 3708 | redo_no_start: | 3732 | redo_no_start: |
| 3709 | c = *p; | 3733 | c = *p; |
| 3710 | switch(c) { | 3734 | switch(c) { |
| 3711 | case ' ': | 3735 | case ' ': |
| 3712 | case '\t': | 3736 | case '\t': |
| 3737 | tok = c; | ||
| 3738 | p++; | ||
| 3739 | goto keep_tok_flags; | ||
| 3713 | case '\f': | 3740 | case '\f': |
| 3714 | case '\v': | 3741 | case '\v': |
| 3715 | case '\r': | 3742 | case '\r': |
| 3716 | cstr_ccat(&tok_spaces, c); | ||
| 3717 | p++; | 3743 | p++; |
| 3718 | goto redo_no_start; | 3744 | goto redo_no_start; |
| 3719 | |||
| 3720 | case '\\': | 3745 | case '\\': |
| 3721 | /* first look if it is in fact an end of buffer */ | 3746 | /* first look if it is in fact an end of buffer */ |
| 3722 | if (p >= file->buf_end) { | 3747 | if (p >= file->buf_end) { |
| @@ -4121,7 +4146,7 @@ keep_tok_flags: · 398 unmodified lines | |||
| 4121 | 4146 | ||
| 4122 | /* return next token without macro substitution. Can read input from | 4147 | /* return next token without macro substitution. Can read input from |
| 4123 | macro_ptr buffer */ | 4148 | macro_ptr buffer */ |
| 4124 | static void next_nomacro(void) | 4149 | static void next_nomacro_spc(void) |
| 4125 | { | 4150 | { |
| 4126 | if (macro_ptr) { | 4151 | if (macro_ptr) { |
| 4127 | redo: | 4152 | redo: |
| @@ -4138,10 +4163,17 @@ static void next_nomacro(void) · 10 unmodified lines | |||
| 4138 | } | 4163 | } |
| 4139 | } | 4164 | } |
| 4140 | 4165 | ||
| 4166 | static void next_nomacro(void) | ||
| 4167 | { | ||
| 4168 | do { | ||
| 4169 | next_nomacro_spc(); | ||
| 4170 | } while (is_space(tok)); | ||
| 4171 | } | ||
| 4172 | |||
| 4141 | /* substitute args in macro_str and return allocated string */ | 4173 | /* substitute args in macro_str and return allocated string */ |
| 4142 | static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args) | 4174 | static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args) |
| 4143 | { | 4175 | { |
| 4144 | int *st, last_tok, t, notfirst; | 4176 | int *st, last_tok, t, spc; |
| 4145 | Sym *s; | 4177 | Sym *s; |
| 4146 | CValue cval; | 4178 | CValue cval; |
| 4147 | TokenString str; | 4179 | TokenString str; |
| @@ -4162,16 +4194,13 @@ static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args) · 14 unmodified lines | |||
| 4162 | if (s) { | 4194 | if (s) { |
| 4163 | cstr_new(&cstr); | 4195 | cstr_new(&cstr); |
| 4164 | st = (int *)s->c; | 4196 | st = (int *)s->c; |
| 4165 | notfirst = 0; | 4197 | spc = 0; |
| 4166 | while (*st) { | 4198 | while (*st) { |
| 4167 | if (notfirst) | ||
| 4168 | cstr_ccat(&cstr, ' '); | ||
| 4169 | TOK_GET(t, st, cval); | 4199 | TOK_GET(t, st, cval); |
| 4170 | cstr_cat(&cstr, get_tok_str(t, &cval)); | 4200 | if (!check_space(t, &spc)) |
| 4171 | #ifndef PP_NOSPACES | 4201 | cstr_cat(&cstr, get_tok_str(t, &cval)); |
| 4172 | notfirst = 1; | ||
| 4173 | #endif | ||
| 4174 | } | 4202 | } |
| 4203 | cstr.size -= spc; | ||
| 4175 | cstr_ccat(&cstr, '\0'); | 4204 | cstr_ccat(&cstr, '\0'); |
| 4176 | #ifdef PP_DEBUG | 4205 | #ifdef PP_DEBUG |
| 4177 | printf("stringize: %s\n", (char *)cstr.data); | 4206 | printf("stringize: %s\n", (char *)cstr.data); |
| @@ -4246,7 +4275,7 @@ static int macro_subst_tok(TokenString *tok_str, · 68 unmodified lines | |||
| 4246 | Sym **nested_list, Sym *s, struct macro_level **can_read_stream) | 4275 | Sym **nested_list, Sym *s, struct macro_level **can_read_stream) |
| 4247 | { | 4276 | { |
| 4248 | Sym *args, *sa, *sa1; | 4277 | Sym *args, *sa, *sa1; |
| 4249 | int mstr_allocated, parlevel, *mstr, t, t1; | 4278 | int mstr_allocated, parlevel, *mstr, t, t1, *p, spc; |
| 4250 | TokenString str; | 4279 | TokenString str; |
| 4251 | char *cstrval; | 4280 | char *cstrval; |
| 4252 | CValue cval; | 4281 | CValue cval; |
| @@ -4294,7 +4323,9 @@ static int macro_subst_tok(TokenString *tok_str, · 41 unmodified lines | |||
| 4294 | next token. XXX: find better solution */ | 4323 | next token. XXX: find better solution */ |
| 4295 | redo: | 4324 | redo: |
| 4296 | if (macro_ptr) { | 4325 | if (macro_ptr) { |
| 4297 | t = *macro_ptr; | 4326 | p = macro_ptr; |
| 4327 | while (is_space(t = *p) || TOK_LINEFEED == t) | ||
| 4328 | ++p; | ||
| 4298 | if (t == 0 && can_read_stream) { | 4329 | if (t == 0 && can_read_stream) { |
| 4299 | /* end of macro stream: we must look at the token | 4330 | /* end of macro stream: we must look at the token |
| 4300 | after in the file */ | 4331 | after in the file */ |
| @@ -4332,7 +4363,7 @@ static int macro_subst_tok(TokenString *tok_str, · 31 unmodified lines | |||
| 4332 | error("macro '%s' used with too many args", | 4363 | error("macro '%s' used with too many args", |
| 4333 | get_tok_str(s->v, 0)); | 4364 | get_tok_str(s->v, 0)); |
| 4334 | tok_str_new(&str); | 4365 | tok_str_new(&str); |
| 4335 | parlevel = 0; | 4366 | parlevel = spc = 0; |
| 4336 | /* NOTE: non zero sa->t indicates VA_ARGS */ | 4367 | /* NOTE: non zero sa->t indicates VA_ARGS */ |
| 4337 | while ((parlevel > 0 || | 4368 | while ((parlevel > 0 || |
| 4338 | (tok != ')' && | 4369 | (tok != ')' && |
| @@ -4342,10 +4373,13 @@ static int macro_subst_tok(TokenString *tok_str, · 3 unmodified lines | |||
| 4342 | parlevel++; | 4373 | parlevel++; |
| 4343 | else if (tok == ')') | 4374 | else if (tok == ')') |
| 4344 | parlevel--; | 4375 | parlevel--; |
| 4345 | if (tok != TOK_LINEFEED) | 4376 | if (tok == TOK_LINEFEED) |
| 4377 | tok = ' '; | ||
| 4378 | if (!check_space(tok, &spc)) | ||
| 4346 | tok_str_add2(&str, tok, &tokc); | 4379 | tok_str_add2(&str, tok, &tokc); |
| 4347 | next_nomacro(); | 4380 | next_nomacro_spc(); |
| 4348 | } | 4381 | } |
| 4382 | str.len -= spc; | ||
| 4349 | tok_str_add(&str, 0); | 4383 | tok_str_add(&str, 0); |
| 4350 | sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str); | 4384 | sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str); |
| 4351 | sa = sa->next; | 4385 | sa = sa->next; |
| @@ -4535,7 +4569,7 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, · 183 unmodified lines | |||
| 4535 | Sym *s; | 4569 | Sym *s; |
| 4536 | int *macro_str1; | 4570 | int *macro_str1; |
| 4537 | const int *ptr; | 4571 | const int *ptr; |
| 4538 | int t, ret; | 4572 | int t, ret, spc; |
| 4539 | CValue cval; | 4573 | CValue cval; |
| 4540 | struct macro_level ml; | 4574 | struct macro_level ml; |
| 4541 | 4575 | ||
| @@ -4544,6 +4578,7 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, · 2 unmodified lines | |||
| 4544 | macro_str1 = macro_twosharps(ptr); | 4578 | macro_str1 = macro_twosharps(ptr); |
| 4545 | if (macro_str1) | 4579 | if (macro_str1) |
| 4546 | ptr = macro_str1; | 4580 | ptr = macro_str1; |
| 4581 | spc = 0; | ||
| 4547 | while (1) { | 4582 | while (1) { |
| 4548 | /* NOTE: ptr == NULL can only happen if tokens are read from | 4583 | /* NOTE: ptr == NULL can only happen if tokens are read from |
| 4549 | file stream due to a macro function call */ | 4584 | file stream due to a macro function call */ |
| @@ -4571,7 +4606,8 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list, · 21 unmodified lines | |||
| 4571 | goto no_subst; | 4606 | goto no_subst; |
| 4572 | } else { | 4607 | } else { |
| 4573 | no_subst: | 4608 | no_subst: |
| 4574 | tok_str_add2(tok_str, t, &cval); | 4609 | if (!check_space(t, &spc)) |
| 4610 | tok_str_add2(tok_str, t, &cval); | ||
| 4575 | } | 4611 | } |
| 4576 | } | 4612 | } |
| 4577 | if (macro_str1) | 4613 | if (macro_str1) |
| @@ -4586,7 +4622,10 @@ static void next(void) · 8 unmodified lines | |||
| 4586 | struct macro_level *ml; | 4622 | struct macro_level *ml; |
| 4587 | 4623 | ||
| 4588 | redo: | 4624 | redo: |
| 4589 | next_nomacro(); | 4625 | if (parse_flags & PARSE_FLAG_SPACES) |
| 4626 | next_nomacro_spc(); | ||
| 4627 | else | ||
| 4628 | next_nomacro(); | ||
| 4590 | if (!macro_ptr) { | 4629 | if (!macro_ptr) { |
| 4591 | /* if not reading from macro substituted string, then try | 4630 | /* if not reading from macro substituted string, then try |
| 4592 | to substitute macros */ | 4631 | to substitute macros */ |
| @@ -9873,10 +9912,6 @@ static int tcc_compile(TCCState *s1) · 5280 unmodified lines | |||
| 9873 | } | 9912 | } |
| 9874 | 9913 | ||
| 9875 | /* Preprocess the current file */ | 9914 | /* Preprocess the current file */ |
| 9876 | /* XXX: add line and file infos, | ||
| 9877 | * XXX: add options to preserve spaces (partly done, only spaces in macro are | ||
| 9878 | * not preserved) | ||
| 9879 | */ | ||
| 9880 | static int tcc_preprocess(TCCState *s1) | 9915 | static int tcc_preprocess(TCCState *s1) |
| 9881 | { | 9916 | { |
| 9882 | Sym *define_start; | 9917 | Sym *define_start; |
| @@ -9886,11 +9921,9 @@ static int tcc_preprocess(TCCState *s1) · 3 unmodified lines | |||
| 9886 | preprocess_init(s1); | 9921 | preprocess_init(s1); |
| 9887 | define_start = define_stack; | 9922 | define_start = define_stack; |
| 9888 | ch = file->buf_ptr[0]; | 9923 | ch = file->buf_ptr[0]; |
| 9889 | |||
| 9890 | tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; | 9924 | tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF; |
| 9891 | parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS | | 9925 | parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS | |
| 9892 | PARSE_FLAG_LINEFEED; | 9926 | PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES; |
| 9893 | |||
| 9894 | token_seen = 0; | 9927 | token_seen = 0; |
| 9895 | line_ref = 0; | 9928 | line_ref = 0; |
| 9896 | file_ref = NULL; | 9929 | file_ref = NULL; |
| @@ -9904,9 +9937,7 @@ static int tcc_preprocess(TCCState *s1) · 7 unmodified lines | |||
| 9904 | continue; | 9937 | continue; |
| 9905 | ++line_ref; | 9938 | ++line_ref; |
| 9906 | token_seen = 0; | 9939 | token_seen = 0; |
| 9907 | } else if (token_seen) { | 9940 | } else if (!token_seen) { |
| 9908 | fwrite(tok_spaces.data, tok_spaces.size, 1, s1->outfile); | ||
| 9909 | } else { | ||
| 9910 | int d = file->line_num - line_ref; | 9941 | int d = file->line_num - line_ref; |
| 9911 | if (file != file_ref || d < 0 || d >= 8) | 9942 | if (file != file_ref || d < 0 || d >= 8) |
| 9912 | fprintf(s1->outfile, "# %d \"%s\"\n", file->line_num, file->filename); | 9943 | fprintf(s1->outfile, "# %d \"%s\"\n", file->line_num, file->filename); |
| @@ -10455,7 +10486,6 @@ static void tcc_cleanup(void) · 542 unmodified lines | |||
| 10455 | dynarray_reset(&sym_pools, &nb_sym_pools); | 10486 | dynarray_reset(&sym_pools, &nb_sym_pools); |
| 10456 | /* string buffer */ | 10487 | /* string buffer */ |
| 10457 | cstr_free(&tokcstr); | 10488 | cstr_free(&tokcstr); |
| 10458 | cstr_free(&tok_spaces); | ||
| 10459 | /* reset symbol stack */ | 10489 | /* reset symbol stack */ |
| 10460 | sym_free_first = NULL; | 10490 | sym_free_first = NULL; |
| 10461 | /* cleanup from error/setjmp */ | 10491 | /* cleanup from error/setjmp */ |