From c6dc756d4e6905df8498596f5bd0c5a6aa1c6d24 Mon Sep 17 00:00:00 2001 From: seyko Date: Fri, 15 Apr 2016 17:15:11 +0300 Subject: [PATCH] preprocessor oprtion -C (keep comments) This is done by impression of the pcc -C option. Usual execution path and speed are not changed. --- libtcc.c | 20 ++++++ tcc.c | 18 +---- tcc.h | 3 +- tccelf.c | 2 +- tccpp.c | 200 ++++++++++++++++++++++++++++++++++++++++++++++--------- 5 files changed, 195 insertions(+), 48 deletions(-) diff --git a/libtcc.c b/libtcc.c index 678ba23..d587179 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1604,6 +1604,21 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) { s->output_type = output_type; + if (s->output_type == TCC_OUTPUT_PREPROCESS) { + if (!s->outfile) { + s->ppfp = stdout; + } else { + s->ppfp = fopen(s->outfile, "w"); + if (!s->ppfp) + tcc_error("could not write '%s'", s->outfile); + } + s->dffp = s->ppfp; + if (s->dflag == 'M') + s->ppfp = NULL; + } + if (s->option_C && !s->ppfp) + s->option_C = 0; + if (!s->nostdinc) { /* default include paths */ /* -isystem paths have already been handled */ @@ -1946,6 +1961,7 @@ enum { TCC_OPTION_b, TCC_OPTION_g, TCC_OPTION_c, + TCC_OPTION_C, TCC_OPTION_dumpversion, TCC_OPTION_d, TCC_OPTION_float_abi, @@ -2003,6 +2019,7 @@ static const TCCOption tcc_options[] = { #endif { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "c", TCC_OPTION_c, 0 }, + { "C", TCC_OPTION_C, 0 }, { "dumpversion", TCC_OPTION_dumpversion, 0}, { "d", TCC_OPTION_d, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, #ifdef TCC_TARGET_ARM @@ -2191,6 +2208,9 @@ ST_FUNC int tcc_parse_args1(TCCState *s, int argc, char **argv) tcc_warning("-c: some compiler action already specified (%d)", s->output_type); s->output_type = TCC_OUTPUT_OBJ; break; + case TCC_OPTION_C: + s->option_C = 1; + break; case TCC_OPTION_d: if (*optarg == 'D' || *optarg == 'M') s->dflag = *optarg; diff --git a/tcc.c b/tcc.c index 722bd4c..e79e1fb 100644 --- a/tcc.c +++ b/tcc.c @@ -98,8 +98,9 @@ static void help(void) " -Dsym[=val] define 'sym' with value 'val'\n" " -Usym undefine 'sym'\n" " -E preprocess only\n" - " -P[1] no/alternative output of #line directives with -E\n" - " -d{D|M} dump defines (only with -E)\n" + " -P[1] no/alternative output of #line directives\n" + " -d{D|M} dump defines\n" + " -C keep comments\n" "Linker options:\n" " -Ldir add library path 'dir'\n" " -llib link with dynamic or static library 'lib'\n" @@ -294,19 +295,6 @@ int main(int argc, char **argv) } } - if (s->output_type == TCC_OUTPUT_PREPROCESS) { - if (!s->outfile) { - s->ppfp = stdout; - } else { - s->ppfp = fopen(s->outfile, "w"); - if (!s->ppfp) - tcc_error("could not write '%s'", s->outfile); - } - s->dffp = s->ppfp; - if (s->dflag == 'M') - s->ppfp = NULL; - } - tcc_set_output_type(s, s->output_type); /* compile or add each files or library */ diff --git a/tcc.h b/tcc.h index dd4ecd5..208af44 100644 --- a/tcc.h +++ b/tcc.h @@ -812,6 +812,7 @@ struct TCCState { char *option_m; /* only -m32/-m64 handled */ int print_search_dirs; /* option */ int option_r; /* option -r */ + int option_C; /* option -C, keep comments when -E */ int do_bench; /* option -bench */ int gen_deps; /* option -MD */ char *deps_outfile; /* option -MF */ @@ -1406,7 +1407,7 @@ ST_FUNC void *tcc_get_symbol_err(TCCState *s, const char *name); #ifndef TCC_TARGET_PE ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level); ST_FUNC int tcc_load_ldscript(TCCState *s1); -ST_FUNC uint8_t *parse_comment(uint8_t *p); +ST_FUNC uint8_t *parse_comment(uint8_t *p, int skip); ST_FUNC void minp(void); ST_INLN void inp(void); ST_FUNC int handle_eob(void); diff --git a/tccelf.c b/tccelf.c index 196dd65..a09e36a 100644 --- a/tccelf.c +++ b/tccelf.c @@ -3282,7 +3282,7 @@ static int ld_next(TCCState *s1, char *name, int name_size) case '/': minp(); if (ch == '*') { - file->buf_ptr = parse_comment(file->buf_ptr); + file->buf_ptr = parse_comment(file->buf_ptr,0); ch = file->buf_ptr[0]; goto redo; } else { diff --git a/tccpp.c b/tccpp.c index cb220ab..765a569 100644 --- a/tccpp.c +++ b/tccpp.c @@ -524,13 +524,163 @@ ST_FUNC void minp(void) handle_stray(); } +static void pp_line(TCCState *s1, BufferedFile *f, int level) +{ + if (s1->ppfp) { + int d = f->line_num - f->line_ref; + if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_NONE + || (level == 0 && f->line_ref && d < 8)) { + while (d > 0) + fputs("\n", s1->ppfp), --d; + } else if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_STD) { + fprintf(s1->ppfp, "#line %d \"%s\"\n", f->line_num, f->filename); + } else { + fprintf(s1->ppfp, "# %d \"%s\"%s\n", f->line_num, f->filename, + level > 0 ? " 1" : level < 0 ? " 2" : ""); + } + } + f->line_ref = f->line_num; +} + +static uint8_t *parse_print_line_comment(uint8_t *p) +{ + int c; + + if ((file->line_num - file->line_ref) > 0) { + fputc('\n', tcc_state->ppfp); + file->line_ref++; + pp_line(tcc_state, file, 0); + } + fputs("// ", tcc_state->ppfp); + + for(;;) { + c = *p; + redo: + if (c == '\n' || c == CH_EOF) + break; + fputc(c, tcc_state->ppfp); + if (c == '\\') { + file->buf_ptr = p; + c = handle_eob(); + p = file->buf_ptr; + if (c == '\\') { + PEEKC_EOB(c, p); + if (c == '\n') { + file->line_num++; + PEEKC_EOB(c, p); + } else if (c == '\r') { + PEEKC_EOB(c, p); + if (c == '\n') { + file->line_num++; + PEEKC_EOB(c, p); + } + } + } else { + goto redo; + } + } else { + p++; + } + } + return p; +} + + +static uint8_t *parse_print_comment(uint8_t *p) +{ + int c; + + if ((file->line_num - file->line_ref) > 0) { + fputc('\n', tcc_state->ppfp); + file->line_ref++; + pp_line(tcc_state, file, 0); + } + fputs("/*", tcc_state->ppfp); + + for(;;) { + /* fast skip loop */ + for(;;) { + c = *p; + if (c == '\n' || c == '*' || c == '\\') + break; + fputc(c, tcc_state->ppfp); + p++; + } + /* now we can handle all the cases */ + if (c == '\n') { + fputc(c, tcc_state->ppfp); + file->line_num++; + p++; + } else if (c == '*') { + fputc(c, tcc_state->ppfp); + p++; + for(;;) { + c = *p; + if (c == '*') { + fputc(c, tcc_state->ppfp); + p++; + } else if (c == '/') { + fputc(c, tcc_state->ppfp); + goto end_of_comment; + } else if (c == '\\') { + file->buf_ptr = p; + c = handle_eob(); + p = file->buf_ptr; + if (c == CH_EOF) + tcc_error("unexpected end of file in comment"); + if (c == '\\') { + /* skip '\[\r]\n', otherwise just skip the stray */ + while (c == '\\') { + fputc(c, tcc_state->ppfp); + PEEKC_EOB(c, p); + if (c == '\n') { + fputc(c, tcc_state->ppfp); + file->line_num++; + PEEKC_EOB(c, p); + } else if (c == '\r') { + PEEKC_EOB(c, p); + if (c == '\n') { + fputc(c, tcc_state->ppfp); + file->line_num++; + PEEKC_EOB(c, p); + } + } else { + goto after_star; + } + } + } + } else { + break; + } + } + after_star: ; + } else { + /* stray, eob or eof */ + file->buf_ptr = p; + c = handle_eob(); + p = file->buf_ptr; + if (c == CH_EOF) + tcc_error("unexpected end of file in comment"); + if (c == '\\') { + fputc(c, tcc_state->ppfp); + p++; + } + } + } + end_of_comment: + p++; + file->line_ref = file->line_num; + return p; +} /* single line C++ comments */ -static uint8_t *parse_line_comment(uint8_t *p) +static uint8_t *parse_line_comment(uint8_t *p, int skip) { int c; p++; + if (tcc_state->option_C && !skip) + return parse_print_line_comment(p); for(;;) { c = *p; redo: @@ -563,11 +713,13 @@ static uint8_t *parse_line_comment(uint8_t *p) } /* C comments */ -ST_FUNC uint8_t *parse_comment(uint8_t *p) +ST_FUNC uint8_t *parse_comment(uint8_t *p, int skip) { int c; - + p++; + if (tcc_state->option_C && !skip) + return parse_print_comment(p); for(;;) { /* fast skip loop */ for(;;) { @@ -774,9 +926,9 @@ redo_start: minp(); p = file->buf_ptr; if (ch == '*') { - p = parse_comment(p); + p = parse_comment(p,1); } else if (ch == '/') { - p = parse_line_comment(p); + p = parse_line_comment(p,1); } break; case '#': @@ -797,9 +949,9 @@ redo_start: else if (tok == TOK_LINEFEED) goto redo_start; else if (parse_flags & PARSE_FLAG_ASM_FILE) - p = parse_line_comment(p); + p = parse_line_comment(p,0); } else if (parse_flags & PARSE_FLAG_ASM_FILE) - p = parse_line_comment(p); + p = parse_line_comment(p,0); break; _default: default: @@ -1072,24 +1224,6 @@ static int macro_is_equal(const int *a, const int *b) return !(*a || *b); } -static void pp_line(TCCState *s1, BufferedFile *f, int level) -{ - if (s1->ppfp) { - int d = f->line_num - f->line_ref; - if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_NONE - || (level == 0 && f->line_ref && d < 8)) { - while (d > 0) - fputs("\n", s1->ppfp), --d; - } else if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_STD) { - fprintf(s1->ppfp, "#line %d \"%s\"\n", f->line_num, f->filename); - } else { - fprintf(s1->ppfp, "# %d \"%s\"%s\n", f->line_num, f->filename, - level > 0 ? " 1" : level < 0 ? " 2" : ""); - } - } - f->line_ref = f->line_num; -} - static void tok_print(const char *msg, const int *str) { FILE *pr = tcc_state->dffp; @@ -1848,7 +1982,7 @@ _line_num: goto ignore; tcc_warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc)); ignore: - file->buf_ptr = parse_line_comment(file->buf_ptr); + file->buf_ptr = parse_line_comment(file->buf_ptr,0); goto the_end; } /* ignore other preprocess commands or #! for C scripts */ @@ -2444,7 +2578,7 @@ maybe_newline: tok = TOK_TWOSHARPS; } else { if (parse_flags & PARSE_FLAG_ASM_FILE) { - p = parse_line_comment(p - 1); + p = parse_line_comment(p - 1,0); goto redo_no_start; } else { tok = '#'; @@ -2711,13 +2845,17 @@ maybe_newline: case '/': PEEKC(c, p); if (c == '*') { - p = parse_comment(p); + p = parse_comment(p,0); /* comments replaced by a blank */ tok = ' '; + if (tcc_state->option_C) + goto redo_no_start; goto keep_tok_flags; } else if (c == '/') { - p = parse_line_comment(p); + p = parse_line_comment(p,0); tok = ' '; + if (tcc_state->option_C) + goto redo_no_start; goto keep_tok_flags; } else if (c == '=') { p++; @@ -2939,10 +3077,10 @@ static int next_argstream(Sym **nested_list, int can_read_stream, TokenString *w uint8_t *p = file->buf_ptr; PEEKC(c, p); if (c == '*') { - p = parse_comment(p); + p = parse_comment(p,0); file->buf_ptr = p - 1; } else if (c == '/') { - p = parse_line_comment(p); + p = parse_line_comment(p,0); file->buf_ptr = p - 1; } else break;