Files
scc/libs/sstream/src/scc_sstream.c
zzy 88846d7479 refactor(log): 统一日志系统并添加链接器实现
- 为所有模块添加统一的 scc_*_log.h 日志头文件,删除旧的 lexer_log.h/c
- 将运行时日志从 scc_utils 迁移到 scc_core 目录,统一日志管理
- 在解析器表达式/语句/类型解析中添加 LOG_TRACE 调试日志
- 实现 SCCF 链接器 (sccf_linker) 支持多目标文件链接
- 重构 CLI 主程序 (main.c/config.c),新增 cmd_log.h 调试支持
- 优化 x86 指令编码操作数对齐检查
- 修复预处理器的指令处理和宏展开逻辑
2026-06-05 13:07:41 +08:00

156 lines
4.9 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#define __SCC_SSTREAM_LOG_IMPL__
#include <scc_sstream_log.h>
#include <scc_sstream.h>
// 内部扫描函数:从指定位置扫描下一个有效字符
static int sstream_scan_at(scc_sstream_t *stream, scc_pos_t scan_pos,
scc_pos_t *out_char_pos, scc_pos_t *out_next_pos) {
while (1) {
if (scan_pos.offset >= stream->len)
return -1; // EOF
scc_pos_t start = scan_pos;
char c = stream->src[scan_pos.offset];
// 处理反斜杠换行
if (c == '\\') {
usize next_off = scan_pos.offset + 1;
if (next_off < stream->len) {
char n = stream->src[next_off];
if (n == '\n') {
// 跳过 '\' 和 '\n'
scan_pos.offset += 2;
scan_pos.line++;
scan_pos.col = 1;
continue;
} else if (n == '\r' && next_off + 1 < stream->len &&
stream->src[next_off + 1] == '\n') {
// 跳过 '\' + '\r' + '\n'
scan_pos.offset += 3;
scan_pos.line++;
scan_pos.col = 1;
continue;
}
}
}
// 处理 \r\n 转换为 \n
if (c == '\r') {
usize next_off = scan_pos.offset + 1;
if (next_off < stream->len && stream->src[next_off] == '\n') {
if (out_char_pos)
*out_char_pos = start;
// 下一个位置:偏移+2行+1列=1
scan_pos.offset += 2;
scan_pos.line++;
scan_pos.col = 1;
if (out_next_pos)
*out_next_pos = scan_pos;
return '\n';
}
}
// 普通字符(包括单独的 '\n'、'\r' 等)
if (out_char_pos)
*out_char_pos = start;
// 计算下一个位置
scan_pos.offset++;
if (c == '\n') {
scan_pos.line++;
scan_pos.col = 1;
} else {
scan_pos.col++;
}
if (out_next_pos)
*out_next_pos = scan_pos;
return c;
}
}
// 环形缓冲区填充回调(通过 userdata 获取流对象)
static cbool fill_func(scc_sstream_char_t *out, void *userdata) {
Assert(out != nullptr && userdata != nullptr);
scc_sstream_t *stream = (scc_sstream_t *)userdata;
if (stream->fill_pos.offset >= stream->len)
return false; // 已到文件尾
int ch = sstream_scan_at(stream, stream->fill_pos, &out->pos,
&(stream->fill_pos));
if (ch == -1)
return false;
out->character = ch;
return true;
}
int scc_sstream_init(scc_sstream_t *stream, const char *fname, int ring_size) {
Assert(stream != nullptr && fname != nullptr);
scc_file_t file = scc_fopen(fname, SCC_FILE_READ);
if (file == nullptr) {
LOG_ERROR("Failed to open file: %s", fname);
return 1;
}
usize fsize = scc_fsize(file);
if (fsize == 0) {
stream->fill_pos = scc_pos_create();
stream->fill_pos.name = fname;
LOG_WARN("file size is 0");
scc_sstream_init_by_buffer(stream, "", 0, false, ring_size);
return 0;
}
char *buffer = (char *)scc_malloc(fsize);
scc_memset(buffer, 0, fsize);
usize read_ret = scc_fread(file, buffer, fsize);
Assert(read_ret == fsize); /* read bytes assert it */
scc_fclose(file);
scc_sstream_init_by_buffer(stream, buffer, read_ret, true, ring_size);
stream->fname = fname;
stream->fill_pos.name = stream->fname;
return 0;
}
int scc_sstream_init_by_buffer(scc_sstream_t *stream, const char *buffer,
usize len, int owned, int ring_size) {
stream->fname = "<buffer>";
stream->fill_pos = scc_pos_create();
stream->fill_pos.name = stream->fname;
stream->src = buffer;
stream->len = len;
stream->owned_src = owned;
scc_ring_init(stream->ring, ring_size <= 0 ? 64 : ring_size, fill_func,
stream);
stream->used = 0;
return 0;
}
scc_sstream_ring_t *scc_sstream_to_ring(scc_sstream_t *stream) {
Assert(stream != nullptr);
stream->used++;
return &stream->ring;
}
void scc_sstream_drop_ring(scc_sstream_ring_t *ring) {
Assert(ring != nullptr && ring->userdata != nullptr);
scc_sstream_t *stream = (scc_sstream_t *)ring->userdata;
if (stream->used > 0) {
stream->used--;
} else {
LOG_WARN("double drop sstream ring");
}
}
void scc_sstream_drop(scc_sstream_t *stream) {
Assert(stream != nullptr);
if (stream->used) {
LOG_FATAL("drop sstream must be drop ring before ref [%d]",
stream->used);
}
if (stream->src && stream->owned_src) {
scc_free((void *)stream->src);
stream->src = nullptr;
}
scc_ring_free(stream->ring);
}