refactor(format): 移除SCF格式相关文件

移除了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操作符解析参数
This commit is contained in:
zzy
2026-02-26 10:25:45 +08:00
parent d2eaf2247f
commit f56b13da2c
19 changed files with 215 additions and 1023 deletions

View File

View File

@@ -1,8 +0,0 @@
[package]
name = "scc_format"
version = "0.1.0"
dependencies = [
{ name = "libcore", path = "../../runtime/libcore" },
{ name = "libutils", path = "../../runtime/libutils" },
]

View File

@@ -1,150 +0,0 @@
/**
* @file scf.h
* @brief scc format (SMF) 头文件
*
* SCF是一个极简的可执行可链接文件格式专注于内部链接处理
* 同时提供外部符号导入/导出的抽象接口。
*/
#ifndef __SCC_FORMAT_H__
#define __SCC_FORMAT_H__
#include <stddef.h>
#include <stdint.h>
#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__ */

View File

@@ -1,42 +0,0 @@
#ifndef __SCC_FORMAT_IMPL_H__
#define __SCC_FORMAT_IMPL_H__
#include <libcore.h>
#include <libutils.h>
#include <scf.h>
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__ */

View File

@@ -1,469 +0,0 @@
/**
* @file scf.c
* @brief SCF 格式实现
*/
#include <scf_impl.h>
/**
* @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;
}

View File

@@ -1,109 +0,0 @@
/**
* @file test_scf.c
* @brief SCF format tests
*/
#include <scf_impl.h>
#include <stdio.h>
#include <string.h>
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;
}

View File

@@ -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 <scf_impl.h>
#include <stdio.h>
#include <string.h>
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;
}

View File

@@ -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;

View File

@@ -1,4 +1,3 @@
#include "scc_lexer.h"
#include <lexer_log.h>
#include <scc_lexer.h>
@@ -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;
}
}

View File

@@ -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__ */

View File

@@ -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:

View File

@@ -1,4 +1,5 @@
#include <pproc_expand.h>
#include <scc_lexer_utils.h>
#include <scc_pproc.h>
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 = &ring;
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);

View File

@@ -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,
static int parse_constant_condition(scc_pproc_t *pp,
scc_lexer_tok_ring_t *tok_ring) {
// TODO
int ok;
scc_lexer_tok_t tok = {0};
ok = scc_lexer_next_non_blank(tok_ring, &tok);
if (ok == false) {
scc_lexer_tok_drop(&tok);
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);
int res = 0;
ok = scc_lexer_next_non_blank(tok_ring, &tok);
if (ok == false) {
LOG_FATAL("unexpected EOF");
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';
}
if (tok.type != SCC_TOK_ENDLINE) {
LOG_ERROR("expected endline");
scc_lexer_skip_until_newline(tok_ring);
} else {
scc_lexer_tok_drop(&tok);
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;
}

View File

@@ -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 <FILENAME>");
SCC_ERROR(pos,
"invalid include filename, expected \"FILENAME\" or <FILENAME>");
scc_cstring_free(&line);
}

View File

@@ -0,0 +1,30 @@
#ifndef __SCC_POS_LOG_H__
#define __SCC_POS_LOG_H__
#include "scc_pos.h"
#include <scc_core.h>
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__ */

View File

@@ -2,6 +2,7 @@
#define __SCC_SSTREAM_H__
#include "scc_pos.h"
#include "scc_pos_log.h"
#include <scc_core.h>
#include <scc_core_ring.h>

View File

@@ -0,0 +1,56 @@
#include <scc_pos_log.h>
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,
};

View File

@@ -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;
}

View File

@@ -7,12 +7,7 @@
#define __SCC_LOG_IMPL_H__
#include "color.h"
#ifndef __SCC__
#include <stdarg.h>
#else
// TODO
#warning "TODO: implement stdarg.h"
#endif
#ifdef __SCC_LOG_IMPL_USE_STD_IMPL__
#include <stdio.h>
@@ -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]; ///< 格式化缓冲区
};