Add -x option

This commit is contained in:
Rui Ueyama 2020-09-19 21:43:35 +09:00
parent 8f5ff07dc0
commit ee0a951b30
2 changed files with 82 additions and 34 deletions

50
main.c
View File

@ -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;
@ -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]))
@ -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.
@ -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;
@ -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();
@ -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) {

View File

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