tcc -E: preserve spaces, alternative solution
/* test case */ #define STR(x) #x #define MKSTR(x) STR(x) MKSTR(-A-) MKSTR(+ B +) tcc -E: expected result: "-A-" "+ B +"
This commit is contained in:
108
tcc.c
108
tcc.c
@ -336,7 +336,6 @@ typedef struct CachedInclude {
|
|||||||
/* parser */
|
/* parser */
|
||||||
static struct BufferedFile *file;
|
static struct BufferedFile *file;
|
||||||
static int ch, tok;
|
static int ch, tok;
|
||||||
static CString tok_spaces; /* spaces before current token */
|
|
||||||
static CValue tokc;
|
static CValue tokc;
|
||||||
static CString tokcstr; /* current parsed string, if any */
|
static CString tokcstr; /* current parsed string, if any */
|
||||||
/* additional informations about token */
|
/* additional informations about token */
|
||||||
@ -357,6 +356,7 @@ static int parse_flags;
|
|||||||
token. line feed is also
|
token. line feed is also
|
||||||
returned at eof */
|
returned at eof */
|
||||||
#define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
|
#define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
|
||||||
|
#define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */
|
||||||
|
|
||||||
static Section *text_section, *data_section, *bss_section; /* predefined sections */
|
static Section *text_section, *data_section, *bss_section; /* predefined sections */
|
||||||
static Section *cur_text_section; /* current section where function code is
|
static Section *cur_text_section; /* current section where function code is
|
||||||
@ -797,6 +797,7 @@ static char *tcc_fileextension (const char *p);
|
|||||||
|
|
||||||
static void next(void);
|
static void next(void);
|
||||||
static void next_nomacro(void);
|
static void next_nomacro(void);
|
||||||
|
static void next_nomacro_spc(void);
|
||||||
static void parse_expr_type(CType *type);
|
static void parse_expr_type(CType *type);
|
||||||
static void expr_type(CType *type);
|
static void expr_type(CType *type);
|
||||||
static void unary_type(CType *type);
|
static void unary_type(CType *type);
|
||||||
@ -2290,6 +2291,17 @@ static inline void skip_spaces(void)
|
|||||||
cinp();
|
cinp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int check_space(int t, int *spc)
|
||||||
|
{
|
||||||
|
if (is_space(t)) {
|
||||||
|
if (*spc)
|
||||||
|
return 1;
|
||||||
|
*spc = 1;
|
||||||
|
} else
|
||||||
|
*spc = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* parse a string without interpreting escapes */
|
/* parse a string without interpreting escapes */
|
||||||
static uint8_t *parse_pp_string(uint8_t *p,
|
static uint8_t *parse_pp_string(uint8_t *p,
|
||||||
int sep, CString *str)
|
int sep, CString *str)
|
||||||
@ -2822,13 +2834,14 @@ static void tok_print(int *str)
|
|||||||
int t;
|
int t;
|
||||||
CValue cval;
|
CValue cval;
|
||||||
|
|
||||||
|
printf("<");
|
||||||
while (1) {
|
while (1) {
|
||||||
TOK_GET(t, str, cval);
|
TOK_GET(t, str, cval);
|
||||||
if (!t)
|
if (!t)
|
||||||
break;
|
break;
|
||||||
printf("%s", get_tok_str(t, &cval));
|
printf("%s", get_tok_str(t, &cval));
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf(">\n");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -2836,7 +2849,7 @@ static void tok_print(int *str)
|
|||||||
static void parse_define(void)
|
static void parse_define(void)
|
||||||
{
|
{
|
||||||
Sym *s, *first, **ps;
|
Sym *s, *first, **ps;
|
||||||
int v, t, varg, is_vaargs, c;
|
int v, t, varg, is_vaargs, spc;
|
||||||
TokenString str;
|
TokenString str;
|
||||||
|
|
||||||
v = tok;
|
v = tok;
|
||||||
@ -2846,11 +2859,8 @@ static void parse_define(void)
|
|||||||
first = NULL;
|
first = NULL;
|
||||||
t = MACRO_OBJ;
|
t = MACRO_OBJ;
|
||||||
/* '(' must be just after macro definition for MACRO_FUNC */
|
/* '(' must be just after macro definition for MACRO_FUNC */
|
||||||
c = file->buf_ptr[0];
|
next_nomacro_spc();
|
||||||
if (c == '\\')
|
if (tok == '(') {
|
||||||
c = handle_stray1(file->buf_ptr);
|
|
||||||
if (c == '(') {
|
|
||||||
next_nomacro();
|
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
ps = &first;
|
ps = &first;
|
||||||
while (tok != ')') {
|
while (tok != ')') {
|
||||||
@ -2873,15 +2883,30 @@ static void parse_define(void)
|
|||||||
break;
|
break;
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
}
|
}
|
||||||
|
if (tok == ')')
|
||||||
|
next_nomacro_spc();
|
||||||
t = MACRO_FUNC;
|
t = MACRO_FUNC;
|
||||||
}
|
}
|
||||||
tok_str_new(&str);
|
tok_str_new(&str);
|
||||||
next_nomacro();
|
spc = 2;
|
||||||
/* EOF testing necessary for '-D' handling */
|
/* EOF testing necessary for '-D' handling */
|
||||||
while (tok != TOK_LINEFEED && tok != TOK_EOF) {
|
while (tok != TOK_LINEFEED && tok != TOK_EOF) {
|
||||||
tok_str_add2(&str, tok, &tokc);
|
/* remove spaces around ## and after '#' */
|
||||||
next_nomacro();
|
if (TOK_TWOSHARPS == tok) {
|
||||||
|
if (1 == spc)
|
||||||
|
--str.len;
|
||||||
|
spc = 2;
|
||||||
|
} else if ('#' == tok) {
|
||||||
|
spc = 2;
|
||||||
|
} else if (check_space(tok, &spc)) {
|
||||||
|
goto skip;
|
||||||
}
|
}
|
||||||
|
tok_str_add2(&str, tok, &tokc);
|
||||||
|
skip:
|
||||||
|
next_nomacro_spc();
|
||||||
|
}
|
||||||
|
if (spc == 1)
|
||||||
|
--str.len; /* remove trailing space */
|
||||||
tok_str_add(&str, 0);
|
tok_str_add(&str, 0);
|
||||||
#ifdef PP_DEBUG
|
#ifdef PP_DEBUG
|
||||||
printf("define %s %d: ", get_tok_str(v, NULL), t);
|
printf("define %s %d: ", get_tok_str(v, NULL), t);
|
||||||
@ -3703,20 +3728,20 @@ static inline void next_nomacro1(void)
|
|||||||
uint8_t *p, *p1;
|
uint8_t *p, *p1;
|
||||||
unsigned int h;
|
unsigned int h;
|
||||||
|
|
||||||
cstr_reset(&tok_spaces);
|
|
||||||
p = file->buf_ptr;
|
p = file->buf_ptr;
|
||||||
redo_no_start:
|
redo_no_start:
|
||||||
c = *p;
|
c = *p;
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case ' ':
|
case ' ':
|
||||||
case '\t':
|
case '\t':
|
||||||
|
tok = c;
|
||||||
|
p++;
|
||||||
|
goto keep_tok_flags;
|
||||||
case '\f':
|
case '\f':
|
||||||
case '\v':
|
case '\v':
|
||||||
case '\r':
|
case '\r':
|
||||||
cstr_ccat(&tok_spaces, c);
|
|
||||||
p++;
|
p++;
|
||||||
goto redo_no_start;
|
goto redo_no_start;
|
||||||
|
|
||||||
case '\\':
|
case '\\':
|
||||||
/* first look if it is in fact an end of buffer */
|
/* first look if it is in fact an end of buffer */
|
||||||
if (p >= file->buf_end) {
|
if (p >= file->buf_end) {
|
||||||
@ -4121,7 +4146,7 @@ keep_tok_flags:
|
|||||||
|
|
||||||
/* return next token without macro substitution. Can read input from
|
/* return next token without macro substitution. Can read input from
|
||||||
macro_ptr buffer */
|
macro_ptr buffer */
|
||||||
static void next_nomacro(void)
|
static void next_nomacro_spc(void)
|
||||||
{
|
{
|
||||||
if (macro_ptr) {
|
if (macro_ptr) {
|
||||||
redo:
|
redo:
|
||||||
@ -4138,10 +4163,17 @@ static void next_nomacro(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void next_nomacro(void)
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
next_nomacro_spc();
|
||||||
|
} while (is_space(tok));
|
||||||
|
}
|
||||||
|
|
||||||
/* substitute args in macro_str and return allocated string */
|
/* substitute args in macro_str and return allocated string */
|
||||||
static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
|
static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
|
||||||
{
|
{
|
||||||
int *st, last_tok, t, notfirst;
|
int *st, last_tok, t, spc;
|
||||||
Sym *s;
|
Sym *s;
|
||||||
CValue cval;
|
CValue cval;
|
||||||
TokenString str;
|
TokenString str;
|
||||||
@ -4162,16 +4194,13 @@ static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
|
|||||||
if (s) {
|
if (s) {
|
||||||
cstr_new(&cstr);
|
cstr_new(&cstr);
|
||||||
st = (int *)s->c;
|
st = (int *)s->c;
|
||||||
notfirst = 0;
|
spc = 0;
|
||||||
while (*st) {
|
while (*st) {
|
||||||
if (notfirst)
|
|
||||||
cstr_ccat(&cstr, ' ');
|
|
||||||
TOK_GET(t, st, cval);
|
TOK_GET(t, st, cval);
|
||||||
|
if (!check_space(t, &spc))
|
||||||
cstr_cat(&cstr, get_tok_str(t, &cval));
|
cstr_cat(&cstr, get_tok_str(t, &cval));
|
||||||
#ifndef PP_NOSPACES
|
|
||||||
notfirst = 1;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
cstr.size -= spc;
|
||||||
cstr_ccat(&cstr, '\0');
|
cstr_ccat(&cstr, '\0');
|
||||||
#ifdef PP_DEBUG
|
#ifdef PP_DEBUG
|
||||||
printf("stringize: %s\n", (char *)cstr.data);
|
printf("stringize: %s\n", (char *)cstr.data);
|
||||||
@ -4246,7 +4275,7 @@ static int macro_subst_tok(TokenString *tok_str,
|
|||||||
Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
|
Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
|
||||||
{
|
{
|
||||||
Sym *args, *sa, *sa1;
|
Sym *args, *sa, *sa1;
|
||||||
int mstr_allocated, parlevel, *mstr, t, t1;
|
int mstr_allocated, parlevel, *mstr, t, t1, *p, spc;
|
||||||
TokenString str;
|
TokenString str;
|
||||||
char *cstrval;
|
char *cstrval;
|
||||||
CValue cval;
|
CValue cval;
|
||||||
@ -4294,7 +4323,9 @@ static int macro_subst_tok(TokenString *tok_str,
|
|||||||
next token. XXX: find better solution */
|
next token. XXX: find better solution */
|
||||||
redo:
|
redo:
|
||||||
if (macro_ptr) {
|
if (macro_ptr) {
|
||||||
t = *macro_ptr;
|
p = macro_ptr;
|
||||||
|
while (is_space(t = *p) || TOK_LINEFEED == t)
|
||||||
|
++p;
|
||||||
if (t == 0 && can_read_stream) {
|
if (t == 0 && can_read_stream) {
|
||||||
/* end of macro stream: we must look at the token
|
/* end of macro stream: we must look at the token
|
||||||
after in the file */
|
after in the file */
|
||||||
@ -4332,7 +4363,7 @@ static int macro_subst_tok(TokenString *tok_str,
|
|||||||
error("macro '%s' used with too many args",
|
error("macro '%s' used with too many args",
|
||||||
get_tok_str(s->v, 0));
|
get_tok_str(s->v, 0));
|
||||||
tok_str_new(&str);
|
tok_str_new(&str);
|
||||||
parlevel = 0;
|
parlevel = spc = 0;
|
||||||
/* NOTE: non zero sa->t indicates VA_ARGS */
|
/* NOTE: non zero sa->t indicates VA_ARGS */
|
||||||
while ((parlevel > 0 ||
|
while ((parlevel > 0 ||
|
||||||
(tok != ')' &&
|
(tok != ')' &&
|
||||||
@ -4342,10 +4373,13 @@ static int macro_subst_tok(TokenString *tok_str,
|
|||||||
parlevel++;
|
parlevel++;
|
||||||
else if (tok == ')')
|
else if (tok == ')')
|
||||||
parlevel--;
|
parlevel--;
|
||||||
if (tok != TOK_LINEFEED)
|
if (tok == TOK_LINEFEED)
|
||||||
|
tok = ' ';
|
||||||
|
if (!check_space(tok, &spc))
|
||||||
tok_str_add2(&str, tok, &tokc);
|
tok_str_add2(&str, tok, &tokc);
|
||||||
next_nomacro();
|
next_nomacro_spc();
|
||||||
}
|
}
|
||||||
|
str.len -= spc;
|
||||||
tok_str_add(&str, 0);
|
tok_str_add(&str, 0);
|
||||||
sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str);
|
sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str);
|
||||||
sa = sa->next;
|
sa = sa->next;
|
||||||
@ -4535,7 +4569,7 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list,
|
|||||||
Sym *s;
|
Sym *s;
|
||||||
int *macro_str1;
|
int *macro_str1;
|
||||||
const int *ptr;
|
const int *ptr;
|
||||||
int t, ret;
|
int t, ret, spc;
|
||||||
CValue cval;
|
CValue cval;
|
||||||
struct macro_level ml;
|
struct macro_level ml;
|
||||||
|
|
||||||
@ -4544,6 +4578,7 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list,
|
|||||||
macro_str1 = macro_twosharps(ptr);
|
macro_str1 = macro_twosharps(ptr);
|
||||||
if (macro_str1)
|
if (macro_str1)
|
||||||
ptr = macro_str1;
|
ptr = macro_str1;
|
||||||
|
spc = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
/* NOTE: ptr == NULL can only happen if tokens are read from
|
/* NOTE: ptr == NULL can only happen if tokens are read from
|
||||||
file stream due to a macro function call */
|
file stream due to a macro function call */
|
||||||
@ -4571,6 +4606,7 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list,
|
|||||||
goto no_subst;
|
goto no_subst;
|
||||||
} else {
|
} else {
|
||||||
no_subst:
|
no_subst:
|
||||||
|
if (!check_space(t, &spc))
|
||||||
tok_str_add2(tok_str, t, &cval);
|
tok_str_add2(tok_str, t, &cval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4586,6 +4622,9 @@ static void next(void)
|
|||||||
struct macro_level *ml;
|
struct macro_level *ml;
|
||||||
|
|
||||||
redo:
|
redo:
|
||||||
|
if (parse_flags & PARSE_FLAG_SPACES)
|
||||||
|
next_nomacro_spc();
|
||||||
|
else
|
||||||
next_nomacro();
|
next_nomacro();
|
||||||
if (!macro_ptr) {
|
if (!macro_ptr) {
|
||||||
/* if not reading from macro substituted string, then try
|
/* if not reading from macro substituted string, then try
|
||||||
@ -9873,10 +9912,6 @@ static int tcc_compile(TCCState *s1)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Preprocess the current file */
|
/* Preprocess the current file */
|
||||||
/* XXX: add line and file infos,
|
|
||||||
* XXX: add options to preserve spaces (partly done, only spaces in macro are
|
|
||||||
* not preserved)
|
|
||||||
*/
|
|
||||||
static int tcc_preprocess(TCCState *s1)
|
static int tcc_preprocess(TCCState *s1)
|
||||||
{
|
{
|
||||||
Sym *define_start;
|
Sym *define_start;
|
||||||
@ -9886,11 +9921,9 @@ static int tcc_preprocess(TCCState *s1)
|
|||||||
preprocess_init(s1);
|
preprocess_init(s1);
|
||||||
define_start = define_stack;
|
define_start = define_stack;
|
||||||
ch = file->buf_ptr[0];
|
ch = file->buf_ptr[0];
|
||||||
|
|
||||||
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
||||||
parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
|
parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
|
||||||
PARSE_FLAG_LINEFEED;
|
PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES;
|
||||||
|
|
||||||
token_seen = 0;
|
token_seen = 0;
|
||||||
line_ref = 0;
|
line_ref = 0;
|
||||||
file_ref = NULL;
|
file_ref = NULL;
|
||||||
@ -9904,9 +9937,7 @@ static int tcc_preprocess(TCCState *s1)
|
|||||||
continue;
|
continue;
|
||||||
++line_ref;
|
++line_ref;
|
||||||
token_seen = 0;
|
token_seen = 0;
|
||||||
} else if (token_seen) {
|
} else if (!token_seen) {
|
||||||
fwrite(tok_spaces.data, tok_spaces.size, 1, s1->outfile);
|
|
||||||
} else {
|
|
||||||
int d = file->line_num - line_ref;
|
int d = file->line_num - line_ref;
|
||||||
if (file != file_ref || d < 0 || d >= 8)
|
if (file != file_ref || d < 0 || d >= 8)
|
||||||
fprintf(s1->outfile, "# %d \"%s\"\n", file->line_num, file->filename);
|
fprintf(s1->outfile, "# %d \"%s\"\n", file->line_num, file->filename);
|
||||||
@ -10455,7 +10486,6 @@ static void tcc_cleanup(void)
|
|||||||
dynarray_reset(&sym_pools, &nb_sym_pools);
|
dynarray_reset(&sym_pools, &nb_sym_pools);
|
||||||
/* string buffer */
|
/* string buffer */
|
||||||
cstr_free(&tokcstr);
|
cstr_free(&tokcstr);
|
||||||
cstr_free(&tok_spaces);
|
|
||||||
/* reset symbol stack */
|
/* reset symbol stack */
|
||||||
sym_free_first = NULL;
|
sym_free_first = NULL;
|
||||||
/* cleanup from error/setjmp */
|
/* cleanup from error/setjmp */
|
||||||
|
|||||||
Reference in New Issue
Block a user