refactor(pproc): 重构预处理器条件编译逻辑

- 提取条件判断逻辑到独立函数 scc_pproc_parse_if_need_skip
- 使用辅助函数 in_if, in_elif, in_else, in_endif 简化条件处理
- 添加宏 __SCC_PPROC_LOG_PNT 统一错误和警告处理逻辑
- 增加嵌套条件测试用例验证非活动状态下的正确行为
This commit is contained in:
zzy
2026-02-27 17:06:04 +08:00
parent 4e2176b7f0
commit 72ef3964ce
4 changed files with 152 additions and 110 deletions

View File

@@ -68,6 +68,7 @@ static inline void scc_pproc_add_include_path_cstr(scc_pproc_t *pp,
void scc_pproc_handle_directive(scc_pproc_t *pp);
cbool scc_pproc_parse_if_need_skip(scc_pproc_t *pp, scc_tok_type_t type);
cbool scc_pproc_parse_if_defined(scc_pproc_t *pp, scc_tok_type_t type,
const scc_lexer_tok_t *tok);
cbool scc_pproc_parse_if_condition(scc_pproc_t *pp, scc_tok_type_t type,

View File

@@ -251,28 +251,7 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) {
}
scc_tok_type_t type = keywords[ret].tok_type;
if (scc_vec_size(pp->if_stack) != 0) {
scc_pproc_if_t *top =
&scc_vec_at(pp->if_stack, scc_vec_size(pp->if_stack) - 1);
pp->enable = top->active;
}
// 非条件指令,且当前不活动时直接跳过整行
int is_conditional = 0;
switch (type) {
case SCC_PP_TOK_IFDEF:
case SCC_PP_TOK_IFNDEF:
case SCC_PP_TOK_ELIFDEF:
case SCC_PP_TOK_ELIFNDEF:
case SCC_PP_TOK_ELSE:
case SCC_PP_TOK_ENDIF:
case SCC_PP_TOK_IF:
case SCC_PP_TOK_ELIF:
is_conditional = 1;
break;
default:
break;
}
if (!is_conditional && !pp->enable) {
if (scc_pproc_parse_if_need_skip(pp, type)) {
scc_lexer_skip_until_newline(pp->cur_ring);
return;
}
@@ -361,34 +340,30 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) {
return;
}
case SCC_PP_TOK_LINE:
goto ERROR;
case SCC_PP_TOK_EMBED:
goto ERROR;
case SCC_PP_TOK_ERROR:
scc_lexer_tok_drop(&tok);
while (1) {
ok = scc_lexer_next_non_blank(pp->cur_ring, &tok);
if (tok.type == SCC_TOK_ENDLINE || ok == false) {
return;
#define __SCC_PPROC_LOG_PNT(func_name) \
do { \
scc_lexer_tok_drop(&tok); \
while (1) { \
ok = scc_lexer_next_non_blank(pp->cur_ring, &tok); \
if (tok.type == SCC_TOK_ENDLINE || ok == false) { \
return; \
} \
if (scc_get_tok_subtype(tok.type) == SCC_TOK_SUBTYPE_LITERAL) { \
func_name(tok.loc, "%s", scc_cstring_as_cstr(&tok.lexeme)); \
} \
scc_lexer_tok_drop(&tok); \
} \
return; \
} while (0)
case SCC_PP_TOK_ERROR: {
__SCC_PPROC_LOG_PNT(SCC_ERROR);
}
if (scc_get_tok_subtype(tok.type) == SCC_TOK_SUBTYPE_LITERAL) {
SCC_ERROR(tok.loc, "%s", scc_cstring_as_cstr(&tok.lexeme));
case SCC_PP_TOK_WARNING: {
__SCC_PPROC_LOG_PNT(SCC_WARN);
}
scc_lexer_tok_drop(&tok);
}
return;
case SCC_PP_TOK_WARNING:
scc_lexer_tok_drop(&tok);
while (1) {
ok = scc_lexer_next_non_blank(pp->cur_ring, &tok);
if (tok.type == SCC_TOK_ENDLINE || ok == false) {
return;
}
if (scc_get_tok_subtype(tok.type) == SCC_TOK_SUBTYPE_LITERAL) {
SCC_WARN(tok.loc, "%s", scc_cstring_as_cstr(&tok.lexeme));
}
scc_lexer_tok_drop(&tok);
}
return;
case SCC_PP_TOK_PRAGMA:
SCC_WARN(tok.loc, "pragma ignored");
scc_lexer_skip_until_newline(pp->cur_ring);

View File

@@ -1,6 +1,83 @@
#include <scc_lexer_utils.h>
#include <scc_pproc.h>
cbool scc_pproc_parse_if_need_skip(scc_pproc_t *pp, scc_tok_type_t type) {
if (pp->enable == true) {
return false;
}
if (scc_vec_size(pp->if_stack) == 0) {
return false;
}
scc_pproc_if_t *top =
&scc_vec_at(pp->if_stack, scc_vec_size(pp->if_stack) - 1);
pp->enable = top->active;
if ((type == SCC_PP_TOK_IF || type == SCC_PP_TOK_IFDEF ||
type == SCC_PP_TOK_IFNDEF || type == SCC_PP_TOK_ELIFDEF ||
type == SCC_PP_TOK_ELIFNDEF || type == SCC_PP_TOK_ELSE ||
type == SCC_PP_TOK_ELIF || type == SCC_PP_TOK_ENDIF)) {
return false;
}
return true;
}
static void in_if(scc_pproc_t *pp, cbool enable) {
scc_pproc_if_t new_if;
if (pp->enable) {
new_if.active = enable;
new_if.found_true = enable;
new_if.seen_else = false;
pp->enable = enable;
} else {
// to disable hole stack if we are in disabled state
new_if.active = false;
new_if.found_true = true;
new_if.seen_else = false;
}
scc_vec_push(pp->if_stack, new_if);
}
static void in_elif(scc_pproc_t *pp, scc_pproc_if_t *top, cbool enable) {
if (top->found_true) {
top->active = false;
} else {
if (enable) {
top->found_true = true;
}
top->active = enable;
}
pp->enable = top->active;
}
static void in_else(scc_pproc_t *pp, scc_pproc_if_t *top) {
if (top->found_true) {
top->active = false;
} else {
top->active = true;
top->found_true = true;
}
top->seen_else = true;
pp->enable = top->active;
}
static void in_endif(scc_pproc_t *pp) {
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 = true;
} else {
pp->enable =
scc_vec_at(pp->if_stack, scc_vec_size(pp->if_stack) - 1).active;
}
}
cbool scc_pproc_parse_if_defined(scc_pproc_t *pp, scc_tok_type_t type,
const scc_lexer_tok_t *tok) {
int defined = 0;
@@ -12,14 +89,7 @@ cbool scc_pproc_parse_if_defined(scc_pproc_t *pp, scc_tok_type_t 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;
in_if(pp, condition);
break;
}
case SCC_PP_TOK_ELIFDEF:
@@ -36,21 +106,7 @@ cbool scc_pproc_parse_if_defined(scc_pproc_t *pp, scc_tok_type_t type,
}
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;
in_elif(pp, top, condition);
break;
}
case SCC_PP_TOK_ELSE: {
@@ -64,31 +120,11 @@ cbool scc_pproc_parse_if_defined(scc_pproc_t *pp, scc_tok_type_t type,
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;
in_else(pp, top);
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;
}
in_endif(pp);
break;
}
default: {
@@ -129,12 +165,7 @@ cbool scc_pproc_parse_if_condition(scc_pproc_t *pp, scc_tok_type_t type,
// 根据指令类型更新条件编译栈
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;
in_if(pp, condition);
break;
}
case SCC_PP_TOK_ELIF: {
@@ -149,17 +180,7 @@ cbool scc_pproc_parse_if_condition(scc_pproc_t *pp, scc_tok_type_t type,
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;
in_elif(pp, top, condition);
break;
}
default:

View File

@@ -417,6 +417,50 @@ static void test_simple_number_conditional_if(void) {
" foo\n bar\n");
}
static void test_conditional_nested_inactive(void) {
TEST_CASE("nested conditional when outer inactive");
CHECK_PP_OUTPUT_EXACT("#ifdef NOT_DEFINED\n"
"#if 1\n"
"should not appear\n"
"#endif\n"
"#endif\n"
"after\n",
"after\n");
CHECK_PP_OUTPUT_EXACT("#define A\n"
"#ifdef A\n"
" #ifdef B\n"
" B defined\n"
" #else\n"
" B not defined\n"
" #endif\n"
"#else\n"
" A not defined\n"
"#endif\n",
" B not defined\n");
CHECK_PP_OUTPUT_EXACT("#undef A\n"
"#ifdef A\n"
" #ifdef B\n"
" B defined\n"
" #else\n"
" B not defined\n"
" #endif\n"
"#else\n"
" A not defined\n"
"#endif\n",
" A not defined\n");
CHECK_PP_OUTPUT_EXACT("#if 0\n"
"#ifdef X\n"
"X defined\n"
"#elifdef Y\n"
"Y defined\n"
"#else\n"
"none\n"
"#endif\n"
"#endif\n"
"end\n",
"end\n");
}
static void test_variadic_macros(void) {
TEST_CASE("variadic macros with __VA_ARGS__");
@@ -560,6 +604,7 @@ TEST_LIST = {
TEST_LIST_CASE(hard_test_define_func_macros),
TEST_LIST_CASE(test_conditional_ifdef),
TEST_LIST_CASE(test_simple_number_conditional_if),
TEST_LIST_CASE(test_conditional_nested_inactive),
TEST_LIST_CASE(test_variadic_macros),
TEST_LIST_CASE(test_gnu_comma_variadic_deletion),