From 73d74f5e13895c1081c08dc37423d98c273262e2 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Sun, 14 Dec 2025 12:59:03 +0800 Subject: [PATCH] refactor(pprocessor): rename macro table type and update function names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Change `scc_macro_table_t` to `scc_pp_macro_table_t` for consistency - Rename `scc_pp_macro_create` to `scc_pp_macro_new` for naming convention - Remove unused `scc_pp_compress_whitespace` function - Update macro table function names: `scc_pp_find_macro` → `scc_pp_macro_table_get`, `scc_pp_remove_macro` → `scc_pp_macro_table_remove` - Add new `scc_pp_macro_table_set` function for setting macros - Update all function signatures to use new type name - Remove commented-out whitespace compression code from implementation --- libs/pprocessor/include/pp_macro.h | 37 ++++++----- libs/pprocessor/include/pp_parse.h | 6 +- libs/pprocessor/include/pp_token.h | 30 ++++----- libs/pprocessor/include/pprocessor.h | 2 +- libs/pprocessor/src/macro.c | 92 ++++++---------------------- libs/pprocessor/src/parse.c | 34 +++++++--- libs/pprocessor/src/pprocessor.c | 18 +++++- libs/pprocessor/tests/test_pp.c | 46 +++++++++----- libs/pprocessor/tests/test_unit.c | 38 ++++++++++++ 9 files changed, 172 insertions(+), 131 deletions(-) diff --git a/libs/pprocessor/include/pp_macro.h b/libs/pprocessor/include/pp_macro.h index 94baf8b..bdd4bd9 100644 --- a/libs/pprocessor/include/pp_macro.h +++ b/libs/pprocessor/include/pp_macro.h @@ -22,7 +22,7 @@ typedef struct scc_macro { typedef struct scc_macro_table { scc_hashtable_t table; // 宏定义表 -} scc_macro_table_t; +} scc_pp_macro_table_t; /** * @brief 创建宏对象 @@ -30,8 +30,8 @@ typedef struct scc_macro_table { * @param type 宏类型 * @return 创建的宏对象指针,失败返回NULL */ -scc_pp_macro_t *scc_pp_macro_create(const scc_cstring_t *name, - scc_pp_macro_type_t type); +scc_pp_macro_t *scc_pp_macro_new(const scc_cstring_t *name, + scc_pp_macro_type_t type); /** * @brief 销毁宏对象 @@ -39,13 +39,6 @@ scc_pp_macro_t *scc_pp_macro_create(const scc_cstring_t *name, */ void scc_pp_macro_drop(scc_pp_macro_t *macro); -/** - * @brief 压缩空白字符 - * @param tokens token列表 - * @return 压缩后的字符串 - */ -scc_cstring_t scc_pp_compress_whitespace(const scc_pp_macro_list_t *tokens); - /** * @brief 添加对象宏 * @param pp 预处理器实例 @@ -53,7 +46,8 @@ scc_cstring_t scc_pp_compress_whitespace(const scc_pp_macro_list_t *tokens); * @param replacement 替换文本列表 * @return 成功返回true,失败返回false */ -cbool scc_pp_add_object_macro(scc_macro_table_t *pp, const scc_cstring_t *name, +cbool scc_pp_add_object_macro(scc_pp_macro_table_t *pp, + const scc_cstring_t *name, const scc_pp_macro_list_t *replacement); /** @@ -64,10 +58,19 @@ cbool scc_pp_add_object_macro(scc_macro_table_t *pp, const scc_cstring_t *name, * @param replacement 替换文本列表 * @return 成功返回true,失败返回false */ -cbool scc_pp_add_function_macro(scc_macro_table_t *pp, +cbool scc_pp_add_function_macro(scc_pp_macro_table_t *pp, const scc_cstring_t *name, const scc_pp_macro_list_t *params, const scc_pp_macro_list_t *replacement); +/** + * @brief + * + * @param pp + * @param macro + * @return scc_pp_macro_t* + */ +scc_pp_macro_t *scc_pp_macro_table_set(scc_pp_macro_table_t *pp, + scc_pp_macro_t *macro); /** * @brief 查找宏定义 @@ -75,7 +78,8 @@ cbool scc_pp_add_function_macro(scc_macro_table_t *pp, * @param name 宏名称 * @return 找到的宏对象指针,未找到返回NULL */ -scc_pp_macro_t *scc_pp_find_macro(scc_macro_table_t *pp, scc_cstring_t *name); +scc_pp_macro_t *scc_pp_macro_table_get(scc_pp_macro_table_t *pp, + scc_cstring_t *name); /** * @brief 从预处理器中删除宏 @@ -83,8 +87,9 @@ scc_pp_macro_t *scc_pp_find_macro(scc_macro_table_t *pp, scc_cstring_t *name); * @param name 宏名称 * @return 成功删除返回true,未找到返回false */ -cbool scc_pp_remove_macro(scc_macro_table_t *pp, const scc_cstring_t *name); +cbool scc_pp_macro_table_remove(scc_pp_macro_table_t *pp, + const scc_cstring_t *name); -void scc_pp_marco_table_init(scc_macro_table_t *macros); -void scc_pp_macro_table_drop(scc_macro_table_t *macros); +void scc_pp_marco_table_init(scc_pp_macro_table_t *macros); +void scc_pp_macro_table_drop(scc_pp_macro_table_t *macros); #endif /* __SCC_PP_MACRO_H__ */ diff --git a/libs/pprocessor/include/pp_parse.h b/libs/pprocessor/include/pp_parse.h index f8232d0..684d873 100644 --- a/libs/pprocessor/include/pp_parse.h +++ b/libs/pprocessor/include/pp_parse.h @@ -4,8 +4,10 @@ #include #include void scc_pp_parse_directive(scc_probe_stream_t *stream, scc_pos_t *pos, - scc_macro_table_t *macros); -cbool scc_pp_expand_macro(scc_probe_stream_t *stream, scc_macro_table_t *macros, + scc_pp_macro_table_t *macros); +cbool scc_pp_expand_macro(scc_probe_stream_t *stream, + scc_pp_macro_table_t *macros, + scc_pp_macro_table_t *expand_stack, scc_probe_stream_t **out_stream, int depth); #endif /* __SCC_PP_PARSE_H__ */ diff --git a/libs/pprocessor/include/pp_token.h b/libs/pprocessor/include/pp_token.h index e751a6c..21316b1 100644 --- a/libs/pprocessor/include/pp_token.h +++ b/libs/pprocessor/include/pp_token.h @@ -5,21 +5,21 @@ /// https://cppreference.cn/w/c/preprocessor #define SCC_PP_INST_TOKEN \ X(define , SCC_PP_STD, SCC_PP_TOK_DEFINE ) \ - X(undef , SCC_PP_STD, SCC_PP_TOK_UNDEF ) \ - X(include , SCC_PP_STD, SCC_PP_TOK_INCLUDE ) \ - X(if , SCC_PP_STD, SCC_PP_TOK_IF ) \ - X(ifdef , SCC_PP_STD, SCC_PP_TOK_IFDEF ) \ - X(ifndef , SCC_PP_STD, SCC_PP_TOK_IFNDEF ) \ - X(else , SCC_PP_STD, SCC_PP_TOK_ELSE ) \ - X(elif , SCC_PP_STD, SCC_PP_TOK_ELIF ) \ - X(elifdef , SCC_PP_STD, SCC_PP_TOK_ELIFDEF ) \ - X(elifndef , SCC_PP_C23, SCC_PP_TOK_ELIFNDEF ) \ - X(endif , SCC_PP_STD, SCC_PP_TOK_ENDIF ) \ - X(line , SCC_PP_STD, SCC_PP_TOK_LINE ) \ - X(embed , SCC_PP_C23, SCC_PP_TOK_EMBED ) \ - X(error , SCC_PP_STD, SCC_PP_TOK_ERROR ) \ - X(warning , SCC_PP_C23, SCC_PP_TOK_WARNING ) \ - X(pragma , SCC_PP_STD, SCC_PP_TOK_PRAMA ) \ + X(elif , SCC_PP_STD, SCC_PP_TOK_UNDEF ) \ + X(elifdef , SCC_PP_STD, SCC_PP_TOK_INCLUDE ) \ + X(elifndef , SCC_PP_STD, SCC_PP_TOK_IF ) \ + X(else , SCC_PP_STD, SCC_PP_TOK_IFDEF ) \ + X(embed , SCC_PP_STD, SCC_PP_TOK_IFNDEF ) \ + X(endif , SCC_PP_STD, SCC_PP_TOK_ELSE ) \ + X(error , SCC_PP_STD, SCC_PP_TOK_ELIF ) \ + X(if , SCC_PP_STD, SCC_PP_TOK_ELIFDEF ) \ + X(ifdef , SCC_PP_C23, SCC_PP_TOK_ELIFNDEF ) \ + X(ifndef , SCC_PP_STD, SCC_PP_TOK_ENDIF ) \ + X(include , SCC_PP_STD, SCC_PP_TOK_LINE ) \ + X(line , SCC_PP_C23, SCC_PP_TOK_EMBED ) \ + X(pragma , SCC_PP_STD, SCC_PP_TOK_ERROR ) \ + X(undef , SCC_PP_C23, SCC_PP_TOK_WARNING ) \ + X(warning , SCC_PP_STD, SCC_PP_TOK_PRAMA ) \ // END /* clang-format on */ diff --git a/libs/pprocessor/include/pprocessor.h b/libs/pprocessor/include/pprocessor.h index cc676fb..cd4e24b 100644 --- a/libs/pprocessor/include/pprocessor.h +++ b/libs/pprocessor/include/pprocessor.h @@ -28,7 +28,7 @@ typedef struct if_stack_item { typedef struct scc_pproc { scc_probe_stream_t *stream; // 输出流 scc_strpool_t strpool; // 字符串池 - scc_macro_table_t macro_table; + scc_pp_macro_table_t macro_table; SCC_VEC(if_stack_item_t) if_stack; // 条件编译栈 } scc_pproc_t; diff --git a/libs/pprocessor/src/macro.c b/libs/pprocessor/src/macro.c index 705c3b8..d8674e3 100644 --- a/libs/pprocessor/src/macro.c +++ b/libs/pprocessor/src/macro.c @@ -1,8 +1,8 @@ #include // 创建宏对象 -scc_pp_macro_t *scc_pp_macro_create(const scc_cstring_t *name, - scc_pp_macro_type_t type) { +scc_pp_macro_t *scc_pp_macro_new(const scc_cstring_t *name, + scc_pp_macro_type_t type) { scc_pp_macro_t *macro = scc_malloc(sizeof(scc_pp_macro_t)); if (!macro) { LOG_ERROR("Failed to allocate memory for macro"); @@ -39,66 +39,17 @@ void scc_pp_macro_drop(scc_pp_macro_t *macro) { scc_free(macro); } -// // 压缩空白字符 -// scc_cstring_t scc_pp_compress_whitespace(const scc_pp_macro_list_t *tokens) { -// scc_cstring_t combined = scc_cstring_new(); -// cbool last_was_space = false; - -// for (usize i = 0; i < tokens->size; ++i) { -// scc_cstring_t *token = &scc_vec_at(*tokens, i); -// const char *str = scc_cstring_as_cstr(token); -// usize len = scc_cstring_len(token); - -// for (usize j = 0; j < len; ++j) { -// char ch = str[j]; -// if (ch == ' ' || ch == '\t') { -// if (!last_was_space && !scc_cstring_is_empty(&combined)) { -// scc_cstring_append_ch(&combined, ' '); -// last_was_space = true; -// } -// } else { -// scc_cstring_append_ch(&combined, ch); -// last_was_space = false; -// } -// } - -// // 在 token 之间添加一个空格(除非已经是空格) -// if (i + 1 < tokens->size && !last_was_space && -// !scc_cstring_is_empty(&combined)) { -// scc_cstring_append_ch(&combined, ' '); -// last_was_space = true; -// } -// } - -// // 去除尾随空格 -// while (!scc_cstring_is_empty(&combined) && -// (combined.data[combined.size - 1] == ' ' || -// combined.data[combined.size - 1] == '\t')) { -// combined.size--; -// } - -// return combined; -// } - // 添加对象宏 -cbool scc_pp_add_object_macro(scc_macro_table_t *macros, +cbool scc_pp_add_object_macro(scc_pp_macro_table_t *macros, const scc_cstring_t *name, const scc_pp_macro_list_t *replacement) { if (!macros || !name || !replacement) return false; - scc_pp_macro_t *macro = scc_pp_macro_create(name, SCC_PP_MACRO_OBJECT); + scc_pp_macro_t *macro = scc_pp_macro_new(name, SCC_PP_MACRO_OBJECT); if (!macro) return false; - // if (replacement->size > 0) { - // scc_cstring_t combined = scc_pp_compress_whitespace(replacement); - // scc_vec_push(macro->replaces, combined); - // // 释放原始 tokens - // for (usize i = 0; i < replacement->size; ++i) { - // scc_cstring_free(&scc_vec_at(*replacement, i)); - // } - // } macro->replaces = *replacement; // 检查是否已存在同名宏 @@ -113,14 +64,14 @@ cbool scc_pp_add_object_macro(scc_macro_table_t *macros, } // 添加函数宏 -cbool scc_pp_add_function_macro(scc_macro_table_t *macros, +cbool scc_pp_add_function_macro(scc_pp_macro_table_t *macros, const scc_cstring_t *name, const scc_pp_macro_list_t *params, const scc_pp_macro_list_t *replacement) { if (!macros || !name || !params || !replacement) return false; - scc_pp_macro_t *macro = scc_pp_macro_create(name, SCC_PP_MACRO_FUNCTION); + scc_pp_macro_t *macro = scc_pp_macro_new(name, SCC_PP_MACRO_FUNCTION); if (!macro) return false; @@ -128,17 +79,6 @@ cbool scc_pp_add_function_macro(scc_macro_table_t *macros, macro->params = *params; macro->replaces = *replacement; - // if (replacement->size > 0) { - // // 函数宏直接存储替换文本 - // scc_cstring_t combined = scc_pp_compress_whitespace(replacement); - // scc_vec_push(macro->replaces, combined); - - // // 释放原始 tokens - // for (usize i = 0; i < replacement->size; ++i) { - // scc_cstring_free(&scc_vec_at(*replacement, i)); - // } - // } - // 检查是否已存在同名宏 scc_pp_macro_t *existing = scc_hashtable_get(¯os->table, ¯o->name); if (existing) { @@ -150,13 +90,23 @@ cbool scc_pp_add_function_macro(scc_macro_table_t *macros, return true; } +/// marco_table + +scc_pp_macro_t *scc_pp_macro_table_set(scc_pp_macro_table_t *pp, + scc_pp_macro_t *macro) { + Assert(pp != null && macro != null); + return scc_hashtable_set(&pp->table, ¯o->name, macro); +} + // 查找宏定义 -scc_pp_macro_t *scc_pp_find_macro(scc_macro_table_t *pp, scc_cstring_t *name) { +scc_pp_macro_t *scc_pp_macro_table_get(scc_pp_macro_table_t *pp, + scc_cstring_t *name) { return scc_hashtable_get(&pp->table, name); } // 从预处理器中删除宏 -cbool scc_pp_remove_macro(scc_macro_table_t *pp, const scc_cstring_t *name) { +cbool scc_pp_macro_table_remove(scc_pp_macro_table_t *pp, + const scc_cstring_t *name) { if (!pp || !name) return false; @@ -169,8 +119,6 @@ cbool scc_pp_remove_macro(scc_macro_table_t *pp, const scc_cstring_t *name) { return true; } -/// marco_table - static u32 hash_func(const void *key) { const scc_cstring_t *string = (const scc_cstring_t *)key; return scc_strhash32(scc_cstring_as_cstr(string)); @@ -186,7 +134,7 @@ static int hash_cmp(const void *key1, const void *key2) { return scc_strcmp(scc_cstring_as_cstr(str1), scc_cstring_as_cstr(str2)); } -void scc_pp_marco_table_init(scc_macro_table_t *macros) { +void scc_pp_marco_table_init(scc_pp_macro_table_t *macros) { Assert(macros != null); macros->table.hash_func = hash_func; macros->table.key_cmp = hash_cmp; @@ -200,7 +148,7 @@ static int macro_free(const void *key, void *value, void *context) { return 0; } -void scc_pp_macro_table_drop(scc_macro_table_t *macros) { +void scc_pp_macro_table_drop(scc_pp_macro_table_t *macros) { Assert(macros != null); scc_hashtable_foreach(¯os->table, macro_free, null); scc_hashtable_drop(¯os->table); diff --git a/libs/pprocessor/src/parse.c b/libs/pprocessor/src/parse.c index 1228a0c..1cb38a4 100644 --- a/libs/pprocessor/src/parse.c +++ b/libs/pprocessor/src/parse.c @@ -193,7 +193,7 @@ static cbool safe_skip_backspace_if_endline(scc_probe_stream_t *stream, } void scc_pp_parse_directive(scc_probe_stream_t *stream, scc_pos_t *pos, - scc_macro_table_t *macros) { + scc_pp_macro_table_t *macros) { Assert(stream != null); scc_probe_stream_reset(stream); @@ -264,7 +264,7 @@ void scc_pp_parse_directive(scc_probe_stream_t *stream, scc_pos_t *pos, case SCC_PP_TOK_UNDEF: { if (scc_lex_parse_identifier(stream, pos, &name)) { // TODO ret value - scc_pp_remove_macro(macros, &name); + scc_pp_macro_table_remove(macros, &name); } break; } @@ -283,7 +283,6 @@ void scc_pp_parse_directive(scc_probe_stream_t *stream, scc_pos_t *pos, case SCC_PP_TOK_WARNING: case SCC_PP_TOK_PRAMA: // 暂时跳过这一行 - TODO(); scc_lex_parse_skip_line(stream, pos); break; default: @@ -390,11 +389,14 @@ cbool scc_pp_expand_function_macro(scc_pp_macro_t *macro, return true; } -cbool scc_pp_expand_macro(scc_probe_stream_t *stream, scc_macro_table_t *macros, +cbool scc_pp_expand_macro(scc_probe_stream_t *stream, + scc_pp_macro_table_t *macros, + scc_pp_macro_table_t *expand_stack, scc_probe_stream_t **out_stream, int depth) { // TODO self position and it maybe is a stack on #include ? // 递归扫描 if (depth <= 0) { + *out_stream = null; return false; } Assert(stream != null && macros != null && out_stream != null); @@ -406,9 +408,11 @@ cbool scc_pp_expand_macro(scc_probe_stream_t *stream, scc_macro_table_t *macros, ret = scc_lex_parse_identifier(stream, &pos, &identifier); Assert(ret == true); - scc_pp_macro_t *macro = scc_pp_find_macro(macros, &identifier); - if (macro == null) { - // 不是宏,直接输出标识符 + scc_pp_macro_t *macro = scc_pp_macro_table_get(macros, &identifier); + // 1. 不是宏,直接输出标识符 + // 2. 检查到重复展开跳过 + if (macro == null || + scc_pp_macro_table_get(expand_stack, ¯o->name) != null) { *out_stream = scc_mem_probe_stream_new(scc_cstring_as_cstr(&identifier), scc_cstring_len(&identifier), false); @@ -436,15 +440,24 @@ cbool scc_pp_expand_macro(scc_probe_stream_t *stream, scc_macro_table_t *macros, Assert(ret == true); } + // 已经展开的将被标记并入栈 + scc_pp_macro_table_set(expand_stack, + scc_pp_macro_new(¯o->name, macro->type)); + + // 将展开内容变换成stream scc_probe_stream_t *tmp_stream = scc_mem_probe_stream_new( scc_cstring_as_cstr(&tmp_buff), scc_cstring_len(&tmp_buff), false); - int ch; scc_cstring_t real_buff = scc_cstring_new(); + while ((ch = scc_probe_stream_peek(tmp_stream)) != scc_stream_eof) { if (scc_lex_parse_is_identifier_prefix(ch)) { + // 递归检查 scc_probe_stream_t *tmp_out_stream; - scc_pp_expand_macro(tmp_stream, macros, &tmp_out_stream, depth - 1); + if (scc_pp_expand_macro(tmp_stream, macros, expand_stack, + &tmp_out_stream, depth - 1) == false) { + return false; + } // scc_cstring_append_cstr(); Assert(tmp_out_stream != null); while (scc_probe_stream_peek(tmp_out_stream) != scc_stream_eof) { @@ -462,6 +475,9 @@ cbool scc_pp_expand_macro(scc_probe_stream_t *stream, scc_macro_table_t *macros, scc_probe_stream_drop(tmp_stream); *out_stream = scc_mem_probe_stream_new(scc_cstring_as_cstr(&real_buff), scc_cstring_len(&real_buff), false); + + // 已经展开的将被标记并出栈 + scc_pp_macro_table_remove(expand_stack, ¯o->name); return true; ERR: *out_stream = null; diff --git a/libs/pprocessor/src/pprocessor.c b/libs/pprocessor/src/pprocessor.c index afb12b9..25f55ac 100644 --- a/libs/pprocessor/src/pprocessor.c +++ b/libs/pprocessor/src/pprocessor.c @@ -30,9 +30,23 @@ RETRY: &stream->self->macro_table); goto RETRY; } else if (scc_lex_parse_is_identifier_prefix(ch)) { - scc_pp_expand_macro(stream->input, &stream->self->macro_table, - &stream->tmp_stream, MAX_MACRO_EXPANSION_DEPTH); + scc_pp_macro_table_t tmp_table; + scc_pp_marco_table_init(&tmp_table); + cbool ret = scc_pp_expand_macro( + stream->input, &stream->self->macro_table, &tmp_table, + &stream->tmp_stream, MAX_MACRO_EXPANSION_DEPTH); + scc_pp_macro_table_drop(&tmp_table); + if (ret == false) { + LOG_ERROR("macro_expand_error"); + } goto READ_BUF; + } else if (scc_probe_stream_next(stream->input) == '/') { + ch = scc_probe_stream_peek(stream->input); + if (ch == '/') { + scc_lex_parse_skip_line(stream->input, &stream->pos); + } else if (ch == '*') { + scc_lex_parse_skip_block_comment(stream->input, &stream->pos); + } } // 非标识符字符,直接消费并返回 diff --git a/libs/pprocessor/tests/test_pp.c b/libs/pprocessor/tests/test_pp.c index 8814a01..105ee95 100644 --- a/libs/pprocessor/tests/test_pp.c +++ b/libs/pprocessor/tests/test_pp.c @@ -22,7 +22,7 @@ static scc_probe_stream_t *from_file_stream(FILE *fp) { scc_mem_probe_stream_t *mem_stream = malloc(sizeof(scc_mem_probe_stream_t)); scc_probe_stream_t *stream = - scc_mem_probe_stream_init(mem_stream, buffer, fsize, true); + scc_mem_probe_stream_init(mem_stream, buffer, read_ret, true); return stream; } @@ -38,32 +38,50 @@ static void test_file(const char *name) { assert(fexpect != NULL); scc_pproc_t pp; - scc_mem_probe_stream_t stream; scc_probe_stream_t *output_stream = scc_pproc_init(&pp, from_file_stream(fsrc)); scc_probe_stream_t *expect_stream = from_file_stream(fexpect); + + fclose(fsrc); + fclose(fexpect); + TEST_CASE(src_fname); - while (1) { - int output_ch = scc_probe_stream_consume(output_stream); - int expect_ch = scc_probe_stream_consume(expect_stream); - TEST_CHECK(output_ch == expect_ch); - TEST_MSG("output: %c %x, expect: %c %x", output_ch, output_ch, - expect_ch, expect_ch); - if (output_ch != expect_ch) { - break; - } - if (output_ch == scc_stream_eof) { +#define BUFFER_LEN 4096 + int ch; + char expect_buffer[BUFFER_LEN]; + char output_buffer[BUFFER_LEN]; + usize size_produced = 0, size_expected = 0; + for (usize i = 0; i < BUFFER_LEN; ++i) { + ch = scc_probe_stream_consume(expect_stream); + if (ch != scc_stream_eof) { + expect_buffer[i] = (char)ch; + } else { + size_expected = i; break; } } + for (usize i = 0; i < BUFFER_LEN; ++i) { + ch = scc_probe_stream_consume(output_stream); + if (ch != scc_stream_eof) { + output_buffer[i] = (char)ch; + } else { + size_produced = i; + break; + } + } + TEST_CHECK(size_produced == size_expected && + memcmp(output_buffer, expect_buffer, size_produced) == 0); + TEST_DUMP("Expected:", expect_buffer, size_expected); + TEST_DUMP("Produced:", output_buffer, size_produced); + scc_pproc_drop(&pp); } static void test_basic(void) { char name[32]; for (int i = 1; i <= 22; ++i) { - // snprintf(name, sizeof(name), "%02d", i); - // test_file(name); + snprintf(name, sizeof(name), "%02d", i); + test_file(name); } } diff --git a/libs/pprocessor/tests/test_unit.c b/libs/pprocessor/tests/test_unit.c index db723cf..ae367ca 100644 --- a/libs/pprocessor/tests/test_unit.c +++ b/libs/pprocessor/tests/test_unit.c @@ -104,6 +104,43 @@ static void test_define_nested_macros(void) { "((1 + 1) + 1)\n"); } +static void hard_test_define_func_macros(void) { + TEST_CASE("func_macros_hard with pp_01"); + CHECK_PP_OUTPUT_EXACT("#define hash_hash # ## #\n" + "#define mkstr(a) # a\n" + "#define in_between(a) mkstr(a)\n" + "#define join(c, d) in_between(c hash_hash d)\n" + "char p[] = join(x, y);\n", + "char p[] = \"x ## y\";\n"); + + TEST_CASE("func_macros_hard with recursive define"); + CHECK_PP_OUTPUT_EXACT("#define M1(x) M2(x + 1)\n" + "#define M2(x) M1(x * 2)\n" + "M1(5)\n", + "M1(5 + 1 * 2)\n"); + CHECK_PP_OUTPUT_EXACT("#define A B\n" + "#define B C\n" + "#define C 1\n" + "A\n", + "1\n"); + + TEST_CASE("func_macros_hard with self recursive call"); + CHECK_PP_OUTPUT_EXACT("#define M(x) x\n" + "M(M(10))\n", + "10\n"); + CHECK_PP_OUTPUT_EXACT("#define M(x) M(x)\n" + "#define N(x) x\n" + "N(M(1))\n", + "M(1)\n"); + + TEST_CASE("func_macros_hard with define by macro"); + CHECK_PP_OUTPUT_EXACT("#define M1(x) M1(x + 1)\n" + "#define M2 M1\n" + "#define M3(x) x\n" + "M3(M3(M2)(0))\n", + "M1(0 + 1)\n"); +} + static void test_conditional_compilation(void) { TEST_CASE("conditional compilation"); CHECK_PP_OUTPUT_EXACT("#if 1\ntrue\n#endif\n", "true\n"); @@ -140,5 +177,6 @@ TEST_LIST = { TEST_LIST_CASE(test_define_stringify_operator), TEST_LIST_CASE(test_define_concat_operator), TEST_LIST_CASE(test_define_nested_macros), + TEST_LIST_CASE(hard_test_define_func_macros), {NULL, NULL}, }; \ No newline at end of file