mirror of
https://github.com/frida/tinycc
synced 2025-01-01 17:44:26 +03:00
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:
parent
90697c4c56
commit
0f0ed4a8bf
116
tcc.c
116
tcc.c
@ -336,7 +336,6 @@ typedef struct CachedInclude {
|
||||
/* parser */
|
||||
static struct BufferedFile *file;
|
||||
static int ch, tok;
|
||||
static CString tok_spaces; /* spaces before current token */
|
||||
static CValue tokc;
|
||||
static CString tokcstr; /* current parsed string, if any */
|
||||
/* additional informations about token */
|
||||
@ -357,6 +356,7 @@ static int parse_flags;
|
||||
token. line feed is also
|
||||
returned at eof */
|
||||
#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 *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_nomacro(void);
|
||||
static void next_nomacro_spc(void);
|
||||
static void parse_expr_type(CType *type);
|
||||
static void expr_type(CType *type);
|
||||
static void unary_type(CType *type);
|
||||
@ -2290,6 +2291,17 @@ static inline void skip_spaces(void)
|
||||
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 */
|
||||
static uint8_t *parse_pp_string(uint8_t *p,
|
||||
int sep, CString *str)
|
||||
@ -2822,13 +2834,14 @@ static void tok_print(int *str)
|
||||
int t;
|
||||
CValue cval;
|
||||
|
||||
printf("<");
|
||||
while (1) {
|
||||
TOK_GET(t, str, cval);
|
||||
if (!t)
|
||||
break;
|
||||
printf(" %s", get_tok_str(t, &cval));
|
||||
printf("%s", get_tok_str(t, &cval));
|
||||
}
|
||||
printf("\n");
|
||||
printf(">\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2836,7 +2849,7 @@ static void tok_print(int *str)
|
||||
static void parse_define(void)
|
||||
{
|
||||
Sym *s, *first, **ps;
|
||||
int v, t, varg, is_vaargs, c;
|
||||
int v, t, varg, is_vaargs, spc;
|
||||
TokenString str;
|
||||
|
||||
v = tok;
|
||||
@ -2846,11 +2859,8 @@ static void parse_define(void)
|
||||
first = NULL;
|
||||
t = MACRO_OBJ;
|
||||
/* '(' must be just after macro definition for MACRO_FUNC */
|
||||
c = file->buf_ptr[0];
|
||||
if (c == '\\')
|
||||
c = handle_stray1(file->buf_ptr);
|
||||
if (c == '(') {
|
||||
next_nomacro();
|
||||
next_nomacro_spc();
|
||||
if (tok == '(') {
|
||||
next_nomacro();
|
||||
ps = &first;
|
||||
while (tok != ')') {
|
||||
@ -2873,15 +2883,30 @@ static void parse_define(void)
|
||||
break;
|
||||
next_nomacro();
|
||||
}
|
||||
if (tok == ')')
|
||||
next_nomacro_spc();
|
||||
t = MACRO_FUNC;
|
||||
}
|
||||
tok_str_new(&str);
|
||||
next_nomacro();
|
||||
spc = 2;
|
||||
/* EOF testing necessary for '-D' handling */
|
||||
while (tok != TOK_LINEFEED && tok != TOK_EOF) {
|
||||
/* remove spaces around ## and after '#' */
|
||||
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);
|
||||
next_nomacro();
|
||||
skip:
|
||||
next_nomacro_spc();
|
||||
}
|
||||
if (spc == 1)
|
||||
--str.len; /* remove trailing space */
|
||||
tok_str_add(&str, 0);
|
||||
#ifdef PP_DEBUG
|
||||
printf("define %s %d: ", get_tok_str(v, NULL), t);
|
||||
@ -3703,20 +3728,20 @@ static inline void next_nomacro1(void)
|
||||
uint8_t *p, *p1;
|
||||
unsigned int h;
|
||||
|
||||
cstr_reset(&tok_spaces);
|
||||
p = file->buf_ptr;
|
||||
redo_no_start:
|
||||
c = *p;
|
||||
switch(c) {
|
||||
case ' ':
|
||||
case '\t':
|
||||
tok = c;
|
||||
p++;
|
||||
goto keep_tok_flags;
|
||||
case '\f':
|
||||
case '\v':
|
||||
case '\r':
|
||||
cstr_ccat(&tok_spaces, c);
|
||||
p++;
|
||||
goto redo_no_start;
|
||||
|
||||
case '\\':
|
||||
/* first look if it is in fact an end of buffer */
|
||||
if (p >= file->buf_end) {
|
||||
@ -4121,7 +4146,7 @@ keep_tok_flags:
|
||||
|
||||
/* return next token without macro substitution. Can read input from
|
||||
macro_ptr buffer */
|
||||
static void next_nomacro(void)
|
||||
static void next_nomacro_spc(void)
|
||||
{
|
||||
if (macro_ptr) {
|
||||
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 */
|
||||
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;
|
||||
CValue cval;
|
||||
TokenString str;
|
||||
@ -4162,16 +4194,13 @@ static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
|
||||
if (s) {
|
||||
cstr_new(&cstr);
|
||||
st = (int *)s->c;
|
||||
notfirst = 0;
|
||||
spc = 0;
|
||||
while (*st) {
|
||||
if (notfirst)
|
||||
cstr_ccat(&cstr, ' ');
|
||||
TOK_GET(t, st, cval);
|
||||
cstr_cat(&cstr, get_tok_str(t, &cval));
|
||||
#ifndef PP_NOSPACES
|
||||
notfirst = 1;
|
||||
#endif
|
||||
if (!check_space(t, &spc))
|
||||
cstr_cat(&cstr, get_tok_str(t, &cval));
|
||||
}
|
||||
cstr.size -= spc;
|
||||
cstr_ccat(&cstr, '\0');
|
||||
#ifdef PP_DEBUG
|
||||
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 *args, *sa, *sa1;
|
||||
int mstr_allocated, parlevel, *mstr, t, t1;
|
||||
int mstr_allocated, parlevel, *mstr, t, t1, *p, spc;
|
||||
TokenString str;
|
||||
char *cstrval;
|
||||
CValue cval;
|
||||
@ -4294,7 +4323,9 @@ static int macro_subst_tok(TokenString *tok_str,
|
||||
next token. XXX: find better solution */
|
||||
redo:
|
||||
if (macro_ptr) {
|
||||
t = *macro_ptr;
|
||||
p = macro_ptr;
|
||||
while (is_space(t = *p) || TOK_LINEFEED == t)
|
||||
++p;
|
||||
if (t == 0 && can_read_stream) {
|
||||
/* end of macro stream: we must look at the token
|
||||
after in the file */
|
||||
@ -4332,7 +4363,7 @@ static int macro_subst_tok(TokenString *tok_str,
|
||||
error("macro '%s' used with too many args",
|
||||
get_tok_str(s->v, 0));
|
||||
tok_str_new(&str);
|
||||
parlevel = 0;
|
||||
parlevel = spc = 0;
|
||||
/* NOTE: non zero sa->t indicates VA_ARGS */
|
||||
while ((parlevel > 0 ||
|
||||
(tok != ')' &&
|
||||
@ -4342,10 +4373,13 @@ static int macro_subst_tok(TokenString *tok_str,
|
||||
parlevel++;
|
||||
else if (tok == ')')
|
||||
parlevel--;
|
||||
if (tok != TOK_LINEFEED)
|
||||
if (tok == TOK_LINEFEED)
|
||||
tok = ' ';
|
||||
if (!check_space(tok, &spc))
|
||||
tok_str_add2(&str, tok, &tokc);
|
||||
next_nomacro();
|
||||
next_nomacro_spc();
|
||||
}
|
||||
str.len -= spc;
|
||||
tok_str_add(&str, 0);
|
||||
sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (long)str.str);
|
||||
sa = sa->next;
|
||||
@ -4535,7 +4569,7 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list,
|
||||
Sym *s;
|
||||
int *macro_str1;
|
||||
const int *ptr;
|
||||
int t, ret;
|
||||
int t, ret, spc;
|
||||
CValue cval;
|
||||
struct macro_level ml;
|
||||
|
||||
@ -4544,6 +4578,7 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list,
|
||||
macro_str1 = macro_twosharps(ptr);
|
||||
if (macro_str1)
|
||||
ptr = macro_str1;
|
||||
spc = 0;
|
||||
while (1) {
|
||||
/* NOTE: ptr == NULL can only happen if tokens are read from
|
||||
file stream due to a macro function call */
|
||||
@ -4571,7 +4606,8 @@ static void macro_subst(TokenString *tok_str, Sym **nested_list,
|
||||
goto no_subst;
|
||||
} else {
|
||||
no_subst:
|
||||
tok_str_add2(tok_str, t, &cval);
|
||||
if (!check_space(t, &spc))
|
||||
tok_str_add2(tok_str, t, &cval);
|
||||
}
|
||||
}
|
||||
if (macro_str1)
|
||||
@ -4586,7 +4622,10 @@ static void next(void)
|
||||
struct macro_level *ml;
|
||||
|
||||
redo:
|
||||
next_nomacro();
|
||||
if (parse_flags & PARSE_FLAG_SPACES)
|
||||
next_nomacro_spc();
|
||||
else
|
||||
next_nomacro();
|
||||
if (!macro_ptr) {
|
||||
/* if not reading from macro substituted string, then try
|
||||
to substitute macros */
|
||||
@ -9873,10 +9912,6 @@ static int tcc_compile(TCCState *s1)
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
Sym *define_start;
|
||||
@ -9886,11 +9921,9 @@ static int tcc_preprocess(TCCState *s1)
|
||||
preprocess_init(s1);
|
||||
define_start = define_stack;
|
||||
ch = file->buf_ptr[0];
|
||||
|
||||
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
|
||||
parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
|
||||
PARSE_FLAG_LINEFEED;
|
||||
|
||||
parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
|
||||
PARSE_FLAG_LINEFEED | PARSE_FLAG_SPACES;
|
||||
token_seen = 0;
|
||||
line_ref = 0;
|
||||
file_ref = NULL;
|
||||
@ -9904,9 +9937,7 @@ static int tcc_preprocess(TCCState *s1)
|
||||
continue;
|
||||
++line_ref;
|
||||
token_seen = 0;
|
||||
} else if (token_seen) {
|
||||
fwrite(tok_spaces.data, tok_spaces.size, 1, s1->outfile);
|
||||
} else {
|
||||
} else if (!token_seen) {
|
||||
int d = file->line_num - line_ref;
|
||||
if (file != file_ref || d < 0 || d >= 8)
|
||||
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);
|
||||
/* string buffer */
|
||||
cstr_free(&tokcstr);
|
||||
cstr_free(&tok_spaces);
|
||||
/* reset symbol stack */
|
||||
sym_free_first = NULL;
|
||||
/* cleanup from error/setjmp */
|
||||
|
Loading…
Reference in New Issue
Block a user