feat(pproc): 添加预处理器包含路径支持和改进头文件查找逻辑
添加了新的类型定义 scc_pproc_cstr_vec_t 用于存储包含路径, 并在 scc_pproc 结构中添加 include_paths 字段。实现改进的 switch_file_stack 函数,支持从当前目录、父目录和系统包含路径 中查找头文件,提供更完整的 #include 指令处理能力。 fix(core): 重命名环形缓冲区内联宏避免命名冲突 将 scc_ring_phys 宏重命名为 _scc_ring_phys,并添加其他相关 内部宏如 _scc_ring_cap、_scc_ring_head 等,以避免与外部接口 的命名冲突并提高代码清晰度。 refactor(main): 添加命令行包含路径选项并清理标准库引用 在命令行参数解析中添加 -I/--include 选项支持,允许用户指定 额外的头文件搜索路径。同时移除不必要的 stdio.h 引用并清理 一些调试相关的缓冲区设置。
This commit is contained in:
@@ -28,6 +28,7 @@ typedef struct {
|
|||||||
} scc_pproc_file_state_t;
|
} scc_pproc_file_state_t;
|
||||||
typedef SCC_VEC(scc_pproc_file_state_t *) scc_pproc_file_stack_t;
|
typedef SCC_VEC(scc_pproc_file_state_t *) scc_pproc_file_stack_t;
|
||||||
typedef SCC_VEC(scc_lexer_tok_ring_t *) scc_pproc_ring_vec_t;
|
typedef SCC_VEC(scc_lexer_tok_ring_t *) scc_pproc_ring_vec_t;
|
||||||
|
typedef SCC_VEC(scc_cstring_t) scc_pproc_cstr_vec_t;
|
||||||
|
|
||||||
typedef struct scc_pproc {
|
typedef struct scc_pproc {
|
||||||
scc_lexer_tok_ring_t *org_ring;
|
scc_lexer_tok_ring_t *org_ring;
|
||||||
@@ -36,6 +37,7 @@ typedef struct scc_pproc {
|
|||||||
scc_strpool_t strpool;
|
scc_strpool_t strpool;
|
||||||
int at_line_start;
|
int at_line_start;
|
||||||
|
|
||||||
|
scc_pproc_cstr_vec_t include_paths;
|
||||||
scc_pproc_macro_table_t macro_table;
|
scc_pproc_macro_table_t macro_table;
|
||||||
scc_pproc_if_stack_t if_stack;
|
scc_pproc_if_stack_t if_stack;
|
||||||
scc_pproc_file_stack_t file_stack;
|
scc_pproc_file_stack_t file_stack;
|
||||||
|
|||||||
@@ -1,11 +1,45 @@
|
|||||||
#include <pproc_expand.h>
|
#include <pproc_expand.h>
|
||||||
#include <scc_pproc.h>
|
#include <scc_pproc.h>
|
||||||
|
|
||||||
static int switch_file_stack(scc_pproc_t *pp, scc_cstring_t fname,
|
static int switch_file_stack(scc_pproc_t *pp, scc_cstring_t *fname,
|
||||||
int is_system) {
|
int is_system) {
|
||||||
|
scc_cstring_t fpath = scc_cstring_create();
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!is_system) {
|
||||||
|
const char parent[] = "/../";
|
||||||
|
// FIXME maybe it can eazy
|
||||||
|
const char *org_fname =
|
||||||
|
(((scc_sstream_t *)(((scc_lexer_t *)pp->org_ring->userdata)
|
||||||
|
->stream_ref->userdata))
|
||||||
|
->fname);
|
||||||
|
scc_cstring_append_cstr(&fpath, org_fname, scc_strlen(org_fname));
|
||||||
|
scc_cstring_append_cstr(&fpath, parent, scc_strlen(parent));
|
||||||
|
scc_cstring_append(&fpath, fname);
|
||||||
|
ret = scc_fexists(scc_cstring_as_cstr(&fpath));
|
||||||
|
if (ret == true) {
|
||||||
|
goto FOPEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* system default path and -I includes path */
|
||||||
|
scc_vec_foreach(pp->include_paths, i) {
|
||||||
|
scc_cstring_free(&fpath);
|
||||||
|
scc_cstring_t *syspath = &scc_vec_at(pp->include_paths, i);
|
||||||
|
scc_cstring_append(&fpath, syspath);
|
||||||
|
scc_cstring_append(&fpath, fname);
|
||||||
|
ret = scc_fexists(scc_cstring_as_cstr(&fpath));
|
||||||
|
if (ret == true) {
|
||||||
|
goto FOPEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG_ERROR("Include File %c%s%c Not Found", is_system ? '<' : '\"',
|
||||||
|
scc_cstring_as_cstr(fname), is_system ? '>' : '\"');
|
||||||
|
return -1;
|
||||||
|
FOPEN:
|
||||||
scc_pproc_file_state_t *file = scc_malloc(sizeof(scc_pproc_file_state_t));
|
scc_pproc_file_state_t *file = scc_malloc(sizeof(scc_pproc_file_state_t));
|
||||||
Assert(file != null);
|
Assert(file != null);
|
||||||
if (scc_sstream_init(&(file->sstream), fname.data, 1024)) {
|
if (scc_sstream_init(&(file->sstream), scc_cstring_as_cstr(&fpath), 1024)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
scc_lexer_init(&(file->lexer), scc_sstream_to_ring(&(file->sstream)));
|
scc_lexer_init(&(file->lexer), scc_sstream_to_ring(&(file->sstream)));
|
||||||
@@ -74,9 +108,10 @@ void scc_pproc_parse_include(scc_pproc_t *pp) {
|
|||||||
}
|
}
|
||||||
scc_cstring_free(&line);
|
scc_cstring_free(&line);
|
||||||
int is_system = includename[0] == '<';
|
int is_system = includename[0] == '<';
|
||||||
if (switch_file_stack(pp, fname, is_system)) {
|
if (switch_file_stack(pp, &fname, is_system)) {
|
||||||
goto ERROR;
|
// LOG_ERROR()
|
||||||
}
|
}
|
||||||
|
scc_cstring_free(&fname);
|
||||||
return;
|
return;
|
||||||
ERROR:
|
ERROR:
|
||||||
LOG_ERROR("Invalid include filename need \"FILENAME\" or <FILENAME>");
|
LOG_ERROR("Invalid include filename need \"FILENAME\" or <FILENAME>");
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ void scc_pproc_init(scc_pproc_t *pp, scc_lexer_tok_ring_t *input) {
|
|||||||
pp->cur_ring = pp->org_ring;
|
pp->cur_ring = pp->org_ring;
|
||||||
scc_ring_init(pp->expanded_ring, 0, 0, 0);
|
scc_ring_init(pp->expanded_ring, 0, 0, 0);
|
||||||
scc_pproc_marco_table_init(&pp->macro_table);
|
scc_pproc_marco_table_init(&pp->macro_table);
|
||||||
|
scc_vec_init(pp->include_paths);
|
||||||
scc_vec_init(pp->if_stack);
|
scc_vec_init(pp->if_stack);
|
||||||
scc_vec_init(pp->file_stack);
|
scc_vec_init(pp->file_stack);
|
||||||
pp->at_line_start = true;
|
pp->at_line_start = true;
|
||||||
|
|||||||
@@ -29,14 +29,20 @@
|
|||||||
|
|
||||||
// ==================== 内部辅助宏 (不直接使用) ====================
|
// ==================== 内部辅助宏 (不直接使用) ====================
|
||||||
|
|
||||||
#define scc_ring_phys(ring, idx) ((idx) % (ring).cap)
|
#define _scc_ring_phys(ring, idx) ((idx) % (ring).cap)
|
||||||
|
#define _scc_ring_cap(ring) ((ring).cap)
|
||||||
|
#define _scc_ring_head(ring) ((ring).head)
|
||||||
|
#define _scc_ring_probe(ring) ((ring).probe)
|
||||||
|
#define _scc_ring_tail(ring) ((ring).tail)
|
||||||
|
#define _scc_ring_size(ring) ((ring).tail - (ring).head)
|
||||||
|
#define _scc_ring_empty(ring) ((ring).head == (ring).tail)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 确保 probe 位置有数据可用 (尝试填充)
|
* @brief 确保 probe 位置有数据可用 (尝试填充)
|
||||||
* @param ring 环形缓冲区变量
|
* @param ring 环形缓冲区变量
|
||||||
* @param ok 变量名 (如 int ok_flag) ,宏会将其设置为 true 或 false
|
* @param ok 变量名 (如 int ok_flag) ,宏会将其设置为 true 或 false
|
||||||
*/
|
*/
|
||||||
#define scc_ring_ensure(ring, ok) \
|
#define _scc_ring_ensure(ring, ok) \
|
||||||
do { \
|
do { \
|
||||||
ok = 1; \
|
ok = 1; \
|
||||||
if ((ring).probe < (ring).tail) \
|
if ((ring).probe < (ring).tail) \
|
||||||
@@ -50,7 +56,7 @@
|
|||||||
ok = 0; /* 缓冲区满,无法填充 */ \
|
ok = 0; /* 缓冲区满,无法填充 */ \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
usize phys_tail = scc_ring_phys(ring, (ring).tail); \
|
usize phys_tail = _scc_ring_phys(ring, (ring).tail); \
|
||||||
if ((ring).fill == null || \
|
if ((ring).fill == null || \
|
||||||
!(ring).fill(&(ring).data[phys_tail], (ring).userdata)) { \
|
!(ring).fill(&(ring).data[phys_tail], (ring).userdata)) { \
|
||||||
ok = 0; \
|
ok = 0; \
|
||||||
@@ -110,14 +116,14 @@
|
|||||||
*/
|
*/
|
||||||
#define scc_ring_peek(ring, val, ok) \
|
#define scc_ring_peek(ring, val, ok) \
|
||||||
do { \
|
do { \
|
||||||
scc_ring_ensure(ring, ok); \
|
_scc_ring_ensure(ring, ok); \
|
||||||
if (!(ok)) \
|
if (!(ok)) \
|
||||||
break; \
|
break; \
|
||||||
if ((ring).probe >= (ring).tail) { \
|
if ((ring).probe >= (ring).tail) { \
|
||||||
ok = 0; \
|
ok = 0; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
usize _phys = scc_ring_phys(ring, (ring).probe); \
|
usize _phys = _scc_ring_phys(ring, (ring).probe); \
|
||||||
val = (ring).data[_phys]; \
|
val = (ring).data[_phys]; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
@@ -129,14 +135,14 @@
|
|||||||
*/
|
*/
|
||||||
#define scc_ring_next(ring, val, ok) \
|
#define scc_ring_next(ring, val, ok) \
|
||||||
do { \
|
do { \
|
||||||
scc_ring_ensure(ring, ok); \
|
_scc_ring_ensure(ring, ok); \
|
||||||
if (!(ok)) \
|
if (!(ok)) \
|
||||||
break; \
|
break; \
|
||||||
if ((ring).probe >= (ring).tail) { \
|
if ((ring).probe >= (ring).tail) { \
|
||||||
ok = 0; \
|
ok = 0; \
|
||||||
break; \
|
break; \
|
||||||
} \
|
} \
|
||||||
usize _phys = scc_ring_phys(ring, (ring).probe); \
|
usize _phys = _scc_ring_phys(ring, (ring).probe); \
|
||||||
val = (ring).data[_phys]; \
|
val = (ring).data[_phys]; \
|
||||||
(ring).probe++; \
|
(ring).probe++; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|||||||
10
src/main.c
10
src/main.c
@@ -7,8 +7,6 @@
|
|||||||
// #include <ir_dump.h>
|
// #include <ir_dump.h>
|
||||||
// #include <scc_ast2ir.h>
|
// #include <scc_ast2ir.h>
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *input_file;
|
const char *input_file;
|
||||||
const char *output_file;
|
const char *output_file;
|
||||||
@@ -26,6 +24,7 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
|
|||||||
SCC_HINT_DESCRIPTION,
|
SCC_HINT_DESCRIPTION,
|
||||||
SCC_HINT_OUTPUT_FILE,
|
SCC_HINT_OUTPUT_FILE,
|
||||||
SCC_HINT_INPUT_FILE,
|
SCC_HINT_INPUT_FILE,
|
||||||
|
SCC_HINT_INCLUDE_PATH,
|
||||||
SCC_HINT_VERBOSE,
|
SCC_HINT_VERBOSE,
|
||||||
|
|
||||||
SCC_HINT_EMIT_LEX,
|
SCC_HINT_EMIT_LEX,
|
||||||
@@ -38,6 +37,7 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
|
|||||||
[SCC_HINT_DESCRIPTION] = "A simple C compiler",
|
[SCC_HINT_DESCRIPTION] = "A simple C compiler",
|
||||||
[SCC_HINT_OUTPUT_FILE] = "Output file",
|
[SCC_HINT_OUTPUT_FILE] = "Output file",
|
||||||
[SCC_HINT_INPUT_FILE] = "Input source file",
|
[SCC_HINT_INPUT_FILE] = "Input source file",
|
||||||
|
[SCC_HINT_INCLUDE_PATH] = "SCC_HINT_INCLUDE_PATH",
|
||||||
[SCC_HINT_VERBOSE] = "Increase verbosity (can be used multiple times)",
|
[SCC_HINT_VERBOSE] = "Increase verbosity (can be used multiple times)",
|
||||||
[SCC_HINT_EMIT_LEX] = "Generate lexer sources tokens and exit",
|
[SCC_HINT_EMIT_LEX] = "Generate lexer sources tokens and exit",
|
||||||
[SCC_HINT_EMIT_PP] = "Generate preprocessed tokens and exit",
|
[SCC_HINT_EMIT_PP] = "Generate preprocessed tokens and exit",
|
||||||
@@ -49,6 +49,7 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
|
|||||||
[SCC_HINT_DESCRIPTION] = "一个简单的C编译器",
|
[SCC_HINT_DESCRIPTION] = "一个简单的C编译器",
|
||||||
[SCC_HINT_OUTPUT_FILE] = "输出文件",
|
[SCC_HINT_OUTPUT_FILE] = "输出文件",
|
||||||
[SCC_HINT_INPUT_FILE] = "输入源文件",
|
[SCC_HINT_INPUT_FILE] = "输入源文件",
|
||||||
|
[SCC_HINT_INCLUDE_PATH] = "SCC_HINT_INCLUDE_PATH",
|
||||||
[SCC_HINT_VERBOSE] = "增加详细输出(可多次使用)",
|
[SCC_HINT_VERBOSE] = "增加详细输出(可多次使用)",
|
||||||
[SCC_HINT_EMIT_LEX] = "生成`源代码的词法单元`并退出",
|
[SCC_HINT_EMIT_LEX] = "生成`源代码的词法单元`并退出",
|
||||||
[SCC_HINT_EMIT_PP] = "生成`预处理后的词法单元`并退出",
|
[SCC_HINT_EMIT_PP] = "生成`预处理后的词法单元`并退出",
|
||||||
@@ -88,6 +89,10 @@ static void setup_argparse(scc_argparse_t *argparse, scc_config_t *config,
|
|||||||
scc_argparse_spec_set_required(&arg_input.spec, true);
|
scc_argparse_spec_set_required(&arg_input.spec, true);
|
||||||
scc_argparse_cmd_add_arg(root, &arg_input);
|
scc_argparse_cmd_add_arg(root, &arg_input);
|
||||||
|
|
||||||
|
scc_argparse_opt_t opt_include;
|
||||||
|
scc_argparse_opt_init(&opt_include, 0, "include",
|
||||||
|
scc_hints[SCC_HINT_INCLUDE_PATH]);
|
||||||
|
|
||||||
// -v, --verbose (计数)
|
// -v, --verbose (计数)
|
||||||
scc_argparse_opt_t opt_verbose;
|
scc_argparse_opt_t opt_verbose;
|
||||||
scc_argparse_opt_init(&opt_verbose, 'V', "verbose",
|
scc_argparse_opt_init(&opt_verbose, 'V', "verbose",
|
||||||
@@ -175,7 +180,6 @@ int main(int argc, const char **argv, const char **envp) {
|
|||||||
SetConsoleOutputCP(CP_UTF8);
|
SetConsoleOutputCP(CP_UTF8);
|
||||||
SetConsoleCP(CP_UTF8);
|
SetConsoleCP(CP_UTF8);
|
||||||
#endif
|
#endif
|
||||||
setbuf(stdout, NULL);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define OUTPUT_DEFAULT_FILE "a.exe"
|
#define OUTPUT_DEFAULT_FILE "a.exe"
|
||||||
|
|||||||
Reference in New Issue
Block a user