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:
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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user