feat(compiler): 添加对裸机环境的支持并改进构建配置
- 更新README描述为C语言裸机环境的自举编译器 - 修改justfile中的构建命令,添加--dev参数并将输出文件名从scc.exe改为scc - 在AST定义中添加SCC_AST_UNKNOWN节点类型 - 修复位置日志格式化中的类型错误 - 实现标准输出流支持,当输出文件为'-'时输出到控制台 - 支持基于环境变量LANG的语言本地化选择 fix(lexer): 改进标记打印功能 - 修复换行符的显示,将实际换行符显示为"\n" - 改进文件输出逻辑,支持标准输出流 refactor(build): 更新cbuild工具的包含路径 - 将包含路径从"scc_libs"更改为"scc_include" test: 添加简单的包含测试用例 - 新增测试文件tests/simple/12_include.c用于测试头文件包含功能
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
> `scc`
|
||||
|
||||
这是一个简单的C语言编译器,可以从C99子集编程语言生成可执行代码。该语言支持基本操作,如算术运算、逻辑运算、条件语句(if/else)、循环语句(while/for)、分支语句(switch/case)、函数调用以及内联汇编调用(asm)。
|
||||
这是一个简单的C语言裸机环境的自举编译器,可以从C99子集编程语言生成可执行代码。该语言支持基本操作,如算术运算、逻辑运算、条件语句(if/else)、循环语句(while/for)、分支语句(switch/case)、函数调用以及内联汇编调用(asm)。
|
||||
|
||||
## Builder
|
||||
|
||||
|
||||
4
justfile
4
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
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* @brief AST 节点类型枚举
|
||||
*/
|
||||
typedef enum {
|
||||
SCC_AST_UNKNOWN,
|
||||
// 声明
|
||||
scc_ast_decl_t_BEGIN, // 声明开始
|
||||
SCC_AST_DECL_VAR, // 变量声明
|
||||
|
||||
@@ -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); \
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
|
||||
49
src/main.c
49
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);
|
||||
|
||||
|
||||
6
tests/simple/12_include.c
Normal file
6
tests/simple/12_include.c
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void) {
|
||||
printf("hello world");
|
||||
return 0;
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user