From d138864a2a99849e43d81ca071b7a799edc0e65a Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 20 Aug 2020 21:37:02 +0900 Subject: [PATCH] Add -E option --- main.c | 39 ++++++++++++++++++++++++++++++++++++--- preprocess.c | 7 ++++++- test/driver.sh | 10 ++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/main.c b/main.c index ae2de82..4e4a4fe 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,6 @@ #include "chibicc.h" +static bool opt_E; static bool opt_S; static bool opt_c; static bool opt_cc1; @@ -63,6 +64,11 @@ static void parse_args(int argc, char **argv) { continue; } + if (!strcmp(argv[i], "-E")) { + opt_E = true; + continue; + } + if (!strcmp(argv[i], "-cc1-input")) { base_file = argv[++i]; continue; @@ -165,6 +171,20 @@ static void run_cc1(int argc, char **argv, char *input, char *output) { run_subprocess(args); } +// Print tokens to stdout. Used for -E. +static void print_tokens(Token *tok) { + FILE *out = open_file(opt_o ? opt_o : "-"); + + int line = 1; + for (; tok->kind != TK_EOF; tok = tok->next) { + if (line > 1 && tok->at_bol) + fprintf(out, "\n"); + fprintf(out, " %.*s", tok->len, tok->loc); + line++; + } + fprintf(out, "\n"); +} + static void cc1(void) { // Tokenize and parse. Token *tok = tokenize_file(base_file); @@ -172,6 +192,13 @@ static void cc1(void) { error("%s: %s", base_file, strerror(errno)); tok = preprocess(tok); + + // If -E is given, print out preprocessed C code as a result. + if (opt_E) { + print_tokens(tok); + return; + } + Obj *prog = parse(tok); // Traverse the AST to emit assembly. @@ -276,8 +303,8 @@ int main(int argc, char **argv) { return 0; } - if (input_paths.len > 1 && opt_o && (opt_c || opt_S)) - error("cannot specify '-o' with '-c' or '-S' with multiple files"); + if (input_paths.len > 1 && opt_o && (opt_c || opt_S | opt_E)) + error("cannot specify '-o' with '-c,' '-S' or '-E' with multiple files"); StringArray ld_args = {}; @@ -309,7 +336,13 @@ int main(int argc, char **argv) { if (!endswith(input, ".c") && strcmp(input, "-")) error("unknown file extension: %s", input); - // Just compile + // Just preprocess + if (opt_E) { + run_cc1(argc, argv, input, NULL); + continue; + } + + // Compile if (opt_S) { run_cc1(argc, argv, input, output); continue; diff --git a/preprocess.c b/preprocess.c index 81d138a..a5f7316 100644 --- a/preprocess.c +++ b/preprocess.c @@ -58,7 +58,12 @@ static Token *preprocess2(Token *tok) { if (tok->kind != TK_STR) error_tok(tok, "expected a filename"); - char *path = format("%s/%s", dirname(strdup(tok->file->name)), tok->str); + char *path; + if (tok->str[0] == '/') + path = tok->str; + else + path = format("%s/%s", dirname(strdup(tok->file->name)), tok->str); + Token *tok2 = tokenize_file(path); if (!tok2) error_tok(tok, "%s", strerror(errno)); diff --git a/test/driver.sh b/test/driver.sh index 9fcc184..2358af8 100755 --- a/test/driver.sh +++ b/test/driver.sh @@ -75,4 +75,14 @@ echo 'int main() {}' > $tmp/foo.c [ -f $tmp/a.out ] check a.out +# -E +echo foo > $tmp/out +echo "#include \"$tmp/out\"" | $chibicc -E - | grep -q foo +check -E + +echo foo > $tmp/out1 +echo "#include \"$tmp/out1\"" | $chibicc -E -o $tmp/out2 - +cat $tmp/out2 | grep -q foo +check '-E and -o' + echo OK -- GitLab