feat(pproc): 改进宏处理器以支持括号嵌套和GNU扩展

- 实现了括号深度跟踪来正确分割带括号的宏参数
- 添加了对 GNU 扩展中 `##` 操作符逗号删除的支持
- 新增辅助函数 `got_left_non_blank` 和 `got_right_non_blank`
  来优化查找非空白 token 的逻辑
- 改进了错误消息以显示预期但得到的实际值类型

fix(pproc): 修复条件编译和包含文件路径的错误消息

- 在 `scc_pproc_parse_if_condition` 中改进错误消息格式
- 修复 `switch_file_stack` 函数中的日志字符串格式问题

test(pproc): 添加宏处理相关的单元测试

- 增加了连接操作符、嵌套宏、括号处理等测试用例
- 添加了 C99 标准示例和 GNU 变参宏删除逗号的测试
- 包含了复杂的宏展开场景测试

chore(justfile): 更新构建脚本添加调试目标

- 为 `test-scc` 目标添加了 `debug-scc` 调试版本
- 更新构建命令以支持开发模式

feat(cbuild): 添加 dry-run 模式和改进编译器参数

- 为编译器类添加 dry-run 功能,只打印命令不执行
- 改进 scc 编译器的包含路径处理逻辑
- 为命令行解析器添加 dry-run 参数选项

refactor(log): 重命名 static_assert 为 StaticAssert 避免冲突

- 为了避免与标准库冲突,将自定义 static_assert 重命名为 StaticAssert

style(scc_core): 移除未使用的预定义宏定义

- 删除了不再需要的基础类型前缀宏定义

fix(scc_core): 初始化 ring 测试中的未初始化变量

- 为测试函数中的字符变量添加初始化值避免未定义行为
This commit is contained in:
zzy
2026-02-21 23:53:44 +08:00
parent 3b2f68111e
commit 51869bf081
9 changed files with 272 additions and 112 deletions

View File

