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