From 8cbb9e698762100bf797f77a78a9d838b8c56820 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Sun, 1 Mar 2026 12:16:23 +0800 Subject: [PATCH] =?UTF-8?q?feat(pproc):=20=E6=B7=BB=E5=8A=A0=E5=AE=8F?= =?UTF-8?q?=E5=AE=9A=E4=B9=89=E7=A6=81=E7=94=A8=E6=9C=BA=E5=88=B6=E5=92=8C?= =?UTF-8?q?defined=E6=93=8D=E4=BD=9C=E7=AC=A6=E8=A7=A3=E6=9E=90=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加SCC_TOK_DISABLED标记类型用于表示被禁用的token 实现disable/enable/need_skip函数来管理宏展开过程中的递归控制 重构defined操作符解析逻辑到独立的parse_defined函数中 移除原有的need_rescan标志和相关重扫描逻辑 fix(sstream): 修复位置日志中行列号格式化问题 将snprintf格式字符串中的%u替换为%llu以支持更大的行列数值 test(pproc): 补充宏定义相关的单元测试用例 添加嵌套宏、自引用宏和无参数宏的测试用例 --- libs/lexer/include/scc_lexer_token.h | 1 + libs/pproc/src/pproc_expand.c | 150 +++++++++++++++------------ libs/pproc/tests/test_pproc_unit.c | 14 ++- libs/sstream/include/scc_pos_log.h | 5 +- 4 files changed, 100 insertions(+), 70 deletions(-) diff --git a/libs/lexer/include/scc_lexer_token.h b/libs/lexer/include/scc_lexer_token.h index c6dd8f9..b4cb458 100644 --- a/libs/lexer/include/scc_lexer_token.h +++ b/libs/lexer/include/scc_lexer_token.h @@ -84,6 +84,7 @@ typedef enum scc_cstd { #define SCC_CTOK_TABLE \ X(unknown , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_UNKNOWN ) \ + X(disabled , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_DISABLED ) \ X(EOF , SCC_TOK_SUBTYPE_EOF, SCC_TOK_EOF ) \ X(blank , SCC_TOK_SUBTYPE_EMPTYSPACE, SCC_TOK_BLANK ) \ X(endline , SCC_TOK_SUBTYPE_EMPTYSPACE, SCC_TOK_ENDLINE ) \ diff --git a/libs/pproc/src/pproc_expand.c b/libs/pproc/src/pproc_expand.c index 37814ef..a9523c5 100644 --- a/libs/pproc/src/pproc_expand.c +++ b/libs/pproc/src/pproc_expand.c @@ -128,6 +128,27 @@ void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table, scc_pproc_macro_table_drop(ctx.expanded_set); } +static void disable(scc_pproc_expand_t *expand_ctx, + const scc_pproc_macro_t *macro) { + scc_pproc_macro_t *expanded_macro = + scc_pproc_macro_new(¯o->name, macro->type); + if (expanded_macro == null) { + LOG_FATAL("Out of memory"); + } + scc_pproc_macro_table_set(expand_ctx->expanded_set, expanded_macro); +} + +static void enable(scc_pproc_expand_t *expand_ctx, + const scc_pproc_macro_t *macro) { + scc_pproc_macro_table_remove(expand_ctx->expanded_set, ¯o->name); +} + +static cbool need_skip(scc_pproc_expand_t *expand_ctx, + const scc_pproc_macro_t *macro) { + return scc_pproc_macro_table_get(expand_ctx->expanded_set, ¯o->name) != + null; +} + static inline void split_arguments(scc_pproc_macro_extened_params_t *splited_params, scc_lexer_tok_vec_t *raw_args, const scc_pproc_macro_t *macro) { @@ -217,14 +238,10 @@ expanded_params_free(scc_pproc_macro_extened_params_t *expanded_params) { static void rescan(scc_pproc_expand_t *expand_ctx, const scc_pproc_macro_t *macro, scc_lexer_tok_vec_t *tok_buffer) { - scc_pproc_macro_t *expanded_macro = - scc_pproc_macro_new(¯o->name, macro->type); - if (expanded_macro == null) { - LOG_FATAL("Out of memory"); - } - scc_pproc_macro_table_set(expand_ctx->expanded_set, expanded_macro); - scc_pproc_expand_t rescan_ctx; + + disable(expand_ctx, macro); + scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(tok_buffer); scc_copy_expand(expand_ctx, &rescan_ctx, &ring); scc_pproc_expand_macro(&rescan_ctx); @@ -233,7 +250,7 @@ static void rescan(scc_pproc_expand_t *expand_ctx, scc_vec_push(expand_ctx->output, scc_vec_at(rescan_ctx.output, i)); } - scc_pproc_macro_table_remove(expand_ctx->expanded_set, ¯o->name); + enable(expand_ctx, macro); } static int find_params(const scc_lexer_tok_t *tok, @@ -246,7 +263,6 @@ 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; @@ -298,6 +314,7 @@ static void concact(scc_lexer_tok_vec_t *tok_buffer, scc_lexer_tok_t *right, 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; scc_vec_init(tok_buffer); @@ -447,6 +464,53 @@ static inline void expand_object_macro(scc_pproc_expand_t *expand_ctx, rescan(expand_ctx, macro, &tok_buffer); } +static cbool parse_defined(scc_pproc_expand_t *expand_ctx, scc_pos_t *tok_pos) { + scc_lexer_tok_t next_tok = {0}; + if (scc_lexer_next_non_blank(expand_ctx->input, &next_tok) == false) { + SCC_ERROR(*tok_pos, "Unexpected before defined EOF"); + } + if (next_tok.type == SCC_TOK_L_PAREN) { + scc_lexer_tok_drop(&next_tok); + scc_lexer_next_non_blank(expand_ctx->input, &next_tok); + if (scc_get_tok_subtype(next_tok.type) != SCC_TOK_SUBTYPE_IDENTIFIER) { + SCC_ERROR(next_tok.loc, "Expected identifier before defined"); + scc_lexer_tok_drop(&next_tok); + } + + if (scc_pproc_macro_table_get(expand_ctx->macro_table, + &next_tok.lexeme) == null) { + scc_lexer_tok_drop(&next_tok); + scc_lexer_gen_number_false(&next_tok); + } else { + scc_lexer_tok_drop(&next_tok); + scc_lexer_gen_number_true(&next_tok); + } + scc_vec_push(expand_ctx->output, next_tok); + + if (scc_lexer_next_non_blank(expand_ctx->input, &next_tok)) { + if (next_tok.type == SCC_TOK_R_PAREN) { + scc_lexer_tok_drop(&next_tok); + return false; + } else { + SCC_ERROR(next_tok.loc, "Expected ')'"); + scc_lexer_tok_drop(&next_tok); + } + } + } else if (scc_get_tok_subtype(next_tok.type) == + SCC_TOK_SUBTYPE_IDENTIFIER) { + if (scc_pproc_macro_table_get(expand_ctx->macro_table, + &next_tok.lexeme) == null) { + scc_lexer_tok_drop(&next_tok); + scc_lexer_gen_number_false(&next_tok); + } else { + scc_lexer_tok_drop(&next_tok); + scc_lexer_gen_number_true(&next_tok); + } + scc_vec_push(expand_ctx->output, next_tok); + } + return true; +} + void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) { int ok; scc_lexer_tok_t tok; @@ -462,60 +526,24 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) { if (expand_ctx->need_parse_defined && scc_strcmp(scc_cstring_as_cstr(&tok.lexeme), "defined") == 0) { - scc_lexer_tok_t next_tok = {0}; - if (scc_lexer_next_non_blank(expand_ctx->input, &next_tok) == - false) { - SCC_ERROR(tok.loc, "Unexpected before defined EOF"); - scc_lexer_tok_drop(&tok); - } + scc_pos_t pos = tok.loc; scc_lexer_tok_drop(&tok); - if (next_tok.type == SCC_TOK_L_PAREN) { - scc_lexer_tok_drop(&next_tok); - scc_lexer_next_non_blank(expand_ctx->input, &next_tok); - if (scc_get_tok_subtype(next_tok.type) != - SCC_TOK_SUBTYPE_IDENTIFIER) { - SCC_ERROR(next_tok.loc, - "Expected identifier before defined"); - scc_lexer_tok_drop(&next_tok); - } - - if (scc_pproc_macro_table_get(expand_ctx->macro_table, - &next_tok.lexeme) == null) { - scc_lexer_gen_number_false(&tok); - } else { - scc_lexer_gen_number_true(&tok); - } - scc_lexer_tok_drop(&next_tok); - scc_vec_push(expand_ctx->output, tok); - - if (scc_lexer_next_non_blank(expand_ctx->input, &next_tok)) { - if (next_tok.type == SCC_TOK_R_PAREN) { - scc_lexer_tok_drop(&next_tok); - break; - } else { - SCC_ERROR(next_tok.loc, "Expected ')'"); - scc_lexer_tok_drop(&next_tok); - } - } - } else if (scc_get_tok_subtype(next_tok.type) == - SCC_TOK_SUBTYPE_IDENTIFIER) { - if (scc_pproc_macro_table_get(expand_ctx->macro_table, - &next_tok.lexeme) == null) { - scc_lexer_gen_number_false(&tok); - } else { - scc_lexer_gen_number_true(&tok); - } - scc_lexer_tok_drop(&next_tok); - scc_vec_push(expand_ctx->output, tok); + if (parse_defined(expand_ctx, &pos)) { + continue; + } else { + break; } - continue; } + // maybe expanded scc_pproc_macro_t *macro = scc_pproc_macro_table_get(expand_ctx->macro_table, &tok.lexeme); - if (macro == null || - scc_pproc_macro_table_get(expand_ctx->expanded_set, ¯o->name)) { + if (macro == null || need_skip(expand_ctx, macro)) { + Assert(tok.type == SCC_TOK_IDENT); + // FIXME maybe keyword is error or don't parse c keyword or number + // 这个地方不太清楚正确的原因 + tok.type = SCC_TOK_DISABLED; scc_vec_push(expand_ctx->output, tok); continue; } @@ -536,14 +564,4 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) { UNREACHABLE(); } } - if (expand_ctx->need_rescan) { - expand_ctx->need_rescan = false; - scc_pproc_expand_t rescan_ctx; - scc_lexer_tok_ring_t ring = - scc_lexer_array_to_ring(&expand_ctx->output); - scc_copy_expand(expand_ctx, &rescan_ctx, &ring); - scc_pproc_expand_macro(&rescan_ctx); - scc_ring_free(ring); - expand_ctx->output = rescan_ctx.output; - } } diff --git a/libs/pproc/tests/test_pproc_unit.c b/libs/pproc/tests/test_pproc_unit.c index a692df2..19d9296 100644 --- a/libs/pproc/tests/test_pproc_unit.c +++ b/libs/pproc/tests/test_pproc_unit.c @@ -151,8 +151,12 @@ static void test_define_nested_macros(void) { // CHECK_PP_OUTPUT_EXACT("#define str(x) # x\n" // "str()\n", // "\"\"\n"); + CHECK_PP_OUTPUT_EXACT("#define w 0,1\n" + "#define m(a) a(w)\n" + "m(f)\n", + "f(0,1)\n"); - TEST_CASE("TODO"); + TEST_CASE("self-reference"); CHECK_PP_OUTPUT_EXACT("#define x 1\n" "#define f(a) f(x * (a))\n" "f(0)\n" @@ -167,6 +171,11 @@ static void test_define_nested_macros(void) { "f(x(0) * (f(x(0) * (0))))\n" "f(x(0) * (f(x(0) * (x(0)))))\n" "f(x(0) * (f(x(0) * (a))))\n"); + + TEST_CASE("NO NAME"); + CHECK_PP_OUTPUT_EXACT("#define f() int\n" + "f()\n", + "int\n"); } static void test_undef_macros(void) { @@ -538,9 +547,10 @@ static void test_c99_docs(void) { "#define str(x) # x\n" "f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);\n" "g(x+(3,4)-w) | h 5) & m\n" - " (f)^m(m);\n" + " (f)^m(m);\n" "p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };\n" "char c[2][6] = { str(hello), str() };\n", + "f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1);\n" "f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1);\n" "int i[] = { 1, 23, 4, 5, };\n" diff --git a/libs/sstream/include/scc_pos_log.h b/libs/sstream/include/scc_pos_log.h index ddaa514..f3b1f61 100644 --- a/libs/sstream/include/scc_pos_log.h +++ b/libs/sstream/include/scc_pos_log.h @@ -9,8 +9,9 @@ extern logger_t __scc_usr_log; #define SCC_POS_LOG(level, pos, fmt, ...) \ do { \ char _full_msg[LOGGER_MAX_BUF_SIZE]; \ - int _n = snprintf_(_full_msg, sizeof(_full_msg), \ - "%s:%u:%u: ", (pos).name, (pos).line, (pos).col); \ + int _n = \ + snprintf_(_full_msg, sizeof(_full_msg), \ + "%s:%llu:%llu: ", (pos).name, (pos).line, (pos).col); \ snprintf_(_full_msg + _n, sizeof(_full_msg) - _n, fmt, ##__VA_ARGS__); \ __scc_usr_log.handler(&__scc_usr_log, level, null, 0, null, "%s", \ _full_msg); \