2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * ***** END GPL LICENSE BLOCK *****
24 /** \file clog/CLG_log.h
27 * C Logging Library (clog)
28 * ========================
33 * - `CLG_LOGREF_DECLARE_GLOBAL` macro to declare #CLG_LogRef pointers.
34 * - `CLOG_` prefixed macros for logging.
39 * #CLG_LogRef holds an identifier which defines the category of the logger.
41 * You can define and use identifiers as needed, logging will lazily initialize them.
43 * By convention lower case dot separated identifiers are used, eg:
44 * `module.sub_module`, this allows filtering by `module.*`,
45 * see #CLG_type_filter_include, #CLG_type_filter_exclude
47 * There is currently no functionality to remove a category once it's created.
52 * - `INFO`: Simply log events, uses verbosity levels to control how much information to show.
53 * - `WARN`: General warnings (which aren't necessary to show to users).
54 * - `ERROR`: An error we can recover from, should not happen.
55 * - `FATAL`: Similar to assert. This logs the message, then a stack trace and abort.
63 * - 0: Always show (used for warnings, errors).
64 * Should never get in the way or become annoying.
66 * - 1: Top level module actions (eg: load a file, create a new window .. etc).
68 * - 2: Actions within a module (steps which compose an action, but don't flood output).
69 * Running a tool, full data recalculation.
71 * - 3: Detailed actions which may be of interest when debugging internal logic of a module
72 * These *may* flood the log with details.
74 * - 4+: May be used for more details than 3, should be avoided but not prevented.
79 #endif /* __cplusplus */
82 # define _CLOG_ATTR_NONNULL(args ...) __attribute__((nonnull(args)))
84 # define _CLOG_ATTR_NONNULL(...)
88 # define _CLOG_ATTR_PRINTF_FORMAT(format_param, dots_param) __attribute__((format(printf, format_param, dots_param)))
90 # define _CLOG_ATTR_PRINTF_FORMAT(format_param, dots_param)
93 #define STRINGIFY_ARG(x) "" #x
94 #define STRINGIFY_APPEND(a, b) "" a #b
95 #define STRINGIFY(x) STRINGIFY_APPEND("", x)
99 /* Don't typedef enums. */
101 CLG_FLAG_USE = (1 << 0),
105 CLG_SEVERITY_INFO = 0,
110 #define CLG_SEVERITY_LEN (CLG_SEVERITY_FATAL + 1)
112 /* Each logger ID has one of these. */
113 typedef struct CLG_LogType {
114 struct CLG_LogType *next;
117 struct CLogContext *ctx;
118 /** Control behavior. */
120 enum CLG_LogFlag flag;
123 typedef struct CLG_LogRef {
124 const char *identifier;
129 CLG_LogType *lg, enum CLG_Severity severity, const char *file_line, const char *fn,
131 _CLOG_ATTR_NONNULL(1, 3, 4, 5);
133 CLG_LogType *lg, enum CLG_Severity severity, const char *file_line, const char *fn,
134 const char *format, ...)
135 _CLOG_ATTR_NONNULL(1, 3, 4, 5) _CLOG_ATTR_PRINTF_FORMAT(5, 6);
137 /* Main initializer and distructor (per session, not logger). */
141 void CLG_output_set(void *file_handle);
142 void CLG_output_use_basename_set(int value);
143 void CLG_output_use_timestamp_set(int value);
144 void CLG_fatal_fn_set(void (*fatal_fn)(void *file_handle));
145 void CLG_backtrace_fn_set(void (*fatal_fn)(void *file_handle));
147 void CLG_type_filter_include(const char *type_filter, int type_filter_len);
148 void CLG_type_filter_exclude(const char *type_filter, int type_filter_len);
150 void CLG_level_set(int level);
152 void CLG_logref_init(CLG_LogRef *clg_ref);
154 /** Declare outside function, declare as extern in header. */
155 #define CLG_LOGREF_DECLARE_GLOBAL(var, id) \
156 static CLG_LogRef _static_ ## var = {id}; \
157 CLG_LogRef *var = &_static_ ## var
159 /** Initialize struct once. */
160 #define CLOG_ENSURE(clg_ref) \
161 ((clg_ref)->type ? (clg_ref)->type : (CLG_logref_init(clg_ref), (clg_ref)->type))
163 #define CLOG_AT_SEVERITY(clg_ref, severity, verbose_level, ...) { \
164 CLG_LogType *_lg_ty = CLOG_ENSURE(clg_ref); \
165 if (((_lg_ty->flag & CLG_FLAG_USE) && (_lg_ty->level >= verbose_level)) || (severity >= CLG_SEVERITY_WARN)) { \
166 CLG_logf(_lg_ty, severity, __FILE__ ":" STRINGIFY(__LINE__), __func__, __VA_ARGS__); \
170 #define CLOG_STR_AT_SEVERITY(clg_ref, severity, verbose_level, str) { \
171 CLG_LogType *_lg_ty = CLOG_ENSURE(clg_ref); \
172 if (((_lg_ty->flag & CLG_FLAG_USE) && (_lg_ty->level >= verbose_level)) || (severity >= CLG_SEVERITY_WARN)) { \
173 CLG_log_str(lg, severity, __FILE__ ":" STRINGIFY(__LINE__), __func__, str); \
177 #define CLOG_STR_AT_SEVERITY_N(clg_ref, severity, verbose_level, str) { \
178 CLG_LogType *_lg_ty = CLOG_ENSURE(clg_ref); \
179 if (((_lg_ty->flag & CLG_FLAG_USE) && (_lg_ty->level >= verbose_level)) || (severity >= CLG_SEVERITY_WARN)) { \
180 const char *_str = str; \
181 CLG_log_str(_lg_ty, severity, __FILE__ ":" STRINGIFY(__LINE__), __func__, _str); \
182 MEM_freeN((void *)_str); \
186 #define CLOG_INFO(clg_ref, level, ...) CLOG_AT_SEVERITY(clg_ref, CLG_SEVERITY_INFO, level, __VA_ARGS__)
187 #define CLOG_WARN(clg_ref, ...) CLOG_AT_SEVERITY(clg_ref, CLG_SEVERITY_WARN, 0, __VA_ARGS__)
188 #define CLOG_ERROR(clg_ref, ...) CLOG_AT_SEVERITY(clg_ref, CLG_SEVERITY_ERROR, 0, __VA_ARGS__)
189 #define CLOG_FATAL(clg_ref, ...) CLOG_AT_SEVERITY(clg_ref, CLG_SEVERITY_FATAL, 0, __VA_ARGS__)
191 #define CLOG_STR_INFO(clg_ref, level, ...) CLOG_STR_AT_SEVERITY(clg_ref, CLG_SEVERITY_INFO, level, __VA_ARGS__)
192 #define CLOG_STR_WARN(clg_ref, ...) CLOG_STR_AT_SEVERITY(clg_ref, CLG_SEVERITY_WARN, 0, __VA_ARGS__)
193 #define CLOG_STR_ERROR(clg_ref, ...) CLOG_STR_AT_SEVERITY(clg_ref, CLG_SEVERITY_ERROR, 0, __VA_ARGS__)
194 #define CLOG_STR_FATAL(clg_ref, ...) CLOG_STR_AT_SEVERITY(clg_ref, CLG_SEVERITY_FATAL, 0, __VA_ARGS__)
196 /* Allocated string which is immediately freed. */
197 #define CLOG_STR_INFO_N(clg_ref, level, ...) CLOG_STR_AT_SEVERITY_N(clg_ref, CLG_SEVERITY_INFO, level, __VA_ARGS__)
198 #define CLOG_STR_WARN_N(clg_ref, ...) CLOG_STR_AT_SEVERITY_N(clg_ref, CLG_SEVERITY_WARN, 0, __VA_ARGS__)
199 #define CLOG_STR_ERROR_N(clg_ref, ...) CLOG_STR_AT_SEVERITY_N(clg_ref, CLG_SEVERITY_ERROR, 0, __VA_ARGS__)
200 #define CLOG_STR_FATAL_N(clg_ref, ...) CLOG_STR_AT_SEVERITY_N(clg_ref, CLG_SEVERITY_FATAL, 0, __VA_ARGS__)
206 #endif /* __CLG_LOG_H__ */