diff --git a/README.md b/README.md index df3d8b5..1bb405e 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ > `scc` -这是一个简单的C语言编译器,可以从C99子集编程语言生成可执行代码。该语言支持基本操作,如算术运算、逻辑运算、条件语句(if/else)、循环语句(while/for)、分支语句(switch/case)、函数调用以及内联汇编调用(asm)。 +这是一个简单的C语言裸机环境的自举编译器,可以从C99子集编程语言生成可执行代码。该语言支持基本操作,如算术运算、逻辑运算、条件语句(if/else)、循环语句(while/for)、分支语句(switch/case)、函数调用以及内联汇编调用(asm)。 ## Builder diff --git a/justfile b/justfile index 3d57fc0..e8fa9db 100644 --- a/justfile +++ b/justfile @@ -19,10 +19,10 @@ clean: cbuild clean build: - cbuild build -cclang + cbuild build -cclang --dev build-install: build - cp ./build/dev/scc.exe ./scc.exe + cp ./build/dev/scc ./scc test-scc: # windows: (Get-Content a.txt -Raw) -replace '\x1b\[[0-9;]*[a-zA-Z]', '' | Set-Content clean.txt diff --git a/libs/ast/include/ast_def.h b/libs/ast/include/ast_def.h index c51e14a..cb3bf78 100644 --- a/libs/ast/include/ast_def.h +++ b/libs/ast/include/ast_def.h @@ -8,6 +8,7 @@ * @brief AST 节点类型枚举 */ typedef enum { + SCC_AST_UNKNOWN, // 声明 scc_ast_decl_t_BEGIN, // 声明开始 SCC_AST_DECL_VAR, // 变量声明 diff --git a/libs/sstream/include/scc_pos_log.h b/libs/sstream/include/scc_pos_log.h index fd9ae2c..ddaa514 100644 --- a/libs/sstream/include/scc_pos_log.h +++ b/libs/sstream/include/scc_pos_log.h @@ -10,7 +10,7 @@ extern logger_t __scc_usr_log; do { \ char _full_msg[LOGGER_MAX_BUF_SIZE]; \ int _n = snprintf_(_full_msg, sizeof(_full_msg), \ - "%s:%lu:%lu: ", (pos).name, (pos).line, (pos).col); \ + "%s:%u:%u: ", (pos).name, (pos).line, (pos).col); \ snprintf_(_full_msg + _n, sizeof(_full_msg) - _n, fmt, ##__VA_ARGS__); \ __scc_usr_log.handler(&__scc_usr_log, level, null, 0, null, "%s", \ _full_msg); \ diff --git a/runtime/scc_core/src/cfg.bale_metal.c b/runtime/scc_core/src/cfg.bale_metal.c index e69de29..8b13789 100644 --- a/runtime/scc_core/src/cfg.bale_metal.c +++ b/runtime/scc_core/src/cfg.bale_metal.c @@ -0,0 +1 @@ + diff --git a/src/main.c b/src/main.c index 6994624..b633ceb 100644 --- a/src/main.c +++ b/src/main.c @@ -36,7 +36,8 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, static const char *scc_hints_en[] = { [SCC_HINT_PROG_NAME] = "scc", [SCC_HINT_DESCRIPTION] = "A simple C compiler", - [SCC_HINT_OUTPUT_FILE] = "Output file", + [SCC_HINT_OUTPUT_FILE] = + "Output file (`-` means standard output stream file)", [SCC_HINT_INPUT_FILE] = "Input source file", [SCC_HINT_INCLUDE_PATH] = "Add directory to the include search paths", [SCC_HINT_VERBOSE] = "Increase verbosity (can be used multiple times)", @@ -48,7 +49,7 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config, static const char *scc_hints_zh[] = { [SCC_HINT_PROG_NAME] = "scc", [SCC_HINT_DESCRIPTION] = "一个简单的C编译器", - [SCC_HINT_OUTPUT_FILE] = "输出文件", + [SCC_HINT_OUTPUT_FILE] = "输出文件(`-`表示标准输出流文件)", [SCC_HINT_INPUT_FILE] = "输入源文件", [SCC_HINT_INCLUDE_PATH] = "添加系统头文件到搜索路径", [SCC_HINT_VERBOSE] = "增加详细输出(可多次使用)", @@ -147,10 +148,11 @@ static void print_ring(scc_lexer_tok_ring_t *ring, int verbose) { if (verbose == 0) { scc_printf("%s ", scc_get_tok_name(tok.type)); } else if (verbose >= 1) { - scc_printf("token [%-8s] `%s` at %s:%d:%d\n", - scc_get_tok_name(tok.type), - scc_cstring_as_cstr(&tok.lexeme), tok.loc.name, - tok.loc.line, tok.loc.col); + scc_printf( + "token [%-8s] `%s` at %s:%d:%d\n", scc_get_tok_name(tok.type), + tok.type != SCC_TOK_ENDLINE ? scc_cstring_as_cstr(&tok.lexeme) + : "\\n", + tok.loc.name, tok.loc.line, tok.loc.col); } scc_lexer_tok_drop(&tok); } @@ -159,20 +161,28 @@ static void print_ring(scc_lexer_tok_ring_t *ring, int verbose) { static void print_file(scc_lexer_tok_ring_t *ring, const char *file_name) { scc_lexer_tok_t tok = {0}; int ret = 0; - scc_file_t fp = scc_fopen(file_name, SCC_FILE_WRITE); - if (fp == null) { - LOG_FATAL("Failed to open file %s", file_name); - return; + scc_file_t fp = null; + cbool is_stdout = scc_strcmp(file_name, "-") == 0; + if (!is_stdout) { + fp = scc_fopen(file_name, SCC_FILE_WRITE); + if (fp == null) { + LOG_FATAL("Failed to open file %s", file_name); + return; + } } while (1) { scc_ring_next_consume(*ring, tok, ret); if (ret == false || tok.type == SCC_TOK_EOF) { break; } - usize ret = scc_fwrite(fp, scc_cstring_as_cstr(&tok.lexeme), - scc_cstring_len(&tok.lexeme)); - if (ret != scc_cstring_len(&tok.lexeme)) { - LOG_FATAL("Failed to write to file %s", file_name); + if (is_stdout) { + scc_printf("%s", scc_cstring_as_cstr(&tok.lexeme)); + } else { + usize ret = scc_fwrite(fp, scc_cstring_as_cstr(&tok.lexeme), + scc_cstring_len(&tok.lexeme)); + if (ret != scc_cstring_len(&tok.lexeme)) { + LOG_FATAL("Failed to write to file %s", file_name); + } } scc_lexer_tok_drop(&tok); } @@ -190,6 +200,13 @@ int main(int argc, const char **argv, const char **envp) { #else #define OUTPUT_DEFAULT_FILE "a.out" #endif + scc_argparse_lang_t argparse_lang = SCC_ARGPARSE_LANG_EN; + for (const char **env = envp; *env != null; env++) { + const char *env_str = *env; + if (scc_strcmp(env_str, "LANG=zh_CN.UTF-8") == 0) { + argparse_lang = SCC_ARGPARSE_LANG_ZH; + } + } scc_config_t config = { .input_file = null, @@ -201,11 +218,11 @@ int main(int argc, const char **argv, const char **envp) { scc_vec_init(config.include_paths); scc_argparse_t argparse; - setup_argparse(&argparse, &config, SCC_ARGPARSE_LANG_ZH); + setup_argparse(&argparse, &config, argparse_lang); int ret = scc_argparse_parse(&argparse, argc, argv); if (ret != 0) { scc_argparse_drop(&argparse); - return ret; + return 0; } scc_argparse_drop(&argparse); diff --git a/tests/simple/12_include.c b/tests/simple/12_include.c new file mode 100644 index 0000000..667cde3 --- /dev/null +++ b/tests/simple/12_include.c @@ -0,0 +1,6 @@ +#include + +int main(void) { + printf("hello world"); + return 0; +} \ No newline at end of file diff --git a/tools/cbuild/cbuild.py b/tools/cbuild/cbuild.py index 0a58573..43d06be 100644 --- a/tools/cbuild/cbuild.py +++ b/tools/cbuild/cbuild.py @@ -692,7 +692,15 @@ class SccCompiler(Compiler): self, source: Path, output: Path, includes: list[Path], flags: list[str] ): # cmd = ["clang"] + flags + ["-c", str(source), "-o", str(output)] - cmd = ["scc", "--emit-pp", "-o", str(output), str(source), "-I", "scc_libs"] + cmd = [ + "scc", + "--emit-pp", + "-o", + str(output), + str(source), + "-I", + "scc_include", + ] for inc in includes: cmd += ["-I", f"{inc}"] self.run(cmd)