feat(pproc): 添加宏定义禁用机制和defined操作符解析功能
添加SCC_TOK_DISABLED标记类型用于表示被禁用的token 实现disable/enable/need_skip函数来管理宏展开过程中的递归控制 重构defined操作符解析逻辑到独立的parse_defined函数中 移除原有的need_rescan标志和相关重扫描逻辑 fix(sstream): 修复位置日志中行列号格式化问题 将snprintf格式字符串中的%u替换为%llu以支持更大的行列数值 test(pproc): 补充宏定义相关的单元测试用例 添加嵌套宏、自引用宏和无参数宏的测试用例
This commit is contained in:
@@ -84,6 +84,7 @@ typedef enum scc_cstd {
|
|||||||
|
|
||||||
#define SCC_CTOK_TABLE \
|
#define SCC_CTOK_TABLE \
|
||||||
X(unknown , SCC_TOK_SUBTYPE_INVALID, SCC_TOK_UNKNOWN ) \
|
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(EOF , SCC_TOK_SUBTYPE_EOF, SCC_TOK_EOF ) \
|
||||||
X(blank , SCC_TOK_SUBTYPE_EMPTYSPACE, SCC_TOK_BLANK ) \
|
X(blank , SCC_TOK_SUBTYPE_EMPTYSPACE, SCC_TOK_BLANK ) \
|
||||||
X(endline , SCC_TOK_SUBTYPE_EMPTYSPACE, SCC_TOK_ENDLINE ) \
|
X(endline , SCC_TOK_SUBTYPE_EMPTYSPACE, SCC_TOK_ENDLINE ) \
|
||||||
|
|||||||
@@ -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);
|
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
|
static inline void
|
||||||
split_arguments(scc_pproc_macro_extened_params_t *splited_params,
|
split_arguments(scc_pproc_macro_extened_params_t *splited_params,
|
||||||
scc_lexer_tok_vec_t *raw_args, const scc_pproc_macro_t *macro) {
|
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,
|
static void rescan(scc_pproc_expand_t *expand_ctx,
|
||||||
const scc_pproc_macro_t *macro,
|
const scc_pproc_macro_t *macro,
|
||||||
scc_lexer_tok_vec_t *tok_buffer) {
|
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;
|
scc_pproc_expand_t rescan_ctx;
|
||||||
|
|
||||||
|
disable(expand_ctx, macro);
|
||||||
|
|
||||||
scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(tok_buffer);
|
scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(tok_buffer);
|
||||||
scc_copy_expand(expand_ctx, &rescan_ctx, &ring);
|
scc_copy_expand(expand_ctx, &rescan_ctx, &ring);
|
||||||
scc_pproc_expand_macro(&rescan_ctx);
|
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_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,
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int got_left_non_blank(int i,
|
static inline int got_left_non_blank(int i,
|
||||||
const scc_lexer_tok_vec_t *replaces) {
|
const scc_lexer_tok_vec_t *replaces) {
|
||||||
int left_idx = i - 1;
|
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,
|
static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx,
|
||||||
const scc_pproc_macro_t *macro) {
|
const scc_pproc_macro_t *macro) {
|
||||||
|
|
||||||
scc_lexer_tok_vec_t tok_buffer;
|
scc_lexer_tok_vec_t tok_buffer;
|
||||||
scc_vec_init(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);
|
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) {
|
void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) {
|
||||||
int ok;
|
int ok;
|
||||||
scc_lexer_tok_t tok;
|
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 &&
|
if (expand_ctx->need_parse_defined &&
|
||||||
scc_strcmp(scc_cstring_as_cstr(&tok.lexeme), "defined") == 0) {
|
scc_strcmp(scc_cstring_as_cstr(&tok.lexeme), "defined") == 0) {
|
||||||
scc_lexer_tok_t next_tok = {0};
|
scc_pos_t pos = tok.loc;
|
||||||
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_lexer_tok_drop(&tok);
|
scc_lexer_tok_drop(&tok);
|
||||||
if (next_tok.type == SCC_TOK_L_PAREN) {
|
if (parse_defined(expand_ctx, &pos)) {
|
||||||
scc_lexer_tok_drop(&next_tok);
|
continue;
|
||||||
scc_lexer_next_non_blank(expand_ctx->input, &next_tok);
|
} else {
|
||||||
if (scc_get_tok_subtype(next_tok.type) !=
|
break;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// maybe expanded
|
// maybe expanded
|
||||||
scc_pproc_macro_t *macro =
|
scc_pproc_macro_t *macro =
|
||||||
scc_pproc_macro_table_get(expand_ctx->macro_table, &tok.lexeme);
|
scc_pproc_macro_table_get(expand_ctx->macro_table, &tok.lexeme);
|
||||||
|
|
||||||
if (macro == null ||
|
if (macro == null || need_skip(expand_ctx, macro)) {
|
||||||
scc_pproc_macro_table_get(expand_ctx->expanded_set, ¯o->name)) {
|
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);
|
scc_vec_push(expand_ctx->output, tok);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -536,14 +564,4 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) {
|
|||||||
UNREACHABLE();
|
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,8 +151,12 @@ static void test_define_nested_macros(void) {
|
|||||||
// CHECK_PP_OUTPUT_EXACT("#define str(x) # x\n"
|
// CHECK_PP_OUTPUT_EXACT("#define str(x) # x\n"
|
||||||
// "str()\n",
|
// "str()\n",
|
||||||
// "\"\"\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"
|
CHECK_PP_OUTPUT_EXACT("#define x 1\n"
|
||||||
"#define f(a) f(x * (a))\n"
|
"#define f(a) f(x * (a))\n"
|
||||||
"f(0)\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) * (0))))\n"
|
||||||
"f(x(0) * (f(x(0) * (x(0)))))\n"
|
"f(x(0) * (f(x(0) * (x(0)))))\n"
|
||||||
"f(x(0) * (f(x(0) * (a))))\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) {
|
static void test_undef_macros(void) {
|
||||||
@@ -538,9 +547,10 @@ static void test_c99_docs(void) {
|
|||||||
"#define str(x) # x\n"
|
"#define str(x) # x\n"
|
||||||
"f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);\n"
|
"f(y+1) + f(f(z)) % t(t(g)(0) + t)(1);\n"
|
||||||
"g(x+(3,4)-w) | h 5) & m\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"
|
"p() i[q()] = { q(1), r(2,3), r(4,), r(,5), r(,) };\n"
|
||||||
"char c[2][6] = { str(hello), str() };\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 * (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"
|
"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"
|
"int i[] = { 1, 23, 4, 5, };\n"
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ extern logger_t __scc_usr_log;
|
|||||||
#define SCC_POS_LOG(level, pos, fmt, ...) \
|
#define SCC_POS_LOG(level, pos, fmt, ...) \
|
||||||
do { \
|
do { \
|
||||||
char _full_msg[LOGGER_MAX_BUF_SIZE]; \
|
char _full_msg[LOGGER_MAX_BUF_SIZE]; \
|
||||||
int _n = snprintf_(_full_msg, sizeof(_full_msg), \
|
int _n = \
|
||||||
"%s:%u:%u: ", (pos).name, (pos).line, (pos).col); \
|
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__); \
|
snprintf_(_full_msg + _n, sizeof(_full_msg) - _n, fmt, ##__VA_ARGS__); \
|
||||||
__scc_usr_log.handler(&__scc_usr_log, level, null, 0, null, "%s", \
|
__scc_usr_log.handler(&__scc_usr_log, level, null, 0, null, "%s", \
|
||||||
_full_msg); \
|
_full_msg); \
|
||||||
|
|||||||
Reference in New Issue
Block a user