mirror of https://github.com/rui314/chibicc
Accept multiple input files
This commit is contained in:
parent
af5e8a98a6
commit
e664fd254a
12
chibicc.h
12
chibicc.h
|
@ -22,6 +22,18 @@ typedef struct Node Node;
|
|||
typedef struct Member Member;
|
||||
typedef struct Relocation Relocation;
|
||||
|
||||
//
|
||||
// strarray.c
|
||||
//
|
||||
|
||||
typedef struct {
|
||||
char **data;
|
||||
int capacity;
|
||||
int len;
|
||||
} StringArray;
|
||||
|
||||
void strarray_push(StringArray *arr, char *s);
|
||||
|
||||
//
|
||||
// tokenize.c
|
||||
//
|
||||
|
|
84
main.c
84
main.c
|
@ -5,7 +5,10 @@ static bool opt_cc1;
|
|||
static bool opt_hash_hash_hash;
|
||||
static char *opt_o;
|
||||
|
||||
static char *input_path;
|
||||
static char *base_file;
|
||||
static char *output_file;
|
||||
|
||||
static StringArray input_paths;
|
||||
|
||||
static char **tmpfiles;
|
||||
|
||||
|
@ -14,7 +17,18 @@ static void usage(int status) {
|
|||
exit(status);
|
||||
}
|
||||
|
||||
static bool take_arg(char *arg) {
|
||||
return !strcmp(arg, "-o");
|
||||
}
|
||||
|
||||
static void parse_args(int argc, char **argv) {
|
||||
// Make sure that all command line options that take an argument
|
||||
// have an argument.
|
||||
for (int i = 1; i < argc; i++)
|
||||
if (take_arg(argv[i]))
|
||||
if (!argv[++i])
|
||||
usage(1);
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (!strcmp(argv[i], "-###")) {
|
||||
opt_hash_hash_hash = true;
|
||||
|
@ -30,9 +44,7 @@ static void parse_args(int argc, char **argv) {
|
|||
usage(0);
|
||||
|
||||
if (!strcmp(argv[i], "-o")) {
|
||||
if (!argv[++i])
|
||||
usage(1);
|
||||
opt_o = argv[i];
|
||||
opt_o = argv[++i];
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -46,13 +58,23 @@ static void parse_args(int argc, char **argv) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[i], "-cc1-input")) {
|
||||
base_file = argv[++i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(argv[i], "-cc1-output")) {
|
||||
output_file = argv[++i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argv[i][0] == '-' && argv[i][1] != '\0')
|
||||
error("unknown argument: %s", argv[i]);
|
||||
|
||||
input_path = argv[i];
|
||||
strarray_push(&input_paths, argv[i]);
|
||||
}
|
||||
|
||||
if (!input_path)
|
||||
if (input_paths.len == 0)
|
||||
error("no input files");
|
||||
}
|
||||
|
||||
|
@ -133,11 +155,13 @@ static void run_cc1(int argc, char **argv, char *input, char *output) {
|
|||
memcpy(args, argv, argc * sizeof(char *));
|
||||
args[argc++] = "-cc1";
|
||||
|
||||
if (input)
|
||||
if (input) {
|
||||
args[argc++] = "-cc1-input";
|
||||
args[argc++] = input;
|
||||
}
|
||||
|
||||
if (output) {
|
||||
args[argc++] = "-o";
|
||||
args[argc++] = "-cc1-output";
|
||||
args[argc++] = output;
|
||||
}
|
||||
|
||||
|
@ -146,12 +170,12 @@ static void run_cc1(int argc, char **argv, char *input, char *output) {
|
|||
|
||||
static void cc1(void) {
|
||||
// Tokenize and parse.
|
||||
Token *tok = tokenize_file(input_path);
|
||||
Token *tok = tokenize_file(base_file);
|
||||
Var *prog = parse(tok);
|
||||
|
||||
// Traverse the AST to emit assembly.
|
||||
FILE *out = open_file(opt_o);
|
||||
fprintf(out, ".file 1 \"%s\"\n", input_path);
|
||||
FILE *out = open_file(output_file);
|
||||
fprintf(out, ".file 1 \"%s\"\n", base_file);
|
||||
codegen(prog, out);
|
||||
}
|
||||
|
||||
|
@ -169,23 +193,31 @@ int main(int argc, char **argv) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
char *output;
|
||||
if (opt_o)
|
||||
output = opt_o;
|
||||
else if (opt_S)
|
||||
output = replace_extn(input_path, ".s");
|
||||
else
|
||||
output = replace_extn(input_path, ".o");
|
||||
if (input_paths.len > 1 && opt_o)
|
||||
error("cannot specify '-o' with multiple files");
|
||||
|
||||
// If -S is given, assembly text is the final output.
|
||||
if (opt_S) {
|
||||
run_cc1(argc, argv, input_path, output);
|
||||
return 0;
|
||||
for (int i = 0; i < input_paths.len; i++) {
|
||||
char *input = input_paths.data[i];
|
||||
|
||||
char *output;
|
||||
if (opt_o)
|
||||
output = opt_o;
|
||||
else if (opt_S)
|
||||
output = replace_extn(input, ".s");
|
||||
else
|
||||
output = replace_extn(input, ".o");
|
||||
|
||||
// If -S is given, assembly text is the final output.
|
||||
if (opt_S) {
|
||||
run_cc1(argc, argv, input, output);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, run the assembler to assemble our output.
|
||||
char *tmpfile = create_tmpfile();
|
||||
run_cc1(argc, argv, input, tmpfile);
|
||||
assemble(tmpfile, output);
|
||||
}
|
||||
|
||||
// Otherwise, run the assembler to assemble our output.
|
||||
char *tmpfile = create_tmpfile();
|
||||
run_cc1(argc, argv, input_path, tmpfile);
|
||||
assemble(tmpfile, output);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#include "chibicc.h"
|
||||
|
||||
void strarray_push(StringArray *arr, char *s) {
|
||||
if (!arr->data) {
|
||||
arr->data = calloc(8, sizeof(char *));
|
||||
arr->capacity = 8;
|
||||
}
|
||||
|
||||
if (arr->capacity == arr->len) {
|
||||
arr->data = realloc(arr->data, sizeof(char *) * arr->capacity * 2);
|
||||
arr->capacity *= 2;
|
||||
for (int i = arr->len; i < arr->capacity; i++)
|
||||
arr->data[i] = NULL;
|
||||
}
|
||||
|
||||
arr->data[arr->len++] = s;
|
||||
}
|
|
@ -39,4 +39,19 @@ check 'default output file'
|
|||
[ -f $tmp/out.s ]
|
||||
check 'default output file'
|
||||
|
||||
# Multiple input files
|
||||
rm -f $tmp/foo.o $tmp/bar.o
|
||||
echo 'int x;' > $tmp/foo.c
|
||||
echo 'int y;' > $tmp/bar.c
|
||||
(cd $tmp; $OLDPWD/$chibicc $tmp/foo.c $tmp/bar.c)
|
||||
[ -f $tmp/foo.o ] && [ -f $tmp/bar.o ]
|
||||
check 'multiple input files'
|
||||
|
||||
rm -f $tmp/foo.s $tmp/bar.s
|
||||
echo 'int x;' > $tmp/foo.c
|
||||
echo 'int y;' > $tmp/bar.c
|
||||
(cd $tmp; $OLDPWD/$chibicc -S $tmp/foo.c $tmp/bar.c)
|
||||
[ -f $tmp/foo.s ] && [ -f $tmp/bar.s ]
|
||||
check 'multiple input files'
|
||||
|
||||
echo OK
|
||||
|
|
Loading…
Reference in New Issue