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:
grischka
2009-04-17 22:44:08 +02:00
parent 90697c4c56
commit 0f0ed4a8bf

110
tcc.c
View File

@ -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 */