- 为所有模块添加统一的 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 指令编码操作数对齐检查 - 修复预处理器的指令处理和宏展开逻辑
156 lines
4.9 KiB
C
156 lines
4.9 KiB
C
#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);
|
||
}
|