Concord - C Discord API library
A Discord API wrapper library written in C
logmod.h
Go to the documentation of this file.
1#ifndef LOGMOD_H
2#define LOGMOD_H
3
4#ifdef __cplusplus
5extern "C" {
6#endif /* __cplusplus */
7
13#ifdef LOGMOD_STATIC
14#define LOGMOD_API static
15#else
16#define LOGMOD_API extern
17#endif /* LOGMOD_STATIC */
18
19#include <stdio.h>
20#include <stdarg.h>
21#include <time.h>
22
32#if defined(__MINGW32__) \
33 || (defined(__GNUC__) && __GNUC__ > 4 ? true : __GNUC_PATCHLEVEL__ >= 4) \
34 || defined(__USE_MINGW_ANSI_STDIO)
35#define LOGMOD_PRINTF_LIKE(a, b) __attribute__((format(gnu_printf, a, b)))
36#else
37#define LOGMOD_PRINTF_LIKE(a, b)
38#endif
39
45#ifndef LOGMOD_FALLBACK_APPLICATION_ID
46#define LOGMOD_FALLBACK_APPLICATION_ID "APPLICATION"
47#endif /* LOGMOD_FALLBACK_APPLICATION_ID */
48
54#ifndef LOGMOD_FALLBACK_CONTEXT_ID
55#define LOGMOD_FALLBACK_CONTEXT_ID "GLOBAL"
56#endif /* LOGMOD_FALLBACK_CONTEXT_ID */
57
74};
75
79typedef enum {
87
92 FILE *logfile;
93 int quiet;
94 int color;
97 unsigned level;
100};
101
108 const char *const name;
109 const char *const style;
110 const char *const visibility;
111 const char *const color;
112 const int output;
113};
114
122#define LOGMOD_LABEL_COLOR(_style, _visibility, _color) \
123 LOGMOD_STYLE_##_style, LOGMOD_VISIBILITY_##_visibility, \
124 LOGMOD_COLOR_##_color
125
130 const unsigned line;
131 const char *const filename;
132 const unsigned level;
133 const struct logmod_label *const label;
134 const struct tm time;
135};
136
137/* forward declaration */
138struct logmod_logger;
139struct tm;
140
141
148typedef void (*logmod_lock)(const struct logmod_logger *logger,
149 int should_lock);
150
161typedef logmod_err (*logmod_callback)(const struct logmod_logger *logger,
162 const struct logmod_info *info,
163 const char *fmt,
164 va_list args);
165
169#define LOGMOD_STYLE_REGULAR "0"
170#define LOGMOD_STYLE_BOLD "1"
171#define LOGMOD_STYLE_UNDERLINE "4"
172#define LOGMOD_STYLE_STRIKETHROUGH "9"
177#define LOGMOD_VISIBILITY_FOREGROUND "3"
178#define LOGMOD_VISIBILITY_BACKGROUND "4"
179#define LOGMOD_VISIBILITY_INTENSITY "9"
180#define LOGMOD_VISIBILITY_BACKGROUND_INTENSITY \
181 "10"
186#define LOGMOD_COLOR_BLACK "0"
187#define LOGMOD_COLOR_RED "1"
188#define LOGMOD_COLOR_GREEN "2"
189#define LOGMOD_COLOR_YELLOW "3"
190#define LOGMOD_COLOR_BLUE "4"
191#define LOGMOD_COLOR_MAGENTA "5"
192#define LOGMOD_COLOR_CYAN "6"
193#define LOGMOD_COLOR_WHITE "7"
203#define __LOGMOD_LOGGER_ATTRS(_qualifier) \
204 const char *context_id; \
205 _qualifier struct logmod_options options; \
206 const long *counter; \
207 _qualifier logmod_callback callback; \
208 void *user_data; \
209 const struct logmod_label *_qualifier custom_labels; \
210 _qualifier size_t num_custom_labels; \
211 _qualifier int disabled
212
213#define __BLANK
221};
222#undef __BLANK
223
231};
232
233#undef __LOGMOD_LOGGER_ATTRS
234
240struct logmod {
241 const char *application_id;
242 const struct logmod_logger *loggers;
243 const size_t length;
244 const size_t real_length;
245 long counter;
246 const struct logmod_options
249};
250
261 const char *const application_id,
262 struct logmod_logger table[],
263 unsigned length);
264
272
281
290 struct logmod_options options);
291
300 const char *const context_id);
301
310 void *user_data);
311
323 const struct logmod_label *const custom_labels,
324 const size_t num_custom_labels,
325 logmod_callback callback);
326
335 struct logmod_options options);
336
346 struct logmod_logger *logger, int show_app_id, int show_context_id);
347
356 int quiet);
357
366 int color);
367
376 unsigned level);
377
386 FILE *logfile);
387
396 int show_time);
397
406 int show_counter);
407
416 struct logmod *logmod, const char *const context_id);
417
426 const struct logmod_logger *logger, const unsigned level);
427
435LOGMOD_API long logmod_logger_get_level(const struct logmod_logger *logger,
436 const char *const label);
437
444LOGMOD_API long logmod_logger_get_counter(const struct logmod_logger *logger);
445
454#define logmod_nlog(_level, _logger, _parenthesized_params, num_params) \
455 _logmod_log(_logger, __LINE__, __FILE__, LOGMOD_LEVEL_##_level, \
456 LOGMOD_SPREAD_TUPLE_##num_params _parenthesized_params)
457
458#if __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
469#define _logmod_log_permissive(_level, _logger, _line, _file, _fmt, ...) \
470 _logmod_log(_logger, _line, _file, _level, _fmt "%s", __VA_ARGS__)
471
480#define logmod_log(_level, _logger, ...) \
481 _logmod_log_permissive(LOGMOD_LEVEL_##_level, _logger, __LINE__, \
482 __FILE__, __VA_ARGS__, "")
483#else
487#define logmod_log logmod_nlog
488#endif /* __STDC_VERSION__ */
489
502 const unsigned line,
503 const char *const filename,
504 const unsigned level,
505 const char *fmt,
506 ...) LOGMOD_PRINTF_LIKE(5, 6);
507
516#define LOGMOD_ENCODE(_style, _visibility, _color, buf) \
517 "\x1b[" _style ";" _visibility _color "m" buf "\x1b[0m"
518
527#define LOGMOD_ENCODE_STATIC(_style, _visibility, _color, buf) \
528 LOGMOD_ENCODE(LOGMOD_STYLE_##_style, LOGMOD_VISIBILITY_##_visibility, \
529 LOGMOD_COLOR_##_color, buf)
530
541#define LOGMOD_ENCODE_TOGGLE(_toggle, _style, _visibility, _color, buf) \
542 ((_toggle) ? LOGMOD_ENCODE_STATIC(_style, _visibility, _color, buf) : buf)
543
555#define LOGMOD_ENCODE_LOGGER(_logger, _style, _visibility, _color, buf) \
556 LOGMOD_ENCODE_TOGGLE((_logger)->options.color, _style, _visibility, \
557 _color, buf)
558
560#define LMS LOGMOD_ENCODE_STATIC
562#define LMT LOGMOD_ENCODE_TOGGLE
564#define LML LOGMOD_ENCODE_LOGGER
566#define LME LOGMOD_ENCODE
567
568#define LOGMOD_SPREAD_TUPLE_0(_fmt) _fmt
569#define LOGMOD_SPREAD_TUPLE_1(_fmt, _1) _fmt, _1
570#define LOGMOD_SPREAD_TUPLE_2(_fmt, _1, _2) _fmt, _1, _2
571#define LOGMOD_SPREAD_TUPLE_3(_fmt, _1, _2, _3) _fmt, _1, _2, _3
572#define LOGMOD_SPREAD_TUPLE_4(_fmt, _1, _2, _3, _4) _fmt, _2, _3, _4
573#define LOGMOD_SPREAD_TUPLE_5(_fmt, _1, _2, _3, _4, _5) \
574 _fmt, _1, _2, _3, _4, _5
575#define LOGMOD_SPREAD_TUPLE_6(_fmt, _1, _2, _3, _4, _5, _6) \
576 _fmt, _1, _2, _3, _4, _6
577#define LOGMOD_SPREAD_TUPLE_7(_fmt, _1, _2, _3, _4, _5, _6, _7) \
578 _fmt, _1, _2, _3, _4, _5, _6, _7
579#define LOGMOD_SPREAD_TUPLE_8(_fmt, _1, _2, _3, _4, _5, _6, _7, _8) \
580 _fmt, _1, _2, _3, _4, _5, _6, _7, _8
581#define LOGMOD_SPREAD_TUPLE_9(_fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9) \
582 _fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9
583#define LOGMOD_SPREAD_TUPLE_10(_fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \
584 _fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10
585#define LOGMOD_SPREAD_TUPLE_11(_fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
586 _11) \
587 _fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11
588#define LOGMOD_SPREAD_TUPLE_12(_fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
589 _11, _12) \
590 _fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12
591#define LOGMOD_SPREAD_TUPLE_13(_fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
592 _11, _12, _13) \
593 _fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13
594#define LOGMOD_SPREAD_TUPLE_14(_fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
595 _11, _12, _13, _14) \
596 _fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14
597#define LOGMOD_SPREAD_TUPLE_15(_fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
598 _11, _12, _13, _14, _15) \
599 _fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15
600#define LOGMOD_SPREAD_TUPLE_16(_fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, \
601 _11, _12, _13, _14, _15, _16) \
602 _fmt, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16
603
604#ifndef LOGMOD_HEADER
605
606#include <stdio.h>
607#include <stdlib.h>
608#include <stdarg.h>
609#include <stddef.h>
610#include <string.h>
611#include <time.h>
612
613#include "logmod.h"
614
615static const struct logmod_label default_labels[__LOGMOD_LEVEL_MAX] = {
616 /*[LOGMOD_LEVEL_TRACE]:*/
617 { "TRACE", LOGMOD_LABEL_COLOR(REGULAR, BACKGROUND_INTENSITY, BLUE), 0 },
618 /*[LOGMOD_LEVEL_DEBUG]:*/
619 { "DEBUG", LOGMOD_LABEL_COLOR(REGULAR, BACKGROUND, CYAN), 0 },
620 /*[LOGMOD_LEVEL_INFO]: */
621 { "INFO", LOGMOD_LABEL_COLOR(REGULAR, BACKGROUND, GREEN), 0 },
622 /*[LOGMOD_LEVEL_WARN]: */
623 { "WARN", LOGMOD_LABEL_COLOR(REGULAR, BACKGROUND, YELLOW), 1 },
624 /*[LOGMOD_LEVEL_ERROR]:*/
625 { "ERROR", LOGMOD_LABEL_COLOR(REGULAR, BACKGROUND, RED), 1 },
626 /*[LOGMOD_LEVEL_FATAL]:*/
627 { "FATAL", LOGMOD_LABEL_COLOR(REGULAR, BACKGROUND, MAGENTA), 1 },
628};
629
631#define LOGMOD_FROM_LOGGER(_ctx) \
632 ((struct logmod *)((char *)(_ctx)->counter \
633 - offsetof(struct logmod, counter)))
634
635#define _LOGMOD_EXPECT(_cond, _error, _return) \
636 do { \
637 if (!(_cond)) { \
638 switch ((_error)) { \
639 case LOGMOD_BAD_PARAMETER: \
640 logmod_nlog(ERROR, NULL, ("Bad parameter: %s", #_cond), 1); \
641 break; \
642 case LOGMOD_ERRNO: \
643 logmod_nlog(ERROR, NULL, \
644 ("System error (check errno): %s", #_cond), 1); \
645 break; \
646 default: \
647 logmod_nlog(ERROR, NULL, ("Unknown error: %s", #_cond), 1); \
648 break; \
649 } \
650 return (_return); \
651 } \
652 } while (0)
653
660#define LOGMOD_EXPECT(_cond, _error) _LOGMOD_EXPECT(_cond, _error, _error)
661
662static void
663_logmod_lock_noop(const struct logmod_logger *_, int __)
664{
665 (void)_;
666 (void)__;
667}
668
671 const char *const application_id,
672 struct logmod_logger table[],
673 unsigned length)
674{
675 size_t *mut_real_length = (size_t *)&logmod->real_length;
677 LOGMOD_EXPECT(application_id && *application_id, LOGMOD_BAD_PARAMETER);
678 LOGMOD_EXPECT(table != NULL, LOGMOD_BAD_PARAMETER);
680 memset(logmod, 0, sizeof *logmod);
681 memset(table, 0, length * sizeof *table);
682 logmod->application_id = application_id;
683 logmod->loggers = table;
684 *mut_real_length = length;
685 logmod->lock = _logmod_lock_noop;
686 return LOGMOD_OK;
687}
688
691{
693 if (logmod->loggers)
694 memset((void *)logmod->loggers, 0,
695 logmod->real_length * sizeof *logmod->loggers);
696 memset(logmod, 0, sizeof *logmod);
697 return LOGMOD_OK;
698}
699
702{
704 logmod->lock = lock;
705 return LOGMOD_OK;
706}
707
710{
711 struct logmod_options *mut_default_options =
714 *mut_default_options = options;
715 return LOGMOD_OK;
716}
717
719logmod_toggle_logger(struct logmod *logmod, const char *const context_id)
720{
721 struct logmod_mut_logger *mut_logger =
723 LOGMOD_EXPECT(mut_logger != NULL, LOGMOD_BAD_PARAMETER);
724 mut_logger->disabled = !mut_logger->disabled;
725 return LOGMOD_OK;
726}
727
730 int show_app_id,
731 int show_context_id)
732{
733 struct logmod_mut_logger *mut_logger = (struct logmod_mut_logger *)logger;
734 LOGMOD_EXPECT(logger != NULL, LOGMOD_BAD_PARAMETER);
735 mut_logger->options.show_application_id = show_app_id;
736 mut_logger->options.hide_context_id = !show_context_id;
737 return LOGMOD_OK;
738}
739
742{
743 struct logmod_mut_logger *mut_logger = (struct logmod_mut_logger *)logger;
744 LOGMOD_EXPECT(logger != NULL, LOGMOD_BAD_PARAMETER);
745 mut_logger->user_data = user_data;
746 return LOGMOD_OK;
747}
748
751 const struct logmod_label *const custom_labels,
752 const size_t num_custom_labels,
754{
755 struct logmod_mut_logger *mut_logger = (struct logmod_mut_logger *)logger;
756 LOGMOD_EXPECT(logger != NULL, LOGMOD_BAD_PARAMETER);
757 mut_logger->callback = callback;
758 if (custom_labels != NULL) {
760 mut_logger->custom_labels = custom_labels;
762 }
763 return LOGMOD_OK;
764}
765
768 struct logmod_options options)
769{
770 struct logmod_mut_logger *mut_logger = (struct logmod_mut_logger *)logger;
771 LOGMOD_EXPECT(logger != NULL, LOGMOD_BAD_PARAMETER);
772 mut_logger->options = options;
773 return LOGMOD_OK;
774}
775
777logmod_logger_set_quiet(struct logmod_logger *logger, int quiet)
778{
779 struct logmod_mut_logger *mut_logger = (struct logmod_mut_logger *)logger;
780 LOGMOD_EXPECT(logger != NULL, LOGMOD_BAD_PARAMETER);
781 mut_logger->options.quiet = quiet;
782 return LOGMOD_OK;
783}
784
786logmod_logger_set_color(struct logmod_logger *logger, int color)
787{
788 struct logmod_mut_logger *mut_logger = (struct logmod_mut_logger *)logger;
789 LOGMOD_EXPECT(logger != NULL, LOGMOD_BAD_PARAMETER);
790 mut_logger->options.color = color;
791 return LOGMOD_OK;
792}
793
795logmod_logger_set_level(struct logmod_logger *logger, unsigned level)
796{
797 struct logmod_mut_logger *mut_logger = (struct logmod_mut_logger *)logger;
798 LOGMOD_EXPECT(logger != NULL, LOGMOD_BAD_PARAMETER);
799 mut_logger->options.level = level;
800 return LOGMOD_OK;
801}
802
804logmod_logger_set_logfile(struct logmod_logger *logger, FILE *logfile)
805{
806 struct logmod_mut_logger *mut_logger = (struct logmod_mut_logger *)logger;
807 LOGMOD_EXPECT(logger != NULL, LOGMOD_BAD_PARAMETER);
808 mut_logger->options.logfile = logfile;
809 return LOGMOD_OK;
810}
811
813logmod_logger_set_time(struct logmod_logger *logger, int show_time)
814{
815 struct logmod_mut_logger *mut_logger = (struct logmod_mut_logger *)logger;
816 LOGMOD_EXPECT(logger != NULL, LOGMOD_BAD_PARAMETER);
817 mut_logger->options.suppress_time = !show_time;
818 return LOGMOD_OK;
819}
820
822logmod_logger_set_counter(struct logmod_logger *logger, int show_counter)
823{
824 struct logmod_mut_logger *mut_logger = (struct logmod_mut_logger *)logger;
825 LOGMOD_EXPECT(logger != NULL, LOGMOD_BAD_PARAMETER);
826 mut_logger->options.hide_counter = !show_counter;
827 return LOGMOD_OK;
828}
829
830LOGMOD_API const struct logmod_label *
832 const unsigned level)
833{
834 static const struct logmod_label unknown_label = {
835 "#UNKNOWN LABEL!!",
836 LOGMOD_LABEL_COLOR(STRIKETHROUGH, BACKGROUND_INTENSITY, YELLOW), 1
837 };
838 if (level < LOGMOD_LEVEL_CUSTOM) {
839 return &default_labels[level];
840 }
841 if (logger && level >= LOGMOD_LEVEL_CUSTOM
842 && level < (LOGMOD_LEVEL_CUSTOM + logger->num_custom_labels))
843 {
844 return &logger->custom_labels[level - LOGMOD_LEVEL_CUSTOM];
845 }
846 logmod_nlog(ERROR, NULL,
847 ("Invalid log level %u for logger %s", level,
848 logger ? logger->context_id : "NULL"),
849 2);
850 return &unknown_label;
851}
852
853LOGMOD_API long
855 const char *const label)
856{
857 size_t i;
858 LOGMOD_EXPECT(logger != NULL, LOGMOD_BAD_PARAMETER);
859 LOGMOD_EXPECT(label != NULL, LOGMOD_BAD_PARAMETER);
860 for (i = 0; i < __LOGMOD_LEVEL_MAX; ++i) {
861 if (strcmp(label, default_labels[i].name) == 0) {
862 return (long)i;
863 }
864 }
865 for (i = 0; i < logger->num_custom_labels; ++i) {
866 if (strcmp(label, logger->custom_labels[i].name) == 0) {
867 return (long)(i + LOGMOD_LEVEL_CUSTOM);
868 }
869 }
871}
872
873LOGMOD_API long
875{
876 struct logmod *logmod = LOGMOD_FROM_LOGGER(logger);
877 long counter;
879 logmod->lock(logger, 1);
881 logmod->lock(logger, 0);
882 return counter;
883}
884
886logmod_get_logger(struct logmod *logmod, const char *const context_id)
887{
888 size_t i;
892 logmod->lock(NULL, 1);
893 for (i = 0; i < logmod->length; ++i) {
894 if (0 == strcmp(logmod->loggers[i].context_id, context_id)) {
895 struct logmod_logger *logger =
896 (struct logmod_logger *)&logmod->loggers[i];
897 logmod->lock(logger, 0);
898 return logger;
899 }
900 }
902 size_t *mut_length = (size_t *)&logmod->length;
903 struct logmod_mut_logger *mut_logger =
905 memset(mut_logger, 0, sizeof *mut_logger);
906 mut_logger->context_id = context_id;
907 mut_logger->counter = &logmod->counter;
908 mut_logger->options = logmod->default_options;
909 ++*mut_length;
910 logmod->lock((struct logmod_logger *)mut_logger, 0);
911 return (struct logmod_logger *)mut_logger;
912 }
913 logmod->lock(NULL, 0);
914 return NULL;
915}
916
917static logmod_err
918_logmod_print(const struct logmod_logger *logger,
919 const struct logmod_info *info,
920 const char *fmt,
921 va_list args,
922 const int color,
923 FILE *output)
924{
925 if (!logger->options.hide_counter) {
926 LOGMOD_EXPECT(fprintf(output,
927 LMT(color, BOLD, FOREGROUND, WHITE, "%-3ld "),
929 >= 0,
931 }
932 if (!logger->options.suppress_time) {
934 fprintf(output,
935 LMT(color, UNDERLINE, FOREGROUND, WHITE, "%02d:%02d:%02d"),
936 info->time.tm_hour, info->time.tm_min, info->time.tm_sec)
937 >= 0,
939 LOGMOD_EXPECT(putc(' ', output) != EOF, LOGMOD_ERRNO);
940 }
941 if (logger->options.show_application_id) {
942 const struct logmod *logmod = LOGMOD_FROM_LOGGER(logger);
943 LOGMOD_EXPECT(fprintf(output,
944 LMT(color, BOLD, FOREGROUND, BLACK, "%s"),
946 >= 0,
948 LOGMOD_EXPECT(fputs(LMT(color, BOLD, FOREGROUND, BLACK, " » "), output)
949 != EOF,
951 }
952 if (!logger->options.hide_context_id) {
953 LOGMOD_EXPECT(fprintf(output,
954 LMT(color, BOLD, FOREGROUND, WHITE, "%s"),
955 logger->context_id)
956 >= 0,
958 LOGMOD_EXPECT(fputs(LMT(color, BOLD, FOREGROUND, WHITE, " » "), output)
959 != EOF,
961 }
962 if (color) {
963 LOGMOD_EXPECT(fprintf(output,
964 LME("%s", "%s", "%s", "%s") " " LMS(
965 REGULAR, FOREGROUND, YELLOW,
966 "%s") LMS(BOLD, FOREGROUND, WHITE, ":")
967 LMS(REGULAR, FOREGROUND, WHITE, "%d") ": ",
968 info->label->style, info->label->visibility,
969 info->label->color, info->label->name,
970 info->filename, info->line)
971 >= 0,
973 }
974 else {
975 LOGMOD_EXPECT(fprintf(output, "%s %s:%d: ", info->label->name,
976 info->filename, info->line)
977 >= 0,
979 }
980 LOGMOD_EXPECT(vfprintf(output, fmt, args) >= 0, LOGMOD_ERRNO);
981 LOGMOD_EXPECT(putc('\n', output) != EOF, LOGMOD_ERRNO);
982 LOGMOD_EXPECT(fflush(output) != EOF, LOGMOD_ERRNO);
983 return LOGMOD_OK;
984}
985
986static struct logmod g_logmod;
987
989static struct logmod_logger g_loggers[] = {
990 {
992 { NULL, 0, 1 },
993 &g_logmod.counter,
994 NULL,
995 NULL,
996 default_labels,
997 0,
998 },
999};
1001static struct logmod g_logmod = {
1003 g_loggers,
1004 sizeof(g_loggers) / sizeof *g_loggers,
1005 sizeof(g_loggers) / sizeof *g_loggers,
1006 0,
1007 { NULL, 0, 1 },
1008 _logmod_lock_noop,
1009};
1010
1011static struct logmod_info
1012_logmod_info_populate(const struct logmod_logger *logger,
1013 const unsigned line,
1014 const char *const filename,
1015 const unsigned level)
1016{
1017 const struct logmod *logmod = LOGMOD_FROM_LOGGER(logger);
1018 const time_t time_raw = time(NULL);
1019 struct logmod_info info;
1020 unsigned *mut_line = (unsigned *)&info.line;
1021 const char **mut_filename = (const char **)&info.filename;
1022 unsigned *mut_level = (unsigned *)&info.level;
1023 const struct logmod_label **mut_label =
1024 (const struct logmod_label **)&info.label;
1025 struct tm *mut_time = (struct tm *)&info.time;
1026 *mut_line = line;
1027 *mut_filename = filename;
1028 *mut_level = level;
1029 *mut_label = logmod_logger_get_label(logger, level);
1030 logmod->lock(logger, 1);
1031 *mut_time = *localtime(&time_raw);
1032 logmod->lock(logger, 0);
1033 return info;
1034}
1035
1037_logmod_log(const struct logmod_logger *logger,
1038 const unsigned line,
1039 const char *const filename,
1040 const unsigned level,
1041 const char *fmt,
1042 ...)
1043{
1044 struct logmod *logmod =
1045 LOGMOD_FROM_LOGGER(!logger ? (logger = &g_loggers[0]) : logger);
1047 if (!logger->disabled) {
1048 const struct logmod_info info =
1049 _logmod_info_populate(logger, line, filename, level);
1050 va_list args;
1051 code = LOGMOD_OK_CONTINUE;
1052 if (logger->callback) {
1053 va_start(args, fmt);
1054 if ((code = logger->callback(logger, &info, fmt, args))
1055 < LOGMOD_OK)
1056 {
1057 goto _end;
1058 }
1059 va_end(args);
1060 }
1061 if (level >= logger->options.level && code == LOGMOD_OK_CONTINUE) {
1062 if (!logger->options.quiet || level == LOGMOD_LEVEL_FATAL) {
1063 va_start(args, fmt);
1064 if ((code = _logmod_print(
1065 logger, &info, fmt, args, logger->options.color,
1066 info.label->output == 0 ? stdout : stderr))
1067 != LOGMOD_OK)
1068 {
1069 goto _end;
1070 }
1071 va_end(args);
1072 }
1073 if (logger->options.logfile) {
1074 va_start(args, fmt);
1075 code = _logmod_print(logger, &info, fmt, args, 0,
1076 logger->options.logfile);
1077 }
1078 }
1079 _end:
1080 logmod->lock(logger, 1);
1081 ++logmod->counter;
1082 logmod->lock(logger, 0);
1083 va_end(args);
1084 }
1085 return code;
1086}
1087
1088#undef LOGMOD_EXPECT
1089
1090#endif /* LOGMOD_HEADER */
1091
1092#ifdef __cplusplus
1093}
1094#endif /* __cplusplus */
1095
1096#endif /* LOGMOD_H */
#define _LOGMOD_EXPECT(_cond, _error, _return)
Definition: logmod.h:635
logmod_err logmod_logger_set_id_visibility(struct logmod_logger *logger, int show_app_id, int show_context_id)
Set visibility of application ID and context ID in log messages.
Definition: logmod.h:729
logmod_err logmod_logger_set_counter(struct logmod_logger *logger, int show_counter)
Set counter display for a logger.
Definition: logmod.h:822
void(* logmod_lock)(const struct logmod_logger *logger, int should_lock)
Lock function type for thread safety.
Definition: logmod.h:148
logmod_err logmod_logger_set_color(struct logmod_logger *logger, int color)
Set color mode for a logger.
Definition: logmod.h:786
#define LOGMOD_LABEL_COLOR(_style, _visibility, _color)
Helper macro to define label color, style, and visibility at once.
Definition: logmod.h:122
#define logmod_nlog(_level, _logger, _parenthesized_params, num_params)
Log a message (C89 compatible version)
Definition: logmod.h:454
logmod_err logmod_logger_set_time(struct logmod_logger *logger, int show_time)
Set time display for a logger.
Definition: logmod.h:813
logmod_err logmod_set_lock(struct logmod *logmod, logmod_lock lock)
Set the lock function for thread safety.
Definition: logmod.h:701
long logmod_logger_get_counter(const struct logmod_logger *logger)
Get the global message counter for a logger.
Definition: logmod.h:874
#define __LOGMOD_LOGGER_ATTRS(_qualifier)
Internal macro for defining logger attributes.
Definition: logmod.h:203
logmod_err
Error codes returned by LogMod functions.
Definition: logmod.h:79
@ LOGMOD_OK
Definition: logmod.h:82
@ LOGMOD_OK_CONTINUE
Definition: logmod.h:83
@ LOGMOD_ERRNO
Definition: logmod.h:80
@ LOGMOD_BAD_PARAMETER
Definition: logmod.h:81
@ LOGMOD_OK_SKIPPED
Definition: logmod.h:84
logmod_err logmod_cleanup(struct logmod *logmod)
Clean up the logging context.
Definition: logmod.h:690
logmod_err _logmod_log(const struct logmod_logger *logger, const unsigned line, const char *const filename, const unsigned level, const char *fmt,...)
Internal logging implementation function.
Definition: logmod.h:1037
logmod_err(* logmod_callback)(const struct logmod_logger *logger, const struct logmod_info *info, const char *fmt, va_list args)
Callback function type for custom log handling.
Definition: logmod.h:161
logmod_err logmod_set_options(struct logmod *logmod, struct logmod_options options)
Set default options for all new loggers.
Definition: logmod.h:709
#define LOGMOD_FALLBACK_APPLICATION_ID
Default application ID for the fallback logger.
Definition: logmod.h:46
#define LOGMOD_FROM_LOGGER(_ctx)
Get logmod from any logmod_logger.
Definition: logmod.h:631
logmod_err logmod_logger_set_logfile(struct logmod_logger *logger, FILE *logfile)
Set logfile for a logger.
Definition: logmod.h:804
#define LOGMOD_EXPECT(_cond, _error)
Check if a condition is met and log an error message if not.
Definition: logmod.h:660
logmod_levels
Log levels supported by LogMod.
Definition: logmod.h:64
@ LOGMOD_LEVEL_WARN
Definition: logmod.h:68
@ LOGMOD_LEVEL_INFO
Definition: logmod.h:67
@ LOGMOD_LEVEL_ERROR
Definition: logmod.h:69
@ __LOGMOD_LEVEL_MAX
Definition: logmod.h:71
@ LOGMOD_LEVEL_DEBUG
Definition: logmod.h:66
@ LOGMOD_LEVEL_FATAL
Definition: logmod.h:70
@ LOGMOD_LEVEL_TRACE
Definition: logmod.h:65
@ LOGMOD_LEVEL_CUSTOM
Definition: logmod.h:73
const struct logmod_label * logmod_logger_get_label(const struct logmod_logger *logger, const unsigned level)
Get the label for a specific log level.
Definition: logmod.h:831
#define LMT
Shorthand for LOGMOD_ENCODE_TOGGLE.
Definition: logmod.h:562
logmod_err logmod_toggle_logger(struct logmod *logmod, const char *const context_id)
Toggle a specific logger from logging (default is true)
Definition: logmod.h:719
logmod_err logmod_logger_set_callback(struct logmod_logger *logger, const struct logmod_label *const custom_labels, const size_t num_custom_labels, logmod_callback callback)
Set callback function and custom labels for a logger.
Definition: logmod.h:750
logmod_err logmod_logger_set_data(struct logmod_logger *logger, void *user_data)
Set user data for a logger.
Definition: logmod.h:741
logmod_err logmod_logger_set_quiet(struct logmod_logger *logger, int quiet)
Set quiet mode for a logger.
Definition: logmod.h:777
#define LMS
Shorthand for LOGMOD_ENCODE_STATIC.
Definition: logmod.h:560
#define LME
Shorthand for LOGMOD_ENCODE.
Definition: logmod.h:566
logmod_err logmod_logger_set_level(struct logmod_logger *logger, unsigned level)
Set minimum log level for a logger.
Definition: logmod.h:795
#define LOGMOD_FALLBACK_CONTEXT_ID
Default context ID for the fallback logger.
Definition: logmod.h:55
struct logmod_logger * logmod_get_logger(struct logmod *logmod, const char *const context_id)
Get or create a logger by context ID.
Definition: logmod.h:886
#define LOGMOD_API
Define symbol visibility for LogMod API.
Definition: logmod.h:16
logmod_err logmod_logger_set_options(struct logmod_logger *logger, struct logmod_options options)
Set all options for a logger at once.
Definition: logmod.h:767
#define __BLANK
Definition: logmod.h:213
logmod_err logmod_init(struct logmod *logmod, const char *const application_id, struct logmod_logger table[], unsigned length)
Initialize the logging context.
Definition: logmod.h:670
long logmod_logger_get_level(const struct logmod_logger *logger, const char *const label)
Get the level value for a label name.
Definition: logmod.h:854
#define LOGMOD_PRINTF_LIKE(a, b)
Format string checking attribute for printf-like functions.
Definition: logmod.h:37
Information about a log entry.
Definition: logmod.h:129
const struct logmod_label *const label
Definition: logmod.h:133
const char *const filename
Definition: logmod.h:131
const unsigned level
Definition: logmod.h:132
const unsigned line
Definition: logmod.h:130
const struct tm time
Definition: logmod.h:134
Label properties for a log level.
Definition: logmod.h:107
const char *const name
Definition: logmod.h:108
const int output
Definition: logmod.h:112
const char *const color
Definition: logmod.h:111
const char *const style
Definition: logmod.h:109
const char *const visibility
Definition: logmod.h:110
Immutable logger structure.
Definition: logmod.h:229
const size_t num_custom_labels
Definition: logmod.h:230
const logmod_callback callback
Definition: logmod.h:230
const char * context_id
Definition: logmod.h:230
const struct logmod_options options
Definition: logmod.h:230
const struct logmod_label *const custom_labels
Definition: logmod.h:230
const int disabled
Definition: logmod.h:230
Mutable version of the logger structure.
Definition: logmod.h:219
int disabled
Definition: logmod.h:220
void * user_data
Definition: logmod.h:220
size_t num_custom_labels
Definition: logmod.h:220
struct logmod_options options
Definition: logmod.h:220
logmod_callback callback
Definition: logmod.h:220
const struct logmod_label * custom_labels
Definition: logmod.h:220
const char * context_id
Definition: logmod.h:220
Configuration options for a logger.
Definition: logmod.h:91
int hide_context_id
Definition: logmod.h:95
unsigned level
Definition: logmod.h:97
int hide_counter
Definition: logmod.h:99
FILE * logfile
Definition: logmod.h:92
int show_application_id
Definition: logmod.h:96
int quiet
Definition: logmod.h:93
int suppress_time
Definition: logmod.h:98
int color
Definition: logmod.h:94
Main logging context structure.
Definition: logmod.h:240
const struct logmod_options default_options
Definition: logmod.h:246
const size_t real_length
Definition: logmod.h:244
const struct logmod_logger * loggers
Definition: logmod.h:242
const char * application_id
Definition: logmod.h:241
const size_t length
Definition: logmod.h:243
logmod_lock lock
Definition: logmod.h:248
long counter
Definition: logmod.h:245