Blender V4.5
clog.c
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2018-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <assert.h>
10#include <stdarg.h>
11#include <stdint.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <string.h>
15
16/* Disable for small single threaded programs
17 * to avoid having to link with pthreads. */
18#ifdef WITH_CLOG_PTHREADS
19# include "atomic_ops.h"
20# include <pthread.h>
21#endif
22
23/* For 'isatty' to check for color. */
24#if defined(__unix__) || defined(__APPLE__) || defined(__HAIKU__)
25# include <sys/time.h>
26# include <unistd.h>
27#endif
28
29#if defined(_MSC_VER)
30# include <Windows.h>
31
32# include <VersionHelpers.h> /* This needs to be included after Windows.h. */
33# include <io.h>
34# if !defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
35# define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
36# endif
37#endif
38
39/* For printing timestamp. */
40#define __STDC_FORMAT_MACROS
41#include <inttypes.h>
42
43/* Only other dependency (could use regular malloc too). */
44#include "MEM_guardedalloc.h"
45
46/* own include. */
47#include "CLG_log.h"
48
49/* Local utility defines */
50#define STREQ(a, b) (strcmp(a, b) == 0)
51#define STREQLEN(a, b, n) (strncmp(a, b, n) == 0)
52
53#ifdef _WIN32
54# define PATHSEP_CHAR '\\'
55#else
56# define PATHSEP_CHAR '/'
57#endif
58
59/* -------------------------------------------------------------------- */
62
63typedef struct CLG_IDFilter {
66 char match[0];
68
69typedef struct CLogContext {
74#ifdef WITH_CLOG_PTHREADS
75 pthread_mutex_t types_lock;
76#endif
77
78 /* exclude, include filters. */
83
85 int output;
87
90
92 struct {
93 int level;
95
96 struct {
97 void (*error_fn)(void *file_handle);
98 void (*fatal_fn)(void *file_handle);
99 void (*backtrace_fn)(void *file_handle);
102
104
105/* -------------------------------------------------------------------- */
110
111#define CLOG_BUF_LEN_INIT 512
112
119
120static void clg_str_init(CLogStringBuf *cstr, char *buf_stack, uint buf_stack_len)
121{
122 cstr->data = buf_stack;
123 cstr->len_alloc = buf_stack_len;
124 cstr->len = 0;
125 cstr->is_alloc = false;
126}
127
128static void clg_str_free(CLogStringBuf *cstr)
129{
130 if (cstr->is_alloc) {
131 MEM_freeN(cstr->data);
132 }
133}
134
135static void clg_str_reserve(CLogStringBuf *cstr, const uint len)
136{
137 if (len > cstr->len_alloc) {
138 cstr->len_alloc *= 2;
139 if (len > cstr->len_alloc) {
140 cstr->len_alloc = len;
141 }
142
143 if (cstr->is_alloc) {
144 cstr->data = MEM_reallocN(cstr->data, cstr->len_alloc);
145 }
146 else {
147 /* Copy the static buffer. */
148 char *data = MEM_mallocN(cstr->len_alloc, __func__);
149 memcpy(data, cstr->data, cstr->len);
150 cstr->data = data;
151 cstr->is_alloc = true;
152 }
153 }
154}
155
156static void clg_str_append_with_len(CLogStringBuf *cstr, const char *str, const uint len)
157{
158 uint len_next = cstr->len + len;
159 clg_str_reserve(cstr, len_next);
160 char *str_dst = cstr->data + cstr->len;
161 memcpy(str_dst, str, len);
162#if 0 /* no need. */
163 str_dst[len] = '\0';
164#endif
165 cstr->len = len_next;
166}
167
168static void clg_str_append(CLogStringBuf *cstr, const char *str)
169{
170 clg_str_append_with_len(cstr, str, strlen(str));
171}
172
174static void clg_str_vappendf(CLogStringBuf *cstr, const char *format, va_list args)
175{
176 /* Use limit because windows may use '-1' for a formatting error. */
177 const uint len_max = 65535;
178 uint len_avail = cstr->len_alloc - cstr->len;
179 while (true) {
180 va_list args_cpy;
181 va_copy(args_cpy, args);
182 int retval = vsnprintf(cstr->data + cstr->len, len_avail, format, args_cpy);
183 va_end(args_cpy);
184
185 if (retval < 0) {
186 /* Some encoding error happened, not much we can do here, besides skipping/canceling this
187 * message. */
188 break;
189 }
190
191 if ((uint)retval <= len_avail) {
192 /* Copy was successful. */
193 cstr->len += (uint)retval;
194 break;
195 }
196
197 /* `vsnprintf` was not successful, due to lack of allocated space, `retval` contains expected
198 * length of the formatted string, use it to allocate required amount of memory. */
199 uint len_alloc = cstr->len + (uint)retval;
200 if (len_alloc >= len_max) {
201 /* Safe upper-limit, just in case... */
202 break;
203 }
204
206 len_avail = cstr->len_alloc - cstr->len;
207 }
208}
209
211
212/* -------------------------------------------------------------------- */
215
224#define COLOR_LEN (COLOR_RESET + 1)
225
226static const char *clg_color_table[COLOR_LEN] = {NULL};
227#ifdef _WIN32
228static DWORD clg_previous_console_mode = 0;
229#endif
230
231static void clg_color_table_init(bool use_color)
232{
233 for (int i = 0; i < COLOR_LEN; i++) {
234 clg_color_table[i] = "";
235 }
236 if (use_color) {
237 clg_color_table[COLOR_DEFAULT] = "\033[1;37m";
238 clg_color_table[COLOR_RED] = "\033[1;31m";
239 clg_color_table[COLOR_GREEN] = "\033[1;32m";
240 clg_color_table[COLOR_YELLOW] = "\033[1;33m";
241 clg_color_table[COLOR_RESET] = "\033[0m";
242 }
243}
244
245static const char *clg_severity_str[CLG_SEVERITY_LEN] = {
246 [CLG_SEVERITY_INFO] = "INFO",
247 [CLG_SEVERITY_WARN] = "WARN",
248 [CLG_SEVERITY_ERROR] = "ERROR",
249 [CLG_SEVERITY_FATAL] = "FATAL",
250};
251
252static const char *clg_severity_as_text(enum CLG_Severity severity)
253{
254 bool ok = (unsigned int)severity < CLG_SEVERITY_LEN;
255 assert(ok);
256 if (ok) {
257 return clg_severity_str[severity];
258 }
259 return "INVALID_SEVERITY";
260}
261
263{
264 assert((unsigned int)severity < CLG_SEVERITY_LEN);
265 enum eCLogColor color = COLOR_DEFAULT;
266 switch (severity) {
268 color = COLOR_DEFAULT;
269 break;
271 color = COLOR_YELLOW;
272 break;
275 color = COLOR_RED;
276 break;
277 default:
278 /* should never get here. */
279 assert(false);
280 }
281 return color;
282}
283
285
286/* -------------------------------------------------------------------- */
289
298static bool clg_ctx_filter_check(CLogContext *ctx, const char *identifier)
299{
300 const size_t identifier_len = strlen(identifier);
301 for (uint i = 0; i < 2; i++) {
302 const CLG_IDFilter *flt = ctx->filters[i];
303 while (flt != NULL) {
304 const size_t len = strlen(flt->match);
305 if (STREQ(flt->match, "*") || ((len == identifier_len) && (STREQ(identifier, flt->match)))) {
306 return (bool)i;
307 }
308 if (flt->match[0] == '*' && flt->match[len - 1] == '*') {
309 char *match = MEM_callocN(sizeof(char) * len - 1, __func__);
310 memcpy(match, flt->match + 1, len - 2);
311 const bool success = (strstr(identifier, match) != NULL);
312 MEM_freeN(match);
313 if (success) {
314 return (bool)i;
315 }
316 }
317 else if ((len >= 2) && (STREQLEN(".*", &flt->match[len - 2], 2))) {
318 if (((identifier_len == len - 2) && STREQLEN(identifier, flt->match, len - 2)) ||
319 ((identifier_len >= len - 1) && STREQLEN(identifier, flt->match, len - 1)))
320 {
321 return (bool)i;
322 }
323 }
324 flt = flt->next;
325 }
326 }
327 return false;
328}
329
334static CLG_LogType *clg_ctx_type_find_by_name(CLogContext *ctx, const char *identifier)
335{
336 for (CLG_LogType *ty = ctx->types; ty; ty = ty->next) {
337 if (STREQ(identifier, ty->identifier)) {
338 return ty;
339 }
340 }
341 return NULL;
342}
343
344static CLG_LogType *clg_ctx_type_register(CLogContext *ctx, const char *identifier)
345{
346 assert(clg_ctx_type_find_by_name(ctx, identifier) == NULL);
347 CLG_LogType *ty = MEM_callocN(sizeof(*ty), __func__);
348 ty->next = ctx->types;
349 ctx->types = ty;
350 strncpy(ty->identifier, identifier, sizeof(ty->identifier) - 1);
351 ty->ctx = ctx;
352 ty->level = ctx->default_type.level;
353
354 if (clg_ctx_filter_check(ctx, ty->identifier)) {
355 ty->flag |= CLG_FLAG_USE;
356 }
357 return ty;
358}
359
361{
362 if (ctx->callbacks.error_fn != NULL) {
363 ctx->callbacks.error_fn(ctx->output_file);
364 }
365}
366
368{
369 if (ctx->callbacks.fatal_fn != NULL) {
370 ctx->callbacks.fatal_fn(ctx->output_file);
371 }
372 fflush(ctx->output_file);
373 abort();
374}
375
377{
378 /* NOTE: we avoid writing to 'FILE', for back-trace we make an exception,
379 * if necessary we could have a version of the callback that writes to file
380 * descriptor all at once. */
382 fflush(ctx->output_file);
383}
384
386{
387 uint64_t tick;
388#if defined(_MSC_VER)
389 tick = GetTickCount64();
390#else
391 struct timeval tv;
392 gettimeofday(&tv, NULL);
393 tick = tv.tv_sec * 1000 + tv.tv_usec / 1000;
394#endif
395 return tick;
396}
397
399
400/* -------------------------------------------------------------------- */
403
404static void write_timestamp(CLogStringBuf *cstr, const uint64_t timestamp_tick_start)
405{
406 char timestamp_str[64];
407 const uint64_t timestamp = clg_timestamp_ticks_get() - timestamp_tick_start;
408 const uint timestamp_len = snprintf(timestamp_str,
409 sizeof(timestamp_str),
410 "%" PRIu64 ".%03u ",
411 timestamp / 1000,
412 (uint)(timestamp % 1000));
413 clg_str_append_with_len(cstr, timestamp_str, timestamp_len);
414}
415
416static void write_severity(CLogStringBuf *cstr, enum CLG_Severity severity, bool use_color)
417{
418 assert((unsigned int)severity < CLG_SEVERITY_LEN);
419 if (use_color) {
420 enum eCLogColor color = clg_severity_to_color(severity);
421 clg_str_append(cstr, clg_color_table[color]);
422 clg_str_append(cstr, clg_severity_as_text(severity));
424 }
425 else {
426 clg_str_append(cstr, clg_severity_as_text(severity));
427 }
428}
429
430static void write_type(CLogStringBuf *cstr, const CLG_LogType *lg)
431{
432 clg_str_append(cstr, " (");
433 clg_str_append(cstr, lg->identifier);
434 clg_str_append(cstr, "): ");
435}
436
438 const char *file_line,
439 const char *fn,
440 const bool use_basename)
441{
442 uint file_line_len = strlen(file_line);
443 if (use_basename) {
444 uint file_line_offset = file_line_len;
445 while (file_line_offset-- > 0) {
446 if (file_line[file_line_offset] == PATHSEP_CHAR) {
447 file_line_offset++;
448 break;
449 }
450 }
451 file_line += file_line_offset;
452 file_line_len -= file_line_offset;
453 }
454 clg_str_append_with_len(cstr, file_line, file_line_len);
455
456 clg_str_append(cstr, " ");
457 clg_str_append(cstr, fn);
458 clg_str_append(cstr, ": ");
459}
460
462 enum CLG_Severity severity,
463 const char *file_line,
464 const char *fn,
465 const char *message)
466{
467 CLogStringBuf cstr;
468 char cstr_stack_buf[CLOG_BUF_LEN_INIT];
469 clg_str_init(&cstr, cstr_stack_buf, sizeof(cstr_stack_buf));
470
471 if (lg->ctx->use_timestamp) {
473 }
474
475 write_severity(&cstr, severity, lg->ctx->use_color);
476 write_type(&cstr, lg);
477
478 {
479 write_file_line_fn(&cstr, file_line, fn, lg->ctx->use_basename);
480 clg_str_append(&cstr, message);
481 }
482 clg_str_append(&cstr, "\n");
483
484 /* could be optional */
485 int bytes_written = write(lg->ctx->output, cstr.data, cstr.len);
486 (void)bytes_written;
487
488 clg_str_free(&cstr);
489
490 if (lg->ctx->callbacks.backtrace_fn) {
492 }
493
494 if (severity == CLG_SEVERITY_FATAL) {
496 }
497}
498
499void CLG_logf(const CLG_LogType *lg,
500 enum CLG_Severity severity,
501 const char *file_line,
502 const char *fn,
503 const char *format,
504 ...)
505{
506 CLogStringBuf cstr;
507 char cstr_stack_buf[CLOG_BUF_LEN_INIT];
508 clg_str_init(&cstr, cstr_stack_buf, sizeof(cstr_stack_buf));
509
510 if (lg->ctx->use_timestamp) {
512 }
513
514 write_severity(&cstr, severity, lg->ctx->use_color);
515 write_type(&cstr, lg);
516
517 {
518 write_file_line_fn(&cstr, file_line, fn, lg->ctx->use_basename);
519
520 va_list ap;
521 va_start(ap, format);
522 clg_str_vappendf(&cstr, format, ap);
523 va_end(ap);
524 }
525 clg_str_append(&cstr, "\n");
526
527 /* could be optional */
528 int bytes_written = write(lg->ctx->output, cstr.data, cstr.len);
529 (void)bytes_written;
530
531 clg_str_free(&cstr);
532
533 if (lg->ctx->callbacks.backtrace_fn) {
535 }
536
537 if (severity == CLG_SEVERITY_ERROR) {
539 }
540
541 if (severity == CLG_SEVERITY_FATAL) {
543 }
544}
545
547
548/* -------------------------------------------------------------------- */
551
552static void CLG_ctx_output_set(CLogContext *ctx, void *file_handle)
553{
554 ctx->output_file = file_handle;
555 ctx->output = fileno(ctx->output_file);
556#if defined(__unix__) || defined(__APPLE__)
557 ctx->use_color = isatty(ctx->output);
558#elif defined(WIN32)
559 /* As of Windows 10 build 18298 all the standard consoles supports color
560 * like the Linux Terminal do, but it needs to be turned on.
561 * To turn on colors we need to enable virtual terminal processing by passing the flag
562 * ENABLE_VIRTUAL_TERMINAL_PROCESSING into SetConsoleMode.
563 * If the system doesn't support virtual terminal processing it will fail silently and the flag
564 * will not be set. */
565
566 GetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), &clg_previous_console_mode);
567
568 ctx->use_color = 0;
569 if (IsWindows10OrGreater() && isatty(ctx->output)) {
570 DWORD mode = clg_previous_console_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING;
571 if (SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), mode)) {
572 ctx->use_color = 1;
573 }
574 }
575#endif
576}
577
579{
580 ctx->use_basename = (bool)value;
581}
582
584{
585 ctx->use_timestamp = (bool)value;
586 if (ctx->use_timestamp) {
588 }
589}
590
592static void CLT_ctx_error_fn_set(CLogContext *ctx, void (*error_fn)(void *file_handle))
593{
594 ctx->callbacks.error_fn = error_fn;
595}
596
598static void CLG_ctx_fatal_fn_set(CLogContext *ctx, void (*fatal_fn)(void *file_handle))
599{
600 ctx->callbacks.fatal_fn = fatal_fn;
601}
602
603static void CLG_ctx_backtrace_fn_set(CLogContext *ctx, void (*backtrace_fn)(void *file_handle))
604{
605 ctx->callbacks.backtrace_fn = backtrace_fn;
606}
607
609 const char *type_match,
610 int type_match_len)
611{
612 if (type_match_len == 0) {
613 return;
614 }
615 CLG_IDFilter *flt = MEM_callocN(sizeof(*flt) + (type_match_len + 1), __func__);
616 flt->next = *flt_list;
617 *flt_list = flt;
618 memcpy(flt->match, type_match, type_match_len);
619 /* no need to null terminate since we calloc'd */
620}
621
623 const char *type_match,
624 int type_match_len)
625{
626 clg_ctx_type_filter_append(&ctx->filters[0], type_match, type_match_len);
627}
628
630 const char *type_match,
631 int type_match_len)
632{
633 clg_ctx_type_filter_append(&ctx->filters[1], type_match, type_match_len);
634}
635
636static void CLG_ctx_level_set(CLogContext *ctx, int level)
637{
638 ctx->default_type.level = level;
639 for (CLG_LogType *ty = ctx->types; ty; ty = ty->next) {
640 ty->level = level;
641 }
642}
643
645{
646 CLogContext *ctx = MEM_callocN(sizeof(*ctx), __func__);
647#ifdef WITH_CLOG_PTHREADS
648 pthread_mutex_init(&ctx->types_lock, NULL);
649#endif
650 ctx->default_type.level = 1;
651 CLG_ctx_output_set(ctx, stdout);
652
653 return ctx;
654}
655
656static void CLG_ctx_free(CLogContext *ctx)
657{
658#if defined(WIN32)
659 SetConsoleMode(GetStdHandle(STD_OUTPUT_HANDLE), clg_previous_console_mode);
660#endif
661 while (ctx->types != NULL) {
662 CLG_LogType *item = ctx->types;
663 ctx->types = item->next;
664 MEM_freeN(item);
665 }
666
667 while (ctx->refs != NULL) {
668 CLG_LogRef *item = ctx->refs;
669 ctx->refs = item->next;
670 item->type = NULL;
671 }
672
673 for (uint i = 0; i < 2; i++) {
674 while (ctx->filters[i] != NULL) {
675 CLG_IDFilter *item = ctx->filters[i];
676 ctx->filters[i] = item->next;
677 MEM_freeN(item);
678 }
679 }
680#ifdef WITH_CLOG_PTHREADS
681 pthread_mutex_destroy(&ctx->types_lock);
682#endif
683 MEM_freeN(ctx);
684}
685
687
688/* -------------------------------------------------------------------- */
693
694/* We could support multiple at once, for now this seems not needed. */
695static struct CLogContext *g_ctx = NULL;
696
697void CLG_init(void)
698{
700
701 clg_color_table_init(g_ctx->use_color);
702}
703
704void CLG_exit(void)
705{
707}
708
709void CLG_output_set(void *file_handle)
710{
711 CLG_ctx_output_set(g_ctx, file_handle);
712}
713
718
723
724void CLG_error_fn_set(void (*error_fn)(void *file_handle))
725{
727}
728
729void CLG_fatal_fn_set(void (*fatal_fn)(void *file_handle))
730{
732}
733
734void CLG_backtrace_fn_set(void (*fatal_fn)(void *file_handle))
735{
737}
738
739void CLG_type_filter_exclude(const char *type_match, int type_match_len)
740{
741 CLG_ctx_type_filter_exclude(g_ctx, type_match, type_match_len);
742}
743
744void CLG_type_filter_include(const char *type_match, int type_match_len)
745{
746 CLG_ctx_type_filter_include(g_ctx, type_match, type_match_len);
747}
748
753
755
756/* -------------------------------------------------------------------- */
761
763{
764#ifdef WITH_CLOG_PTHREADS
765 /* Only runs once when initializing a static type in most cases. */
766 pthread_mutex_lock(&g_ctx->types_lock);
767#endif
768 if (clg_ref->type == NULL) {
769 /* Add to the refs list so we can NULL the pointers to 'type' when CLG_exit() is called. */
770 clg_ref->next = g_ctx->refs;
771 g_ctx->refs = clg_ref;
772
774 if (clg_ty == NULL) {
775 clg_ty = clg_ctx_type_register(g_ctx, clg_ref->identifier);
776 }
777#ifdef WITH_CLOG_PTHREADS
778 atomic_cas_ptr((void **)&clg_ref->type, clg_ref->type, clg_ty);
779#else
780 clg_ref->type = clg_ty;
781#endif
782 }
783#ifdef WITH_CLOG_PTHREADS
784 pthread_mutex_unlock(&g_ctx->types_lock);
785#endif
786}
787
789{
790 if (clg_ref->type == NULL) {
791 CLG_logref_init(clg_ref);
792 }
793 return clg_ref->type->ctx->use_color;
794}
795
#define ATTR_PRINTF_FORMAT(format_param, dots_param)
unsigned int uint
#define STREQLEN(a, b, n)
#define STREQ(a, b)
CLG_Severity
Definition CLG_log.h:87
@ CLG_SEVERITY_INFO
Definition CLG_log.h:88
@ CLG_SEVERITY_WARN
Definition CLG_log.h:89
@ CLG_SEVERITY_FATAL
Definition CLG_log.h:91
@ CLG_SEVERITY_ERROR
Definition CLG_log.h:90
@ CLG_FLAG_USE
Definition CLG_log.h:84
#define CLG_SEVERITY_LEN
Definition CLG_log.h:93
Read Guarded memory(de)allocation.
Provides wrapper around system-specific atomic primitives, and some extensions (faked-atomic operatio...
ATOMIC_INLINE void * atomic_cas_ptr(void **v, void *old, void *_new)
BMesh const char void * data
unsigned long long int uint64_t
static void CLG_ctx_output_set(CLogContext *ctx, void *file_handle)
Definition clog.c:552
static void write_type(CLogStringBuf *cstr, const CLG_LogType *lg)
Definition clog.c:430
void CLG_logf(const CLG_LogType *lg, enum CLG_Severity severity, const char *file_line, const char *fn, const char *format,...)
Definition clog.c:499
void CLG_type_filter_exclude(const char *type_match, int type_match_len)
Definition clog.c:739
static void clg_str_vappendf(CLogStringBuf *cstr, const char *format, va_list args)
Definition clog.c:174
static void clg_ctx_fatal_action(CLogContext *ctx)
Definition clog.c:367
void CLG_output_set(void *file_handle)
Definition clog.c:709
static void CLG_ctx_free(CLogContext *ctx)
Definition clog.c:656
void CLG_output_use_basename_set(int value)
Definition clog.c:714
void CLG_exit(void)
Definition clog.c:704
void CLG_log_str(const CLG_LogType *lg, enum CLG_Severity severity, const char *file_line, const char *fn, const char *message)
Definition clog.c:461
void CLG_error_fn_set(void(*error_fn)(void *file_handle))
Definition clog.c:724
static void clg_ctx_error_action(CLogContext *ctx)
Definition clog.c:360
static CLG_LogType * clg_ctx_type_find_by_name(CLogContext *ctx, const char *identifier)
Definition clog.c:334
void CLG_backtrace_fn_set(void(*fatal_fn)(void *file_handle))
Definition clog.c:734
static void CLG_ctx_output_use_timestamp_set(CLogContext *ctx, int value)
Definition clog.c:583
static uint64_t clg_timestamp_ticks_get(void)
Definition clog.c:385
static void clg_str_append_with_len(CLogStringBuf *cstr, const char *str, const uint len)
Definition clog.c:156
static void write_timestamp(CLogStringBuf *cstr, const uint64_t timestamp_tick_start)
Definition clog.c:404
#define CLOG_BUF_LEN_INIT
Definition clog.c:111
#define STREQLEN(a, b, n)
Definition clog.c:51
void CLG_fatal_fn_set(void(*fatal_fn)(void *file_handle))
Definition clog.c:729
static void clg_str_append(CLogStringBuf *cstr, const char *str)
Definition clog.c:168
static const char * clg_color_table[COLOR_LEN]
Definition clog.c:226
static void CLG_ctx_fatal_fn_set(CLogContext *ctx, void(*fatal_fn)(void *file_handle))
Definition clog.c:598
void CLG_type_filter_include(const char *type_match, int type_match_len)
Definition clog.c:744
void CLG_logref_init(CLG_LogRef *clg_ref)
Definition clog.c:762
static void clg_ctx_type_filter_append(CLG_IDFilter **flt_list, const char *type_match, int type_match_len)
Definition clog.c:608
void CLG_level_set(int level)
Definition clog.c:749
static struct CLogContext * g_ctx
Definition clog.c:695
static CLogContext * CLG_ctx_init(void)
Definition clog.c:644
static void clg_str_free(CLogStringBuf *cstr)
Definition clog.c:128
void CLG_output_use_timestamp_set(int value)
Definition clog.c:719
static void CLG_ctx_output_use_basename_set(CLogContext *ctx, int value)
Definition clog.c:578
static CLG_LogType * clg_ctx_type_register(CLogContext *ctx, const char *identifier)
Definition clog.c:344
void CLG_init(void)
Definition clog.c:697
static void clg_str_init(CLogStringBuf *cstr, char *buf_stack, uint buf_stack_len)
Definition clog.c:120
static void clg_ctx_backtrace(CLogContext *ctx)
Definition clog.c:376
static void CLG_ctx_backtrace_fn_set(CLogContext *ctx, void(*backtrace_fn)(void *file_handle))
Definition clog.c:603
#define COLOR_LEN
Definition clog.c:224
static const char * clg_severity_str[CLG_SEVERITY_LEN]
Definition clog.c:245
static void clg_str_reserve(CLogStringBuf *cstr, const uint len)
Definition clog.c:135
static void CLG_ctx_type_filter_exclude(CLogContext *ctx, const char *type_match, int type_match_len)
Definition clog.c:622
static const char * clg_severity_as_text(enum CLG_Severity severity)
Definition clog.c:252
eCLogColor
Definition clog.c:216
@ COLOR_DEFAULT
Definition clog.c:217
@ COLOR_RED
Definition clog.c:218
@ COLOR_YELLOW
Definition clog.c:220
@ COLOR_GREEN
Definition clog.c:219
@ COLOR_RESET
Definition clog.c:222
static void clg_color_table_init(bool use_color)
Definition clog.c:231
static void CLG_ctx_level_set(CLogContext *ctx, int level)
Definition clog.c:636
int CLG_color_support_get(CLG_LogRef *clg_ref)
Definition clog.c:788
static bool clg_ctx_filter_check(CLogContext *ctx, const char *identifier)
Definition clog.c:298
#define STREQ(a, b)
Definition clog.c:50
static void CLG_ctx_type_filter_include(CLogContext *ctx, const char *type_match, int type_match_len)
Definition clog.c:629
static enum eCLogColor clg_severity_to_color(enum CLG_Severity severity)
Definition clog.c:262
static void write_severity(CLogStringBuf *cstr, enum CLG_Severity severity, bool use_color)
Definition clog.c:416
static void CLT_ctx_error_fn_set(CLogContext *ctx, void(*error_fn)(void *file_handle))
Definition clog.c:592
static void write_file_line_fn(CLogStringBuf *cstr, const char *file_line, const char *fn, const bool use_basename)
Definition clog.c:437
#define str(s)
#define assert(assertion)
#define MEM_reallocN(vmemh, len)
#define PRIu64
Definition inttypes.h:132
format
#define PATHSEP_CHAR
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
char match[0]
Definition clog.c:66
struct CLG_IDFilter * next
Definition clog.c:64
const char * identifier
Definition CLG_log.h:107
struct CLG_LogRef * next
Definition CLG_log.h:109
CLG_LogType * type
Definition CLG_log.h:108
char identifier[64]
Definition CLG_log.h:98
struct CLG_LogType * next
Definition CLG_log.h:97
enum CLG_LogFlag flag
Definition CLG_log.h:103
struct CLogContext * ctx
Definition CLG_log.h:100
bool use_basename
Definition clog.c:81
void(* fatal_fn)(void *file_handle)
Definition clog.c:98
void(* error_fn)(void *file_handle)
Definition clog.c:97
CLG_LogRef * refs
Definition clog.c:73
bool use_timestamp
Definition clog.c:82
uint64_t timestamp_tick_start
Definition clog.c:89
FILE * output_file
Definition clog.c:86
int level
Definition clog.c:93
int output
Definition clog.c:85
void(* backtrace_fn)(void *file_handle)
Definition clog.c:99
struct CLogContext::@335164264314070226242132364016264076031306275256 default_type
bool use_color
Definition clog.c:80
CLG_IDFilter * filters[2]
Definition clog.c:79
CLG_LogType * types
Definition clog.c:71
struct CLogContext::@011126022155065025051001013240315061334270116173 callbacks
bool is_alloc
Definition clog.c:117
char * data
Definition clog.c:114
uint len_alloc
Definition clog.c:116
uint len
Definition clog.c:115
i
Definition text_draw.cc:230
uint len_alloc
uint len