From b4929be6b867fe0ddecafe06815597ea063cfc85 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Mon, 16 Feb 2026 21:21:23 +0800 Subject: [PATCH] =?UTF-8?q?refactor(lexer):=20=E9=87=8D=E6=9E=84=E8=AF=8D?= =?UTF-8?q?=E6=B3=95=E5=88=86=E6=9E=90=E5=99=A8=E5=A4=B4=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E5=B9=B6=E4=BC=98=E5=8C=96=E7=BC=93=E5=86=B2?= =?UTF-8?q?=E5=8C=BA=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除了旧的lexer_stream.c实现,引入新的环形缓冲区机制来替代原有的 动态数组缓冲区。更新了词法分析器的核心数据结构,修改了token获取 相关函数的实现以支持新的缓冲区管理方式。 BREAKING CHANGE: 移除了scc_lexer_stream_t相关的API,替换为基于 环形缓冲区的新接口scc_lexer_to_ring和相关函数。 feat(lexer_token): 添加词法分析结果内存泄漏警告注释 docs: 移除预处理器模块的测试文件和相关配置 --- libs/lexer/include/lexer.h | 100 ----- libs/lexer/include/lexer_token.h | 4 + libs/lexer/include/scc_lexer.h | 54 +++ libs/lexer/src/lexer.c | 59 ++- libs/lexer/src/lexer_stream.c | 139 ------- libs/lexer/src/main.c | 7 +- libs/lexer/tests/test_lexer.c | 2 +- libs/pprocessor/README.md | 4 - libs/pprocessor/cbuild.toml | 8 - libs/pprocessor/include/pp_macro.h | 96 ----- libs/pprocessor/include/pp_parse.h | 18 - libs/pprocessor/include/pp_token.h | 30 -- libs/pprocessor/include/pprocessor.h | 62 ---- libs/pprocessor/src/expand_macro.c | 412 --------------------- libs/pprocessor/src/macro.c | 155 -------- libs/pprocessor/src/parse.c | 295 --------------- libs/pprocessor/src/pprocessor.c | 132 ------- libs/pprocessor/tests/pp/01.c | 6 - libs/pprocessor/tests/pp/01.expect | 1 - libs/pprocessor/tests/pp/02.c | 28 -- libs/pprocessor/tests/pp/02.expect | 5 - libs/pprocessor/tests/pp/03.c | 15 - libs/pprocessor/tests/pp/03.expect | 5 - libs/pprocessor/tests/pp/04.c | 4 - libs/pprocessor/tests/pp/04.expect | 1 - libs/pprocessor/tests/pp/05.c | 7 - libs/pprocessor/tests/pp/05.expect | 3 - libs/pprocessor/tests/pp/06.c | 5 - libs/pprocessor/tests/pp/06.expect | 1 - libs/pprocessor/tests/pp/07.c | 4 - libs/pprocessor/tests/pp/07.expect | 2 - libs/pprocessor/tests/pp/08.c | 4 - libs/pprocessor/tests/pp/08.expect | 1 - libs/pprocessor/tests/pp/09.c | 4 - libs/pprocessor/tests/pp/09.expect | 1 - libs/pprocessor/tests/pp/10.c | 10 - libs/pprocessor/tests/pp/10.expect | 5 - libs/pprocessor/tests/pp/11.c | 36 -- libs/pprocessor/tests/pp/11.expect | 16 - libs/pprocessor/tests/pp/12.S | 8 - libs/pprocessor/tests/pp/12.expect | 2 - libs/pprocessor/tests/pp/13.S | 6 - libs/pprocessor/tests/pp/13.expect | 2 - libs/pprocessor/tests/pp/14.c | 13 - libs/pprocessor/tests/pp/14.expect | 3 - libs/pprocessor/tests/pp/15.c | 18 - libs/pprocessor/tests/pp/15.expect | 5 - libs/pprocessor/tests/pp/16.c | 3 - libs/pprocessor/tests/pp/16.expect | 2 - libs/pprocessor/tests/pp/17.c | 14 - libs/pprocessor/tests/pp/17.expect | 6 - libs/pprocessor/tests/pp/18.c | 30 -- libs/pprocessor/tests/pp/18.expect | 5 - libs/pprocessor/tests/pp/19.c | 101 ----- libs/pprocessor/tests/pp/19.expect | 14 - libs/pprocessor/tests/pp/20.c | 13 - libs/pprocessor/tests/pp/20.expect | 6 - libs/pprocessor/tests/pp/21.c | 41 -- libs/pprocessor/tests/pp/21.expect | 11 - libs/pprocessor/tests/pp/22.c | 12 - libs/pprocessor/tests/pp/22.expect | 2 - libs/pprocessor/tests/pp/Makefile | 55 --- libs/pprocessor/tests/pp/README | 96 ----- libs/pprocessor/tests/pp/pp-counter.c | 27 -- libs/pprocessor/tests/pp/pp-counter.expect | 15 - libs/pprocessor/tests/test_pp.c | 91 ----- libs/pprocessor/tests/test_run.c | 24 -- libs/pprocessor/tests/test_unit.c | 215 ----------- libs/sstream/{src => examples}/main.c | 0 libs/sstream/include/scc_sstream.h | 2 +- libs/sstream/src/scc_sstream.c | 8 +- runtime/scc_core/include/scc_core_ring.h | 2 +- 72 files changed, 119 insertions(+), 2474 deletions(-) delete mode 100644 libs/lexer/include/lexer.h create mode 100644 libs/lexer/include/scc_lexer.h delete mode 100644 libs/lexer/src/lexer_stream.c delete mode 100644 libs/pprocessor/README.md delete mode 100644 libs/pprocessor/cbuild.toml delete mode 100644 libs/pprocessor/include/pp_macro.h delete mode 100644 libs/pprocessor/include/pp_parse.h delete mode 100644 libs/pprocessor/include/pp_token.h delete mode 100644 libs/pprocessor/include/pprocessor.h delete mode 100644 libs/pprocessor/src/expand_macro.c delete mode 100644 libs/pprocessor/src/macro.c delete mode 100644 libs/pprocessor/src/parse.c delete mode 100644 libs/pprocessor/src/pprocessor.c delete mode 100644 libs/pprocessor/tests/pp/01.c delete mode 100644 libs/pprocessor/tests/pp/01.expect delete mode 100644 libs/pprocessor/tests/pp/02.c delete mode 100644 libs/pprocessor/tests/pp/02.expect delete mode 100644 libs/pprocessor/tests/pp/03.c delete mode 100644 libs/pprocessor/tests/pp/03.expect delete mode 100644 libs/pprocessor/tests/pp/04.c delete mode 100644 libs/pprocessor/tests/pp/04.expect delete mode 100644 libs/pprocessor/tests/pp/05.c delete mode 100644 libs/pprocessor/tests/pp/05.expect delete mode 100644 libs/pprocessor/tests/pp/06.c delete mode 100644 libs/pprocessor/tests/pp/06.expect delete mode 100644 libs/pprocessor/tests/pp/07.c delete mode 100644 libs/pprocessor/tests/pp/07.expect delete mode 100644 libs/pprocessor/tests/pp/08.c delete mode 100644 libs/pprocessor/tests/pp/08.expect delete mode 100644 libs/pprocessor/tests/pp/09.c delete mode 100644 libs/pprocessor/tests/pp/09.expect delete mode 100644 libs/pprocessor/tests/pp/10.c delete mode 100644 libs/pprocessor/tests/pp/10.expect delete mode 100644 libs/pprocessor/tests/pp/11.c delete mode 100644 libs/pprocessor/tests/pp/11.expect delete mode 100644 libs/pprocessor/tests/pp/12.S delete mode 100644 libs/pprocessor/tests/pp/12.expect delete mode 100644 libs/pprocessor/tests/pp/13.S delete mode 100644 libs/pprocessor/tests/pp/13.expect delete mode 100644 libs/pprocessor/tests/pp/14.c delete mode 100644 libs/pprocessor/tests/pp/14.expect delete mode 100644 libs/pprocessor/tests/pp/15.c delete mode 100644 libs/pprocessor/tests/pp/15.expect delete mode 100644 libs/pprocessor/tests/pp/16.c delete mode 100644 libs/pprocessor/tests/pp/16.expect delete mode 100644 libs/pprocessor/tests/pp/17.c delete mode 100644 libs/pprocessor/tests/pp/17.expect delete mode 100644 libs/pprocessor/tests/pp/18.c delete mode 100644 libs/pprocessor/tests/pp/18.expect delete mode 100644 libs/pprocessor/tests/pp/19.c delete mode 100644 libs/pprocessor/tests/pp/19.expect delete mode 100644 libs/pprocessor/tests/pp/20.c delete mode 100644 libs/pprocessor/tests/pp/20.expect delete mode 100644 libs/pprocessor/tests/pp/21.c delete mode 100644 libs/pprocessor/tests/pp/21.expect delete mode 100644 libs/pprocessor/tests/pp/22.c delete mode 100644 libs/pprocessor/tests/pp/22.expect delete mode 100644 libs/pprocessor/tests/pp/Makefile delete mode 100644 libs/pprocessor/tests/pp/README delete mode 100644 libs/pprocessor/tests/pp/pp-counter.c delete mode 100644 libs/pprocessor/tests/pp/pp-counter.expect delete mode 100644 libs/pprocessor/tests/test_pp.c delete mode 100644 libs/pprocessor/tests/test_run.c delete mode 100644 libs/pprocessor/tests/test_unit.c rename libs/sstream/{src => examples}/main.c (100%) diff --git a/libs/lexer/include/lexer.h b/libs/lexer/include/lexer.h deleted file mode 100644 index 251f4fb..0000000 --- a/libs/lexer/include/lexer.h +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @file lexer.h - * @brief C语言词法分析器核心数据结构与接口 - */ - -#ifndef __SCC_LEXER_H__ -#define __SCC_LEXER_H__ - -#include "lexer_token.h" -#include -#include - -/** - * @brief 词法分析器核心结构体 - * - * 封装词法分析所需的状态信息和缓冲区管理 - */ -typedef struct scc_lexer { - scc_sstream_ring_t stream_ref; - int jump_macro; -} scc_lexer_t; - -void scc_lexer_init(scc_lexer_t *lexer, scc_sstream_ring_t *stream_ref); - -/** - * @brief 获取原始token - * @param[in] lexer 词法分析器实例 - * @param[out] token 输出token存储位置 - * - * 此函数会返回所有类型的token,包括空白符等无效token - */ -void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token); - -/** - * @brief 获取有效token - * @param[in] lexer 词法分析器实例 - * @param[out] token 输出token存储位置 - * - * 此函数会自动跳过空白符等无效token,返回对语法分析有意义的token - */ -void scc_lexer_get_valid_token(scc_lexer_t *lexer, scc_lexer_tok_t *token); - -typedef SCC_VEC(scc_lexer_tok_t) scc_lexer_tok_vec_t; - -typedef struct scc_lexer_stream scc_lexer_stream_t; -struct scc_lexer_stream { - scc_lexer_t *lexer; - scc_lexer_tok_vec_t toks; // 循环缓冲区 - usize curr_pos; // 当前读取位置(逻辑位置) - usize probe_pos; // 已填充位置(逻辑位置) - cbool need_comment; - - /// @brief 向前读取n个token - const scc_lexer_tok_t *(*peek)(scc_lexer_stream_t *stream, usize n); - - /// @brief 指针推进到offset - void (*advance)(scc_lexer_stream_t *stream, usize offset); - - /// @brief 销毁并释放资源 - void (*drop)(scc_lexer_stream_t *stream); -}; - -/** - * @brief 将词法分析器转换成流式输出(自带缓冲区) - * @param[in] lexer 已经词法分析器实例 - * @param[out] stream 输出流对象指针 - * @param[in] need_comment 输出时是否需要注释 - */ -void scc_lexer_to_stream(scc_lexer_t *lexer, scc_lexer_stream_t *stream, - cbool need_comment); - -static inline const scc_lexer_tok_t * -scc_lexer_stream_current(scc_lexer_stream_t *stream) { - Assert(stream != null); - return stream->peek(stream, 0); -} - -static inline const scc_lexer_tok_t * -scc_lexer_stream_peek(scc_lexer_stream_t *stream, usize n) { - Assert(stream != null); - return stream->peek(stream, n); -} - -static inline void scc_lexer_stream_consume(scc_lexer_stream_t *stream) { - Assert(stream != null); - return stream->advance(stream, 1); -} - -static inline void scc_lexer_stream_advance(scc_lexer_stream_t *stream, - usize n) { - Assert(stream != null); - return stream->advance(stream, n); -} - -static inline void scc_lexer_stream_drop(scc_lexer_stream_t *stream) { - Assert(stream != null); - return stream->drop(stream); -} - -#endif /* __SCC_LEXER_H__ */ diff --git a/libs/lexer/include/lexer_token.h b/libs/lexer/include/lexer_token.h index f4c3c55..9ccfc3a 100644 --- a/libs/lexer/include/lexer_token.h +++ b/libs/lexer/include/lexer_token.h @@ -144,6 +144,10 @@ typedef enum scc_tok_subtype { scc_tok_subtype_t scc_get_tok_subtype(scc_tok_type_t type); const char *scc_get_tok_name(scc_tok_type_t type); +/** + * @brief 词法分析结果 + * @warning 需要手动释放lexeme否则会出现内存泄漏 + */ typedef struct scc_lexer_token { scc_tok_type_t type; scc_cstring_t lexeme; diff --git a/libs/lexer/include/scc_lexer.h b/libs/lexer/include/scc_lexer.h new file mode 100644 index 0000000..c8c246f --- /dev/null +++ b/libs/lexer/include/scc_lexer.h @@ -0,0 +1,54 @@ +/** + * @file lexer.h + * @brief C语言词法分析器核心数据结构与接口 + */ + +#ifndef __SCC_LEXER_H__ +#define __SCC_LEXER_H__ + +#include "lexer_token.h" +#include +#include +#include + +typedef SCC_RING(scc_lexer_tok_t) scc_lexer_tok_ring_t; +typedef SCC_VEC(scc_lexer_tok_t) scc_lexer_tok_vec_t; +/** + * @brief 词法分析器核心结构体 + * + * 封装词法分析所需的状态信息和缓冲区管理 + */ +typedef struct scc_lexer { + scc_sstream_ring_t *stream_ref; + scc_lexer_tok_ring_t ring; + int ring_ref_count; + int jump_macro; +} scc_lexer_t; + +void scc_lexer_init(scc_lexer_t *lexer, scc_sstream_ring_t *stream_ref); + +/** + * @brief 获取原始token + * @param[in] lexer 词法分析器实例 + * @param[out] token 输出token存储位置 + * + * 此函数会返回所有类型的token,包括空白符等无效token + */ +void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token); + +/** + * @brief 获取有效token + * @param[in] lexer 词法分析器实例 + * @param[out] token 输出token存储位置 + * + * 此函数会自动跳过空白符等无效token,返回对语法分析有意义的token + */ +void scc_lexer_get_valid_token(scc_lexer_t *lexer, scc_lexer_tok_t *token); + +scc_lexer_tok_ring_t *scc_lexer_to_ring(scc_lexer_t *lexer, int ring_size, + cbool need_comment); + +void scc_lexer_drop_ring(scc_lexer_tok_ring_t *ring_ref); +void scc_lexer_drop(scc_lexer_t *lexer); + +#endif /* __SCC_LEXER_H__ */ diff --git a/libs/lexer/src/lexer.c b/libs/lexer/src/lexer.c index 14ee507..723389e 100644 --- a/libs/lexer/src/lexer.c +++ b/libs/lexer/src/lexer.c @@ -1,5 +1,6 @@ -#include +#include "scc_lexer.h" #include +#include static const struct { const char *name; @@ -41,7 +42,8 @@ static int keyword_cmp(const char *name, int len) { } void scc_lexer_init(scc_lexer_t *lexer, scc_sstream_ring_t *stream_ref) { - lexer->stream_ref = *stream_ref; + lexer->stream_ref = stream_ref; + lexer->ring_ref_count = 0; lexer->jump_macro = false; } @@ -68,7 +70,7 @@ static inline cbool is_hex_digit(int ch) { /* 从环形缓冲区预览一个字符(带EOF检测) */ static inline cbool peek_char(scc_lexer_t *lexer, scc_sstream_char_t *out) { cbool ok; - scc_ring_peek(lexer->stream_ref, *out, ok); + scc_ring_peek(*lexer->stream_ref, *out, ok); return ok; } @@ -76,7 +78,7 @@ static inline cbool peek_char(scc_lexer_t *lexer, scc_sstream_char_t *out) { static inline cbool next_char(scc_lexer_t *lexer, scc_cstring_t *lexeme, scc_sstream_char_t *out) { cbool ok; - scc_ring_next(lexer->stream_ref, *out, ok); + scc_ring_next(*lexer->stream_ref, *out, ok); if (!ok) return false; scc_cstring_append_ch(lexeme, out->character); @@ -132,7 +134,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { next_char(lexer, &lex, &cur); // 消费 '/' while (peek_char(lexer, &cur) && !is_newline(cur.character)) { next_char(lexer, &lex, &cur); - scc_ring_consume(lexer->stream_ref); + scc_ring_consume(*lexer->stream_ref); } // 注释结束,不包含换行符(换行符单独成token) } else if (next.character == '*') { @@ -150,7 +152,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { next_char(lexer, &lex, &cur); // 消费 '/' break; } - scc_ring_consume(lexer->stream_ref); + scc_ring_consume(*lexer->stream_ref); } } else { // 只是除号 / @@ -161,7 +163,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { token->type = SCC_TOK_IDENT; // 暂定 while (peek_char(lexer, &cur) && is_identifier_part(cur.character)) { next_char(lexer, &lex, &cur); - scc_ring_consume(lexer->stream_ref); + scc_ring_consume(*lexer->stream_ref); } // 检查是否为关键字 int idx = keyword_cmp(scc_cstring_as_cstr(&lex), scc_cstring_len(&lex)); @@ -241,7 +243,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { } else { next_char(lexer, &lex, &cur); } - scc_ring_consume(lexer->stream_ref); + scc_ring_consume(*lexer->stream_ref); } } else { scc_sstream_char_t next = {0}; @@ -447,7 +449,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { } // 设置token - scc_ring_consume(lexer->stream_ref); + scc_ring_consume(*lexer->stream_ref); token->type = token->type; // 上面已设 token->loc = start_loc; token->lexeme = lex; // 转移所有权 @@ -469,3 +471,42 @@ void scc_lexer_get_valid_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { } while (subtype == SCC_TOK_SUBTYPE_EMPTYSPACE || subtype == SCC_TOK_SUBTYPE_COMMENT); } + +static int fill_token(scc_lexer_tok_t *out, void *userdata) { + scc_lexer_t *lexer = userdata; + scc_lexer_get_token(lexer, out); + return 0; +} + +static int fill_valid_token(scc_lexer_tok_t *out, void *userdata) { + scc_lexer_t *lexer = userdata; + scc_lexer_get_valid_token(lexer, out); + return 0; +} + +scc_lexer_tok_ring_t *scc_lexer_to_ring(scc_lexer_t *lexer, int ring_size, + cbool need_comment) { + scc_ring_init(lexer->ring, ring_size, + need_comment ? fill_token : fill_valid_token, lexer); + lexer->ring_ref_count++; + return &lexer->ring; +} + +void scc_lexer_drop_ring(scc_lexer_tok_ring_t *ring_ref) { + scc_lexer_t *lexer = ring_ref->userdata; + if (lexer->ring_ref_count > 0) { + lexer->ring_ref_count--; + } else { + LOG_WARN("double drop sstream ring"); + } +} + +void scc_lexer_drop(scc_lexer_t *lexer) { + Assert(lexer != null); + if (lexer->ring_ref_count) { + LOG_FATAL("drop sstream must be drop ring before ref [%d]", + lexer->ring_ref_count); + } + scc_ring_free(lexer->ring); + scc_sstream_drop_ring(lexer->stream_ref); +} diff --git a/libs/lexer/src/lexer_stream.c b/libs/lexer/src/lexer_stream.c deleted file mode 100644 index 87deb3f..0000000 --- a/libs/lexer/src/lexer_stream.c +++ /dev/null @@ -1,139 +0,0 @@ -#include - -static void lexer_stream_extend(scc_lexer_stream_t *stream, usize n) { - Assert(stream != null); - // 检查是否需要扩容 - if ((stream->probe_pos - stream->curr_pos + n) >= stream->toks.cap) { - // 需要扩容 - 创建新缓冲区 - usize new_cap = stream->toks.cap * 2; - if (new_cap < stream->probe_pos - stream->curr_pos + n + 1) { - new_cap = stream->probe_pos - stream->curr_pos + n + 1; - } - - scc_lexer_tok_t *new_data = - scc_realloc(null, new_cap * sizeof(scc_lexer_tok_t)); - if (!new_data) { - LOG_FATAL("lexer_stream_extend: realloc failed\n"); - return; - } - - // 将旧缓冲区中的数据拷贝到新缓冲区,保持顺序 - usize data_count = stream->probe_pos - stream->curr_pos; - for (usize i = 0; i < data_count; ++i) { - usize old_idx = (stream->curr_pos + i) % stream->toks.cap; - new_data[i] = stream->toks.data[old_idx]; - } - - // 释放旧缓冲区 - if (stream->toks.data) { - scc_free(stream->toks.data); - } - - // 更新结构体 - stream->toks.data = new_data; - stream->toks.cap = new_cap; - stream->curr_pos = 0; - stream->probe_pos = data_count; - } - - // 填充新token - for (usize i = 0; i < n; ++i) { - usize idx = (stream->probe_pos + i) % stream->toks.cap; - if (stream->need_comment) - scc_lexer_get_token(stream->lexer, &stream->toks.data[idx]); - else - scc_lexer_get_valid_token(stream->lexer, &stream->toks.data[idx]); - } - - stream->probe_pos += n; -} - -static const scc_lexer_tok_t *lexer_stream_peek(scc_lexer_stream_t *stream, - usize n) { - Assert(stream != null); - - // 计算需要的前看token数量 - usize available = stream->probe_pos - stream->curr_pos; - if (n >= available) { - // 需要扩展缓冲区 - usize need = n - available + 1; - lexer_stream_extend(stream, need); - } - - // 计算实际缓冲区中的位置 - usize idx = (stream->curr_pos + n) % stream->toks.cap; - return &stream->toks.data[idx]; -} - -static void lexer_stream_advance(scc_lexer_stream_t *stream, usize offset) { - Assert(stream != null); - - if (stream->curr_pos + offset > stream->probe_pos) { - // 尝试填充更多token - usize need = stream->curr_pos + offset - stream->probe_pos; - lexer_stream_extend(stream, need); - } - - stream->curr_pos += offset; - - // 可选:当已消费的token过多时,压缩缓冲区 - if (stream->curr_pos > stream->toks.cap * 3 / 4) { - // 压缩缓冲区:将有效数据移动到前面 - usize data_count = stream->probe_pos - stream->curr_pos; - scc_lexer_tok_t *temp = - scc_realloc(null, data_count * sizeof(scc_lexer_tok_t)); - if (!temp) - return; // 压缩失败也没关系 - - for (usize i = 0; i < data_count; ++i) { - usize old_idx = (stream->curr_pos + i) % stream->toks.cap; - temp[i] = stream->toks.data[old_idx]; - } - - scc_free(stream->toks.data); - stream->toks.data = temp; - stream->toks.cap = data_count; - stream->curr_pos = 0; - stream->probe_pos = data_count; - } -} - -static void lexer_stream_drop(scc_lexer_stream_t *stream) { - Assert(stream != null); - - // 清理所有token(如果有需要清理的内部资源) - for (usize i = 0; i < stream->toks.cap; ++i) { - // 这里假设scc_lexer_tok_t可能包含需要释放的资源 - // 如果有,需要调用相应的清理函数 - // 例如: if (stream->toks.data[i].needs_free) - // scc_free(stream->toks.data[i].ptr); - } - - scc_vec_free(stream->toks); - stream->lexer = null; - stream->curr_pos = 0; - stream->probe_pos = 0; - stream->need_comment = false; - - stream->peek = null; - stream->advance = null; - stream->drop = null; -} - -void scc_lexer_to_stream(scc_lexer_t *lexer, scc_lexer_stream_t *stream, - cbool need_comment) { - Assert(lexer != null && stream != null); - - stream->lexer = lexer; - stream->curr_pos = 0; - stream->probe_pos = 0; - stream->need_comment = need_comment; - - // 初始化循环缓冲区 - scc_vec_init(stream->toks); - scc_vec_realloc(stream->toks, 8); // 初始容量为8 - - stream->peek = lexer_stream_peek; - stream->advance = lexer_stream_advance; - stream->drop = lexer_stream_drop; -} diff --git a/libs/lexer/src/main.c b/libs/lexer/src/main.c index 73755cd..ed273de 100644 --- a/libs/lexer/src/main.c +++ b/libs/lexer/src/main.c @@ -1,5 +1,5 @@ -#include #include +#include #include #include #include @@ -53,10 +53,7 @@ int main(int argc, char *argv[]) { scc_get_tok_name(token.type), scc_cstring_as_cstr(&token.lexeme), token.loc.name, token.loc.line, token.loc.col); - // LOG_DEBUG("%s", token.val.str); - // printf("line: %d, column: %d, type: %3d, typename: %s\n", - // lexer.line, lexer.index, token.type, - // scc_get_tok_name(token.type)); + scc_cstring_free(&token.lexeme); } scc_sstream_drop_ring(ref); scc_sstream_drop(&stream); diff --git a/libs/lexer/tests/test_lexer.c b/libs/lexer/tests/test_lexer.c index 2cdd5f3..2218576 100644 --- a/libs/lexer/tests/test_lexer.c +++ b/libs/lexer/tests/test_lexer.c @@ -1,5 +1,5 @@ // test_lexer.c -#include +#include #include #include diff --git a/libs/pprocessor/README.md b/libs/pprocessor/README.md deleted file mode 100644 index b4443a9..0000000 --- a/libs/pprocessor/README.md +++ /dev/null @@ -1,4 +0,0 @@ - -tests/pp 复制了 TinyCC 的 tests/pp 测试 - -详情见 [README](tests/pp/README) diff --git a/libs/pprocessor/cbuild.toml b/libs/pprocessor/cbuild.toml deleted file mode 100644 index 423480d..0000000 --- a/libs/pprocessor/cbuild.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "scc_pprocesser" - -dependencies = [ - { name = "scc_core", path = "../../runtime/scc_core" }, - { name = "scc_utils", path = "../../runtime/scc_utils" }, - { name = "lex_parser", path = "../lex_parser" }, -] diff --git a/libs/pprocessor/include/pp_macro.h b/libs/pprocessor/include/pp_macro.h deleted file mode 100644 index 1b547ba..0000000 --- a/libs/pprocessor/include/pp_macro.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef __SCC_PP_MACRO_H__ -#define __SCC_PP_MACRO_H__ - -#include -#include - -// 宏定义类型 -typedef enum { - SCC_PP_MACRO_OBJECT, // 对象宏 - SCC_PP_MACRO_FUNCTION, // 函数宏 - SCC_PP_MACRO_NONE, // 不是宏 -} scc_pp_macro_type_t; - -typedef SCC_VEC(scc_cstring_t) scc_pp_macro_list_t; - -// 宏定义结构 -typedef struct scc_macro { - scc_cstring_t name; // 宏名称 - scc_pp_macro_type_t type; // 宏类型 - scc_pp_macro_list_t replaces; // 替换列表 - scc_pp_macro_list_t params; // 参数列表(仅函数宏) -} scc_pp_macro_t; - -typedef struct scc_macro_table { - scc_hashtable_t table; // 宏定义表 -} scc_pp_macro_table_t; - -/** - * @brief 创建宏对象 - * @param name 宏名称 - * @param type 宏类型 - * @return 创建的宏对象指针,失败返回NULL - */ -scc_pp_macro_t *scc_pp_macro_new(const scc_cstring_t *name, - scc_pp_macro_type_t type); - -/** - * @brief 销毁宏对象 - * @param macro 要销毁的宏对象 - */ -void scc_pp_macro_drop(scc_pp_macro_t *macro); - -/** - * @brief 添加对象宏 - * @param pp 预处理器实例 - * @param name 宏名称 - * @param replacement 替换文本列表 - * @return 成功返回true,失败返回false - */ -cbool scc_pp_add_object_macro(scc_pp_macro_table_t *pp, - const scc_cstring_t *name, - const scc_pp_macro_list_t *replacement); - -/** - * @brief 添加函数宏 - * @param pp 预处理器实例 - * @param name 宏名称 - * @param params 参数列表 - * @param replacement 替换文本列表 - * @return 成功返回true,失败返回false - */ -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 查找宏定义 - * @param pp 预处理器实例 - * @param name 宏名称 - * @return 找到的宏对象指针,未找到返回NULL - */ -scc_pp_macro_t *scc_pp_macro_table_get(scc_pp_macro_table_t *pp, - const scc_cstring_t *name); - -/** - * @brief 从预处理器中删除宏 - * @param pp 预处理器实例 - * @param name 宏名称 - * @return 成功删除返回true,未找到返回false - */ -cbool scc_pp_macro_table_remove(scc_pp_macro_table_t *pp, - const scc_cstring_t *name); - -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 deleted file mode 100644 index e9309ee..0000000 --- a/libs/pprocessor/include/pp_parse.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __SCC_PP_PARSE_H__ -#define __SCC_PP_PARSE_H__ - -#include -#include -void scc_pp_parse_directive(scc_probe_stream_t *stream, scc_pos_t *pos, - scc_pp_macro_table_t *macros); -cbool scc_pp_parse_macro_replace_list(scc_probe_stream_t *stream, - scc_pp_macro_list_t *list); -cbool scc_pp_parse_macro_arguments(scc_probe_stream_t *stream, - scc_pp_macro_list_t *args); - -// expand -cbool scc_pp_expand_macro(scc_probe_stream_t *stream, - scc_pp_macro_table_t *macros, - 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 deleted file mode 100644 index eb46c08..0000000 --- a/libs/pprocessor/include/pp_token.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __SCC_PP_TOKEN_H__ -#define __SCC_PP_TOKEN_H__ - -/* clang-format off */ -/// https://cppreference.cn/w/c/preprocessor -#define SCC_PP_INST_TOKEN \ - X(define , SCC_PP_STD, SCC_PP_TOK_DEFINE ) \ - X(elif , SCC_PP_STD, SCC_PP_TOK_ELIF ) \ - X(elifdef , SCC_PP_STD, SCC_PP_TOK_ELIFDEF ) \ - X(elifndef , SCC_PP_STD, SCC_PP_TOK_ELIFNDEF ) \ - X(else , SCC_PP_STD, SCC_PP_TOK_ELSE ) \ - X(embed , SCC_PP_STD, SCC_PP_TOK_EMBED ) \ - X(endif , SCC_PP_STD, SCC_PP_TOK_ENDIF ) \ - X(error , SCC_PP_STD, SCC_PP_TOK_ERROR ) \ - X(if , SCC_PP_STD, SCC_PP_TOK_IF ) \ - X(ifdef , SCC_PP_C23, SCC_PP_TOK_IFDEF ) \ - X(ifndef , SCC_PP_STD, SCC_PP_TOK_IFNDEF ) \ - X(include , SCC_PP_STD, SCC_PP_TOK_INCLUDE ) \ - X(line , SCC_PP_C23, SCC_PP_TOK_LINE ) \ - X(pragma , SCC_PP_STD, SCC_PP_TOK_PRAGMA ) \ - X(undef , SCC_PP_C23, SCC_PP_TOK_UNDEF ) \ - X(warning , SCC_PP_STD, SCC_PP_TOK_WARNING ) \ - // END -/* clang-format on */ - -#define X(name, type, tok) tok, -typedef enum scc_pp_token { SCC_PP_INST_TOKEN } scc_pp_token_t; -#undef X - -#endif /* __SCC_PP_TOKEN_H__ */ diff --git a/libs/pprocessor/include/pprocessor.h b/libs/pprocessor/include/pprocessor.h deleted file mode 100644 index b1d5ec1..0000000 --- a/libs/pprocessor/include/pprocessor.h +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @file pprocessor.h - * @brief C语言预处理器核心数据结构与接口 - */ - -#ifndef __SCC_PP_H__ -#define __SCC_PP_H__ - -#include -#include -#include - -// 条件编译状态 -typedef enum { - IFState_NONE, // 不在条件编译中 - IFState_TRUE, // 条件为真 - IFState_FALSE, // 条件为假 - IFState_ELSE // 已经执行过else分支 -} if_state_t; - -// 条件编译栈项 -typedef struct if_stack_item { - if_state_t state; - int skip; // 是否跳过当前段 -} if_stack_item_t; - -// 预处理器状态结构 -typedef struct scc_pproc { - scc_probe_stream_t *stream; // 输出流 - scc_strpool_t strpool; // 字符串池 - scc_pp_macro_table_t macro_table; - SCC_VEC(if_stack_item_t) if_stack; // 条件编译栈 -} scc_pproc_t; - -/** - * @brief 初始化预处理器 - * @param[out] pp 要初始化的预处理器实例 - * @param[in] input 输入流对象指针 - * @return output 输出流对象指针 - */ -// TODO 内存释放问题 -scc_probe_stream_t *scc_pproc_init(scc_pproc_t *pp, scc_probe_stream_t *input); - -/** - * @brief 销毁预处理器 - * @param[in] pp 预处理器实例 - */ -void scc_pproc_drop(scc_pproc_t *pp); - -/// inner private struct - -typedef SCC_VEC(u8) scc_pp_buffer_t; -typedef struct pp_stream { - scc_probe_stream_t stream; - scc_probe_stream_t *input; - scc_pproc_t *self; - - scc_pos_t pos; - scc_probe_stream_t *tmp_stream; -} scc_pp_stream_t; - -#endif /* __SCC_PP_H__ */ diff --git a/libs/pprocessor/src/expand_macro.c b/libs/pprocessor/src/expand_macro.c deleted file mode 100644 index f57c053..0000000 --- a/libs/pprocessor/src/expand_macro.c +++ /dev/null @@ -1,412 +0,0 @@ -#include -#include -#include -static inline void scc_generate_cstr(scc_cstring_t *buff) { - scc_cstring_t out_buff = scc_cstring_create(); - scc_cstring_append_ch(&out_buff, '\"'); - // TODO it is too simple - scc_cstring_append(&out_buff, buff); - scc_cstring_append_ch(&out_buff, '\"'); - - // FIXME 可能有着更好的解决方案 - scc_cstring_clear(buff); - scc_cstring_append(buff, &out_buff); - scc_cstring_free(&out_buff); -} - -#define SCC_PP_IS_LIST_BLANK(i) \ - ((i) < list->size && scc_vec_at(*list, (i)).data[0] == ' ' && \ - scc_vec_at(*list, (i)).data[1] == '\0') -#define SCC_PP_IS_LIST_TO_STRING(i) \ - ((i) < list->size && scc_vec_at(*list, (i)).data[0] == '#' && \ - scc_vec_at(*list, (i)).data[1] == '\0') -#define SCC_PP_IS_LIST_CONNECT(i) \ - ((i) < list->size && scc_vec_at(*list, (i)).data[0] == '#' && \ - scc_vec_at(*list, (i)).data[1] == '#' && \ - scc_vec_at(*list, (i)).data[2] == '\0') -#define SCC_PP_USE_CONNECT(font, rear) \ - if (rear < list->size) { \ - scc_cstring_append(out_buff, &scc_vec_at(*list, font)); \ - scc_cstring_append(out_buff, &scc_vec_at(*list, rear)); \ - } else { \ - scc_cstring_append(out_buff, &scc_vec_at(*list, font)); \ - } -// for # ## to generator string -static inline cbool scc_pp_expand_string_unsafe(const scc_pp_macro_list_t *list, - scc_cstring_t *out_buff) { - for (usize i = 0; i < list->size; ++i) { - if (SCC_PP_IS_LIST_BLANK(i + 1)) { - if (SCC_PP_IS_LIST_CONNECT(i + 2)) { - SCC_PP_USE_CONNECT(i, i + 3); - i += 3; - continue; - } - } else if (SCC_PP_IS_LIST_CONNECT(i + 1)) { - SCC_PP_USE_CONNECT(i, i + 2); - i += 2; - continue; - } else if (SCC_PP_IS_LIST_TO_STRING(i)) { - i += 1; - if (i < list->size) { - scc_generate_cstr(&scc_vec_at(*list, i)); - } else { - LOG_ERROR("# need a valid literator"); - break; - } - } - scc_cstring_append(out_buff, &scc_vec_at(*list, i)); - } - return true; -} - -// 展开对象宏 -cbool scc_pp_expand_object_macro(const scc_pp_macro_t *macro, - scc_cstring_t *out_buff) { - Assert(macro->type == SCC_PP_MACRO_OBJECT && macro->params.size == 0); - Assert(scc_cstring_is_empty(out_buff) == true); - // 对象宏输出替换文本并进行递归展开 - scc_pp_expand_string_unsafe(¯o->replaces, out_buff); - return true; -} - -// 展开函数宏 -cbool scc_pp_expand_function_macro(const scc_pp_macro_t *macro, - const scc_pp_macro_list_t *origin_params, - scc_pp_macro_list_t *params, - scc_cstring_t *out_buff) { - Assert(macro->type == SCC_PP_MACRO_FUNCTION); - Assert(out_buff != null); - Assert(scc_cstring_is_empty(out_buff) == true); - Assert(params->size == macro->params.size || params->size == 0); - - scc_pp_macro_list_t list; - scc_vec_init(list); - for (usize i = 0; i < macro->replaces.size; ++i) { - // TODO ... __VA_ARGS__ - for (usize j = 0; j < macro->params.size; ++j) { - if (scc_strcmp( - scc_cstring_as_cstr(&scc_vec_at(macro->replaces, i)), - scc_cstring_as_cstr(&scc_vec_at(macro->params, j))) != 0) { - continue; - } - if (params->size == 0) { - scc_vec_push(list, scc_cstring_from_cstr("")); - goto END; - } - Assert(&scc_vec_at(*params, j) != null); - scc_vec_push(list, scc_cstring_copy(&scc_vec_at(*params, j))); - goto END; - } - scc_vec_push(list, scc_cstring_copy(&scc_vec_at(macro->replaces, i))); - END:; - } - scc_pp_expand_string_unsafe(&list, out_buff); - for (usize i = 0; i < list.size; ++i) { - scc_cstring_free(&scc_vec_at(list, i)); - } - scc_vec_free(list); - return true; -} - -// 状态管理结构 -typedef struct { - scc_pp_macro_table_t *macros; - scc_pp_macro_table_t painted_blue; // 正在展开的宏 - int depth; -} scc_expansion_ctx_t; - -// 进入宏展开 -static void enter_macro_expansion(scc_expansion_ctx_t *state, - scc_pp_macro_t *macro) { - // 添加到活动宏集合 - scc_pp_macro_table_set(&state->painted_blue, - scc_pp_macro_new(¯o->name, macro->type)); -} - -// 离开宏展开(开始重新扫描) -static void leave_macro_expansion(scc_expansion_ctx_t *state, - scc_pp_macro_t *macro) { - // 从活动宏移除,添加到禁用宏 - scc_pp_macro_table_remove(&state->painted_blue, ¯o->name); -} - -// 检查是否可以展开 -static cbool can_expand_macro(scc_expansion_ctx_t *state, - scc_pp_macro_t *macro) { - return scc_pp_macro_table_get(&state->painted_blue, ¯o->name) == null; -} - -typedef struct { - scc_cstring_t identifier; - scc_pp_macro_list_t args; -} scc_expand_unit_t; - -void scc_pp_parse_expand_macro(scc_probe_stream_t *stream, scc_pos_t *pos, - scc_expand_unit_t *unit) { - Assert(stream != null && pos != null && unit != null); - // TODO Assert empty unit - scc_cstring_init(&unit->identifier); - scc_vec_init(unit->args); - cbool ret = scc_lex_parse_identifier(stream, pos, &unit->identifier); - Assert(ret == true); - scc_probe_stream_sync(stream); - do { - if (scc_lex_parse_is_whitespace(scc_probe_stream_peek(stream))) { - scc_lex_parse_skip_whitespace(stream, pos); - } - if (scc_probe_stream_peek(stream) != '(') { - // TODO maybe error - // 因为没能正确表述空值 - break; - } - // TODO maybe like f()() => maybe twice expand - ret = scc_pp_parse_macro_arguments(stream, &unit->args); - scc_probe_stream_sync(stream); - Assert(ret == true); - } while (0); -} - -static cbool expand_buffer(const scc_cstring_t *in, scc_cstring_t *out, - scc_expansion_ctx_t *state); - -static inline void args2str_append(const scc_pp_macro_list_t *args, - scc_cstring_t *out) { - Assert(args != null); - if (args->size != 0) { - scc_cstring_append_ch(out, '('); - for (usize i = 0; i < args->size; ++i) { - scc_cstring_append(out, &scc_vec_at(*args, i)); - if (i != args->size - 1) { - scc_cstring_append_ch(out, ','); - scc_cstring_append_ch(out, ' '); - } - } - scc_cstring_append_ch(out, ')'); - } -} - -static cbool expand_macro(const scc_expand_unit_t *unit, scc_cstring_t *out, - scc_expansion_ctx_t *state) { - scc_pp_macro_t *macro = - scc_pp_macro_table_get(state->macros, &unit->identifier); - if (macro == null) { - scc_cstring_append(out, &unit->identifier); - args2str_append(&unit->args, out); - return true; - } - cbool ret; - if (macro->type == SCC_PP_MACRO_OBJECT) { - if (can_expand_macro(state, macro)) { - ret = scc_pp_expand_object_macro(macro, out); - Assert(ret == true); - args2str_append(&unit->args, out); - } else { - scc_cstring_append(out, ¯o->name); - args2str_append(&unit->args, out); - return true; - } - } else if (macro->type == SCC_PP_MACRO_FUNCTION) { - /** - * 1. 参数先展开 - * 2. 替换后重扫描 - * 3. 蓝色集合中不展开 - * 4. #, ## 不展开 - * 5. 最后的括号要检查 - */ - - scc_pp_macro_list_t expanded_params; - scc_vec_init(expanded_params); - // expand params fisrt and recursive - for (usize i = 0; i < unit->args.size; ++i) { - scc_cstring_t param = scc_vec_at(unit->args, i); - scc_cstring_t out = scc_cstring_create(); - expand_buffer(¶m, &out, state); - scc_vec_push(expanded_params, out); - } - - if (can_expand_macro(state, macro)) { - ret = scc_pp_expand_function_macro(macro, &unit->args, - &expanded_params, out); - Assert(ret == true); - } else { - scc_cstring_append(out, ¯o->name); - args2str_append(&expanded_params, out); - return true; - } - // TODO memory leak - } else { - UNREACHABLE(); - } - - // 重新扫描展开结果 - scc_cstring_t rescanned = scc_cstring_create(); - enter_macro_expansion(state, macro); - expand_buffer(out, &rescanned, state); - leave_macro_expansion(state, macro); - - scc_cstring_free(out); - *out = rescanned; - return true; -} - -static cbool expand_buffer(const scc_cstring_t *in, scc_cstring_t *out, - scc_expansion_ctx_t *state) { - scc_probe_stream_t *in_stream = scc_mem_probe_stream_alloc( - scc_cstring_as_cstr(in), scc_cstring_len(in), false); - - int ch; - scc_pos_t pos; - scc_expand_unit_t unit; - while ((ch = scc_probe_stream_peek(in_stream)) != scc_stream_eof) { - if (scc_lex_parse_is_identifier_prefix(ch)) { - // 递归检查 - scc_cstring_t expanded_buffer = scc_cstring_create(); - scc_pp_parse_expand_macro(in_stream, &pos, &unit); - scc_probe_stream_reset(in_stream); - if (expand_macro(&unit, &expanded_buffer, state) == false) { - scc_cstring_free(&expanded_buffer); - return false; - } else { - scc_cstring_append(out, &expanded_buffer); - scc_cstring_free(&expanded_buffer); - } - } else { - scc_cstring_append_ch(out, scc_probe_stream_consume(in_stream)); - } - } - - scc_probe_stream_drop(in_stream); - return true; -} - -// static cbool scc_pp_expand_macro_impl(scc_probe_stream_t *stream, -// scc_expansion_ctx_t *ctx, scc_pos_t -// *pos, scc_cstring_t *output) { -// // TODO self position and it maybe is a stack on #include ? -// // 递归扫描 -// if (ctx->depth-- <= 0) { -// scc_cstring_free(output); -// return false; -// } -// cbool ret; -// scc_pp_macro_table_t *macros = ctx->macros; - -// scc_cstring_t identifier = scc_cstring_create(); -// ret = scc_lex_parse_identifier(stream, pos, &identifier); -// Assert(ret == true); - -// scc_pp_macro_t *macro = scc_pp_macro_table_get(macros, &identifier); - -// // 1. 不是宏,直接输出标识符 -// if (macro == null) { -// // 不是宏,直接输出 -// usize length = scc_cstring_len(&identifier); -// *out_stream = scc_mem_probe_stream_alloc( -// scc_cstring_move_cstr(&identifier), length, true); -// return true; -// } else { -// scc_cstring_free(&identifier); -// } - -// // 收集参数(如果是函数宏) -// scc_pp_macro_list_t params; -// scc_pp_macro_list_t expanded_params; -// scc_vec_init(params); -// scc_vec_init(expanded_params); -// if (macro->type == SCC_PP_MACRO_FUNCTION) { -// // TODO when expand need check another func with () at the end -// scc_lex_parse_skip_whitespace(stream, &pos); -// if (scc_probe_stream_peek(stream) != '(') { -// goto ORIGIN; -// } -// ret = scc_pp_parse_macro_arguments(stream, ¶ms); -// Assert(ret == true); - -// // expand params fisrt and recursive -// for (usize i = 0; i < params.size; ++i) { -// scc_cstring_t param = scc_vec_at(params, i); -// scc_cstring_t out = scc_cstring_create(); -// expand_buffer(¶m, &out, ctx); -// scc_vec_push(expanded_params, out); -// } -// } - -// // 2. 检查到重复展开跳过 -// // 检查是否可以展开 -// if (!can_expand_macro(ctx, macro)) { -// ORIGIN: -// // 输出原始调用 -// scc_cstring_t original = scc_cstring_create(); -// scc_cstring_append(&original, ¯o->name); -// if (macro->type == SCC_PP_MACRO_FUNCTION && expanded_params.size != -// 0) { -// scc_cstring_append_ch(&original, '('); -// for (usize i = 0; i < expanded_params.size; ++i) { -// scc_cstring_append(&original, &scc_vec_at(expanded_params, -// i)); if (i != expanded_params.size - 1) { -// scc_cstring_append_ch(&original, ','); -// scc_cstring_append_ch(&original, ' '); -// } -// } -// scc_cstring_append_ch(&original, ')'); -// } -// *out_stream = scc_mem_probe_stream_alloc( -// scc_cstring_as_cstr(&original), scc_cstring_len(&original), -// true); -// scc_vec_free(params); -// scc_vec_free(expanded_params); -// return true; -// } - -// // 开始展开 -// scc_cstring_t expanded = scc_cstring_create(); -// if (macro->type == SCC_PP_MACRO_OBJECT) { -// ret = scc_pp_expand_object_macro(macro, &expanded); -// Assert(ret == true); -// } else if (macro->type == SCC_PP_MACRO_FUNCTION) { -// ret = scc_pp_expand_function_macro(macro, ¶ms, &expanded_params, -// &expanded); -// Assert(ret == true); -// } else { -// UNREACHABLE(); -// } - -// // 重新扫描展开结果 -// // 将展开内容变换成stream并递归展开 -// scc_cstring_t rescanned = scc_cstring_create(); -// enter_macro_expansion(ctx, macro); -// expand_buffer(&expanded, &rescanned, ctx); -// leave_macro_expansion(ctx, macro); - -// scc_cstring_free(&expanded); -// // TODO memory leak - -// *out_stream = scc_mem_probe_stream_alloc(scc_cstring_as_cstr(&rescanned), -// scc_cstring_len(&rescanned), -// true); -// return true; -// } - -cbool scc_pp_expand_macro(scc_probe_stream_t *stream, - scc_pp_macro_table_t *macros, - scc_probe_stream_t **out_stream, int depth) { - Assert(depth > 0 && stream != null && macros != null && out_stream != null); - scc_expansion_ctx_t state; - state.depth = depth; - scc_pp_marco_table_init(&state.painted_blue); - state.macros = macros; - scc_cstring_t buffer = scc_cstring_create(); - scc_pos_t pos; - // cbool ret = scc_pp_expand_macro_impl(stream, &state, &pos, &buffer); - - // expand_buffer(stream, &buffer, &state); - scc_expand_unit_t unit; - scc_pp_parse_expand_macro(stream, &pos, &unit); - scc_probe_stream_reset(stream); - expand_macro(&unit, &buffer, &state); - - *out_stream = scc_mem_probe_stream_alloc(scc_cstring_as_cstr(&buffer), - scc_cstring_len(&buffer), true); - scc_pp_macro_table_drop(&state.painted_blue); - return true; -} diff --git a/libs/pprocessor/src/macro.c b/libs/pprocessor/src/macro.c deleted file mode 100644 index d3d8a62..0000000 --- a/libs/pprocessor/src/macro.c +++ /dev/null @@ -1,155 +0,0 @@ -#include - -// 创建宏对象 -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"); - return null; - } - - macro->name = scc_cstring_copy(name); - macro->type = type; - scc_vec_init(macro->params); - scc_vec_init(macro->replaces); - - return macro; -} - -// 销毁宏对象 -void scc_pp_macro_drop(scc_pp_macro_t *macro) { - if (!macro) - return; - - scc_cstring_free(¯o->name); - - // 释放参数列表 - for (usize i = 0; i < macro->params.size; ++i) { - scc_cstring_free(&scc_vec_at(macro->params, i)); - } - scc_vec_free(macro->params); - - // 释放替换列表 - for (usize i = 0; i < macro->replaces.size; ++i) { - scc_cstring_free(&scc_vec_at(macro->replaces, i)); - } - scc_vec_free(macro->replaces); - - scc_free(macro); -} - -// 添加对象宏 -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_new(name, SCC_PP_MACRO_OBJECT); - if (!macro) - return false; - - macro->replaces = *replacement; - - // 检查是否已存在同名宏 - scc_pp_macro_t *existing = scc_hashtable_get(¯os->table, ¯o->name); - if (existing) { - LOG_WARN("Redefining macro: %s", scc_cstring_as_cstr(¯o->name)); - scc_pp_macro_drop(existing); - } - - scc_hashtable_set(¯os->table, ¯o->name, macro); - return true; -} - -// 添加函数宏 -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_new(name, SCC_PP_MACRO_FUNCTION); - if (!macro) - return false; - - // 复制参数列表 - macro->params = *params; - macro->replaces = *replacement; - - // 检查是否已存在同名宏 - scc_pp_macro_t *existing = scc_hashtable_get(¯os->table, ¯o->name); - if (existing) { - LOG_WARN("Redefining macro: %s", scc_cstring_as_cstr(¯o->name)); - scc_pp_macro_drop(existing); - } - - scc_hashtable_set(¯os->table, ¯o->name, macro); - 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_macro_table_get(scc_pp_macro_table_t *pp, - const scc_cstring_t *name) { - return scc_hashtable_get(&pp->table, name); -} - -// 从预处理器中删除宏 -cbool scc_pp_macro_table_remove(scc_pp_macro_table_t *pp, - const scc_cstring_t *name) { - if (!pp || !name) - return false; - - scc_pp_macro_t *macro = scc_hashtable_get(&pp->table, name); - if (!macro) - return false; - - scc_hashtable_del(&pp->table, name); - scc_pp_macro_drop(macro); - return true; -} - -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)); -} - -static int hash_cmp(const void *key1, const void *key2) { - const scc_cstring_t *str1 = (const scc_cstring_t *)key1; - const scc_cstring_t *str2 = (const scc_cstring_t *)key2; - - if (str1->size != str2->size) { - return str1->size - str2->size; - } - return scc_strcmp(scc_cstring_as_cstr(str1), scc_cstring_as_cstr(str2)); -} - -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; - scc_hashtable_init(¯os->table); -} - -static int macro_free(const void *key, void *value, void *context) { - (void)key; - (void)context; - scc_pp_macro_drop(value); - return 0; -} - -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 deleted file mode 100644 index 9cb90a2..0000000 --- a/libs/pprocessor/src/parse.c +++ /dev/null @@ -1,295 +0,0 @@ -#include -#include -#include -#include - -static const struct { - const char *name; - scc_pp_token_t tok; -} keywords[] = { -#define X(name, type, tok) {#name, tok}, - SCC_PP_INST_TOKEN -#undef X -}; - -// 使用二分查找查找关键字 -static inline int keyword_cmp(const char *name, int len) { - int low = 0; - int high = sizeof(keywords) / sizeof(keywords[0]) - 1; - while (low <= high) { - int mid = (low + high) / 2; - const char *key = keywords[mid].name; - int cmp = 0; - - // 自定义字符串比较逻辑 - for (int i = 0; i < len; i++) { - if (name[i] != key[i]) { - cmp = (unsigned char)name[i] - (unsigned char)key[i]; - break; - } - if (name[i] == '\0') - break; // 遇到终止符提前结束 - } - - if (cmp == 0) { - // 完全匹配检查(长度相同) - if (key[len] == '\0') - return mid; - cmp = -1; // 当前关键词比输入长 - } - - if (cmp < 0) { - high = mid - 1; - } else { - low = mid + 1; - } - } - return -1; // Not a keyword. -} - -static inline void try_to_cut_list(scc_pp_macro_list_t *list, - scc_cstring_t *buff) { - if (scc_cstring_len(buff) != 0) { - scc_vec_push(*list, *buff); - *buff = scc_cstring_create(); - } -} - -cbool scc_pp_parse_macro_replace_list(scc_probe_stream_t *stream, - scc_pp_macro_list_t *list) { - Assert(stream != null && list != null); - // scc_probe_stream_reset(stream); - - scc_vec_init(*list); - scc_cstring_t replacement = scc_cstring_create(); - int ch; - scc_pos_t pos = scc_pos_create(); - - while ((ch = scc_probe_stream_peek(stream)) != scc_stream_eof) { - if (scc_lex_parse_is_endline(ch)) { - break; - } - if (scc_lex_parse_is_identifier_prefix(ch)) { - try_to_cut_list(list, &replacement); - cbool ret = scc_lex_parse_identifier(stream, &pos, &replacement); - Assert(ret == true); - try_to_cut_list(list, &replacement); - } else if (ch == '#') { - // 处理 # 和 ## 操作符 - scc_probe_stream_next(stream); - try_to_cut_list(list, &replacement); - - scc_cstring_append_ch(&replacement, '#'); - if (scc_probe_stream_peek(stream) == '#') { - // ## 连接操作符 - scc_probe_stream_next(stream); - scc_cstring_append_ch(&replacement, '#'); - } - // 我需要尽可能防止空白字符干扰解析 - scc_lex_parse_skip_whitespace(stream, &pos); - try_to_cut_list(list, &replacement); - } else if (scc_lex_parse_is_whitespace(ch)) { - try_to_cut_list(list, &replacement); - scc_lex_parse_skip_whitespace(stream, &pos); - scc_cstring_append_ch(&replacement, ' '); - try_to_cut_list(list, &replacement); - } else { - scc_probe_stream_next(stream); - scc_cstring_append_ch(&replacement, (char)ch); - } - } - - if (scc_cstring_len(&replacement) != 0) { - scc_vec_push(*list, replacement); - replacement = scc_cstring_create(); - } - - // for (usize i = 0; i < list->size; ++i) { - // LOG_DEBUG("list %d: %s", (int)i, - // scc_cstring_as_cstr(&scc_vec_at(*list, i))); - // } - return true; -} - -// 解析宏参数列表 -cbool scc_pp_parse_macro_arguments(scc_probe_stream_t *stream, - scc_pp_macro_list_t *args) { - Assert(stream != null && args != null); - - scc_vec_init(*args); - int ch; - // scc_probe_stream_reset(stream); - - // 跳过 '(' - ch = scc_probe_stream_peek(stream); - if (ch != '(') { - return false; - } - scc_probe_stream_next(stream); // 消费 '(' - - int paren_depth = 1; - scc_cstring_t current_arg = scc_cstring_create(); - scc_pos_t pos = scc_pos_create(); - - while (paren_depth > 0) { - ch = scc_probe_stream_peek(stream); - if (ch == scc_stream_eof) { - scc_cstring_free(¤t_arg); - scc_cstring_free(&pos.name); - return false; - } - - if (ch == '(') { - paren_depth++; - scc_cstring_append_ch(¤t_arg, (char)ch); - scc_probe_stream_next(stream); - } else if (ch == ')') { - paren_depth--; - if (paren_depth > 0) { - scc_cstring_append_ch(¤t_arg, (char)ch); - } - scc_probe_stream_next(stream); - } else if (ch == ',' && paren_depth == 1) { - // 参数分隔符 - scc_vec_push(*args, current_arg); - current_arg = scc_cstring_create(); - scc_probe_stream_next(stream); - // 跳过参数后的空白 - scc_lex_parse_skip_whitespace(stream, &pos); - } else { - scc_cstring_append_ch(¤t_arg, (char)ch); - scc_probe_stream_next(stream); - } - } - - // 添加最后一个参数 - if (!scc_cstring_is_empty(¤t_arg)) { - scc_vec_push(*args, current_arg); - } else { - scc_cstring_free(¤t_arg); - } - - scc_cstring_free(&pos.name); - return true; -} - -static cbool safe_skip_backspace_if_endline(scc_probe_stream_t *stream, - scc_pos_t *pos) { - // scc_probe_stream_reset(stream); - int ch = scc_probe_stream_peek(stream); - // FIXME maybe it not correct - while (ch == '\r' || ch == '\n' || ch == ' ' || ch == '\t') { - if (scc_lex_parse_is_endline(ch)) { - scc_lex_parse_skip_endline(stream, pos); - return true; - } - scc_probe_stream_next(stream); - ch = scc_probe_stream_peek(stream); - } - // scc_probe_stream_reset(stream); - return false; -} - -void scc_pp_parse_directive(scc_probe_stream_t *stream, scc_pos_t *pos, - scc_pp_macro_table_t *macros) { - Assert(stream != null); - - // scc_probe_stream_reset(stream); - // 跳过 '#' 和后续空白 - if (scc_probe_stream_peek(stream) != '#') { - LOG_WARN("Invalid directive"); - return; - } - scc_pos_next(pos); - scc_probe_stream_next(stream); - if (safe_skip_backspace_if_endline(stream, pos)) - return; - - // 解析指令名称 - scc_cstring_t directive = scc_cstring_create(); - if (!scc_lex_parse_identifier(stream, pos, &directive)) { - goto ERR; - } - if (safe_skip_backspace_if_endline(stream, pos)) - goto FREE; - - scc_pp_token_t token = keyword_cmp(scc_cstring_as_cstr(&directive), - scc_cstring_len(&directive)); - - scc_cstring_t name = scc_cstring_create(); - switch (token) { - case SCC_PP_TOK_DEFINE: { - if (!scc_lex_parse_identifier(stream, pos, &name)) { - goto ERR; - } - - // 检查是否是函数宏:宏名后是否直接跟着 '('(没有空白字符) - // scc_probe_stream_reset(stream); - int ch = scc_probe_stream_peek(stream); - cbool has_whitespace = scc_lex_parse_is_whitespace(ch); - if (has_whitespace && safe_skip_backspace_if_endline(stream, pos)) { - goto FREE; - } - - if (!has_whitespace && ch == '(') { - // 函数宏 - scc_pp_macro_list_t params; - if (!scc_pp_parse_macro_arguments(stream, ¶ms)) { - goto ERR; - } - - ch = scc_probe_stream_peek(stream); - if (ch == ')') { - scc_probe_stream_next(stream); // 消费 ')' - } - if (safe_skip_backspace_if_endline(stream, pos)) { - goto FREE; - } - - scc_pp_macro_list_t replacement; - scc_pp_parse_macro_replace_list(stream, &replacement); - scc_pp_add_function_macro(macros, &name, ¶ms, &replacement); - } else { - // 对象宏 - scc_pp_macro_list_t replacement; - scc_pp_parse_macro_replace_list(stream, &replacement); - scc_pp_add_object_macro(macros, &name, &replacement); - } - break; - } - case SCC_PP_TOK_UNDEF: { - if (scc_lex_parse_identifier(stream, pos, &name)) { - cbool ret = scc_pp_macro_table_remove(macros, &name); - Assert(ret == true); - } - break; - } - case SCC_PP_TOK_INCLUDE: - case SCC_PP_TOK_IF: - case SCC_PP_TOK_IFDEF: - case SCC_PP_TOK_IFNDEF: - case SCC_PP_TOK_ELSE: - case SCC_PP_TOK_ELIF: - case SCC_PP_TOK_ELIFDEF: - case SCC_PP_TOK_ELIFNDEF: - case SCC_PP_TOK_ENDIF: - case SCC_PP_TOK_LINE: - case SCC_PP_TOK_EMBED: - case SCC_PP_TOK_ERROR: - case SCC_PP_TOK_WARNING: - case SCC_PP_TOK_PRAGMA: - // 暂时跳过这一行 - scc_lex_parse_skip_line(stream, pos); - TODO(); - break; - default: - LOG_WARN("Unknown preprocessor directive: %s", - scc_cstring_as_cstr(&directive)); - scc_lex_parse_skip_line(stream, pos); - } -ERR: - scc_lex_parse_skip_line(stream, pos); -FREE: - scc_cstring_free(&directive); - scc_cstring_free(&name); -} diff --git a/libs/pprocessor/src/pprocessor.c b/libs/pprocessor/src/pprocessor.c deleted file mode 100644 index 01b4eed..0000000 --- a/libs/pprocessor/src/pprocessor.c +++ /dev/null @@ -1,132 +0,0 @@ -/** - * @file pprocessor.c - * @brief C语言预处理器实现 - */ - -#include -#include -#include -#include -#include - -#ifdef TEST_MODE -#define MAX_MACRO_EXPANSION_DEPTH 16 -#else -#define MAX_MACRO_EXPANSION_DEPTH 64 // 防止无限递归的最大展开深度 -#endif - -static int pp_stream_read_char(scc_probe_stream_t *_stream) { - scc_pp_stream_t *stream = (scc_pp_stream_t *)_stream; - Assert(stream != null); - int ch; - -READ_BUF: - if (stream->tmp_stream != null && - (ch = scc_probe_stream_consume(stream->tmp_stream)) != scc_stream_eof) { - return ch; - } -RETRY: - scc_probe_stream_reset(stream->input); - ch = scc_probe_stream_peek(stream->input); - - if (ch == '#') { - scc_pp_parse_directive(stream->input, &stream->pos, - &stream->self->macro_table); - scc_probe_stream_sync(stream->input); - goto RETRY; - } else if (scc_lex_parse_is_identifier_prefix(ch)) { - cbool ret = - scc_pp_expand_macro(stream->input, &stream->self->macro_table, - &stream->tmp_stream, MAX_MACRO_EXPANSION_DEPTH); - 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_probe_stream_reset(stream->input); - scc_lex_parse_skip_line(stream->input, &stream->pos); - scc_probe_stream_sync(stream->input); - } else if (ch == '*') { - scc_probe_stream_reset(stream->input); - scc_lex_parse_skip_block_comment(stream->input, &stream->pos); - scc_probe_stream_sync(stream->input); - } - } - - // 非标识符字符,直接消费并返回 - return scc_probe_stream_consume(stream->input); -} - -static void pp_stream_drop(scc_probe_stream_t *_stream) { - scc_pp_stream_t *stream = (scc_pp_stream_t *)_stream; - Assert(stream != null); - scc_cstring_free(&stream->stream.name); - if (stream->tmp_stream) { - scc_probe_stream_drop(stream->tmp_stream); - } - scc_free(_stream); -} - -static scc_probe_stream_t *pp_stream_init(scc_pproc_t *self, - scc_probe_stream_t *input) { - scc_pp_stream_t *stream = scc_malloc(sizeof(scc_pp_stream_t)); - if (stream == null) { - LOG_FATAL("Failed to allocate memory for output stream"); - return null; - } - - if (self == null) { - scc_free(stream); - return null; - } - - stream->self = self; - stream->input = input; - - stream->tmp_stream = null; - stream->pos = scc_pos_create(); - - stream->stream.name = scc_cstring_from_cstr("pp_stream"); - stream->stream.consume = pp_stream_read_char; - stream->stream.peek = null; - stream->stream.next = null; - stream->stream.sync = null; - stream->stream.reset = null; - stream->stream.back = null; - stream->stream.read_buf = null; - stream->stream.is_at_end = null; - stream->stream.drop = pp_stream_drop; - - return (scc_probe_stream_t *)stream; -} - -scc_probe_stream_t *scc_pproc_init(scc_pproc_t *pp, scc_probe_stream_t *input) { - if (pp == null || input == null) { - return null; - } - - pp->stream = pp_stream_init(pp, input); - if (pp->stream == null) { - return null; - } - - scc_pp_marco_table_init(&pp->macro_table); - - return pp->stream; -} - -// 销毁预处理器 -void scc_pproc_drop(scc_pproc_t *pp) { - if (pp == null) - return; - - scc_pp_macro_table_drop(&pp->macro_table); - - // 清理流 - if (pp->stream) { - scc_probe_stream_drop(pp->stream); - pp->stream = null; - } -} diff --git a/libs/pprocessor/tests/pp/01.c b/libs/pprocessor/tests/pp/01.c deleted file mode 100644 index 2fc3d79..0000000 --- a/libs/pprocessor/tests/pp/01.c +++ /dev/null @@ -1,6 +0,0 @@ -#define hash_hash # ## # -#define mkstr(a) # a -#define in_between(a) mkstr(a) -#define join(c, d) in_between(c hash_hash d) -char p[] = join(x, y); -// char p[] = "x ## y"; diff --git a/libs/pprocessor/tests/pp/01.expect b/libs/pprocessor/tests/pp/01.expect deleted file mode 100644 index cf5b153..0000000 --- a/libs/pprocessor/tests/pp/01.expect +++ /dev/null @@ -1 +0,0 @@ -char p[] = "x ## y"; diff --git a/libs/pprocessor/tests/pp/02.c b/libs/pprocessor/tests/pp/02.c deleted file mode 100644 index feb1254..0000000 --- a/libs/pprocessor/tests/pp/02.c +++ /dev/null @@ -1,28 +0,0 @@ -#define x 3 -#define f(a) f(x * (a)) -#undef x -#define x 2 -#define g f -#define z z[0] -#define h g(~ -#define m(a) a(w) -#define w 0,1 -#define t(a) a -#define p() int -#define q(x) x -#define r(x,y) x ## y -#define str(x) # x -f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); -g(x+(3,4)-w) | h 5) & m -(f)^m(m); -char c[2][6] = { str(hello), str() }; -/* - * f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); - * f(2 * (2+(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); - * char c[2][6] = { "hello", "" }; - */ -#define L21 f(y+1) + f(f(z)) % t(t(g)(0) + t)(1); -#define L22 g(x+(3,4)-w) | h 5) & m\ -(f)^m(m); -L21 -L22 diff --git a/libs/pprocessor/tests/pp/02.expect b/libs/pprocessor/tests/pp/02.expect deleted file mode 100644 index 8ae2eb9..0000000 --- a/libs/pprocessor/tests/pp/02.expect +++ /dev/null @@ -1,5 +0,0 @@ -f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); -f(2 * (2 +(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); -char c[2][6] = { "hello", "" }; -f(2 * (y+1)) + f(2 * (f(2 * (z[0])))) % f(2 * (0)) + t(1); -f(2 * (2 +(3,4)-0,1)) | f(2 * (~ 5)) & f(2 * (0,1))^m(0,1); diff --git a/libs/pprocessor/tests/pp/03.c b/libs/pprocessor/tests/pp/03.c deleted file mode 100644 index a659245..0000000 --- a/libs/pprocessor/tests/pp/03.c +++ /dev/null @@ -1,15 +0,0 @@ -#define str(s) # s -#define xstr(s) str(s) -#define debug(s, t) printf("x" # s "= %d, x" # t "= %s", \ - x ## s, x ## t) -#define INCFILE(n) vers ## n -#define glue(a, b) a ## b -#define xglue(a, b) glue(a, b) -#define HIGHLOW "hello" -#define LOW LOW ", world" -debug(1, 2); -fputs(str(strncmp("abc\0d", "abc", '\4') // this goes away - == 0) str(: @\n), s); -\#include xstr(INCFILE(2).h) -glue(HIGH, LOW); -xglue(HIGH, LOW) diff --git a/libs/pprocessor/tests/pp/03.expect b/libs/pprocessor/tests/pp/03.expect deleted file mode 100644 index 44aad0a..0000000 --- a/libs/pprocessor/tests/pp/03.expect +++ /dev/null @@ -1,5 +0,0 @@ -printf("x" "1" "= %d, x" "2" "= %s", x1, x2); -fputs("strncmp(\"abc\\0d\", \"abc\", '\\4') == 0" ": @\n", s); -\#include "vers2.h" -"hello"; -"hello" ", world" diff --git a/libs/pprocessor/tests/pp/04.c b/libs/pprocessor/tests/pp/04.c deleted file mode 100644 index 0068f37..0000000 --- a/libs/pprocessor/tests/pp/04.c +++ /dev/null @@ -1,4 +0,0 @@ -#define foobar 1 -#define C(x,y) x##y -#define D(x) (C(x,bar)) -D(foo) diff --git a/libs/pprocessor/tests/pp/04.expect b/libs/pprocessor/tests/pp/04.expect deleted file mode 100644 index 7c67b01..0000000 --- a/libs/pprocessor/tests/pp/04.expect +++ /dev/null @@ -1 +0,0 @@ -(1) diff --git a/libs/pprocessor/tests/pp/05.c b/libs/pprocessor/tests/pp/05.c deleted file mode 100644 index 7274941..0000000 --- a/libs/pprocessor/tests/pp/05.c +++ /dev/null @@ -1,7 +0,0 @@ -#define t(x,y,z) x ## y ## z -#define xxx(s) int s[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), \ - t(10,,), t(,11,), t(,,12), t(,,) }; - -int j[] = { t(1,2,3), t(,4,5), t(6,,7), t(8,9,), - t(10,,), t(,11,), t(,,12), t(,,) }; -xxx(j) diff --git a/libs/pprocessor/tests/pp/05.expect b/libs/pprocessor/tests/pp/05.expect deleted file mode 100644 index 9f9be37..0000000 --- a/libs/pprocessor/tests/pp/05.expect +++ /dev/null @@ -1,3 +0,0 @@ -int j[] = { 123, 45, 67, 89, - 10, 11, 12, }; -int j[] = { 123, 45, 67, 89, 10, 11, 12, }; diff --git a/libs/pprocessor/tests/pp/06.c b/libs/pprocessor/tests/pp/06.c deleted file mode 100644 index 28cfdde..0000000 --- a/libs/pprocessor/tests/pp/06.c +++ /dev/null @@ -1,5 +0,0 @@ -#define X(a,b, \ - c,d) \ - foo - -X(1,2,3,4) diff --git a/libs/pprocessor/tests/pp/06.expect b/libs/pprocessor/tests/pp/06.expect deleted file mode 100644 index 257cc56..0000000 --- a/libs/pprocessor/tests/pp/06.expect +++ /dev/null @@ -1 +0,0 @@ -foo diff --git a/libs/pprocessor/tests/pp/07.c b/libs/pprocessor/tests/pp/07.c deleted file mode 100644 index b22b22b..0000000 --- a/libs/pprocessor/tests/pp/07.c +++ /dev/null @@ -1,4 +0,0 @@ -#define a() YES -#define b() a -b() -b()() diff --git a/libs/pprocessor/tests/pp/07.expect b/libs/pprocessor/tests/pp/07.expect deleted file mode 100644 index ad0e20a..0000000 --- a/libs/pprocessor/tests/pp/07.expect +++ /dev/null @@ -1,2 +0,0 @@ -a -YES diff --git a/libs/pprocessor/tests/pp/08.c b/libs/pprocessor/tests/pp/08.c deleted file mode 100644 index 93018e1..0000000 --- a/libs/pprocessor/tests/pp/08.c +++ /dev/null @@ -1,4 +0,0 @@ -// test macro expansion in arguments -#define s_pos s_s.s_pos -#define foo(x) (x) -foo(hej.s_pos) diff --git a/libs/pprocessor/tests/pp/08.expect b/libs/pprocessor/tests/pp/08.expect deleted file mode 100644 index 2b2e3ee..0000000 --- a/libs/pprocessor/tests/pp/08.expect +++ /dev/null @@ -1 +0,0 @@ -(hej.s_s.s_pos) diff --git a/libs/pprocessor/tests/pp/09.c b/libs/pprocessor/tests/pp/09.c deleted file mode 100644 index 315b297..0000000 --- a/libs/pprocessor/tests/pp/09.c +++ /dev/null @@ -1,4 +0,0 @@ -#define C(a,b,c) a##b##c -#define N(x,y) C(x,_,y) -#define A_O aaaaoooo -N(A,O) diff --git a/libs/pprocessor/tests/pp/09.expect b/libs/pprocessor/tests/pp/09.expect deleted file mode 100644 index adce0f9..0000000 --- a/libs/pprocessor/tests/pp/09.expect +++ /dev/null @@ -1 +0,0 @@ -aaaaoooo diff --git a/libs/pprocessor/tests/pp/10.c b/libs/pprocessor/tests/pp/10.c deleted file mode 100644 index f180eff..0000000 --- a/libs/pprocessor/tests/pp/10.c +++ /dev/null @@ -1,10 +0,0 @@ -#define f(x) x -#define g(x) f(x) f(x -#define i(x) g(x)) g(x -#define h(x) i(x))) i(x -#define k(x) i(x))) i(x)))) -f(x) -g(x)) -i(x))) -h(x)))) -k(x)))) diff --git a/libs/pprocessor/tests/pp/10.expect b/libs/pprocessor/tests/pp/10.expect deleted file mode 100644 index bd18e18..0000000 --- a/libs/pprocessor/tests/pp/10.expect +++ /dev/null @@ -1,5 +0,0 @@ -x -x x -x x x x -x x x x x x x x -x x x x x x x x)))) diff --git a/libs/pprocessor/tests/pp/11.c b/libs/pprocessor/tests/pp/11.c deleted file mode 100644 index d6ba7a9..0000000 --- a/libs/pprocessor/tests/pp/11.c +++ /dev/null @@ -1,36 +0,0 @@ -#define D1(s, ...) s -#define D2(s, ...) s D1(__VA_ARGS__) -#define D3(s, ...) s D2(__VA_ARGS__) -#define D4(s, ...) s D3(__VA_ARGS__) - -D1(a) -D2(a, b) -D3(a, b, c) -D4(a, b, c, d) - -x D4(a, b, c, d) y -x D4(a, b, c) y -x D4(a, b) y -x D4(a) y -x D4() y - -#define GNU_COMMA(X,Y...) X,##Y - -x GNU_COMMA(A,B,C) y -x GNU_COMMA(A,B) y -x GNU_COMMA(A) y -x GNU_COMMA() y - -#define __sun_attr___noreturn__ __attribute__((__noreturn__)) -#define ___sun_attr_inner(__a) __sun_attr_##__a -#define __sun_attr__(__a) ___sun_attr_inner __a -#define __NORETURN __sun_attr__((__noreturn__)) -__NORETURN -#define X(...) -#define Y(...) 1 __VA_ARGS__ 2 -Y(X X() ()) - -#define DDD(A, B) D_ ## B ## _D_ ## A -#define CCC(X, ...) DDD(X,## __VA_ARGS__) -/* must be D_B_D_A (not D_B _D_A) */ -CCC(A,B) diff --git a/libs/pprocessor/tests/pp/11.expect b/libs/pprocessor/tests/pp/11.expect deleted file mode 100644 index c1c99fe..0000000 --- a/libs/pprocessor/tests/pp/11.expect +++ /dev/null @@ -1,16 +0,0 @@ -a -a b -a b c -a b c d -x a b c d y -x a b c y -x a b y -x a y -x y -x A,B,C y -x A,B y -x A y -x y -__attribute__((__noreturn__)) -1 2 -D_B_D_A diff --git a/libs/pprocessor/tests/pp/12.S b/libs/pprocessor/tests/pp/12.S deleted file mode 100644 index 597ccb4..0000000 --- a/libs/pprocessor/tests/pp/12.S +++ /dev/null @@ -1,8 +0,0 @@ -#define SRC(y...) \ - 9999: y; \ - .section __ex_table, "a"; \ - .long 9999b, 6001f ; \ - // .previous - - SRC(1: movw (%esi), %bx) -6001: diff --git a/libs/pprocessor/tests/pp/12.expect b/libs/pprocessor/tests/pp/12.expect deleted file mode 100644 index 17a861c..0000000 --- a/libs/pprocessor/tests/pp/12.expect +++ /dev/null @@ -1,2 +0,0 @@ - 9999: 1: movw (%esi), %bx; .section __ex_table, "a"; .long 9999b, 6001f ; -6001: diff --git a/libs/pprocessor/tests/pp/13.S b/libs/pprocessor/tests/pp/13.S deleted file mode 100644 index bf0b525..0000000 --- a/libs/pprocessor/tests/pp/13.S +++ /dev/null @@ -1,6 +0,0 @@ -# `modelist' label. Each video mode record looks like: -#ifdef AAA -# modelist' label. Each video mode record looks like: -#endif -.text -endtext: diff --git a/libs/pprocessor/tests/pp/13.expect b/libs/pprocessor/tests/pp/13.expect deleted file mode 100644 index c7a3230..0000000 --- a/libs/pprocessor/tests/pp/13.expect +++ /dev/null @@ -1,2 +0,0 @@ -.text -endtext: diff --git a/libs/pprocessor/tests/pp/14.c b/libs/pprocessor/tests/pp/14.c deleted file mode 100644 index e15468c..0000000 --- a/libs/pprocessor/tests/pp/14.c +++ /dev/null @@ -1,13 +0,0 @@ -#define W Z -#define Z(X) W(X,2) -#define Y(X) Z(X) -#define X Y -return X(X(1)); - -#define P Q -#define Q(n) P(n,2) -return P(1); - -#define A (B * B) -#define B (A + A) -return A + B; diff --git a/libs/pprocessor/tests/pp/14.expect b/libs/pprocessor/tests/pp/14.expect deleted file mode 100644 index 3786044..0000000 --- a/libs/pprocessor/tests/pp/14.expect +++ /dev/null @@ -1,3 +0,0 @@ -return Z(Z(1,2),2); -return Q(1,2); -return ((A + A) * (A + A)) + ((B * B) + (B * B)); diff --git a/libs/pprocessor/tests/pp/15.c b/libs/pprocessor/tests/pp/15.c deleted file mode 100644 index cf13f9a..0000000 --- a/libs/pprocessor/tests/pp/15.c +++ /dev/null @@ -1,18 +0,0 @@ -// insert a space between two tokens if otherwise they -// would form a single token when read back - -#define n(x) x - -return (n(long)n(double))d; -return n(A)n(++)n(+)n(B); -return n(A)n(+)n(++)n(B); -return n(A)n(++)n(+)n(+)n(B); - -// not a hex float -return n(0x1E)n(-1); - -// unlike gcc but correct -// XXX: return n(x)+n(x)-n(1)+n(1)-2; - -// unlike gcc, but cannot appear in valid C -// XXX: return n(x)n(x)n(1)n(2)n(x); diff --git a/libs/pprocessor/tests/pp/15.expect b/libs/pprocessor/tests/pp/15.expect deleted file mode 100644 index b4f885e..0000000 --- a/libs/pprocessor/tests/pp/15.expect +++ /dev/null @@ -1,5 +0,0 @@ -return (long double)d; -return A+++B; -return A+ ++B; -return A+++ +B; -return 0x1E -1; diff --git a/libs/pprocessor/tests/pp/16.c b/libs/pprocessor/tests/pp/16.c deleted file mode 100644 index 8b5b642..0000000 --- a/libs/pprocessor/tests/pp/16.c +++ /dev/null @@ -1,3 +0,0 @@ -/* The following should warn */ -#define A ... -#define A <<= diff --git a/libs/pprocessor/tests/pp/16.expect b/libs/pprocessor/tests/pp/16.expect deleted file mode 100644 index 695d6d4..0000000 --- a/libs/pprocessor/tests/pp/16.expect +++ /dev/null @@ -1,2 +0,0 @@ - -16.c:3: warning: A redefined diff --git a/libs/pprocessor/tests/pp/17.c b/libs/pprocessor/tests/pp/17.c deleted file mode 100644 index f12196f..0000000 --- a/libs/pprocessor/tests/pp/17.c +++ /dev/null @@ -1,14 +0,0 @@ -#define STR1(u) # u -#define pass(a) a -#define __ASM_REG(reg) STR1(one##reg) -#define _ASM_DX __ASM_REG(tok) -X162 pass(__ASM_REG(tok)) -X161 pass(_ASM_DX) -X163 pass(STR1(one##tok)) - -X170 pass(x ## y) -X171 pass(x pass(##) y) - -#define Y(x) Z(x) -#define X Y -X180 return X(X(1)); diff --git a/libs/pprocessor/tests/pp/17.expect b/libs/pprocessor/tests/pp/17.expect deleted file mode 100644 index e95aafe..0000000 --- a/libs/pprocessor/tests/pp/17.expect +++ /dev/null @@ -1,6 +0,0 @@ -X162 "onetok" -X161 "onetok" -X163 "one##tok" -X170 x ## y -X171 x ## y -X180 return Z(Z(1)); diff --git a/libs/pprocessor/tests/pp/18.c b/libs/pprocessor/tests/pp/18.c deleted file mode 100644 index de47790..0000000 --- a/libs/pprocessor/tests/pp/18.c +++ /dev/null @@ -1,30 +0,0 @@ -#define M_RETI_ARG27(x,y,z,aa, ...) aa -#define M_RET_ARG27(...) M_RETI_ARG27(__VA_ARGS__) -#define M_COMMA_P(...) M_RET_ARG27(__VA_ARGS__, 1, 1, 0, useless) -#define M_EMPTYI_DETECT(...) 0, 1, -#define M_EMPTYI_P_C1(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__ () ) -#define EX -#define empty(x) -#define fnlike(x) yeah x -/* If the following macro is called with empty arg (X183), the use - of 'x' between fnlike and '(' doesn't hinder the recognition of this - being a further fnlike macro invocation. */ -#define usefnlike(x) fnlike x (x) -X181 M_EMPTYI_P_C1() -X182 M_EMPTYI_P_C1(x) -X183 usefnlike() - -#define ABC(x) ABC : x -#define A(a,b,c) a ## b ## c -#define B(a,b,c) A(a,b,c) -#define C(a,b,c) a b c -B( - C(A,C(,,),), - C(B(,,),B,B(,,)), - C(B(,,),B(,,),C) - )/* */(a b c) - -#define TEST(x) TEST : x -#define K(a,b) a ## b -#define L(a,b) K( TE a , b ST ) -L(,)(t e s t) diff --git a/libs/pprocessor/tests/pp/18.expect b/libs/pprocessor/tests/pp/18.expect deleted file mode 100644 index a8d1a4c..0000000 --- a/libs/pprocessor/tests/pp/18.expect +++ /dev/null @@ -1,5 +0,0 @@ -X181 1 -X182 0 -X183 yeah -ABC : a b c -TEST : t e s t diff --git a/libs/pprocessor/tests/pp/19.c b/libs/pprocessor/tests/pp/19.c deleted file mode 100644 index aa91abe..0000000 --- a/libs/pprocessor/tests/pp/19.c +++ /dev/null @@ -1,101 +0,0 @@ -#define M_C2I(a, ...) a ## __VA_ARGS__ -#define M_C(a, ...) M_C2I(a, __VA_ARGS__) -#define M_C3I(a, b, ...) a ## b ## __VA_ARGS__ -#define M_C3(a, b, ...) M_C3I(a ,b, __VA_ARGS__) - -#define M_RETI_ARG2(a, b, ...) b -#define M_RET_ARG2(...) M_RETI_ARG2(__VA_ARGS__) -#define M_RETI_ARG27(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,aa, ...) aa -#define M_RET_ARG27(...) M_RETI_ARG27(__VA_ARGS__) - -#define M_TOBOOLI_0 1, 0, -#define M_BOOL(x) M_RET_ARG2(M_C(M_TOBOOLI_, x), 1, useless) - -#define M_IFI_0(true_macro, ...) __VA_ARGS__ -#define M_IFI_1(true_macro, ...) true_macro -#define M_IF(c) M_C(M_IFI_, M_BOOL(c)) - -#define M_FLAT(...) __VA_ARGS__ -#define M_INVI_0 1 -#define M_INVI_1 0 -#define M_INV(x) M_C(M_INVI_, x) - -#define M_ANDI_00 0 -#define M_ANDI_01 0 -#define M_ANDI_10 0 -#define M_ANDI_11 1 -#define M_AND(x,y) M_C3(M_ANDI_, x, y) - -#define M_ORI_00 0 -#define M_ORI_01 1 -#define M_ORI_10 1 -#define M_ORI_11 1 -#define M_OR(x,y) M_C3(M_ORI_, x, y) - -#define M_COMMA_P(...) M_RET_ARG27(__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, useless) - -#define M_EMPTYI_DETECT(...) 0, 1, -#define M_EMPTYI_P_C1(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__ ()) -#define M_EMPTYI_P_C2(...) M_COMMA_P(M_EMPTYI_DETECT __VA_ARGS__) -#define M_EMPTYI_P_C3(...) M_COMMA_P(__VA_ARGS__ () ) -#define M_EMPTY_P(...) M_AND(M_EMPTYI_P_C1(__VA_ARGS__), M_INV(M_OR(M_OR(M_EMPTYI_P_C2(__VA_ARGS__), M_COMMA_P(__VA_ARGS__)),M_EMPTYI_P_C3(__VA_ARGS__)))) -#define M_APPLY_FUNC2B(func, arg1, arg2) \ - M_IF(M_EMPTY_P(arg2))(,func(arg1, arg2)) -#define M_MAP2B_0(func, data, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z,...) \ - M_APPLY_FUNC2B(func, data, a) M_APPLY_FUNC2B(func, data, b) M_APPLY_FUNC2B(func, data, c) \ - M_APPLY_FUNC2B(func, data, d) M_APPLY_FUNC2B(func, data, e) M_APPLY_FUNC2B(func, data, f) \ - M_APPLY_FUNC2B(func, data, g) M_APPLY_FUNC2B(func, data, h) M_APPLY_FUNC2B(func, data, i) \ - M_APPLY_FUNC2B(func, data, j) M_APPLY_FUNC2B(func, data, k) M_APPLY_FUNC2B(func, data, l) \ - M_APPLY_FUNC2B(func, data, m) M_APPLY_FUNC2B(func, data, n) M_APPLY_FUNC2B(func, data, o) \ - M_APPLY_FUNC2B(func, data, p) M_APPLY_FUNC2B(func, data, q) M_APPLY_FUNC2B(func, data, r) \ - M_APPLY_FUNC2B(func, data, s) M_APPLY_FUNC2B(func, data, t) M_APPLY_FUNC2B(func, data, u) \ - M_APPLY_FUNC2B(func, data, v) M_APPLY_FUNC2B(func, data, w) M_APPLY_FUNC2B(func, data, x) \ - M_APPLY_FUNC2B(func, data, y) M_APPLY_FUNC2B(func, data, z) -#define M_MAP2B(f, ...) M_MAP2B_0(f, __VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ) -#define M_INIT_INIT(a) ,a, - -#define M_GET_METHOD(method, method_default, ...) \ - M_RET_ARG2 (M_MAP2B(M_C, M_C3(M_, method, _), __VA_ARGS__), method_default,) - -#define M_TEST_METHOD_P(method, oplist) \ - M_BOOL(M_GET_METHOD (method, 0, M_FLAT oplist)) - -#define TRUE 1 -#define TEST1(n) \ - M_IF(n)(ok,nok) -#define TEST2(op) \ - M_TEST_METHOD_P(INIT, op) -#define TEST3(op) \ - M_IF(M_TEST_METHOD_P(INIT, op))(ok, nok) -#define TEST4(op) \ - TEST1(TEST2(op)) -#define KO(a) ((void)1) - -/* This checks that the various expansions that ultimately lead to - something like 'KO(arg,arg)', where 'KO' comes from a macro - expansion reducing from a large macro chain do not are regarded - as funclike macro invocation of KO. E.g. X93 and X94 expand to 'KO', - but X95 must not consume the (a,b) arguments outside the M_IF() - invocation to reduce the 'KO' macro to an invocation. Instead - X95 should reduce via M_IF(KO)(a,b) to 'a'. - - The other lines here are variations on this scheme, with X1 to - X6 coming from the bug report at - http://lists.nongnu.org/archive/html/tinycc-devel/2017-07/msg00017.html */ -X92 M_IF(KO) -X93 M_GET_METHOD(INIT, 0, INIT(KO)) -X94 M_GET_METHOD(INIT, 0, M_FLAT (INIT(KO))) -X95 M_IF(M_GET_METHOD(INIT, 0, INIT(KO)))(a,b) -X96 M_IF(M_GET_METHOD(INIT, 0, M_FLAT (INIT(KO)))) -X97 M_IF(M_GET_METHOD(INIT, 0, M_FLAT (INIT(KO))))(ok,nok) -X98 (M_TEST_METHOD_P(INIT, (INIT(KO))))(ok, nok) -X99 M_IF(M_TEST_METHOD_P(INIT, (INIT(KO))))(ok, nok) -// test begins -X1 TEST1(TRUE) // ==> expect ok, get ok -// First test with a token which is not a macro -X2 TEST2((INIT(ok))) // ==> expect 1, get 1 -X3 TEST3((INIT(ok))) // ==> expect ok, get ok -// Then test with a token which is a macro, but should not be expanded. -X4 TEST2((INIT(KO))) // ==> expect 1, get 1 -X5 TEST4(INIT(KO)) -X6 TEST3((INIT(KO))) // ==> expect ok, get "error: macro 'KO' used with too many args" diff --git a/libs/pprocessor/tests/pp/19.expect b/libs/pprocessor/tests/pp/19.expect deleted file mode 100644 index 08c0858..0000000 --- a/libs/pprocessor/tests/pp/19.expect +++ /dev/null @@ -1,14 +0,0 @@ -X92 M_IFI_1 -X93 KO -X94 KO -X95 a -X96 M_IFI_1 -X97 ok -X98 (1)(ok, nok) -X99 ok -X1 ok -X2 1 -X3 ok -X4 1 -X5 nok -X6 ok diff --git a/libs/pprocessor/tests/pp/20.c b/libs/pprocessor/tests/pp/20.c deleted file mode 100644 index 7944d62..0000000 --- a/libs/pprocessor/tests/pp/20.c +++ /dev/null @@ -1,13 +0,0 @@ -/* Various things I encountered while hacking the pre processor */ -#define wrap(x) x -#define pr_warning(fmt, ...) printk(KERN_WARNING fmt, ##__VA_ARGS__) -#define pr_warn(x,y) pr_warning(x,y) -#define net_ratelimited_function(function, ...) function(__VA_ARGS__) -X1 net_ratelimited_function(pr_warn, "pipapo", bla); -X2 net_ratelimited_function(wrap(pr_warn), "bla", foo); -#define two m n -#define chain4(a,b,c,d) a ## b ## c ## d -X2 chain4(two,o,p,q) -X3 chain4(o,two,p,q) -X4 chain4(o,p,two,q) -X5 chain4(o,p,q,two) diff --git a/libs/pprocessor/tests/pp/20.expect b/libs/pprocessor/tests/pp/20.expect deleted file mode 100644 index d19405d..0000000 --- a/libs/pprocessor/tests/pp/20.expect +++ /dev/null @@ -1,6 +0,0 @@ -X1 printk(KERN_WARNING "pipapo",bla); -X2 printk(KERN_WARNING "bla",foo); -X2 twoopq -X3 otwopq -X4 optwoq -X5 opqtwo diff --git a/libs/pprocessor/tests/pp/21.c b/libs/pprocessor/tests/pp/21.c deleted file mode 100644 index c28988d..0000000 --- a/libs/pprocessor/tests/pp/21.c +++ /dev/null @@ -1,41 +0,0 @@ -/* accept 'defined' as result of substitution */ - ------ 1 ------ -#define AAA 2 -#define BBB -#define CCC (defined ( AAA ) && AAA > 1 && !defined BBB) -#if !CCC -OK -#else -NOT OK -#endif - ------ 2 ------ -#undef BBB -#if CCC -OK -#else -NOT OK -#endif - ------ 3 ------ -#define DEFINED defined -#define DDD (DEFINED ( AAA ) && AAA > 1 && !DEFINED BBB) -#if (DDD) -OK -#else -NOT OK -#endif - ------ 4 ------ -#undef AAA -#if !(DDD) -OK -#else -NOT OK -#endif - ------ 5 ------ -line __LINE__ -#define __LINE__ # ## # -line __LINE__ diff --git a/libs/pprocessor/tests/pp/21.expect b/libs/pprocessor/tests/pp/21.expect deleted file mode 100644 index 297b4d4..0000000 --- a/libs/pprocessor/tests/pp/21.expect +++ /dev/null @@ -1,11 +0,0 @@ ------ 1 ------ -OK ------ 2 ------ -OK ------ 3 ------ -OK ------ 4 ------ -OK ------ 5 ------ -line 39 -line ## diff --git a/libs/pprocessor/tests/pp/22.c b/libs/pprocessor/tests/pp/22.c deleted file mode 100644 index 76e2315..0000000 --- a/libs/pprocessor/tests/pp/22.c +++ /dev/null @@ -1,12 +0,0 @@ -#define TRACE(a,b,c) X a X b X c X -#define rettrue(x) 1 -A rettrue(bla) B -TRACE( - ARG_1, -#if rettrue(bla) - ARG_2, -#else - ARG_2_wrong, -#endif - ARG_3 -); diff --git a/libs/pprocessor/tests/pp/22.expect b/libs/pprocessor/tests/pp/22.expect deleted file mode 100644 index ceaea03..0000000 --- a/libs/pprocessor/tests/pp/22.expect +++ /dev/null @@ -1,2 +0,0 @@ -A 1 B -X ARG_1 X ARG_2 X ARG_3 X; diff --git a/libs/pprocessor/tests/pp/Makefile b/libs/pprocessor/tests/pp/Makefile deleted file mode 100644 index 7e989c9..0000000 --- a/libs/pprocessor/tests/pp/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# -# credits: 01..13.c from the pcc cpp-tests suite -# - -TOP = ../.. -include $(TOP)/Makefile -SRC = $(TOPSRC)/tests/pp -VPATH = $(SRC) - -files = $(patsubst %.$1,%.test,$(notdir $(wildcard $(SRC)/*.$1))) -TESTS = $(call files,c) $(call files,S) - -all test testspp.all: $(sort $(TESTS)) - -DIFF_OPTS = -Nu -b - -# Filter source directory in warnings/errors (out-of-tree builds) -FILTER = 2>&1 | sed 's,$(SRC)/,,g' - -%.test: %.c %.expect - @echo PPTest $* ... - -@$(TCC) -E -P $< $(FILTER) >$*.output 2>&1 ; \ - diff $(DIFF_OPTS) $(SRC)/$*.expect $*.output \ - && rm -f $*.output - -%.test: %.S %.expect - @echo PPTest $* ... - -@$(TCC) -E -P $< $(FILTER) >$*.output 2>&1 ; \ - diff $(DIFF_OPTS) $(SRC)/$*.expect $*.output \ - && rm -f $*.output - -testspp.%: %.test ; - -# generate .expect file with tcc, e.g. "make testspp.17+" -testspp.%+: %.c - $(TCC) -E -P $*.[cS] -o $*.expect - -# automatically generate .expect files with gcc: -%.expect: # %.c - gcc -E -P $*.[cS] >$*.expect 2>&1 - -# tell make not to delete -.PRECIOUS: %.expect - -clean: - rm -f *.output - -02.test : DIFF_OPTS += -w -# 15.test : DIFF_OPTS += -I"^XXX:" - -# diff options: -# -b ighore space changes -# -w ighore all whitespace -# -B ignore blank lines -# -I ignore lines matching RE diff --git a/libs/pprocessor/tests/pp/README b/libs/pprocessor/tests/pp/README deleted file mode 100644 index 809dd8d..0000000 --- a/libs/pprocessor/tests/pp/README +++ /dev/null @@ -1,96 +0,0 @@ -Tiny C Compiler - C Scripting Everywhere - The Smallest ANSI C compiler ------------------------------------------------------------------------ - -Features: --------- - -- SMALL! You can compile and execute C code everywhere, for example on - rescue disks. - -- FAST! tcc generates optimized x86 code. No byte code - overhead. Compile, assemble and link about 7 times faster than 'gcc - -O0'. - -- UNLIMITED! Any C dynamic library can be used directly. TCC is - heading toward full ISOC99 compliance. TCC can of course compile - itself. - -- SAFE! tcc includes an optional memory and bound checker. Bound - checked code can be mixed freely with standard code. - -- Compile and execute C source directly. No linking or assembly - necessary. Full C preprocessor included. - -- C script supported : just add '#!/usr/local/bin/tcc -run' at the first - line of your C source, and execute it directly from the command - line. - -Documentation: -------------- - -1) Installation on a i386/x86_64/arm/aarch64/riscv64 - Linux/macOS/FreeBSD/NetBSD/OpenBSD hosts. - - ./configure - make - make test - make install - - Notes: For FreeBSD, NetBSD and OpenBSD, gmake should be used instead of make. - For Windows read tcc-win32.txt. - -makeinfo must be installed to compile the doc. By default, tcc is -installed in /usr/local/bin. ./configure --help shows configuration -options. - - -2) Introduction - -We assume here that you know ANSI C. Look at the example ex1.c to know -what the programs look like. - -The include file can be used if you want a small basic libc -include support (especially useful for floppy disks). Of course, you -can also use standard headers, although they are slower to compile. - -You can begin your C script with '#!/usr/local/bin/tcc -run' on the first -line and set its execute bits (chmod a+x your_script). Then, you can -launch the C code as a shell or perl script :-) The command line -arguments are put in 'argc' and 'argv' of the main functions, as in -ANSI C. - -3) Examples - -ex1.c: simplest example (hello world). Can also be launched directly -as a script: './ex1.c'. - -ex2.c: more complicated example: find a number with the four -operations given a list of numbers (benchmark). - -ex3.c: compute fibonacci numbers (benchmark). - -ex4.c: more complicated: X11 program. Very complicated test in fact -because standard headers are being used ! As for ex1.c, can also be launched -directly as a script: './ex4.c'. - -ex5.c: 'hello world' with standard glibc headers. - -tcc.c: TCC can of course compile itself. Used to check the code -generator. - -tcctest.c: auto test for TCC which tests many subtle possible bugs. Used -when doing 'make test'. - -4) Full Documentation - -Please read tcc-doc.html to have all the features of TCC. - -Additional information is available for the Windows port in tcc-win32.txt. - -License: -------- - -TCC is distributed under the GNU Lesser General Public License (see -COPYING file). - -Fabrice Bellard. diff --git a/libs/pprocessor/tests/pp/pp-counter.c b/libs/pprocessor/tests/pp/pp-counter.c deleted file mode 100644 index 3978e1a..0000000 --- a/libs/pprocessor/tests/pp/pp-counter.c +++ /dev/null @@ -1,27 +0,0 @@ -X1 __COUNTER__ -X2 __COUNTER__ -#if __COUNTER__ -X3 __COUNTER__ -#endif -#define pass(x) x -#define a x __COUNTER__ y -#define a2 pass(__COUNTER__) -#define f(c) c __COUNTER__ -#define apply(d) d d __COUNTER__ x2 f(d) y2 __COUNTER__ -#define _paste(a,b) a ## b -#define paste(a,b) _paste(a,b) -#define _paste3(a,b,c) a ## b ## c -#define doublepaste(a,b) _paste3(a,b,b) -#define str(x) #x -X4 a -X5 f(a) -X6 f(b) -X7 f(__COUNTER__) -X8 apply(a) -X9 apply(f(a)) -X10 apply(__COUNTER__) -X11 apply(a2) -X12 str(__COUNTER__) -X13 paste(x,__COUNTER__) -X14 _paste(x,__COUNTER__) -X15 doublepaste(x,__COUNTER__) diff --git a/libs/pprocessor/tests/pp/pp-counter.expect b/libs/pprocessor/tests/pp/pp-counter.expect deleted file mode 100644 index 02fc535..0000000 --- a/libs/pprocessor/tests/pp/pp-counter.expect +++ /dev/null @@ -1,15 +0,0 @@ -X1 0 -X2 1 -X3 3 -X4 x 4 y -X5 x 5 y 6 -X6 b 7 -X7 8 9 -X8 x 10 y x 10 y 11 x2 x 10 y 12 y2 13 -X9 x 14 y 15 x 14 y 15 16 x2 x 14 y 15 17 y2 18 -X10 19 19 20 x2 19 21 y2 22 -X11 23 23 24 x2 23 25 y2 26 -X12 "__COUNTER__" -X13 x27 -X14 x__COUNTER__ -X15 x2828 diff --git a/libs/pprocessor/tests/test_pp.c b/libs/pprocessor/tests/test_pp.c deleted file mode 100644 index 105ee95..0000000 --- a/libs/pprocessor/tests/test_pp.c +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include -#include -#include -#include - -static scc_probe_stream_t *from_file_stream(FILE *fp) { - if (fseek(fp, 0, SEEK_END) != 0) { - perror("fseek failed"); - return NULL; - } - usize fsize = ftell(fp); - if (fseek(fp, 0, SEEK_SET)) { - perror("fseek failed"); - return NULL; - } - - char *buffer = (char *)malloc(fsize); - - usize read_ret = fread(buffer, 1, fsize, fp); - fclose(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, read_ret, true); - return stream; -} - -static void test_file(const char *name) { - char src_fname[1024]; - char expected_fname[1024]; - snprintf(src_fname, sizeof(src_fname), __FILE__ "/../pp/%s.c", name); - snprintf(expected_fname, sizeof(expected_fname), - __FILE__ "/../pp/%s.expect", name); - FILE *fsrc = fopen(src_fname, "r"); - assert(fsrc != NULL); - FILE *fexpect = fopen(expected_fname, "r"); - assert(fexpect != NULL); - - scc_pproc_t pp; - 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); -#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); - } -} - -TEST_LIST = { - {"basic", test_basic}, - {NULL, NULL}, -}; diff --git a/libs/pprocessor/tests/test_run.c b/libs/pprocessor/tests/test_run.c deleted file mode 100644 index 3392ad3..0000000 --- a/libs/pprocessor/tests/test_run.c +++ /dev/null @@ -1,24 +0,0 @@ -#include -#include - -int main(void) { - scc_pproc_t pp; - scc_mem_probe_stream_t input; - scc_probe_stream_t *output; - - const char buf[] = "#define A 123 \"asd\"\nA A A\n"; - output = scc_pproc_init( - &pp, scc_mem_probe_stream_init(&input, buf, sizeof(buf) - 1, false)); - - int ch = 0; - - while (1) { - ch = scc_probe_stream_consume(output); - if (ch == scc_stream_eof) { - break; - } - putc(ch, stdout); - } - - return 0; -} \ No newline at end of file diff --git a/libs/pprocessor/tests/test_unit.c b/libs/pprocessor/tests/test_unit.c deleted file mode 100644 index 6a2c405..0000000 --- a/libs/pprocessor/tests/test_unit.c +++ /dev/null @@ -1,215 +0,0 @@ -#include -#include -#include -#include - -static cbool process_input(const char *input, scc_cstring_t *output) { - scc_pproc_t pp; - scc_mem_probe_stream_t mem_stream; - scc_probe_stream_t *output_stream; - - // 初始化预处理器 - output_stream = - scc_pproc_init(&pp, scc_mem_probe_stream_init(&mem_stream, input, - strlen(input), false)); - - // 获取输出结果 - int ch; - *output = scc_cstring_create(); - while (1) { - ch = scc_probe_stream_consume(output_stream); - if (ch == scc_stream_eof) { - break; - } - scc_cstring_append_ch(output, (char)ch); - } - // 清理资源 - scc_pproc_drop(&pp); - - return true; -} - -#define CHECK_PP_OUTPUT_EXACT(input, expect) \ - do { \ - scc_cstring_t output; \ - process_input(input, &output); \ - assert(output.data != NULL); \ - TEST_CHECK(strcmp(output.data, expect) == 0); \ - TEST_MSG("Expected: %s", expect); \ - TEST_MSG("Produced: %s", output.data); \ - } while (0) - -#define CHECK_PP_OUTPUT_CONTAIN(input, expect) \ - do { \ - scc_cstring_t output; \ - process_input(input, &output); \ - assert(output.data != NULL); \ - TEST_CHECK(strstr(output.data, expect) != NULL); \ - TEST_MSG("Expected: %s", expect); \ - TEST_MSG("Produced: %s", output.data); \ - } while (0) - -static void test_define_simple_object_macro(void) { - TEST_CASE("simple object-like macro"); - CHECK_PP_OUTPUT_EXACT("#define MAX 100\nMAX\n", "100\n"); - CHECK_PP_OUTPUT_EXACT("#define NAME test\r\nNAME\n", "test\n"); -} - -static void test_define_complex_object_macro(void) { - TEST_CASE("complex object-like macro"); - CHECK_PP_OUTPUT_EXACT("#define VALUE (100 + 50)\nVALUE\n", "(100 + 50)\n"); - CHECK_PP_OUTPUT_EXACT("#define PI 3.14159\nPI\n", "3.14159\n"); -} - -static void test_define_object_macro_backspace(void) { - TEST_CASE("object-like macro check backspace"); - CHECK_PP_OUTPUT_EXACT("#define MAX 100\nMAX\n", "100\n"); - CHECK_PP_OUTPUT_EXACT("#define NAME \ttest\r\nNAME\n", "test\n"); - CHECK_PP_OUTPUT_EXACT("#define \tVALUE (100 \t+ 50)\nVALUE\n", - "(100 + 50)\n"); - CHECK_PP_OUTPUT_EXACT("#define \tPI \t 3.14159\nPI\n", "3.14159\n"); -} - -static void test_define_function_macro(void) { - TEST_CASE("function-like macro"); - CHECK_PP_OUTPUT_EXACT("#define ADD(a,b) a + b\nADD(1, 2)\n", "1 + 2\n"); - CHECK_PP_OUTPUT_EXACT( - "#define MAX(a,b) ((a) > (b) ? (a) : (b))\nMAX(10, 20)\n", - "((10) > (20) ? (10) : (20))\n"); -} - -static void test_define_stringify_operator(void) { - TEST_CASE("stringify operator (#)"); - CHECK_PP_OUTPUT_EXACT("#define STRINGIFY(x) #x\nSTRINGIFY(hello)\n", - "\"hello\"\n"); - CHECK_PP_OUTPUT_EXACT("#define STR(x) #x\nSTR(test value)\n", - "\"test value\"\n"); -} - -static void test_define_concat_operator(void) { - TEST_CASE("concatenation operator (##)"); - CHECK_PP_OUTPUT_EXACT("#define CONCAT(a,b) a##b\nCONCAT(hello,world)\n", - "helloworld\n"); - CHECK_PP_OUTPUT_EXACT("#define JOIN(pre,suf) pre ## suf\nJOIN(var, 123)\n", - "var123\n"); -} - -static void test_define_nested_macros(void) { - TEST_CASE("nested macros"); - CHECK_PP_OUTPUT_EXACT( - "#define MAX 100\n#define TWICE_MAX (MAX * 2)\nTWICE_MAX\n", - "(100 * 2)\n"); - CHECK_PP_OUTPUT_EXACT( - "#define A 1\n#define B (A + 1)\n#define C (B + 1)\nC\n", - "((1 + 1) + 1)\n"); -} - -static void test_undef_macros(void) { - TEST_CASE("test_undef_macros"); - CHECK_PP_OUTPUT_EXACT("#define x 1\n" - "x\n" - "#undef x\n" - "x\n" - "#define x 2\n" - "x\n", - "1\nx\n2\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"); - - TEST_CASE("TODO"); - CHECK_PP_OUTPUT_EXACT("#define str(x) # x\n" - "str()\n", - "\"\"\n"); - - TEST_CASE("TODO"); - CHECK_PP_OUTPUT_EXACT("#define x 1\n" - "#define f(a) f(x * (a))\n" - "f(0)\n" - "f(x)", - "f(1 * (0))\n" - "f(1 * (1))"); - CHECK_PP_OUTPUT_EXACT("#define x x(0)\n" - "#define f(a) f(x * (a))\n" - "f(f(0))\n" - "f(f(x))\n" - "f(f(a))\n", - "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"); -} - -static void test_conditional_compilation(void) { - TEST_CASE("conditional compilation"); - CHECK_PP_OUTPUT_EXACT("#if 1\ntrue\n#endif\n", "true\n"); - CHECK_PP_OUTPUT_EXACT("#if 0\nfalse\n#endif\n", ""); - CHECK_PP_OUTPUT_EXACT("#define FLAG 1\n#if FLAG\ntrue\n#endif\n", "true\n"); -} - -static void test_error_cases(void) { - TEST_CASE("macro redefinition"); - // 应检测到警告或错误 - // CHECK_PP_OUTPUT_CONTAIN("#define A 1\n#define A 2\n", "warning"); - - TEST_CASE("undefined macro"); - CHECK_PP_OUTPUT_EXACT("UNDEFINED_MACRO\n", "UNDEFINED_MACRO\n"); -} - -static void test_edge_cases(void) { - TEST_CASE("empty macro"); - CHECK_PP_OUTPUT_EXACT("#define EMPTY\nEMPTY\n", "\n"); - - TEST_CASE("macro with only spaces"); - CHECK_PP_OUTPUT_EXACT("#define SPACE \nSPACE\n", "\n"); - - TEST_CASE("deep nesting"); - CHECK_PP_OUTPUT_EXACT("#define A B\n#define B C\n#define C 1\nA\n", "1\n"); -} - -#define TEST_LIST_CASE(func_name) {#func_name, func_name} -TEST_LIST = { - TEST_LIST_CASE(test_define_simple_object_macro), - TEST_LIST_CASE(test_define_complex_object_macro), - TEST_LIST_CASE(test_define_object_macro_backspace), - TEST_LIST_CASE(test_define_function_macro), - TEST_LIST_CASE(test_define_stringify_operator), - TEST_LIST_CASE(test_define_concat_operator), - TEST_LIST_CASE(test_define_nested_macros), - TEST_LIST_CASE(test_undef_macros), - TEST_LIST_CASE(hard_test_define_func_macros), - {NULL, NULL}, -}; \ No newline at end of file diff --git a/libs/sstream/src/main.c b/libs/sstream/examples/main.c similarity index 100% rename from libs/sstream/src/main.c rename to libs/sstream/examples/main.c diff --git a/libs/sstream/include/scc_sstream.h b/libs/sstream/include/scc_sstream.h index 6b81c93..5a1511b 100644 --- a/libs/sstream/include/scc_sstream.h +++ b/libs/sstream/include/scc_sstream.h @@ -26,7 +26,7 @@ typedef struct { int scc_sstream_init(scc_sstream_t *stream, const char *fname, int ring_size); int scc_sstream_init_by_buffer(scc_sstream_t *stream, const char *buffer, usize len, int owned, int ring_size); -scc_sstream_ring_t *scc_sstream_ref_ring(scc_sstream_t *stream); +scc_sstream_ring_t *scc_sstream_to_ring(scc_sstream_t *stream); void scc_sstream_drop_ring(scc_sstream_ring_t *ring); void scc_sstream_drop(scc_sstream_t *stream); diff --git a/libs/sstream/src/scc_sstream.c b/libs/sstream/src/scc_sstream.c index 251e850..630666e 100644 --- a/libs/sstream/src/scc_sstream.c +++ b/libs/sstream/src/scc_sstream.c @@ -66,7 +66,7 @@ static int sstream_scan_at(scc_sstream_t *stream, scc_pos_t scan_pos, } // 环形缓冲区填充回调(通过 userdata 获取流对象) -static cbool fill_func(scc_sstream_char_t *out, void *userdata) { +static int fill_func(scc_sstream_char_t *out, void *userdata) { scc_sstream_t *stream = (scc_sstream_t *)userdata; if (stream->fill_pos.offset >= stream->len) return false; // 已到文件尾 @@ -82,6 +82,10 @@ static cbool fill_func(scc_sstream_char_t *out, void *userdata) { int scc_sstream_init(scc_sstream_t *stream, const char *fname, int ring_size) { Assert(stream != null && fname != null); scc_file_t file = scc_fopen(fname, SCC_FILE_READ); + if (file == null) { + LOG_ERROR("Failed to open file: %s", fname); + return 0; + } usize fsize = scc_fsize(file); if (fsize == 0) { LOG_WARN("file size is 0"); @@ -115,7 +119,7 @@ int scc_sstream_init_by_buffer(scc_sstream_t *stream, const char *buffer, return 0; } -scc_sstream_ring_t *scc_sstream_ref_ring(scc_sstream_t *stream) { +scc_sstream_ring_t *scc_sstream_to_ring(scc_sstream_t *stream) { Assert(stream != null); stream->used++; return &stream->ring; diff --git a/runtime/scc_core/include/scc_core_ring.h b/runtime/scc_core/include/scc_core_ring.h index de651b8..152dbf2 100644 --- a/runtime/scc_core/include/scc_core_ring.h +++ b/runtime/scc_core/include/scc_core_ring.h @@ -23,7 +23,7 @@ usize head; \ usize probe; \ usize tail; \ - cbool (*fill)(type * out, void *userdata); \ + int (*fill)(type * out, void *userdata); \ void *userdata; \ }