diff --git a/libtcc.c b/libtcc.c index fb78c37..df98bb0 100644 --- a/libtcc.c +++ b/libtcc.c @@ -1567,6 +1567,10 @@ LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type) put_extern_sym(sym, NULL, 0, 0); } #endif + + if (s->output_type == TCC_OUTPUT_PREPROCESS) + print_defines(); + return 0; } @@ -1843,6 +1847,7 @@ enum { TCC_OPTION_g, TCC_OPTION_c, TCC_OPTION_dumpversion, + TCC_OPTION_d, TCC_OPTION_float_abi, TCC_OPTION_static, TCC_OPTION_std, @@ -1899,6 +1904,7 @@ static const TCCOption tcc_options[] = { { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP }, { "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 { "mfloat-abi", TCC_OPTION_float_abi, TCC_OPTION_HAS_ARG }, #endif @@ -2066,10 +2072,19 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv) s->do_debug = 1; break; case TCC_OPTION_c: - if (s->output_type) + if (s->output_type) tcc_warning("-c: some compiler action already specified (%d)", s->output_type); s->output_type = TCC_OUTPUT_OBJ; break; + case TCC_OPTION_d: + if (*optarg == 'D') + s->dflag = 1; + else { + if (s->warn_unsupported) + goto unsupported_option; + tcc_error("invalid option -- '%s'", r); + } + break; #ifdef TCC_TARGET_ARM case TCC_OPTION_float_abi: /* tcc doesn't support soft float yet */ diff --git a/tcc.c b/tcc.c index ac820ce..704f8bc 100644 --- a/tcc.c +++ b/tcc.c @@ -96,6 +96,7 @@ static void help(void) " -Usym undefine 'sym'\n" " -E preprocess only\n" " -P[1] no/alternative output of #line directives with -E\n" + " -dD dump defines\n" "Linker options:\n" " -Ldir add library path 'dir'\n" " -llib link with dynamic or static library 'lib'\n" diff --git a/tcc.h b/tcc.h index 4d55cc5..99f4183 100644 --- a/tcc.h +++ b/tcc.h @@ -669,6 +669,7 @@ struct TCCState { LINE_MACRO_OUTPUT_FORMAT_NONE, LINE_MACRO_OUTPUT_FORMAT_STD, } Pflag; /* -P switch */ + int dflag; /* -dX value */ /* for -MD/-MF: collected dependencies for this compilation */ char **target_deps; @@ -1185,6 +1186,7 @@ ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg); ST_FUNC void define_undef(Sym *s); ST_INLN Sym *define_find(int v); ST_FUNC void free_defines(Sym *b); +ST_FUNC void print_defines(void); ST_FUNC Sym *label_find(int v); ST_FUNC Sym *label_push(Sym **ptop, int v, int flags); ST_FUNC void label_pop(Sym **ptop, Sym *slast); diff --git a/tccpp.c b/tccpp.c index ac251c3..2936ef7 100644 --- a/tccpp.c +++ b/tccpp.c @@ -1045,6 +1045,104 @@ static int macro_is_equal(const int *a, const int *b) return !(*a || *b); } +static void pp_line(TCCState *s1, BufferedFile *f, int level) +{ + 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->ppfp; + int t; + CValue cval; + + fprintf(pr, "%s ", msg); + while (str) { + TOK_GET(&t, &str, &cval); + if (!t) + break; + fprintf(pr,"%s", get_tok_str(t, &cval)); + } + fprintf(pr, "\n"); +} + +static int define_print_prepared(Sym *s) +{ + if (!s || !tcc_state->ppfp || tcc_state->dflag == 0) + return 0; + + if (s->v < TOK_IDENT || s->v >= tok_ident) + return 0; + + if (file) { + file->line_num--; + pp_line(tcc_state, file, 0); + file->line_ref = ++file->line_num; + } + return 1; +} + +static void define_print(int v) +{ + FILE *pr = tcc_state->ppfp; + Sym *s, *a; + + s = define_find(v); + if (define_print_prepared(s) == 0) + return; + + fprintf(pr, "// #define %s", get_tok_str(v, NULL)); + if (s->type.t == MACRO_FUNC) { + a = s->next; + fprintf(pr,"("); + if (a) + for (;;) { + fprintf(pr,"%s", get_tok_str(a->v & ~SYM_FIELD, NULL)); + if (!(a = a->next)) + break; + fprintf(pr,","); + } + fprintf(pr,")"); + } + tok_print("", s->d); +} + +static void undef_print(int v) +{ + FILE *pr = tcc_state->ppfp; + Sym *s; + + s = define_find(v); + if (define_print_prepared(s) == 0) + return; + + fprintf(pr, "// #undef %s\n", get_tok_str(s->v, NULL)); +} + +ST_FUNC void print_defines(void) +{ + Sym *top = define_stack; + while (top) { + define_print(top->v); + top = top->prev; + } +} + /* defines handling */ ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg) { @@ -1063,8 +1161,8 @@ ST_INLN void define_push(int v, int macro_type, int *str, Sym *first_arg) /* undefined a define symbol. Its name is just set to zero */ ST_FUNC void define_undef(Sym *s) { - int v; - v = s->v; + int v = s->v; + undef_print(v); if (v >= TOK_IDENT && v < tok_ident) table_ident[v - TOK_IDENT]->sym_define = NULL; } @@ -1186,45 +1284,6 @@ static int expr_preprocess(void) return c != 0; } -//#define PP_DEBUG - -#if defined(PARSE_DEBUG) || defined(PP_DEBUG) -static void tok_print(const char *msg, const int *str) -{ - int t; - CValue cval; - - printf("%s ", msg); - while (1) { - TOK_GET(&t, &str, &cval); - if (!t) - break; - printf("%s", get_tok_str(t, &cval)); - } - printf("\n"); -} - -static void define_print(int v) -{ - Sym *s, *a; - - s = define_find(v); - printf("#define %s", get_tok_str(v, NULL)); - if (s->type.t == MACRO_FUNC) { - a = s->next; - printf("("); - if (a) - for (;;) { - printf("%s", get_tok_str(a->v & ~SYM_FIELD, NULL)); - if (!(a = a->next)) - break; - printf(","); - } - printf(")"); - } - tok_print("", s->d); -} -#endif /* parse after #define */ ST_FUNC void parse_define(void) @@ -1301,9 +1360,7 @@ ST_FUNC void parse_define(void) bad_twosharp: tcc_error("'##' cannot appear at either end of macro"); define_push(v, t, str.str, first); -#ifdef PP_DEBUG define_print(v); -#endif } static inline int hash_cached_include(const char *filename) @@ -3312,23 +3369,6 @@ ST_FUNC void preprocess_delete(void) table_ident = NULL; } -static void pp_line(TCCState *s1, BufferedFile *f, int level) -{ - int d; - if (s1->Pflag == LINE_MACRO_OUTPUT_FORMAT_NONE) - return; - if (level == 0 && f->line_ref && (d = f->line_num - f->line_ref) < 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; -} - /* Preprocess the current file */ ST_FUNC int tcc_preprocess(TCCState *s1) {