Skip to content

Commit

Permalink
Add -x option
Browse files Browse the repository at this point in the history
  • Loading branch information
rui314 committed Dec 7, 2020
1 parent 8f5ff07 commit ee0a951
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 34 deletions.
50 changes: 44 additions & 6 deletions main.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
#include "chibicc.h"

typedef enum { FILE_NONE, FILE_C, FILE_ASM, FILE_OBJ } FileType;

StringArray include_paths;
bool opt_fcommon = true;

static FileType opt_x;
static StringArray opt_include;
static bool opt_E;
static bool opt_S;
Expand All @@ -23,7 +26,7 @@ static void usage(int status) {
}

static bool take_arg(char *arg) {
char *x[] = {"-o", "-I", "-idirafter", "-include"};
char *x[] = {"-o", "-I", "-idirafter", "-include", "-x"};

for (int i = 0; i < sizeof(x) / sizeof(*x); i++)
if (!strcmp(arg, x[i]))
Expand All @@ -50,6 +53,16 @@ static void define(char *str) {
define_macro(str, "1");
}

static FileType parse_opt_x(char *s) {
if (!strcmp(s, "c"))
return FILE_C;
if (!strcmp(s, "assembler"))
return FILE_ASM;
if (!strcmp(s, "none"))
return FILE_NONE;
error("<command line>: unknown argument for -x: %s", s);
}

static void parse_args(int argc, char **argv) {
// Make sure that all command line options that take an argument
// have an argument.
Expand Down Expand Up @@ -139,6 +152,16 @@ static void parse_args(int argc, char **argv) {
continue;
}

if (!strcmp(argv[i], "-x")) {
opt_x = parse_opt_x(argv[++i]);
continue;
}

if (!strncmp(argv[i], "-x", 2)) {
opt_x = parse_opt_x(argv[i] + 2);
continue;
}

if (!strcmp(argv[i], "-cc1-input")) {
base_file = argv[++i];
continue;
Expand Down Expand Up @@ -434,6 +457,21 @@ static void run_linker(StringArray *inputs, char *output) {
run_subprocess(arr.data);
}

static FileType get_file_type(char *filename) {
if (endswith(filename, ".o"))
return FILE_OBJ;

if (opt_x != FILE_NONE)
return opt_x;

if (endswith(filename, ".c"))
return FILE_C;
if (endswith(filename, ".s"))
return FILE_ASM;

error("<command line>: unknown file extension: %s", filename);
}

int main(int argc, char **argv) {
atexit(cleanup);
init_macros();
Expand Down Expand Up @@ -461,22 +499,22 @@ int main(int argc, char **argv) {
else
output = replace_extn(input, ".o");

FileType type = get_file_type(input);

// Handle .o
if (endswith(input, ".o")) {
if (type == FILE_OBJ) {
strarray_push(&ld_args, input);
continue;
}

// Handle .s
if (endswith(input, ".s")) {
if (type == FILE_ASM) {
if (!opt_S)
assemble(input, output);
continue;
}

// Handle .c
if (!endswith(input, ".c") && strcmp(input, "-"))
error("unknown file extension: %s", input);
assert(type == FILE_C);

// Just preprocess
if (opt_E) {
Expand Down
66 changes: 38 additions & 28 deletions test/driver.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ $chibicc --help 2>&1 | grep -q chibicc
check --help

# -S
echo 'int main() {}' | $chibicc -S -o - - | grep -q 'main:'
echo 'int main() {}' | $chibicc -S -o- -xc - | grep -q 'main:'
check -S

# Default output file
Expand Down Expand Up @@ -56,7 +56,7 @@ check 'multiple input files'

# Run linker
rm -f $tmp/foo
echo 'int main() { return 0; }' | $chibicc -o $tmp/foo -
echo 'int main() { return 0; }' | $chibicc -o $tmp/foo -xc -xc -
$tmp/foo
check linker

Expand All @@ -77,30 +77,30 @@ check a.out

# -E
echo foo > $tmp/out
echo "#include \"$tmp/out\"" | $chibicc -E - | grep -q foo
echo "#include \"$tmp/out\"" | $chibicc -E -xc - | grep -q foo
check -E

echo foo > $tmp/out1
echo "#include \"$tmp/out1\"" | $chibicc -E -o $tmp/out2 -
echo "#include \"$tmp/out1\"" | $chibicc -E -o $tmp/out2 -xc -
cat $tmp/out2 | grep -q foo
check '-E and -o'

# -I
mkdir $tmp/dir
echo foo > $tmp/dir/i-option-test
echo "#include \"i-option-test\"" | $chibicc -I$tmp/dir -E - | grep -q foo
echo "#include \"i-option-test\"" | $chibicc -I$tmp/dir -E -xc - | grep -q foo
check -I

# -D
echo foo | $chibicc -Dfoo -E - | grep -q 1
echo foo | $chibicc -Dfoo -E -xc - | grep -q 1
check -D

# -D
echo foo | $chibicc -Dfoo=bar -E - | grep -q bar
echo foo | $chibicc -Dfoo=bar -E -xc - | grep -q bar
check -D

# -U
echo foo | $chibicc -Dfoo=bar -Ufoo -E - | grep -q foo
echo foo | $chibicc -Dfoo=bar -Ufoo -E -xc - | grep -q foo
check -U

# ignored options
Expand All @@ -110,7 +110,7 @@ $chibicc -c -O -Wall -g -std=c11 -ffreestanding -fno-builtin \
check 'ignored options'

# BOM marker
printf '\xef\xbb\xbfxyz\n' | $chibicc -E -o- - | grep -q '^xyz'
printf '\xef\xbb\xbfxyz\n' | $chibicc -E -o- -xc - | grep -q '^xyz'
check 'BOM marker'

# Inline functions
Expand All @@ -125,67 +125,77 @@ echo 'int foo(); int main() { foo(); }' > $tmp/inline2.c
$chibicc -o /dev/null $tmp/inline1.c $tmp/inline2.c
check inline

echo 'static inline void f1() {}' | $chibicc -o- -S - | grep -v -q f1:
echo 'static inline void f1() {}' | $chibicc -o- -S -xc - | grep -v -q f1:
check inline

echo 'static inline void f1() {} void foo() { f1(); }' | $chibicc -o- -S - | grep -q f1:
echo 'static inline void f1() {} void foo() { f1(); }' | $chibicc -o- -S -xc - | grep -q f1:
check inline

echo 'static inline void f1() {} static inline void f2() { f1(); } void foo() { f1(); }' | $chibicc -o- -S - | grep -q f1:
echo 'static inline void f1() {} static inline void f2() { f1(); } void foo() { f1(); }' | $chibicc -o- -S -xc - | grep -q f1:
check inline

echo 'static inline void f1() {} static inline void f2() { f1(); } void foo() { f1(); }' | $chibicc -o- -S - | grep -v -q f2:
echo 'static inline void f1() {} static inline void f2() { f1(); } void foo() { f1(); }' | $chibicc -o- -S -xc - | grep -v -q f2:
check inline

echo 'static inline void f1() {} static inline void f2() { f1(); } void foo() { f2(); }' | $chibicc -o- -S - | grep -q f1:
echo 'static inline void f1() {} static inline void f2() { f1(); } void foo() { f2(); }' | $chibicc -o- -S -xc - | grep -q f1:
check inline

echo 'static inline void f1() {} static inline void f2() { f1(); } void foo() { f2(); }' | $chibicc -o- -S - | grep -q f2:
echo 'static inline void f1() {} static inline void f2() { f1(); } void foo() { f2(); }' | $chibicc -o- -S -xc - | grep -q f2:
check inline

echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() {}' | $chibicc -o- -S - | grep -v -q f1:
echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() {}' | $chibicc -o- -S -xc - | grep -v -q f1:
check inline

echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() {}' | $chibicc -o- -S - | grep -v -q f2:
echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() {}' | $chibicc -o- -S -xc - | grep -v -q f2:
check inline

echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() { f1(); }' | $chibicc -o- -S - | grep -q f1:
echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() { f1(); }' | $chibicc -o- -S -xc - | grep -q f1:
check inline

echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() { f1(); }' | $chibicc -o- -S - | grep -q f2:
echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() { f1(); }' | $chibicc -o- -S -xc - | grep -q f2:
check inline

echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() { f2(); }' | $chibicc -o- -S - | grep -q f1:
echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() { f2(); }' | $chibicc -o- -S -xc - | grep -q f1:
check inline

echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() { f2(); }' | $chibicc -o- -S - | grep -q f2:
echo 'static inline void f2(); static inline void f1() { f2(); } static inline void f2() { f1(); } void foo() { f2(); }' | $chibicc -o- -S -xc - | grep -q f2:
check inline

# -idirafter
mkdir -p $tmp/dir1 $tmp/dir2
echo foo > $tmp/dir1/idirafter
echo bar > $tmp/dir2/idirafter
echo "#include \"idirafter\"" | $chibicc -I$tmp/dir1 -I$tmp/dir2 -E - | grep -q foo
echo "#include \"idirafter\"" | $chibicc -I$tmp/dir1 -I$tmp/dir2 -E -xc - | grep -q foo
check -idirafter
echo "#include \"idirafter\"" | $chibicc -idirafter $tmp/dir1 -I$tmp/dir2 -E - | grep -q bar
echo "#include \"idirafter\"" | $chibicc -idirafter $tmp/dir1 -I$tmp/dir2 -E -xc - | grep -q bar
check -idirafter

# -fcommon
echo 'int foo;' | $chibicc -S -o- - | grep -q '\.comm foo'
echo 'int foo;' | $chibicc -S -o- -xc - | grep -q '\.comm foo'
check '-fcommon (default)'

echo 'int foo;' | $chibicc -fcommon -S -o- - | grep -q '\.comm foo'
echo 'int foo;' | $chibicc -fcommon -S -o- -xc - | grep -q '\.comm foo'
check '-fcommon'

# -fno-common
echo 'int foo;' | $chibicc -fno-common -S -o- - | grep -q '^foo:'
echo 'int foo;' | $chibicc -fno-common -S -o- -xc - | grep -q '^foo:'
check '-fno-common'

# -include
echo foo > $tmp/out.h
echo bar | $chibicc -include $tmp/out.h -E -o- - | grep -q -z 'foo.*bar'
echo bar | $chibicc -include $tmp/out.h -E -o- -xc - | grep -q -z 'foo.*bar'
check -include
echo NULL | $chibicc -Iinclude -include stdio.h -E -o- - | grep -q 0
echo NULL | $chibicc -Iinclude -include stdio.h -E -o- -xc - | grep -q 0
check -include

# -x
echo 'int x;' | $chibicc -c -xc -o $tmp/foo.o -
check -xc
echo 'x:' | $chibicc -c -x assembler -o $tmp/foo.o -
check '-x assembler'

echo 'int x;' > $tmp/foo.c
$chibicc -c -x assembler -x none -o $tmp/foo.o $tmp/foo.c
check '-x none'

echo OK

0 comments on commit ee0a951

Please sign in to comment.