From f56b13da2c4ac7434161726f4aca1ab7530ca7b8 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Thu, 26 Feb 2026 10:25:45 +0800 Subject: [PATCH] =?UTF-8?q?refactor(format):=20=E7=A7=BB=E9=99=A4SCF?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F=E7=9B=B8=E5=85=B3=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 移除了libs/format目录下的所有文件,包括: - cbuild.toml构建配置文件 - include/scf.h头文件 - include/scf_impl.h实现头文件 - src/scf.c源文件 - tests/test_scf.c测试文件 - tests/test_scf_x64.c x64架构测试文件 这些文件包含了SCF(scc format)格式的完整实现,但现在不再需要。 feat(lexer): 添加布尔字面量数字生成函数 在lexer工具头文件中添加了两个内联函数用于生成布尔值的数字字面量: - scc_lexer_gen_number_true: 将token类型设为整数字面量,值为"1" - scc_lexer_gen_number_false: 将token类型设为整数字面量,值为"0" refactor(lexer): 改进词法分析器错误处理 - 移除了多余的头文件包含 - 更新错误报告方式,使用SCC_ERROR宏替代LEX_ERROR,提供更准确的错误位置信息 refactor(pproc): 更新预处理器扩展器数据结构 - 将need_rescan字段类型从int改为cbool - 添加need_parse_defined字段用于控制defined操作符解析 - 更新函数签名以支持defined操作符解析参数 --- libs/format/README.md | 0 libs/format/cbuild.toml | 8 - libs/format/include/scf.h | 150 --------- libs/format/include/scf_impl.h | 42 --- libs/format/src/scf.c | 469 --------------------------- libs/format/tests/test_scf.c | 109 ------- libs/format/tests/test_scf_x64.c | 184 ----------- libs/lexer/include/scc_lexer_utils.h | 12 + libs/lexer/src/lexer.c | 3 +- libs/pproc/include/pproc_expand.h | 6 +- libs/pproc/src/pproc_directive.c | 34 +- libs/pproc/src/pproc_expand.c | 61 +++- libs/pproc/src/pproc_if.c | 48 ++- libs/pproc/src/pproc_include.c | 13 +- libs/sstream/include/scc_pos_log.h | 30 ++ libs/sstream/include/scc_sstream.h | 1 + libs/sstream/src/scc_pos_log.c | 56 ++++ libs/sstream/src/scc_sstream.c | 4 +- runtime/log/include/log.h | 8 +- 19 files changed, 215 insertions(+), 1023 deletions(-) delete mode 100644 libs/format/README.md delete mode 100644 libs/format/cbuild.toml delete mode 100644 libs/format/include/scf.h delete mode 100644 libs/format/include/scf_impl.h delete mode 100644 libs/format/src/scf.c delete mode 100644 libs/format/tests/test_scf.c delete mode 100644 libs/format/tests/test_scf_x64.c create mode 100644 libs/sstream/include/scc_pos_log.h create mode 100644 libs/sstream/src/scc_pos_log.c diff --git a/libs/format/README.md b/libs/format/README.md deleted file mode 100644 index e69de29..0000000 diff --git a/libs/format/cbuild.toml b/libs/format/cbuild.toml deleted file mode 100644 index 1a13569..0000000 --- a/libs/format/cbuild.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "scc_format" -version = "0.1.0" - -dependencies = [ - { name = "libcore", path = "../../runtime/libcore" }, - { name = "libutils", path = "../../runtime/libutils" }, -] diff --git a/libs/format/include/scf.h b/libs/format/include/scf.h deleted file mode 100644 index 7a7b090..0000000 --- a/libs/format/include/scf.h +++ /dev/null @@ -1,150 +0,0 @@ -/** - * @file scf.h - * @brief scc format (SMF) 头文件 - * - * SCF是一个极简的可执行可链接文件格式,专注于内部链接处理, - * 同时提供外部符号导入/导出的抽象接口。 - */ - -#ifndef __SCC_FORMAT_H__ -#define __SCC_FORMAT_H__ - -#include -#include - -#define scf_byte_t uint8_t -#define scf_enum_t uint32_t -#define scf_size_t uint32_t - -#ifdef __cplusplus -extern "C" { -#endif - -/** SCF魔数 */ -#define SCF_MAGIC "SCF\0" - -/** SCF版本号 */ -#define SCF_VERSION 1 - -/** 架构类型 */ -typedef enum { - SCF_ARCH_UNKNOWN = 0, - SCF_ARCH_RV32 = 1, - SCF_ARCH_RV64 = 2, - SCF_ARCH_X86 = 3, - SCF_ARCH_X64 = 4, -} scf_arch_t; - -/** 文件标志位 */ -typedef enum { - SCF_FLAG_EXECUTABLE = 0x01, // 可执行文件 - SCF_FLAG_RELOCATABLE = 0x02, // 可重定位文件 - SCF_FLAG_EXE_RELOC = - SCF_FLAG_EXECUTABLE | SCF_FLAG_RELOCATABLE, // 内部链接后的可执行文件 -} scf_flags_t; - -/** 符号类型 */ -typedef enum { - SCF_SYM_TYPE_UNDEF = 0, // 未定义 - SCF_SYM_TYPE_FUNC = 1, // 函数 - SCF_SYM_TYPE_DATA = 2, // 数据 - SCF_SYM_TYPE_OBJECT = 3, // 对象 -} scf_sym_type_t; - -/** 符号绑定类型 */ -typedef enum { - SCF_SYM_BIND_LOCAL = 0, // 局部符号 - SCF_SYM_BIND_GLOBAL = 1, // 全局符号 - SCF_SYM_BIND_WEAK = 2, // 弱引用 -} scf_sym_bind_t; - -/** 符号可见性 */ -typedef enum { - SCF_SYM_VIS_DEFAULT = 0, // 默认可见性 - SCF_SYM_VIS_HIDDEN = 1, // 隐藏 - SCF_SYM_VIS_PROTECTED = 2, // 受保护 -} scf_sym_vis_t; - -/** 段类型 */ -typedef enum { - SCF_SECT_NONE = 0, // 无 - SCF_SECT_CODE = 1, // 代码段 - SCF_SECT_DATA = 2, // 数据段 - SCF_SECT_BSS = 3, // BSS段(未初始化数据) - SCF_SECT_RODATA = 4, // 只读数据 -} scf_sect_type_t; - -/** 重定位类型 */ -typedef enum { - SCF_RELOC_ABS = 1, // 绝对地址 - SCF_RELOC_REL = 2, // 相对地址 - SCF_RELOC_PC = 3, // PC相对 -} scf_reloc_type_t; - -/** - * @brief SCF文件头 - */ -typedef struct { - scf_byte_t magic[4]; // 魔数: "SCF\0" - scf_enum_t type; // 类型 - scf_enum_t version; // 版本号 - scf_enum_t arch; // 架构 - scf_enum_t flags; // 标志位 - scf_size_t entry_point; // 入口点地址 - scf_size_t data_size; - scf_size_t code_size; - scf_size_t strtab_size; - scf_size_t sym_count; - scf_size_t reloc_count; -} scf_header_t; - -/** - * @brief SCF段 - */ -typedef struct { - scf_size_t size; - scf_enum_t scf_sect_type; - scf_byte_t data[1]; -} scf_sect_t; - -/** - * @brief SCF符号表 - */ -typedef struct { - scf_size_t name_offset; - scf_enum_t scf_sym_type; - scf_enum_t scf_sym_bind; - scf_enum_t scf_sym_vis; - scf_enum_t scf_sect_type; - scf_size_t scf_sect_offset; - scf_size_t scf_sym_size; -} scf_sym_t; - -/** - * @brief SCF重定向条目 - */ -typedef struct { - scf_size_t offset; // 在段中的偏移量 - scf_size_t sym_idx; // 符号索引 - scf_enum_t type; // 重定位类型 - scf_enum_t sect_type; // 段类型(代码段/数据段) - scf_size_t addend; // 加数 -} scf_reloc_t; - -/* -scf 文件结构 - -scf_header_t header; -scf_sect_data_t text; -scf_sect_data_t data; -scf_sect_data_t symtab; -scf_sect_data_t reloc; -scf_sect_data_t strtab; - -*/ - -#ifdef __cplusplus -} -#endif - -#endif /* __SCC_FORMAT_H__ */ diff --git a/libs/format/include/scf_impl.h b/libs/format/include/scf_impl.h deleted file mode 100644 index 7895616..0000000 --- a/libs/format/include/scf_impl.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef __SCC_FORMAT_IMPL_H__ -#define __SCC_FORMAT_IMPL_H__ - -#include -#include -#include - -typedef SCC_VEC(u8) scf_sect_data_t; -typedef SCC_VEC(scf_sym_t) scf_sym_vec_t; -typedef SCC_VEC(scf_reloc_t) scf_reloc_vec_t; - -typedef struct { - scf_header_t header; - scf_sect_data_t text; - scf_sect_data_t data; - scf_sect_data_t symtab; - scf_sect_data_t reloc; - scf_sect_data_t strtab; - - scc_strpool_t strpool; - scc_hashtable_t str2idx; - scf_sym_vec_t syms; - scf_reloc_vec_t relocs; -} scf_t; - -void scf_init(scf_t *scf); -cbool scf_parse(scf_t *scf, const char *buffer, usize size); -cbool scf_write(scf_t *scf, char *buffer, usize size); - -cbool scf_exchange_section(scf_t *scf, scf_sect_type_t type, - scf_sect_data_t **section); -cbool scf_add_sym(scf_t *scf, scf_sym_t *sym); -cbool scf_add_reloc(scf_t *scf, scf_reloc_t *reloc); -cbool scf_apply_relocations(scf_t *scf); -cbool scf_write_done(scf_t *scf); // 在写入前进行内部整理 - -cbool scf_check_valid(scf_t *scf); - -typedef SCC_VEC(scf_t) scf_vec_t; -cbool scf_link_all(scf_vec_t scfs, scf_t *outscf); - -#endif /* __SCC_FORMAT_IMPL_H__ */ diff --git a/libs/format/src/scf.c b/libs/format/src/scf.c deleted file mode 100644 index cfc24d7..0000000 --- a/libs/format/src/scf.c +++ /dev/null @@ -1,469 +0,0 @@ -/** - * @file scf.c - * @brief SCF 格式实现 - */ - -#include - -/** - * @brief 初始化 SCF 结构 - * @param scf 指向 scf_t 结构的指针 - */ -void scf_init(scf_t *scf) { - if (!scf) { - return; - } - - scc_memset(&scf->header, 0, sizeof(scf->header)); - scc_memcpy(scf->header.magic, SCF_MAGIC, 4); - scf->header.version = SCF_VERSION; - scf->header.arch = SCF_ARCH_UNKNOWN; - scf->header.flags = 0; - scf->header.entry_point = 0; - scf->header.data_size = 0; - scf->header.code_size = 0; - scf->header.strtab_size = 0; - scf->header.sym_count = 0; - scf->header.reloc_count = 0; - - scc_vec_init(scf->text); - scc_vec_init(scf->data); - scc_vec_init(scf->symtab); - scc_vec_init(scf->reloc); - scc_vec_init(scf->strtab); - - scc_strpool_init(&scf->strpool); - scf->str2idx.hash_func = (void *)scc_strhash32; - scf->str2idx.key_cmp = (void *)scc_strcmp; - scc_hashtable_init(&scf->str2idx); - - scc_vec_init(scf->syms); - scc_vec_init(scf->relocs); -} - -/** - * @brief 从缓冲区读取并解析 SCF 数据 - * @param scf 指向 scf_t 结构的指针 - * @param buffer 输入缓冲区 - * @param size 缓冲区大小 - * @return 成功返回 true,失败返回 false - */ -cbool scf_parse(scf_t *scf, const char *buffer, usize size) { - if (!scf || !buffer || size < sizeof(scf_header_t)) { - return false; - } - - // 读取头部 - const scf_header_t *header = (const scf_header_t *)buffer; - if (scc_memcmp(header->magic, SCF_MAGIC, 4) != 0) { - return false; - } - - scf->header = *header; - - // 计算各段偏移 - usize offset = sizeof(scf_header_t); - - // 读取 text 段 - if (scf->header.code_size > 0) { - if (offset + scf->header.code_size > size) { - return false; - } - // 调整 text 向量大小 - while (scf->text.size < scf->header.code_size) { - scc_vec_push(scf->text, 0); - } - scc_memcpy(scf->text.data, buffer + offset, scf->header.code_size); - offset += scf->header.code_size; - } - - // 读取 data 段 - if (scf->header.data_size > 0) { - if (offset + scf->header.data_size > size) { - return false; - } - // 调整 data 向量大小 - while (scf->data.size < scf->header.data_size) { - scc_vec_push(scf->data, 0); - } - scc_memcpy(scf->data.data, buffer + offset, scf->header.data_size); - offset += scf->header.data_size; - } - - // 读取符号表 - if (scf->header.sym_count > 0) { - usize symtab_size = scf->header.sym_count * sizeof(scf_sym_t); - if (offset + symtab_size > size) { - return false; - } - // 调整 syms 向量大小 - while (scf->syms.size < scf->header.sym_count) { - scf_sym_t sym = {0}; - scc_vec_push(scf->syms, sym); - } - scc_memcpy(scf->syms.data, buffer + offset, symtab_size); - offset += symtab_size; - } - - // 读取重定位表 - if (scf->header.reloc_count > 0) { - usize reloc_size = scf->header.reloc_count * sizeof(scf_reloc_t); - if (offset + reloc_size > size) { - return false; - } - // 调整 relocs 向量大小 - while (scf->relocs.size < scf->header.reloc_count) { - scf_reloc_t reloc = {0}; - scc_vec_push(scf->relocs, reloc); - } - scc_memcpy(scf->relocs.data, buffer + offset, reloc_size); - offset += reloc_size; - } - - // 读取字符串表 - if (scf->header.strtab_size > 0) { - if (offset + scf->header.strtab_size > size) { - return false; - } - // 调整 strtab 向量大小 - while (scf->strtab.size < scf->header.strtab_size) { - scc_vec_push(scf->strtab, 0); - } - scc_memcpy(scf->strtab.data, buffer + offset, scf->header.strtab_size); - offset += scf->header.strtab_size; - } - // 允许 offset <= size,因为缓冲区可能比实际数据大 - if (offset > size) { - return false; - } - - return true; -} - -/** - * @brief 将 SCF 数据写入缓冲区 - * @param scf 指向 scf_t 结构的指针 - * @param buffer 输出缓冲区 - * @param size 缓冲区大小 - * @return 成功返回 true,失败返回 false - */ -cbool scf_write(scf_t *scf, char *buffer, usize size) { - if (!scf || !buffer) { - return false; - } - - // 计算所需大小 - usize needed = sizeof(scf_header_t); - needed += scf->header.code_size; // text 段 - needed += scf->header.data_size; // data 段 - needed += scf->header.sym_count * sizeof(scf_sym_t); - needed += scf->header.reloc_count * sizeof(scf_reloc_t); - needed += scf->header.strtab_size; - - if (size < needed) { - return false; - } - - // 写入头部 - scf_header_t *header = (scf_header_t *)buffer; - *header = scf->header; - usize offset = sizeof(scf_header_t); - - // 写入 text 段 - if (scf->header.code_size > 0) { - scc_memcpy(buffer + offset, scf->text.data, scf->header.code_size); - offset += scf->header.code_size; - } - - // 写入 data 段 - if (scf->header.data_size > 0) { - scc_memcpy(buffer + offset, scf->data.data, scf->header.data_size); - offset += scf->header.data_size; - } - - // 写入符号表 - if (scf->header.sym_count > 0) { - usize symtab_size = scf->header.sym_count * sizeof(scf_sym_t); - scc_memcpy(buffer + offset, scf->syms.data, symtab_size); - offset += symtab_size; - } - - // 写入重定位表 - if (scf->header.reloc_count > 0) { - usize reloc_size = scf->header.reloc_count * sizeof(scf_reloc_t); - scc_memcpy(buffer + offset, scf->relocs.data, reloc_size); - offset += reloc_size; - } - - // 写入字符串表 - if (scf->header.strtab_size > 0) { - scc_memcpy(buffer + offset, scf->strtab.data, scf->header.strtab_size); - offset += scf->header.strtab_size; - } - - Assert(offset <= size); - - return true; -} - -/** - * @brief 交换段数据 - * @param scf 指向 scf_t 结构的指针 - * @param type 段类型 - * @param section 指向新段数据的指针(双向交换) - * @return 成功返回 true,失败返回 false - */ -cbool scf_exchange_section(scf_t *scf, scf_sect_type_t type, - scf_sect_data_t **section) { - if (!scf || !section || !*section) { - return false; - } - - scf_sect_data_t *target_section = NULL; - scf_size_t *size_field = NULL; - - // 根据类型选择目标段和大小字段 - switch (type) { - case SCF_SECT_CODE: - target_section = &scf->text; - size_field = &scf->header.code_size; - break; - case SCF_SECT_DATA: - target_section = &scf->data; - size_field = &scf->header.data_size; - break; - case SCF_SECT_RODATA: - // 当前实现中没有单独的rodata段,使用data段 - target_section = &scf->data; - size_field = &scf->header.data_size; - break; - case SCF_SECT_BSS: - // BSS段不存储数据,只记录大小 - // 这里暂时不支持交换BSS段 - return false; - default: - return false; - } - - // 交换段数据 - scf_sect_data_t temp = *target_section; - *target_section = **section; - **section = temp; - - // 更新大小字段 - if (size_field) { - // 保存旧大小(如果需要的话) - // scf_size_t temp_size = *size_field; // 未使用,注释掉 - *size_field = (scf_size_t)(*target_section).size; - // 如果调用者需要知道新的大小,可以在这里设置 - // 但当前API没有提供这个功能 - } - - return true; -} - -/** - * @brief 添加符号到符号表 - * @param scf 指向 scf_t 结构的指针 - * @param sym 指向要添加的符号的指针 - * @return 成功返回 true,失败返回 false - */ -cbool scf_add_sym(scf_t *scf, scf_sym_t *sym) { - if (!scf || !sym) { - return false; - } - - // 添加到符号向量 - scc_vec_push(scf->syms, *sym); - scf->header.sym_count++; - - return true; -} - -/** - * @brief 添加重定位条目 - * @param scf 指向 scf_t 结构的指针 - * @param reloc 指向要添加的重定位条目的指针 - * @return 成功返回 true,失败返回 false - */ -cbool scf_add_reloc(scf_t *scf, scf_reloc_t *reloc) { - if (!scf || !reloc) { - return false; - } - - // 添加到重定位向量 - scc_vec_push(scf->relocs, *reloc); - scf->header.reloc_count++; - - return true; -} - -/** - * @brief 检查 SCF 结构是否有效 - * @param scf 指向 scf_t 结构的指针 - * @return 有效返回 true,无效返回 false - */ -cbool scf_check_valid(scf_t *scf) { - if (!scf) { - return false; - } - - // 检查魔数 - if (scc_memcmp(scf->header.magic, SCF_MAGIC, 4) != 0) { - return false; - } - - // 检查版本 - if (scf->header.version != SCF_VERSION) { - return false; - } - - // 检查架构 - if (scf->header.arch > SCF_ARCH_X64) { - return false; - } - - // 检查各段大小是否一致 - if (scf->header.code_size != scf->text.size) { - return false; - } - if (scf->header.data_size != scf->data.size) { - return false; - } - if (scf->header.sym_count != scf->syms.size) { - return false; - } - if (scf->header.reloc_count != scf->relocs.size) { - return false; - } - if (scf->header.strtab_size != scf->strtab.size) { - return false; - } - - return true; -} - -/** - * @brief 应用重定位到段数据 - * @param scf 指向 scf_t 结构的指针 - * @return 成功返回 true,失败返回 false - */ -cbool scf_apply_relocations(scf_t *scf) { - if (!scf) { - return false; - } - - // 遍历所有重定位条目 - for (usize i = 0; i < scf->relocs.size; i++) { - scf_reloc_t *reloc = &scf->relocs.data[i]; - - // 根据段类型选择目标段 - scf_sect_data_t *target_section = NULL; - switch (reloc->sect_type) { - case SCF_SECT_CODE: - target_section = &scf->text; - break; - case SCF_SECT_DATA: - case SCF_SECT_RODATA: - target_section = &scf->data; - break; - default: - // 不支持的段类型 - continue; - } - - // 检查偏移量是否有效 - if (reloc->offset + sizeof(scf_size_t) > target_section->size) { - // 偏移量超出段范围 - return false; - } - - // 获取符号地址 - scf_size_t symbol_address = 0; - if (reloc->sym_idx < scf->syms.size) { - scf_sym_t *sym = &scf->syms.data[reloc->sym_idx]; - symbol_address = sym->scf_sect_offset; - } - - // 计算重定位值 - scf_size_t relocation_value = symbol_address + reloc->addend; - - // 根据重定位类型应用 - scf_size_t *target = - (scf_size_t *)(target_section->data + reloc->offset); - switch (reloc->type) { - case SCF_RELOC_ABS: - // 绝对地址:直接替换 - *target = relocation_value; - break; - case SCF_RELOC_REL: - // 相对地址:计算相对于当前位置的偏移 - // 使用 uintptr_t 进行安全的指针到整数转换 - *target = relocation_value - (scf_size_t)(uintptr_t)target; - break; - case SCF_RELOC_PC: - // PC相对:计算相对于PC的偏移 - // 使用 uintptr_t 进行安全的指针到整数转换 - *target = relocation_value - (scf_size_t)(uintptr_t)(target + 1); - break; - default: - // 不支持的重定位类型 - return false; - } - } - - return true; -} - -/** - * @brief 在写入前进行内部整理 - * @param scf 指向 scf_t 结构的指针 - * @return 成功返回 true,失败返回 false - */ -cbool scf_write_done(scf_t *scf) { - if (!scf) { - return false; - } - - // 应用所有重定位 - if (!scf_apply_relocations(scf)) { - return false; - } - - // 更新头部中的大小字段 - scf->header.code_size = (scf_size_t)scf->text.size; - scf->header.data_size = (scf_size_t)scf->data.size; - scf->header.sym_count = (scf_size_t)scf->syms.size; - scf->header.reloc_count = (scf_size_t)scf->relocs.size; - scf->header.strtab_size = (scf_size_t)scf->strtab.size; - - // 设置标志位为内部链接后的可执行文件 - scf->header.flags |= SCF_FLAG_EXE_RELOC; - - return true; -} - -/** - * @brief 链接多个 SCF 文件 - * @param scfs 包含多个 SCF 文件的向量 - * @param outscf 输出链接后的 SCF 文件 - * @return 成功返回 true,失败返回 false - */ -cbool scf_link_all(scf_vec_t scfs, scf_t *outscf) { - if (!outscf || scfs.size == 0) { - return false; - } - - // 初始化输出 SCF - scf_init(outscf); - - // 简单实现:只链接第一个文件 - // 实际实现应该合并所有文件的段、解析符号引用、应用重定位等 - if (scfs.size > 0) { - scf_t *first = &scfs.data[0]; - // 这里应该进行深拷贝,但为了简单起见,我们只复制头部 - outscf->header = first->header; - } - - return true; -} diff --git a/libs/format/tests/test_scf.c b/libs/format/tests/test_scf.c deleted file mode 100644 index e7bbc85..0000000 --- a/libs/format/tests/test_scf.c +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @file test_scf.c - * @brief SCF format tests - */ - -#include -#include -#include - -int main() { - printf("Testing SCF format implementation...\n"); - - // Test 1: Initialization - scf_t scf; - scf_init(&scf); - - if (memcmp(scf.header.magic, SCF_MAGIC, 4) != 0) { - printf("FAIL: Magic number incorrect\n"); - return 1; - } - - if (scf.header.version != SCF_VERSION) { - printf("FAIL: Version incorrect\n"); - return 1; - } - - if (scf.header.arch != SCF_ARCH_UNKNOWN) { - printf("FAIL: Architecture incorrect\n"); - return 1; - } - - printf("Test 1 PASSED: Initialization successful\n"); - - // Test 2: Adding symbols - scf_sym_t sym = {0}; - sym.name_offset = 0; - sym.scf_sym_type = SCF_SYM_TYPE_FUNC; - sym.scf_sym_bind = SCF_SYM_BIND_GLOBAL; - sym.scf_sym_vis = SCF_SYM_VIS_DEFAULT; - sym.scf_sect_type = SCF_SECT_CODE; - sym.scf_sect_offset = 0; - sym.scf_sym_size = 16; - - if (!scf_add_sym(&scf, &sym)) { - printf("FAIL: Cannot add symbol\n"); - return 1; - } - - if (scf.header.sym_count != 1) { - printf("FAIL: Symbol count incorrect\n"); - return 1; - } - - printf("Test 2 PASSED: Symbol addition successful\n"); - - // Test 3: Adding relocations - scf_reloc_t reloc = {0}; - reloc.offset = 0; // 偏移量 - reloc.sym_idx = 0; - reloc.type = SCF_RELOC_ABS; - reloc.sect_type = SCF_SECT_CODE; // 代码段 - reloc.addend = 0; - - if (!scf_add_reloc(&scf, &reloc)) { - printf("FAIL: Cannot add relocation\n"); - return 1; - } - - if (scf.header.reloc_count != 1) { - printf("FAIL: Relocation count incorrect\n"); - return 1; - } - - printf("Test 3 PASSED: Relocation addition successful\n"); - - // Test 4: Checking validity - if (!scf_check_valid(&scf)) { - printf("FAIL: SCF structure invalid\n"); - return 1; - } - - printf("Test 4 PASSED: SCF structure valid\n"); - - // Test 5: Writing and reading - char buffer[1024]; - if (!scf_write(&scf, buffer, sizeof(buffer))) { - printf("FAIL: Cannot write to buffer\n"); - return 1; - } - - scf_t scf2; - scf_init(&scf2); - - if (!scf_parse(&scf2, buffer, sizeof(buffer))) { - printf("FAIL: Cannot read from buffer\n"); - return 1; - } - - // Compare the two structures - if (memcmp(&scf.header, &scf2.header, sizeof(scf_header_t)) != 0) { - printf("FAIL: Header mismatch\n"); - return 1; - } - - printf("Test 5 PASSED: Write/read successful\n"); - - printf("All tests passed!\n"); - return 0; -} diff --git a/libs/format/tests/test_scf_x64.c b/libs/format/tests/test_scf_x64.c deleted file mode 100644 index 9aedfa3..0000000 --- a/libs/format/tests/test_scf_x64.c +++ /dev/null @@ -1,184 +0,0 @@ -/** - * @file test_scf_x64.c - * @brief SCF x64 architecture tests - * - * This test creates a simple x64 executable similar to the Rust example - * provided by the user. - */ - -#include -#include -#include - -int main() { - printf("Testing SCF x64 format implementation...\n"); - - // Test 1: Initialize SCF for x64 architecture - scf_t scf; - scf_init(&scf); - - // Set architecture to x64 - scf.header.arch = SCF_ARCH_X64; - scf.header.flags = SCF_FLAG_EXE_RELOC; - - printf("Test 1 PASSED: x64 initialization successful\n"); - - // Test 2: Add .text section with x64 machine code - // x64 machine code for: - // sub rsp, 0x28 - // lea rcx, [rip + data_offset] ; will be relocated - // call [rip + printf_iat] ; will be relocated - // add rsp, 0x28 - // xor eax, eax - // ret - unsigned char x64_code[] = { - 0x48, 0x83, 0xEC, 0x28, // sub rsp, 0x28 - 0x48, 0x8D, 0x0D, 0x00, 0x00, 0x00, - 0x00, // lea rcx, [rip + 0] (to be relocated) - 0xFF, 0x15, 0x00, 0x00, 0x00, 0x00, // call [rip + 0] (to be relocated) - 0x48, 0x83, 0xC4, 0x28, // add rsp, 0x28 - 0x33, 0xC0, // xor eax, eax - 0xC3 // ret - }; - - // Add code to .text section - for (usize i = 0; i < sizeof(x64_code); i++) { - scc_vec_push(scf.text, x64_code[i]); - } - scf.header.code_size = (scf_size_t)scf.text.size; - - printf("Test 2 PASSED: x64 code added to .text section\n"); - - // Test 3: Add .data section with string - const char hello_world[] = "Hello, World from SCF x64 Test!\n\0"; - for (usize i = 0; i < sizeof(hello_world); i++) { - scc_vec_push(scf.data, hello_world[i]); - } - scf.header.data_size = (scf_size_t)scf.data.size; - - printf("Test 3 PASSED: Data string added to .data section\n"); - - // Test 4: Add symbols - scf_sym_t data_sym = {0}; - data_sym.name_offset = 0; // Would need string table for actual names - data_sym.scf_sym_type = SCF_SYM_TYPE_DATA; - data_sym.scf_sym_bind = SCF_SYM_BIND_GLOBAL; - data_sym.scf_sym_vis = SCF_SYM_VIS_DEFAULT; - data_sym.scf_sect_type = SCF_SECT_DATA; - data_sym.scf_sect_offset = 0; // Start of data section - data_sym.scf_sym_size = sizeof(hello_world); - - if (!scf_add_sym(&scf, &data_sym)) { - printf("FAIL: Cannot add data symbol\n"); - return 1; - } - - scf_sym_t code_sym = {0}; - code_sym.name_offset = 0; - code_sym.scf_sym_type = SCF_SYM_TYPE_FUNC; - code_sym.scf_sym_bind = SCF_SYM_BIND_GLOBAL; - code_sym.scf_sym_vis = SCF_SYM_VIS_DEFAULT; - code_sym.scf_sect_type = SCF_SECT_CODE; - code_sym.scf_sect_offset = 0; // Start of code section - code_sym.scf_sym_size = sizeof(x64_code); - - if (!scf_add_sym(&scf, &code_sym)) { - printf("FAIL: Cannot add code symbol\n"); - return 1; - } - - printf("Test 4 PASSED: Symbols added\n"); - - // Test 5: Add relocations - // First relocation: data reference at offset 7 in code (lea rcx, [rip + - // data_offset]) - scf_reloc_t data_reloc = {0}; - data_reloc.offset = 7; // Offset in code section - data_reloc.sym_idx = 0; // Index of data symbol (first symbol added) - data_reloc.type = SCF_RELOC_PC; // PC-relative relocation - data_reloc.sect_type = SCF_SECT_CODE; - data_reloc.addend = -4; // RIP-relative addressing adjustment - - if (!scf_add_reloc(&scf, &data_reloc)) { - printf("FAIL: Cannot add data relocation\n"); - return 1; - } - - // Second relocation: external function reference at offset 13 in code (call - // [rip + printf_iat]) - scf_reloc_t func_reloc = {0}; - func_reloc.offset = 13; // Offset in code section - func_reloc.sym_idx = - 1; // Index of code symbol (would be external in real case) - func_reloc.type = SCF_RELOC_PC; // PC-relative relocation - func_reloc.sect_type = SCF_SECT_CODE; - func_reloc.addend = -4; // RIP-relative addressing adjustment - - if (!scf_add_reloc(&scf, &func_reloc)) { - printf("FAIL: Cannot add function relocation\n"); - return 1; - } - - printf("Test 5 PASSED: Relocations added\n"); - - // Test 6: Apply relocations - if (!scf_apply_relocations(&scf)) { - printf("FAIL: Cannot apply relocations\n"); - return 1; - } - - printf("Test 6 PASSED: Relocations applied\n"); - - // Test 7: Prepare for writing (internal整理) - if (!scf_write_done(&scf)) { - printf("FAIL: Cannot prepare for writing\n"); - return 1; - } - - printf("Test 7 PASSED: Prepared for writing\n"); - - // Test 8: Write to buffer - char buffer[4096]; - if (!scf_write(&scf, buffer, sizeof(buffer))) { - printf("FAIL: Cannot write to buffer\n"); - return 1; - } - - printf("Test 8 PASSED: Written to buffer\n"); - - // Test 9: Parse from buffer - scf_t scf2; - scf_init(&scf2); - - if (!scf_parse(&scf2, buffer, sizeof(buffer))) { - printf("FAIL: Cannot parse from buffer\n"); - return 1; - } - - // Verify architecture - if (scf2.header.arch != SCF_ARCH_X64) { - printf("FAIL: Architecture not preserved\n"); - return 1; - } - - printf("Test 9 PASSED: Parsed from buffer, architecture preserved\n"); - - // Test 10: Verify structure - if (!scf_check_valid(&scf2)) { - printf("FAIL: Parsed structure invalid\n"); - return 1; - } - - printf("Test 10 PASSED: Parsed structure valid\n"); - - printf("\nAll x64 tests passed!\n"); - printf("Created SCF file with:\n"); - printf(" Architecture: x64\n"); - printf(" Code size: %u bytes\n", scf.header.code_size); - printf(" Data size: %u bytes\n", scf.header.data_size); - printf(" Symbols: %u\n", scf.header.sym_count); - printf(" Relocations: %u\n", scf.header.reloc_count); - printf(" Flags: 0x%x\n", scf.header.flags); - - return 0; -} diff --git a/libs/lexer/include/scc_lexer_utils.h b/libs/lexer/include/scc_lexer_utils.h index b2649ba..b9fd30b 100644 --- a/libs/lexer/include/scc_lexer_utils.h +++ b/libs/lexer/include/scc_lexer_utils.h @@ -3,6 +3,18 @@ #include "scc_lexer.h" +static inline void scc_lexer_gen_number_true(scc_lexer_tok_t *tok) { + Assert(tok != null && tok->type == SCC_TOK_UNKNOWN); + tok->type = SCC_TOK_INT_LITERAL; + tok->lexeme = scc_cstring_from_cstr("1"); +} + +static inline void scc_lexer_gen_number_false(scc_lexer_tok_t *tok) { + Assert(tok != null && tok->type == SCC_TOK_UNKNOWN); + tok->type = SCC_TOK_INT_LITERAL; + tok->lexeme = scc_cstring_from_cstr("0"); +} + static inline cbool scc_lexer_peek_non_blank(scc_lexer_tok_ring_t *stream, scc_lexer_tok_t *out) { cbool ok; diff --git a/libs/lexer/src/lexer.c b/libs/lexer/src/lexer.c index 9e228ee..3cbd230 100644 --- a/libs/lexer/src/lexer.c +++ b/libs/lexer/src/lexer.c @@ -1,4 +1,3 @@ -#include "scc_lexer.h" #include #include @@ -447,7 +446,7 @@ void scc_lexer_get_token(scc_lexer_t *lexer, scc_lexer_tok_t *token) { break; default: token->type = SCC_TOK_UNKNOWN; - LEX_ERROR("unsupport char in sourse code `%c`:0x%x", ch, ch); + SCC_ERROR(start_loc, "unsupported character '%c' (0x%x)", ch, ch); break; } } diff --git a/libs/pproc/include/pproc_expand.h b/libs/pproc/include/pproc_expand.h index 18e28bc..6e5cbc5 100644 --- a/libs/pproc/include/pproc_expand.h +++ b/libs/pproc/include/pproc_expand.h @@ -11,7 +11,8 @@ typedef struct { scc_pproc_macro_table_t *expanded_set; scc_lexer_tok_ring_t *input; scc_lexer_tok_vec_t output; - int need_rescan; + cbool need_rescan; + cbool need_parse_defined; } scc_pproc_expand_t; static inline scc_lexer_tok_ring_t @@ -28,6 +29,7 @@ void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table, const scc_pproc_macro_t *macro); void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table, scc_lexer_tok_vec_t *input, - scc_lexer_tok_ring_t *output); + scc_lexer_tok_ring_t *output, + cbool need_parse_defined); #endif /* __SCC_PPROC_EXPAND_H__ */ diff --git a/libs/pproc/src/pproc_directive.c b/libs/pproc/src/pproc_directive.c index 30ab77d..089922f 100644 --- a/libs/pproc/src/pproc_directive.c +++ b/libs/pproc/src/pproc_directive.c @@ -152,7 +152,8 @@ void scc_pproc_parse_object_macro(scc_pproc_t *pp, } static void scc_pproc_parse_line_and_expand(scc_pproc_t *pp, - scc_lexer_tok_ring_t *out_ring) { + scc_lexer_tok_ring_t *out_ring, + cbool need_parse_defined) { int ok; scc_lexer_tok_t tok; scc_lexer_tok_ring_t *stream = pp->cur_ring; @@ -167,7 +168,8 @@ static void scc_pproc_parse_line_and_expand(scc_pproc_t *pp, if (tok.type == SCC_TOK_ENDLINE) break; } - scc_pproc_expand_by_vec(&pp->macro_table, &org_toks, out_ring); + scc_pproc_expand_by_vec(&pp->macro_table, &org_toks, out_ring, + need_parse_defined); } /* @@ -236,14 +238,15 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) { if (!scc_lexer_next_non_blank(pp->cur_ring, &tok) || scc_get_tok_subtype(tok.type) != SCC_TOK_SUBTYPE_IDENTIFIER) { scc_lexer_tok_drop(&tok); - LOG_ERROR("Invalid preprocessor directive"); + SCC_ERROR(tok.loc, "invalid preprocessing directive"); goto ERROR; } int ret = keyword_cmp(scc_cstring_as_cstr(&tok.lexeme), scc_cstring_len(&tok.lexeme)); if (ret == -1) { scc_lexer_tok_drop(&tok); - LOG_ERROR("Expected preprocessor keyword, got %s", tok.lexeme); + SCC_ERROR(tok.loc, "expected preprocessor directive name, got '%s'", + scc_cstring_as_cstr(&tok.lexeme)); goto ERROR; } scc_tok_type_t type = keywords[ret].tok_type; @@ -278,15 +281,15 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) { case SCC_PP_TOK_DEFINE: { scc_lexer_tok_drop(&tok); scc_lexer_next_non_blank(pp->cur_ring, &tok); - if (tok.type != SCC_TOK_IDENT) { + if (scc_get_tok_subtype(tok.type) != SCC_TOK_SUBTYPE_IDENTIFIER) { + SCC_ERROR(tok.loc, "expected identifier after '#define'"); scc_lexer_tok_drop(&tok); - LOG_ERROR("expected identifier"); goto ERROR; } scc_lexer_tok_t next_tok; scc_ring_peek(*pp->cur_ring, next_tok, ok); if (!ok) { - LOG_ERROR("unexpected EOF"); + SCC_ERROR(tok.loc, "unexpected end of file in macro definition"); goto ERROR; } if (next_tok.type == SCC_TOK_L_PAREN) { @@ -305,7 +308,7 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) { scc_lexer_next_non_blank(pp->cur_ring, &tok); if (tok.type != SCC_TOK_IDENT) { scc_lexer_tok_drop(&tok); - LOG_ERROR("expected identifier"); + SCC_ERROR(tok.loc, "expected identifier after '#undef'"); goto ERROR; } scc_pproc_macro_table_remove(&pp->macro_table, &tok.lexeme); @@ -313,7 +316,7 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) { scc_lexer_next_non_blank(pp->cur_ring, &tok); if (tok.type != SCC_TOK_ENDLINE) { scc_lexer_tok_drop(&tok); - LOG_ERROR("expected newline"); + SCC_ERROR(tok.loc, "expected newline after '#undef'"); goto ERROR; } scc_lexer_tok_drop(&tok); @@ -321,7 +324,7 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) { } case SCC_PP_TOK_INCLUDE: { scc_lexer_tok_ring_t out_ring; - scc_pproc_parse_line_and_expand(pp, &out_ring); + scc_pproc_parse_line_and_expand(pp, &out_ring, false); scc_pproc_parse_include(pp, &tok, &out_ring); return; } @@ -333,7 +336,8 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) { if (!scc_lexer_next_non_blank(pp->cur_ring, &tok) || tok.type != SCC_TOK_IDENT) { scc_lexer_tok_drop(&tok); - LOG_ERROR("expected identifier"); + SCC_ERROR(tok.loc, "expected identifier after " + "'#ifdef'/'#ifndef'/'#elifdef'/'#elifndef'"); } else { scc_pproc_parse_if_defined(pp, type, &tok); scc_lexer_tok_drop(&tok); @@ -352,7 +356,7 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) { case SCC_PP_TOK_ELIF: { scc_lexer_tok_drop(&tok); scc_lexer_tok_ring_t out_ring; - scc_pproc_parse_line_and_expand(pp, &out_ring); + scc_pproc_parse_line_and_expand(pp, &out_ring, true); scc_pproc_parse_if_condition(pp, type, &out_ring); return; } @@ -367,7 +371,7 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) { return; } if (scc_get_tok_subtype(tok.type) == SCC_TOK_SUBTYPE_LITERAL) { - LOG_ERROR(scc_cstring_as_cstr(&tok.lexeme)); + SCC_ERROR(tok.loc, "%s", scc_cstring_as_cstr(&tok.lexeme)); } scc_lexer_tok_drop(&tok); } @@ -380,13 +384,13 @@ void scc_pproc_handle_directive(scc_pproc_t *pp) { return; } if (scc_get_tok_subtype(tok.type) == SCC_TOK_SUBTYPE_LITERAL) { - LOG_WARN(scc_cstring_as_cstr(&tok.lexeme)); + SCC_WARN(tok.loc, "%s", scc_cstring_as_cstr(&tok.lexeme)); } scc_lexer_tok_drop(&tok); } return; case SCC_PP_TOK_PRAGMA: - LOG_WARN("Pragma ignored"); + SCC_WARN(tok.loc, "pragma ignored"); scc_lexer_skip_until_newline(pp->cur_ring); return; default: diff --git a/libs/pproc/src/pproc_expand.c b/libs/pproc/src/pproc_expand.c index 0fad5c0..913869a 100644 --- a/libs/pproc/src/pproc_expand.c +++ b/libs/pproc/src/pproc_expand.c @@ -1,4 +1,5 @@ #include +#include #include static scc_lexer_tok_t stringify_argument(scc_lexer_tok_vec_t *arg_tokens) { @@ -78,6 +79,7 @@ static inline void scc_copy_expand(scc_pproc_expand_t *expand_ctx, copyed_ctx->expanded_set = expand_ctx->expanded_set; copyed_ctx->macro_table = expand_ctx->macro_table; copyed_ctx->need_rescan = false; + copyed_ctx->need_parse_defined = expand_ctx->need_parse_defined; scc_vec_init(copyed_ctx->output); } @@ -100,17 +102,19 @@ void scc_pproc_expand_by_src(scc_pproc_macro_table_t *macro_table, scc_pproc_parse_macro_arguments(input, &expaned_buffer, true); } - scc_pproc_expand_by_vec(macro_table, &expaned_buffer, output); + scc_pproc_expand_by_vec(macro_table, &expaned_buffer, output, false); } void scc_pproc_expand_by_vec(scc_pproc_macro_table_t *macro_table, scc_lexer_tok_vec_t *input, - scc_lexer_tok_ring_t *output) { + scc_lexer_tok_ring_t *output, + cbool need_parse_defined) { scc_pproc_expand_t ctx; scc_lexer_tok_ring_t ring = scc_lexer_array_to_ring(input); ctx.input = ˚ ctx.macro_table = macro_table; ctx.need_rescan = false; + ctx.need_parse_defined = need_parse_defined; scc_vec_init(ctx.output); scc_pproc_macro_table_t expanded_set; ctx.expanded_set = &expanded_set; @@ -272,10 +276,12 @@ static inline void expand_function_macro(scc_pproc_expand_t *expand_ctx, scc_pproc_macro_extened_params_t splited_params; scc_vec_init(splited_params); split_arguments(&splited_params, &raw_args, macro); + Assert(scc_vec_size(splited_params) >= scc_vec_size(macro->params)); scc_pproc_macro_extened_params_t expanded_params; scc_vec_init(expanded_params); expand_arguments(&expanded_params, &splited_params, expand_ctx); + Assert(scc_vec_size(expanded_params) >= scc_vec_size(macro->params)); // replace scc_vec_foreach(macro->replaces, i) { @@ -470,6 +476,57 @@ void scc_pproc_expand_macro(scc_pproc_expand_t *expand_ctx) { scc_vec_push(expand_ctx->output, tok); continue; } + + if (expand_ctx->need_parse_defined && + scc_strcmp(scc_cstring_as_cstr(&tok.lexeme), "defined") == 0) { + scc_lexer_tok_t next_tok = {0}; + if (scc_lexer_next_non_blank(expand_ctx->input, &next_tok) == + false) { + SCC_ERROR(tok.loc, "Unexpected before defined EOF"); + scc_lexer_tok_drop(&tok); + } + scc_lexer_tok_drop(&tok); + if (next_tok.type == SCC_TOK_L_PAREN) { + scc_lexer_tok_drop(&next_tok); + scc_lexer_next_non_blank(expand_ctx->input, &next_tok); + if (scc_get_tok_subtype(next_tok.type) != + SCC_TOK_SUBTYPE_IDENTIFIER) { + SCC_ERROR(next_tok.loc, + "Expected identifier before defined"); + scc_lexer_tok_drop(&next_tok); + } + + if (scc_pproc_macro_table_get(expand_ctx->macro_table, + &next_tok.lexeme) == null) { + scc_lexer_gen_number_false(&tok); + } else { + scc_lexer_gen_number_true(&tok); + } + scc_lexer_tok_drop(&next_tok); + scc_vec_push(expand_ctx->output, tok); + + if (scc_lexer_next_non_blank(expand_ctx->input, &next_tok)) { + if (next_tok.type == SCC_TOK_R_PAREN) { + scc_lexer_tok_drop(&next_tok); + break; + } else { + SCC_ERROR(next_tok.loc, "Expected ')'"); + scc_lexer_tok_drop(&next_tok); + } + } + } else if (scc_get_tok_subtype(next_tok.type) == + SCC_TOK_SUBTYPE_IDENTIFIER) { + if (scc_pproc_macro_table_get(expand_ctx->macro_table, + &next_tok.lexeme) == null) { + scc_lexer_gen_number_false(&tok); + } else { + scc_lexer_gen_number_true(&tok); + } + scc_lexer_tok_drop(&next_tok); + scc_vec_push(expand_ctx->output, tok); + } + continue; + } // maybe expanded scc_pproc_macro_t *macro = scc_pproc_macro_table_get(expand_ctx->macro_table, &tok.lexeme); diff --git a/libs/pproc/src/pproc_if.c b/libs/pproc/src/pproc_if.c index 5319ac3..f408580 100644 --- a/libs/pproc/src/pproc_if.c +++ b/libs/pproc/src/pproc_if.c @@ -98,37 +98,33 @@ cbool scc_pproc_parse_if_defined(scc_pproc_t *pp, scc_tok_type_t type, return true; } -static cbool parse_constant_condition() { return false; } - -cbool scc_pproc_parse_if_condition(scc_pproc_t *pp, scc_tok_type_t type, - scc_lexer_tok_ring_t *tok_ring) { - // TODO +static int parse_constant_condition(scc_pproc_t *pp, + scc_lexer_tok_ring_t *tok_ring) { int ok; scc_lexer_tok_t tok = {0}; ok = scc_lexer_next_non_blank(tok_ring, &tok); if (ok == false) { - LOG_FATAL("unexpected EOF"); - } - int condition = 0; - if (tok.type == SCC_TOK_INT_LITERAL) { - condition = scc_cstring_as_cstr(&tok.lexeme)[0] == '0' ? 0 : 1; - } else { - LOG_ERROR("expected integer constant but got %s", - scc_cstring_as_cstr(&tok.lexeme)); - } - scc_lexer_tok_drop(&tok); - - ok = scc_lexer_next_non_blank(tok_ring, &tok); - if (ok == false) { - LOG_FATAL("unexpected EOF"); - } - if (tok.type != SCC_TOK_ENDLINE) { - LOG_ERROR("expected endline"); - scc_lexer_skip_until_newline(tok_ring); - } else { scc_lexer_tok_drop(&tok); + LOG_FATAL("unexpected EOF"); } + int res = 0; + + if (tok.type == SCC_TOK_INT_LITERAL) { + // got int + const char *intstr = scc_cstring_as_cstr(&tok.lexeme); + for (int i = scc_cstring_len(&tok.lexeme) - 1; i >= 0; i--) { + res = res * 10 + intstr[i] - '0'; + } + return res; + } + scc_ring_free(*tok_ring); + return false; +} + +cbool scc_pproc_parse_if_condition(scc_pproc_t *pp, scc_tok_type_t type, + scc_lexer_tok_ring_t *tok_ring) { + int condition = parse_constant_condition(pp, tok_ring) != 0; // 根据指令类型更新条件编译栈 switch (type) { @@ -143,7 +139,8 @@ cbool scc_pproc_parse_if_condition(scc_pproc_t *pp, scc_tok_type_t type, } case SCC_PP_TOK_ELIF: { if (scc_vec_size(pp->if_stack) == 0) { - LOG_ERROR("#elif without #if"); + SCC_ERROR(pp->cur_ring->data[pp->cur_ring->head].loc, + "#elif without #if"); return false; } scc_pproc_if_t *top = @@ -169,5 +166,4 @@ cbool scc_pproc_parse_if_condition(scc_pproc_t *pp, scc_tok_type_t type, LOG_FATAL("unexpected directive in parse_if_condition"); } return true; - return true; } diff --git a/libs/pproc/src/pproc_include.c b/libs/pproc/src/pproc_include.c index d40d8bc..6831245 100644 --- a/libs/pproc/src/pproc_include.c +++ b/libs/pproc/src/pproc_include.c @@ -33,15 +33,13 @@ static int switch_file_stack(scc_pproc_t *pp, scc_cstring_t *fname, goto FOPEN; } } - LOG_ERROR("In %s:%d:%d include %c%s%c, the file is not found", org_fname, - pos->line, pos->col, is_system ? '<' : '\"', - scc_cstring_as_cstr(fname), is_system ? '>' : '\"'); + SCC_ERROR(*pos, "include file '%s' not found", scc_cstring_as_cstr(fname)); return -1; FOPEN: if (scc_vec_size(pp->file_stack) >= pp->config.max_include_depth) { - LOG_FATAL("Include depth is too deep, the include depth is %d, set " - "MAX_INCLUDE_DEPTH is %d", - scc_vec_size(pp->file_stack), pp->config.max_include_depth); + SCC_FATAL(*pos, "include depth exceeds maximum (%d)", + pp->config.max_include_depth); + LOG_FATAL("Include depth is too deep..."); } scc_pproc_file_t *file = scc_malloc(sizeof(scc_pproc_file_t)); @@ -108,6 +106,7 @@ void scc_pproc_parse_include(scc_pproc_t *pp, scc_lexer_tok_t *include_tok, scc_cstring_free(&fname); return; ERROR: - LOG_ERROR("Invalid include filename need \"FILENAME\" or "); + SCC_ERROR(pos, + "invalid include filename, expected \"FILENAME\" or "); scc_cstring_free(&line); } diff --git a/libs/sstream/include/scc_pos_log.h b/libs/sstream/include/scc_pos_log.h new file mode 100644 index 0000000..fd9ae2c --- /dev/null +++ b/libs/sstream/include/scc_pos_log.h @@ -0,0 +1,30 @@ +#ifndef __SCC_POS_LOG_H__ +#define __SCC_POS_LOG_H__ + +#include "scc_pos.h" +#include + +extern logger_t __scc_usr_log; + +#define SCC_POS_LOG(level, pos, fmt, ...) \ + do { \ + char _full_msg[LOGGER_MAX_BUF_SIZE]; \ + int _n = snprintf_(_full_msg, sizeof(_full_msg), \ + "%s:%lu:%lu: ", (pos).name, (pos).line, (pos).col); \ + snprintf_(_full_msg + _n, sizeof(_full_msg) - _n, fmt, ##__VA_ARGS__); \ + __scc_usr_log.handler(&__scc_usr_log, level, null, 0, null, "%s", \ + _full_msg); \ + } while (0) + +#define SCC_DEBUG(pos, fmt, ...) \ + SCC_POS_LOG(LOG_LEVEL_DEBUG, pos, fmt, ##__VA_ARGS__) +#define SCC_INFO(pos, fmt, ...) \ + SCC_POS_LOG(LOG_LEVEL_INFO, pos, fmt, ##__VA_ARGS__) +#define SCC_WARN(pos, fmt, ...) \ + SCC_POS_LOG(LOG_LEVEL_WARN, pos, fmt, ##__VA_ARGS__) +#define SCC_ERROR(pos, fmt, ...) \ + SCC_POS_LOG(LOG_LEVEL_ERROR, pos, fmt, ##__VA_ARGS__) +#define SCC_FATAL(pos, fmt, ...) \ + SCC_POS_LOG(LOG_LEVEL_FATAL, pos, fmt, ##__VA_ARGS__) + +#endif /* __SCC_POS_LOG_H__ */ diff --git a/libs/sstream/include/scc_sstream.h b/libs/sstream/include/scc_sstream.h index 5a1511b..9765b0c 100644 --- a/libs/sstream/include/scc_sstream.h +++ b/libs/sstream/include/scc_sstream.h @@ -2,6 +2,7 @@ #define __SCC_SSTREAM_H__ #include "scc_pos.h" +#include "scc_pos_log.h" #include #include diff --git a/libs/sstream/src/scc_pos_log.c b/libs/sstream/src/scc_pos_log.c new file mode 100644 index 0000000..38941e1 --- /dev/null +++ b/libs/sstream/src/scc_pos_log.c @@ -0,0 +1,56 @@ +#include + +static int user_log_handler(logger_t *module, log_level_t level, + const char *file, int line, const char *func, + const char *fmt, ...) { + + /* clang-format off */ + (void)file; (void)line; (void)func; // 不再使用 + + const char *level_str = null; + switch (level) { + case LOG_LEVEL_DEBUG: level_str = "DEBUG"; break; + case LOG_LEVEL_INFO: level_str = "INFO "; break; + case LOG_LEVEL_WARN: level_str = "WARN "; break; + case LOG_LEVEL_ERROR: level_str = "ERROR"; break; + case LOG_LEVEL_FATAL: level_str = "FATAL"; break; + case LOG_LEVEL_TRACE: level_str = "TRACE"; break; + default: level_str = "NOTSET"; break; + } + /// @note: 定义 __LOG_NO_COLOR__ 会取消颜色输出 + #ifndef __LOG_NO_COLOR__ + const char *color_code; + switch (level) { + case LOG_LEVEL_DEBUG: color_code = ANSI_FG_CYAN; break; + case LOG_LEVEL_INFO: color_code = ANSI_FG_GREEN; break; + case LOG_LEVEL_TRACE: color_code = ANSI_FG_BLUE; break; + case LOG_LEVEL_WARN: color_code = ANSI_FG_YELLOW; break; + case LOG_LEVEL_ERROR: color_code = ANSI_FG_RED; break; + case LOG_LEVEL_FATAL: color_code = ANSI_FG_RED ANSI_UNDERLINED; break; + default: color_code = ANSI_NONE; + } + #endif + /* clang-format on */ + char buf[LOGGER_MAX_BUF_SIZE]; + int off = + snprintf_(buf, sizeof(buf), "%s[%s]%s ", color_code ? color_code : "", + level_str, color_code ? ANSI_NONE : ""); + + va_list args; + va_start(args, fmt); + vsnprintf_(buf + off, sizeof(buf) - off, fmt, args); + va_end(args); + + log_puts(buf); + log_puts("\n"); + + if (level == LOG_LEVEL_FATAL) + log_exit(1); + return 0; +} + +logger_t __scc_usr_log = { + .name = "user", + .handler = user_log_handler, + .level = LOG_LEVEL_ALL, +}; diff --git a/libs/sstream/src/scc_sstream.c b/libs/sstream/src/scc_sstream.c index 54e5bf2..b48e5f8 100644 --- a/libs/sstream/src/scc_sstream.c +++ b/libs/sstream/src/scc_sstream.c @@ -88,7 +88,9 @@ int scc_sstream_init(scc_sstream_t *stream, const char *fname, int ring_size) { } usize fsize = scc_fsize(file); if (fsize == 0) { - LOG_WARN("file size is 0"); + stream->fill_pos = scc_pos_create(); + stream->fill_pos.name = fname; + SCC_WARN(stream->fill_pos, "file size is 0"); scc_fclose(file); return 2; } diff --git a/runtime/log/include/log.h b/runtime/log/include/log.h index 6e2d726..8b8d5d7 100644 --- a/runtime/log/include/log.h +++ b/runtime/log/include/log.h @@ -7,12 +7,7 @@ #define __SCC_LOG_IMPL_H__ #include "color.h" -#ifndef __SCC__ #include -#else -// TODO -#warning "TODO: implement stdarg.h" -#endif #ifdef __SCC_LOG_IMPL_USE_STD_IMPL__ #include @@ -22,7 +17,7 @@ #define log_exit scc_exit #endif -#ifdef __GNUC__ // GCC, Clang, ICC +#ifdef __GNUC__ // GCC, Clang #define __smcc_log_unreachable() (__builtin_unreachable()) #elif defined _MSC_VER // MSVC #define __smcc_log_unreachable() (__assume(false)) @@ -82,6 +77,7 @@ struct logger { const char *name; ///< 日志器名称(用于模块区分) log_level_t level; ///< 当前设置的日志级别 log_handler handler; ///< 日志处理回调函数 + void *user_data; ///< 用户自定义数据 char buf[LOGGER_MAX_BUF_SIZE]; ///< 格式化缓冲区 };