aboutsummaryrefslogtreecommitdiff
path: root/tccpp.c
diff options
context:
space:
mode:
authorgrischka <grischka>2017-07-20 22:21:27 +0200
committergrischka <grischka>2017-07-20 22:21:27 +0200
commit0cc24d0e8487eaf53bb2849fef7e438a8e8fc94d (patch)
treeba77f5e03cb8944f995b103abb668e37a9dceef2 /tccpp.c
parentba2b25e4ead7f0037d548289e517b31d29242880 (diff)
downloadtinycc-0cc24d0e8487eaf53bb2849fef7e438a8e8fc94d.tar.gz
tinycc-0cc24d0e8487eaf53bb2849fef7e438a8e8fc94d.tar.bz2
tcc -dt -run ... : simpler is better
* -dt now with lowercase t * test snippets now separated by real preprocessor statements which is valid C also for other compilers #if defined test_xxx < test snippet x > #elif defined test_yyy < test snippet y > #elif ... #endif * simpler implementation, behaves like -run if no 'test_...' macros are seen, works with -E too * for demonstration I combined some of the small tests for errors and warnings (56..63,74) in "60_errors_and_warnings.c" Also: * libtcc.c: put tcc_preprocess() and tcc_assemble() under the setjmp clause to let them return to caller after errors. This is for -dt -E. * tccgen.c: - get rid of save/restore_parse_state(), macro_ptr is saved by begin_macro anyway, now line_num too. - use expr_eq for parsing _Generic's controlling_type - set nocode_wanted with const_wanted. too, This is to keep VT_JMP on vtop when parsing preprocessor expressions. * tccpp.c: tcc -E: suppress trailing whitespace from lines with comments (that -E removes) such as NO_GOTPLT_ENTRY,\t /* never generate ... */
Diffstat (limited to 'tccpp.c')
-rw-r--r--tccpp.c136
1 files changed, 64 insertions, 72 deletions
diff --git a/tccpp.c b/tccpp.c
index 0e46510..8d003d7 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -820,9 +820,11 @@ ST_FUNC uint8_t *parse_comment(uint8_t *p)
return p;
}
-ST_FUNC void set_idnum(int c, int val)
+ST_FUNC int set_idnum(int c, int val)
{
+ int prev = isidnum_table[c - CH_EOF];
isidnum_table[c - CH_EOF] = val;
+ return prev;
}
#define cinp minp
@@ -999,30 +1001,6 @@ _default:
file->buf_ptr = p;
}
-/* ParseState handling */
-
-/* XXX: currently, no include file info is stored. Thus, we cannot display
- accurate messages if the function or data definition spans multiple
- files */
-
-/* save current parse state in 's' */
-ST_FUNC void save_parse_state(ParseState *s)
-{
- s->line_num = file->line_num;
- s->macro_ptr = macro_ptr;
- s->tok = tok;
- s->tokc = tokc;
-}
-
-/* restore parse state from 's' */
-ST_FUNC void restore_parse_state(ParseState *s)
-{
- file->line_num = s->line_num;
- macro_ptr = s->macro_ptr;
- tok = s->tok;
- tokc = s->tokc;
-}
-
#if 0
/* return the number of additional 'ints' necessary to store the
token */
@@ -1124,6 +1102,7 @@ ST_FUNC void begin_macro(TokenString *str, int alloc)
str->alloc = alloc;
str->prev = macro_stack;
str->prev_ptr = macro_ptr;
+ str->save_line_num = file->line_num;
macro_ptr = str->str;
macro_stack = str;
}
@@ -1133,6 +1112,7 @@ ST_FUNC void end_macro(void)
TokenString *str = macro_stack;
macro_stack = str->prev;
macro_ptr = str->prev_ptr;
+ file->line_num = str->save_line_num;
if (str->alloc == 2) {
str->alloc = 3; /* just mark as finished */
} else {
@@ -1402,6 +1382,21 @@ ST_FUNC void label_pop(Sym **ptop, Sym *slast, int keep)
*ptop = slast;
}
+/* fake the nth "#if defined test_..." for tcc -dt -run */
+static void maybe_run_test(TCCState *s, int *c)
+{
+ const char *p;
+ if (s->include_stack_ptr != s->include_stack)
+ return;
+ p = get_tok_str(tok, NULL);
+ if (0 != memcmp(p, "test_", 5))
+ return;
+ if (0 != --s->run_test)
+ return;
+ fprintf(s->ppfp, "\n[%s]\n" + !(s->dflag & 32), p), fflush(s->ppfp);
+ *c = 1;
+}
+
/* eval an expression for #if/#elif */
static int expr_preprocess(void)
{
@@ -1420,6 +1415,8 @@ static int expr_preprocess(void)
if (tok < TOK_IDENT)
expect("identifier");
c = define_find(tok) != 0;
+ if (tcc_state->run_test)
+ maybe_run_test(tcc_state, &c);
if (t == '(') {
next_nomacro();
if (tok != ')')
@@ -1467,7 +1464,7 @@ ST_FUNC void parse_define(void)
/* '(' must be just after macro definition for MACRO_FUNC */
next_nomacro_spc();
if (tok == '(') {
- set_idnum('.', 0);
+ int dotid = set_idnum('.', 0);
next_nomacro();
ps = &first;
if (tok != ')') for (;;) {
@@ -1495,6 +1492,7 @@ ST_FUNC void parse_define(void)
}
next_nomacro_spc();
t = MACRO_FUNC;
+ set_idnum('.', dotid);
}
tokstr_buf.len = 0;
@@ -1505,7 +1503,6 @@ ST_FUNC void parse_define(void)
ID character in asm mode). But '#' should be retained instead of
regarded as line comment leader, so still don't set ASM_FILE
in parse_flags. */
- set_idnum('.', (saved_parse_flags & PARSE_FLAG_ASM_FILE) ? IS_ID : 0);
while (tok != TOK_LINEFEED && tok != TOK_EOF) {
/* remove spaces around ## and after '#' */
if (TOK_TWOSHARPS == tok) {
@@ -1613,7 +1610,7 @@ static void pragma_parse(TCCState *s1)
} else if (tok == TOK_once) {
search_cached_include(s1, file->filename, 1)->once = pp_once;
- } else if (s1->ppfp) {
+ } else if (s1->output_type == TCC_OUTPUT_PREPROCESS) {
/* tcc -E: keep pragmas below unchanged */
unget_tok(' ');
unget_tok(TOK_PRAGMA);
@@ -3043,6 +3040,7 @@ static int paste_tokens(int t1, CValue *v1, int t2, CValue *v2)
tcc_open_bf(tcc_state, ":paste:", cstr.size);
memcpy(file->buffer, cstr.data, cstr.size);
+ tok_flags = 0;
for (;;) {
next_nomacro1();
if (0 == *file->buf_ptr)
@@ -3164,6 +3162,8 @@ static int next_argstream(Sym **nested_list, TokenString *ws_str)
break;
ch = ' ';
}
+ if (ch == '\n')
+ file->line_num++;
if (!(ch == '\f' || ch == '\v' || ch == '\r'))
tok_str_add(ws_str, ch);
cinp();
@@ -3483,7 +3483,7 @@ ST_INLN void unget_tok(int last_tok)
tok = last_tok;
}
-ST_FUNC void preprocess_start(TCCState *s1)
+ST_FUNC void preprocess_start(TCCState *s1, int is_asm)
{
char *buf;
@@ -3496,7 +3496,7 @@ ST_FUNC void preprocess_start(TCCState *s1)
s1->pack_stack_ptr = s1->pack_stack;
set_idnum('$', s1->dollars_in_identifiers ? IS_ID : 0);
- set_idnum('.', (parse_flags & PARSE_FLAG_ASM_FILE) ? IS_ID : 0);
+ set_idnum('.', is_asm ? IS_ID : 0);
buf = tcc_malloc(3 + strlen(file->filename));
sprintf(buf, "\"%s\"", file->filename);
@@ -3517,6 +3517,20 @@ ST_FUNC void preprocess_start(TCCState *s1)
memcpy(file->buffer, cstr.data, cstr.size);
cstr_free(&cstr);
}
+
+ if (is_asm)
+ tcc_define_symbol(s1, "__ASSEMBLER__", NULL);
+
+ parse_flags = is_asm ? PARSE_FLAG_ASM_FILE : 0;
+ tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
+}
+
+/* cleanup from error/setjmp */
+ST_FUNC void preprocess_end(TCCState *s1)
+{
+ while (macro_stack)
+ end_macro();
+ macro_ptr = NULL;
}
ST_FUNC void tccpp_new(TCCState *s)
@@ -3526,6 +3540,7 @@ ST_FUNC void tccpp_new(TCCState *s)
/* might be used in error() before preprocess_start() */
s->include_stack_ptr = s->include_stack;
+ s->ppfp = stdout;
/* init isid table */
for(i = CH_EOF; i<128; i++)
@@ -3570,14 +3585,6 @@ ST_FUNC void tccpp_delete(TCCState *s)
/* free -D and compiler defines */
free_defines(NULL);
- /* cleanup from error/setjmp */
- while (macro_stack)
- end_macro();
- macro_ptr = NULL;
-
- while (file)
- tcc_close();
-
/* free tokens */
n = tok_ident - TOK_IDENT;
for(i = 0; i < n; i++)
@@ -3606,19 +3613,16 @@ ST_FUNC void tccpp_delete(TCCState *s)
static void tok_print(const char *msg, const int *str)
{
FILE *fp;
- int t;
+ int t, s = 0;
CValue cval;
fp = tcc_state->ppfp;
- if (!fp || !tcc_state->dflag)
- fp = stdout;
-
- fprintf(fp, "%s ", msg);
+ fprintf(fp, "%s", msg);
while (str) {
TOK_GET(&t, &str, &cval);
if (!t)
break;
- fprintf(fp,"%s", get_tok_str(t, &cval));
+ fprintf(fp, " %s" + s, get_tok_str(t, &cval)), s = 1;
}
fprintf(fp, "\n");
}
@@ -3731,20 +3735,14 @@ ST_FUNC int tcc_preprocess(TCCState *s1)
BufferedFile **iptr;
int token_seen, spcs, level;
const char *p;
- Sym *define_start;
+ char white[400];
- define_start = define_stack;
- preprocess_start(s1);
-
- ch = file->buf_ptr[0];
- tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
parse_flags = PARSE_FLAG_PREPROCESS
| (parse_flags & PARSE_FLAG_ASM_FILE)
| PARSE_FLAG_LINEFEED
| PARSE_FLAG_SPACES
| PARSE_FLAG_ACCEPT_STRAYS
;
-
/* Credits to Fabrice Bellard's initial revision to demonstrate its
capability to compile and run itself, provided all numbers are
given as decimals. tcc -E -P10 will do. */
@@ -3754,7 +3752,6 @@ ST_FUNC int tcc_preprocess(TCCState *s1)
#ifdef PP_BENCH
/* for PP benchmarks */
do next(); while (tok != TOK_EOF);
- free_defines(define_start);
return 0;
#endif
@@ -3765,48 +3762,43 @@ ST_FUNC int tcc_preprocess(TCCState *s1)
token_seen = TOK_LINEFEED, spcs = 0;
pp_line(s1, file, 0);
-
for (;;) {
iptr = s1->include_stack_ptr;
next();
if (tok == TOK_EOF)
break;
+
level = s1->include_stack_ptr - iptr;
if (level) {
if (level > 0)
pp_line(s1, *iptr, 0);
pp_line(s1, file, level);
}
-
- if (s1->dflag) {
+ if (s1->dflag & 7) {
pp_debug_defines(s1);
if (s1->dflag & 4)
continue;
}
- if (token_seen == TOK_LINEFEED) {
- if (tok == ' ') {
- ++spcs;
- continue;
- }
- if (tok == TOK_LINEFEED) {
- spcs = 0;
- continue;
- }
- pp_line(s1, file, 0);
+ if (is_space(tok)) {
+ if (spcs < sizeof white - 1)
+ white[spcs++] = tok;
+ continue;
} else if (tok == TOK_LINEFEED) {
+ spcs = 0;
+ if (token_seen == TOK_LINEFEED)
+ continue;
++file->line_ref;
- } else {
- spcs = pp_need_space(token_seen, tok);
+ } else if (token_seen == TOK_LINEFEED) {
+ pp_line(s1, file, 0);
+ } else if (spcs == 0 && pp_need_space(token_seen, tok)) {
+ white[spcs++] = ' ';
}
- while (spcs)
- fputs(" ", s1->ppfp), --spcs;
+ white[spcs] = 0, fputs(white, s1->ppfp), spcs = 0;
fputs(p = get_tok_str(tok, &tokc), s1->ppfp);
- token_seen = pp_check_he0xE(tok, p);;
+ token_seen = pp_check_he0xE(tok, p);
}
- /* reset define stack, but keep -D and built-ins */
- free_defines(define_start);
return 0;
}