@@ -132,9 +132,16 @@ split_arguments(scc_pproc_macro_extened_params_t *splited_params,
(named_count > 0 &&
scc_vec_at(macro->params, named_count - 1).type == SCC_TOK_ELLIPSIS);
int depth = 0;
scc_vec_foreach(*raw_args, i) {
scc_lexer_tok_t *raw_arg = &scc_vec_at(*raw_args, i);
if (raw_arg->type != SCC_TOK_COMMA ||
if (raw_arg->type == SCC_TOK_L_PAREN) {
depth++;
} else if (raw_arg->type == SCC_TOK_R_PAREN) {
depth--;
}
if (depth != 0 || raw_arg->type != SCC_TOK_COMMA ||
(is_variadic && scc_vec_size(*splited_params) == named_count - 1)) {
if (scc_vec_size(arg) == 0 && raw_arg->type == SCC_TOK_BLANK) {
scc_lexer_tok_drop(raw_arg);
@@ -142,14 +149,15 @@ split_arguments(scc_pproc_macro_extened_params_t *splited_params,
scc_vec_push(arg, *raw_arg);
}
continue;
} else {
scc_lexer_tok_drop(raw_arg);
if (scc_vec_size(arg) &&
scc_vec_at(arg, scc_vec_size(arg) - 1).type == SCC_TOK_BLANK) {
scc_lexer_tok_drop(&scc_vec_pop(arg));
}
scc_vec_push(*splited_params, arg);
scc_vec_init(arg);
}
scc_lexer_tok_drop(raw_arg);
if (scc_vec_size(arg) &&
scc_vec_at(arg, scc_vec_size(arg) - 1).type == SCC_TOK_BLANK) {
scc_lexer_tok_drop(&scc_vec_pop(arg));
}
scc_vec_push(*splited_params, arg);
scc_vec_init(arg);
}
if (scc_vec_size(arg) &&
scc_vec_at(arg, scc_vec_size(arg) - 1).type == SCC_TOK_BLANK) {
@@ -231,6 +239,25 @@ static int find_params(const scc_lexer_tok_t *tok,
return -1;
}
static inline int got_left_non_blank(int i,
const scc_lexer_tok_vec_t *replaces) {
int left_idx = i - 1;
while (left_idx >= 0 &&
scc_vec_at(*replaces, left_idx).type == SCC_TOK_BLANK) {
left_idx--;
}
return left_idx;
}
static inline int got_right_non_blank(int i,
const scc_lexer_tok_vec_t *replaces) {
int right_idx = i + 1;
while (right_idx < (int)scc_vec_size(*replaces) &&
scc_vec_at(*replaces, right_idx).type == SCC_TOK_BLANK) {
right_idx++;
}
return right_idx;
}
static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
const scc_pproc_macro_t *macro) {
scc_lexer_tok_vec_t tok_buffer;
@@ -264,12 +291,7 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
if (tok.type == SCC_TOK_SHARP) {
// # stringify
scc_lexer_tok_drop(&tok);
int right_idx = i + 1;
while (right_idx < (int)macro->replaces.size &&
scc_vec_at(macro->replaces, right_idx).type ==
SCC_TOK_BLANK) {
right_idx++;
}
int right_idx = got_right_non_blank(i, &macro->replaces);
if (right_idx >= (int)macro->replaces.size) {
LOG_WARN("generate empty stringify");
scc_cstring_free(&tok.lexeme);
@@ -286,21 +308,10 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
continue;
} else if (tok.type == SCC_TOK_SHARP_SHARP) {
// ## contact
// 向左扫描找到上一个非空白 token
scc_lexer_tok_drop(&tok);
int left_idx = i - 1;
while (left_idx >= 0 &&
scc_vec_at(macro->replaces, left_idx).type ==
SCC_TOK_BLANK) {
left_idx--;
}
// 向右扫描找到下一个非空白 token
int right_idx = i + 1;
while (right_idx < (int)macro->replaces.size &&
scc_vec_at(macro->replaces, right_idx).type ==
SCC_TOK_BLANK) {
right_idx++;
}
int left_idx = got_left_non_blank(i, &macro->replaces);
int right_idx = got_right_non_blank(i, &macro->replaces);
if (left_idx < 0 || right_idx >= (int)macro->replaces.size) {
LOG_FATAL("Invalid ## operator");
}
@@ -308,13 +319,53 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
scc_lexer_tok_drop(&scc_vec_pop(tok_buffer));
}
int j;
j = find_params(&scc_vec_at(macro->replaces, left_idx), macro);
Assert(j != -1 && j < (int)scc_vec_size(splited_params));
scc_lexer_tok_vec_t left_vec = scc_vec_at(splited_params, j);
j = find_params(&scc_vec_at(macro->replaces, right_idx), macro);
Assert(j != -1 && j < (int)scc_vec_size(splited_params));
scc_lexer_tok_vec_t right_vec = scc_vec_at(splited_params, j);
scc_lexer_tok_t *left_tok = &scc_vec_at(macro->replaces, left_idx);
scc_lexer_tok_t *right_tok =
&scc_vec_at(macro->replaces, right_idx);
if (left_tok->type == SCC_TOK_COMMA &&
scc_strcmp(scc_cstring_as_cstr(&(right_tok->lexeme)),
"__VA_ARGS__") == 0) {
// GNU 扩展:处理逗号删除
int right_param_idx = find_params(right_tok, macro);
Assert(right_param_idx != -1);
scc_lexer_tok_vec_t right_vec =
scc_vec_at(expanded_params, right_param_idx);
if (scc_vec_size(right_vec) != 0) {
// 可变参数非空:输出逗号副本,然后输出右侧参数的展开
scc_lexer_tok_t comma_tok = scc_lexer_tok_copy(left_tok);
scc_vec_push(tok_buffer, comma_tok);
}
scc_vec_foreach(right_vec, k) {
scc_lexer_tok_t tok =
scc_lexer_tok_copy(&scc_vec_at(right_vec, k));
scc_vec_push(tok_buffer, tok);
}
i = right_idx;
continue;
}
int idx;
idx = find_params(left_tok, macro);
scc_lexer_tok_vec_t left_vec;
if (idx != -1) {
Assert(idx < (int)scc_vec_size(splited_params));
left_vec = scc_vec_at(splited_params, idx);
} else {
scc_vec_init(left_vec);
scc_vec_push(left_vec, scc_lexer_tok_copy(left_tok));
}
idx = find_params(right_tok, macro);
scc_lexer_tok_vec_t right_vec;
if (idx != -1) {
Assert(idx < (int)scc_vec_size(splited_params));
right_vec = scc_vec_at(splited_params, idx);
} else {
scc_vec_init(right_vec);
scc_vec_push(right_vec, scc_lexer_tok_copy(right_tok));
}
scc_lexer_tok_t *left =
scc_vec_size(left_vec)
? &scc_vec_at(left_vec, scc_vec_size(left_vec) - 1)
@@ -380,25 +431,16 @@ static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx,
tok.lexeme = scc_cstring_from_cstr(" ");
} else if (tok.type == SCC_TOK_SHARP_SHARP) {
// ## contact
// 向左扫描找到上一个非空白 token
int left_idx = i - 1;
while (left_idx >= 0 &&
scc_vec_at(macro->replaces, left_idx).type ==
SCC_TOK_BLANK) {
left_idx--;
}
// 向右扫描找到下一个非空白 token
int right_idx = i + 1;
while (right_idx < (int)macro->replaces.size &&
scc_vec_at(macro->replaces, right_idx).type ==
SCC_TOK_BLANK) {
right_idx++;
}
if (left_idx < 0 || right_idx >= (int)macro->replaces.size) {
int left_idx = got_left_non_blank(i, &macro->replaces);
int right_idx = got_right_non_blank(i, &macro->replaces);
if (left_idx < 0 ||
right_idx >= (int)scc_vec_size(macro->replaces)) {
LOG_FATAL("Invalid ## operator");
}
scc_lexer_tok_t *left = &scc_vec_at(macro->replaces, left_idx);
scc_lexer_tok_t *right = &scc_vec_at(macro->replaces, right_idx);
scc_lexer_tok_t concate_tok = concatenate_tokens(left, right);
while (i++ < right_idx) {
scc_lexer_tok_drop(&scc_vec_pop(tok_buffer));