feat(lexer, preprocessor): replace cstring conversion with copy and refactor macro expansion

- Replace `scc_cstring_from_cstr(scc_cstring_as_cstr(...))` with `scc_cstring_copy()` in lexer to fix memory leaks
- Extract macro expansion logic into separate `expand_macro.c` file
- Remove `expand_stack` parameter from `scc_pp_expand_macro()` function
- Add new parsing functions for macro replacement lists and arguments
- Add string utility functions for whitespace trimming and string joining
- Update memory stream documentation for clarity
This commit is contained in:
zzy
2025-12-15 20:24:39 +08:00
parent 73d74f5e13
commit 07f5d9331b
15 changed files with 574 additions and 346 deletions

View File

@@ -20,6 +20,7 @@ typedef struct scc_cstring {
*
* @return cstring_t 初始化后的对象
*/
// FIXME need using `init` beacuse it not malloc
static inline scc_cstring_t scc_cstring_new(void) {
return (scc_cstring_t){.data = null, .size = 0, .cap = 0};
}
@@ -48,6 +49,10 @@ static inline scc_cstring_t scc_cstring_from_cstr(const char *s) {
return (scc_cstring_t){.size = len + 1, .cap = len + 1, .data = data};
}
static inline scc_cstring_t scc_cstring_copy(const scc_cstring_t *s) {
return scc_cstring_from_cstr(s->data);
}
/**
* @brief 释放动态字符串占用的内存资源
*
@@ -182,4 +187,15 @@ static inline char *scc_cstring_as_cstr(const scc_cstring_t *str) {
return str->data;
}
static inline char *scc_cstring_move_cstr(scc_cstring_t *str) {
if (str == null || str->data == null) {
return "";
}
char *ret = str->data;
str->data = null;
str->cap = 0;
str->size = 0;
return ret;
}
#endif /* __SCC_CORE_STR_H__ */

View File

@@ -100,7 +100,7 @@ typedef struct scc_mem_probe_stream {
usize data_length;
usize curr_pos; // 当前读取位置
usize probe_pos; // 探针位置用于peek
cbool owned; // 是否拥有数据(需要释放)
cbool owned; // 是否拥有数据(如果拥有将会自动释放)
} scc_mem_probe_stream_t;
/**
@@ -109,22 +109,22 @@ typedef struct scc_mem_probe_stream {
* @param stream 流结构指针
* @param data 数据指针
* @param length 数据长度
* @param need_copy 是否需要复制数据
* @param owned 是否拥有数据(如果拥有将会自动释放)
* @return core_probe_stream_t* 成功返回流指针失败返回NULL
*/
scc_probe_stream_t *scc_mem_probe_stream_init(scc_mem_probe_stream_t *stream,
const char *data, usize length,
cbool need_copy);
cbool owned);
/**
* @brief 构造内存探针流(其中drop会自动释放内存)
*
* @param data
* @param length
* @param need_copy
* @param owned 是否拥有数据(如果拥有将会自动释放)
* @return scc_probe_stream_t*
*/
scc_probe_stream_t *scc_mem_probe_stream_new(const char *data, usize length,
cbool need_copy);
cbool owned);
#endif
#endif /* __SMCC_CORE_PROBE_STREAM_H__ */

View File

@@ -125,7 +125,7 @@ static void mem_probe_stream_drop(scc_probe_stream_t *_stream) {
scc_probe_stream_t *scc_mem_probe_stream_init(scc_mem_probe_stream_t *stream,
const char *data, usize length,
cbool need_copy) {
cbool owned) {
if (stream == null || data == null) {
LOG_ERROR("param error");
return null;
@@ -133,22 +133,11 @@ scc_probe_stream_t *scc_mem_probe_stream_init(scc_mem_probe_stream_t *stream,
if (length == 0) {
LOG_WARN("input memory is empty");
need_copy = false;
owned = false;
}
stream->owned = need_copy;
if (need_copy) {
char *buf = (char *)scc_malloc(length);
if (buf == null) {
LOG_ERROR("malloc error");
return null;
}
scc_memcpy(buf, data, length);
stream->data = buf;
} else {
stream->data = data;
}
stream->owned = owned;
stream->data = data;
stream->data_length = length;
stream->curr_pos = 0;
stream->probe_pos = 0;
@@ -176,7 +165,7 @@ static void scc_owned_mem_stream_drop(scc_probe_stream_t *_stream) {
}
scc_probe_stream_t *scc_mem_probe_stream_new(const char *data, usize length,
cbool need_copy) {
cbool owned) {
scc_mem_probe_stream_t *stream =
(scc_mem_probe_stream_t *)scc_malloc(sizeof(scc_mem_probe_stream_t));
if (stream == null) {
@@ -184,7 +173,7 @@ scc_probe_stream_t *scc_mem_probe_stream_new(const char *data, usize length,
}
scc_probe_stream_t *ret =
scc_mem_probe_stream_init(stream, data, length, need_copy);
scc_mem_probe_stream_init(stream, data, length, owned);
stream->stream.drop = scc_owned_mem_stream_drop;
Assert(ret != null);
return ret;