Files
scc/runtime/log/include/log.h
zzy c99f64708e feat(parser): 改进解析器错误处理和表达式解析逻辑
- 在初始化解析中添加缺失的赋值操作符检查
- 改进后缀表达式解析逻辑,处理嵌套情况
- 添加数组下标初始化的赋值操作符验证
- 修复主表达式解析中的返回语句处理

refactor(pproc): 优化预处理器宏展开和位置追踪

- 添加token复制函数来保持原始位置信息
- 重构宏展开函数参数传递方式
- 修复字符串化参数的位置信息处理
- 改进可变参数宏的处理逻辑

test(parser): 增加标签语句和字符串字面量测试用例

- 添加返回语句with复合字面量的测试
- 增加标签继续语句的测试用例
- 添加字符串连接的解析测试

test(pproc): 添加预处理器位置追踪测试

- 增加双重宏定义位置追踪测试
- 添加带参数宏定义位置追踪测试
- 增加字符串化操作位置追踪测试

docs: 更新代码中的宏定义和注释

- 修正未定义标识符的拼写错误
- 添加必要的头文件包含
- 改进错误消息提示文本
2026-03-13 13:48:55 +08:00

197 lines
8.0 KiB
C
Raw 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.
/**
* @file log.h
* @brief 日志系统核心模块(支持多级日志、断言和异常处理)
*/
#ifndef __SCC_LOG_IMPL_H__
#define __SCC_LOG_IMPL_H__
#include "color.h"
#include <stdarg.h>
#ifdef __SCC_LOG_IMPL_USE_STD_IMPL__
#include <stdio.h>
#include <stdlib.h>
#define log_vsnprintf vsnprintf
#define log_puts puts
#define log_exit scc_exit
#endif
#ifdef __GNUC__ // GCC, Clang
#define __scc_log_unreachable() (__builtin_unreachable())
#elif defined _MSC_VER // MSVC
#define __scc_log_unreachable() (__assume(false))
#elif defined __SCC_BUILTIN__ // The SCC Compiler (my compiler)
#define __scc_log_unreachable() (__scc_builtin_unreachable())
#else
#define __scc_log_unreachable() ((void)0)
#endif
#ifndef log_vsnprintf
#define log_vsnprintf(...)
#warning "log_vsnprintf not defined"
#endif
#ifndef log_puts
#define log_puts(...)
#warning "log_puts not defined"
#endif
#ifndef log_exit
#define log_exit(...)
#warning "log_exit not defined"
#endif
/**
* @brief 日志级别枚举
*
* 定义日志系统的输出级别和组合标志位
*/
typedef enum log_level {
LOG_LEVEL_NOTSET = 0, ///< 未设置级别(继承默认配置)
LOG_LEVEL_DEBUG = 1 << 0, ///< 调试信息(开发阶段详细信息)
LOG_LEVEL_INFO = 1 << 1, ///< 常规信息(系统运行状态)
LOG_LEVEL_WARN = 1 << 2, ///< 警告信息(潜在问题提示)
LOG_LEVEL_ERROR = 1 << 3, ///< 错误信息(可恢复的错误)
LOG_LEVEL_FATAL = 1 << 4, ///< 致命错误(导致程序终止的严重错误)
LOG_LEVEL_TRACE = 1 << 5, ///< 追踪(性能追踪或者栈帧追踪)
LOG_LEVEL_ALL = 0xFF, ///< 全级别标志(组合所有日志级别)
} log_level_t;
#ifndef LOGGER_MAX_BUF_SIZE
#define LOGGER_MAX_BUF_SIZE 512 ///< 单条日志最大缓冲区尺寸
#endif
typedef struct logger logger_t;
typedef int (*log_handler)(logger_t *module, log_level_t level,
const char *file, int line, const char *func,
const char *fmt, ...);
/**
* @brief 日志器实例结构体
*
* 每个日志器实例维护独立的配置和缓冲区
*/
struct logger {
const char *name; ///< 日志器名称(用于模块区分)
log_level_t level; ///< 当前设置的日志级别
log_handler handler; ///< 日志处理回调函数
void *user_data; ///< 用户自定义数据
char buf[LOGGER_MAX_BUF_SIZE]; ///< 格式化缓冲区
};
int log_default_handler(logger_t *module, log_level_t level, const char *file,
int line, const char *func, const char *fmt, ...);
extern logger_t __default_logger_root;
/**
* @brief 初始化日志实例 其余参数设置为默认值
* @param[in] logger 日志器实例指针
* @param[in] name 日志器名称NULL表示获取默认日志器名称
*/
void init_logger(logger_t *logger, const char *name);
/**
* @brief 设置日志级别
* @param[in] logger 目标日志器实例
* @param[in] level 要设置的日志级别(可组合多个级别)
*/
void log_set_level(logger_t *logger, int level);
/**
* @brief 设置自定义日志处理器
* @param[in] logger 目标日志器实例
* @param[in] handler 自定义处理函数NULL恢复默认处理
*/
void log_set_handler(logger_t *logger, log_handler handler);
#ifndef LOG_MAX_MAROC_BUF_SIZE
#define LOG_MAX_MAROC_BUF_SIZE LOGGER_MAX_BUF_SIZE ///< 宏展开缓冲区尺寸
#endif
#define SCC_LOG_HANDLE_ARGS(_module_, _level_, ...) \
(_module_), (_level_), __FILE__, __LINE__, __func__, ##__VA_ARGS__
#define SCC_LOG_IMPL(_module_, _level_, _fmt_, ...) \
do { \
/* TODO check _module_ is NULL */ \
if ((_module_)->handler && ((_module_)->level & (_level_))) \
(_module_)->handler( \
SCC_LOG_HANDLE_ARGS(_module_, _level_, _fmt_, ##__VA_ARGS__)); \
} while (0)
/* clang-format off */
/// @name 模块日志宏
/// @{
#define MLOG_NOTSET(module, ...)SCC_LOG_IMPL(module, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志
#define MLOG_DEBUG(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志需启用DEBUG级别
#define MLOG_INFO(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志)
#define MLOG_WARN(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题)
#define MLOG_ERROR(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误)
#define MLOG_FATAL(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前)
#define MLOG_TRACE(module, ...) SCC_LOG_IMPL(module, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪)
/// @}
/// @name 快捷日志宏
/// @{
#define LOG_NOTSET(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_NOTSET, __VA_ARGS__) ///< 未分类日志
#define LOG_DEBUG(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_DEBUG, __VA_ARGS__) ///< 调试日志需启用DEBUG级别
#define LOG_INFO(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_INFO, __VA_ARGS__) ///< 信息日志(常规运行日志)
#define LOG_WARN(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_WARN, __VA_ARGS__) ///< 警告日志(潜在问题)
#define LOG_ERROR(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_ERROR, __VA_ARGS__) ///< 错误日志(可恢复错误)
#define LOG_FATAL(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_FATAL, __VA_ARGS__) ///< 致命错误日志(程序终止前)
#define LOG_TRACE(...) SCC_LOG_IMPL(&__default_logger_root, LOG_LEVEL_TRACE, __VA_ARGS__) ///< 追踪日志(调用栈跟踪)
/// @}
/* clang-format on */
/**
* @def _Assert
* @brief 断言检查内部宏
* @param cond 检查条件表达式
* @param ... 错误信息参数(格式字符串+参数)
*/
#define _Assert(cond, ...) \
((void)((cond) || \
(__default_logger_root.handler(SCC_LOG_HANDLE_ARGS( \
&__default_logger_root, LOG_LEVEL_FATAL, __VA_ARGS__)), \
log_exit(1), __scc_log_unreachable(), 0)))
/// @name 断言工具宏
/// @{
#define __INNERSCC_LOG_IMPL_STR(str) #str
#define _SCC_LOG_IMPL_STR(str) __INNERSCC_LOG_IMPL_STR(str)
#define AssertFmt(cond, format, ...) \
_Assert(cond, "Assertion Failure: " format, \
##__VA_ARGS__) ///< 带格式的断言检查
#define PanicFmt(format, ...) \
_Assert(0, "Panic: " format, ##__VA_ARGS__) ///< 立即触发致命错误
#define Assert(cond) \
AssertFmt(cond, "cond is `" _SCC_LOG_IMPL_STR(cond) "`") ///< 基础断言检查
#define Panic(...) PanicFmt(__VA_ARGS__) ///< 触发致命错误(带自定义消息)
#define TODO() \
PanicFmt("TODO please implement me") ///< 标记未实现代码(触发致命错误)
#define UNREACHABLE() PanicFmt("UNREACHABLE") ///< 触发致命错误(代码不可达)
#define FIXME(str) \
PanicFmt("FIXME " _SCC_LOG_IMPL_STR( \
str)) ///< 提醒开发者修改代码(触发致命错误)
/// @}
/**
* @brief 静态断言(编译时)
*
* 利用数组大小不能为负的特性
* 或使用 _Static_assert (C11)
*/
#if __STDC_VERSION__ >= 201112L
#define StaticAssert static_assert
#else
#define StaticAssert(cond, msg) extern char __static_assertion[(cond) ? 1 : -1]
#endif
#ifdef __SCC_LOG_IMPL_IMPORT_SRC__
#include "log.c"
#endif
#endif /* __SCC_LOG_IMPL_H__ */