Add -E option

This commit is contained in:
Rui Ueyama 2020-08-20 21:37:02 +09:00
parent ec149f64d2
commit d138864a2a
3 changed files with 52 additions and 4 deletions

39
main.c
View File

@ -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;

View File

@ -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));

View File

@ -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