- 实现了括号深度跟踪来正确分割带括号的宏参数 - 添加了对 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 测试中的未初始化变量 - 为测试函数中的字符变量添加初始化值避免未定义行为
174 lines
4.8 KiB
C
174 lines
4.8 KiB
C
#include <scc_lexer_utils.h>
|
|
#include <scc_pproc.h>
|
|
|
|
cbool scc_pproc_parse_if_defined(scc_pproc_t *pp, scc_tok_type_t type,
|
|
const scc_lexer_tok_t *tok) {
|
|
int defined = 0;
|
|
if (tok) {
|
|
defined = (scc_pproc_macro_table_get(&pp->macro_table,
|
|
&(tok->lexeme)) != null);
|
|
}
|
|
switch (type) {
|
|
case SCC_PP_TOK_IFDEF:
|
|
case SCC_PP_TOK_IFNDEF: {
|
|
cbool condition = (type == SCC_PP_TOK_IFDEF) ? defined : !defined;
|
|
|
|
scc_pproc_if_t new_if;
|
|
new_if.found_true = condition;
|
|
new_if.seen_else = 0;
|
|
new_if.active = pp->enable ? condition : 0;
|
|
scc_vec_push(pp->if_stack, new_if);
|
|
|
|
pp->enable = new_if.active;
|
|
break;
|
|
}
|
|
case SCC_PP_TOK_ELIFDEF:
|
|
case SCC_PP_TOK_ELIFNDEF: {
|
|
if (scc_vec_size(pp->if_stack) == 0) {
|
|
LOG_ERROR("#elif without #if");
|
|
return false;
|
|
}
|
|
scc_pproc_if_t *top =
|
|
&scc_vec_at(pp->if_stack, scc_vec_size(pp->if_stack) - 1);
|
|
if (top->seen_else) {
|
|
LOG_ERROR("#elif after #else");
|
|
return false;
|
|
}
|
|
|
|
int condition = (type == SCC_PP_TOK_ELIFDEF) ? defined : !defined;
|
|
|
|
if (top->found_true) {
|
|
// 前面已有真分支,本 elif 不激活
|
|
top->active = 0;
|
|
} else {
|
|
if (condition) {
|
|
top->active = 1;
|
|
top->found_true = 1;
|
|
} else {
|
|
top->active = 0;
|
|
}
|
|
}
|
|
|
|
// seen_else 仍为 0
|
|
pp->enable = top->active;
|
|
break;
|
|
}
|
|
case SCC_PP_TOK_ELSE: {
|
|
if (scc_vec_size(pp->if_stack) == 0) {
|
|
LOG_ERROR("#else without #if");
|
|
return false;
|
|
}
|
|
scc_pproc_if_t *top =
|
|
&scc_vec_at(pp->if_stack, scc_vec_size(pp->if_stack) - 1);
|
|
if (top->seen_else) {
|
|
LOG_ERROR("multiple #else");
|
|
return false;
|
|
}
|
|
|
|
if (top->found_true) {
|
|
top->active = 0;
|
|
} else {
|
|
top->active = 1;
|
|
top->found_true = 1;
|
|
}
|
|
|
|
top->seen_else = 1;
|
|
|
|
pp->enable = top->active;
|
|
break;
|
|
}
|
|
case SCC_PP_TOK_ENDIF: {
|
|
if (scc_vec_size(pp->if_stack) == 0) {
|
|
LOG_ERROR("#endif without #if");
|
|
} else {
|
|
scc_vec_pop(pp->if_stack);
|
|
}
|
|
if (scc_vec_size(pp->if_stack) == 0) {
|
|
pp->enable = 1;
|
|
} else {
|
|
pp->enable =
|
|
scc_vec_at(pp->if_stack, scc_vec_size(pp->if_stack) - 1).active;
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
LOG_FATAL("unexpected directive");
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static cbool parse_constant_condition() { return false; }
|
|
|
|
cbool scc_pproc_parse_if_condition(scc_pproc_t *pp, scc_tok_type_t type,
|
|
scc_lexer_tok_ring_t *tok_ring) {
|
|
// TODO
|
|
int ok;
|
|
scc_lexer_tok_t tok = {0};
|
|
ok = scc_lexer_next_non_blank(tok_ring, &tok);
|
|
if (ok == false) {
|
|
LOG_FATAL("unexpected EOF");
|
|
}
|
|
int condition = 0;
|
|
if (tok.type == SCC_TOK_INT_LITERAL) {
|
|
condition = scc_cstring_as_cstr(&tok.lexeme)[0] == '0' ? 0 : 1;
|
|
} else {
|
|
LOG_ERROR("expected integer constant but got %s",
|
|
scc_cstring_as_cstr(&tok.lexeme));
|
|
}
|
|
scc_lexer_tok_drop(&tok);
|
|
|
|
ok = scc_lexer_next_non_blank(tok_ring, &tok);
|
|
if (ok == false) {
|
|
LOG_FATAL("unexpected EOF");
|
|
}
|
|
if (tok.type != SCC_TOK_ENDLINE) {
|
|
LOG_ERROR("expected endline");
|
|
scc_lexer_skip_until_newline(tok_ring);
|
|
} else {
|
|
scc_lexer_tok_drop(&tok);
|
|
}
|
|
scc_ring_free(*tok_ring);
|
|
|
|
// 根据指令类型更新条件编译栈
|
|
switch (type) {
|
|
case SCC_PP_TOK_IF: {
|
|
scc_pproc_if_t new_if;
|
|
new_if.found_true = condition;
|
|
new_if.seen_else = 0;
|
|
new_if.active = pp->enable ? condition : 0;
|
|
scc_vec_push(pp->if_stack, new_if);
|
|
pp->enable = new_if.active;
|
|
break;
|
|
}
|
|
case SCC_PP_TOK_ELIF: {
|
|
if (scc_vec_size(pp->if_stack) == 0) {
|
|
LOG_ERROR("#elif without #if");
|
|
return false;
|
|
}
|
|
scc_pproc_if_t *top =
|
|
&scc_vec_at(pp->if_stack, scc_vec_size(pp->if_stack) - 1);
|
|
if (top->seen_else) {
|
|
LOG_ERROR("#elif after #else");
|
|
return false;
|
|
}
|
|
if (top->found_true) {
|
|
top->active = 0;
|
|
} else {
|
|
if (condition) {
|
|
top->active = 1;
|
|
top->found_true = 1;
|
|
} else {
|
|
top->active = 0;
|
|
}
|
|
}
|
|
pp->enable = top->active;
|
|
break;
|
|
}
|
|
default:
|
|
LOG_FATAL("unexpected directive in parse_if_condition");
|
|
}
|
|
return true;
|
|
return true;
|
|
}
|