1 |
|
2 #include "log.h" |
|
3 #include "str.h" |
|
4 |
|
5 #include <stdio.h> |
|
6 #include <stdarg.h> |
|
7 #include <string.h> |
|
8 |
|
9 /** |
|
10 * The default log output func |
|
11 */ |
|
12 void log_default_func (const char *line, void *arg) |
|
13 { |
|
14 (void) arg; |
|
15 |
|
16 // display |
|
17 printf("%s\n", line); |
|
18 } |
|
19 |
|
20 /** |
|
21 * The global log level |
|
22 */ |
|
23 static enum log_level _log_level = LOG_LEVEL_DEFAULT; |
|
24 |
|
25 /** |
|
26 * The global log output func |
|
27 */ |
|
28 static struct log_output_ctx { |
|
29 /** The function itself */ |
|
30 log_output_func func; |
|
31 |
|
32 /** The arg */ |
|
33 void *arg; |
|
34 } _log_output_ctx = { log_default_func, NULL }; |
|
35 |
|
36 /** |
|
37 * List of log level names |
|
38 */ |
|
39 const char *log_level_names[] = { |
|
40 "DEBUG", |
|
41 "INFO", |
|
42 "WARN", |
|
43 "ERROR", |
|
44 "FATAL", |
|
45 NULL |
|
46 }; |
|
47 |
|
48 #define _LOG_LEVEL_NAME(ll) case LOG_ ## ll: return #ll; |
|
49 const char *log_level_name (enum log_level level) |
|
50 { |
|
51 switch (level) { |
|
52 _LOG_LEVEL_NAME(DEBUG) |
|
53 _LOG_LEVEL_NAME(INFO) |
|
54 _LOG_LEVEL_NAME(WARN) |
|
55 _LOG_LEVEL_NAME(ERROR) |
|
56 _LOG_LEVEL_NAME(FATAL) |
|
57 default: return "???"; |
|
58 } |
|
59 } |
|
60 #undef _LOG_LEVEL_NAME |
|
61 |
|
62 void set_log_level (enum log_level level) |
|
63 { |
|
64 // meep meep |
|
65 _log_level = level; |
|
66 } |
|
67 |
|
68 void log_set_func (log_output_func func, void *arg) |
|
69 { |
|
70 // replace the current one |
|
71 _log_output_ctx.func = func ? func : log_default_func; |
|
72 _log_output_ctx.arg = arg; |
|
73 } |
|
74 |
|
75 void log_output_tag_va (enum log_level level, const char *tag, const char *func, const char *user_fmt, va_list user_fmtargs, const char *log_fmt, va_list log_fmtargs) |
|
76 { |
|
77 char buf[LOG_MSG_MAX], *buf_ptr = buf; |
|
78 size_t buf_size = sizeof(buf); |
|
79 |
|
80 // filter out? |
|
81 if (level < _log_level) |
|
82 return; |
|
83 |
|
84 // output the header |
|
85 buf_ptr += str_advance(NULL, &buf_size, str_append_fmt(buf_ptr, buf_size, "[%5s] %20s : ", tag, func)); |
|
86 |
|
87 // output the user data |
|
88 if (user_fmt) |
|
89 buf_ptr += str_advance(NULL, &buf_size, str_append_fmt_va(buf_ptr, buf_size, user_fmt, user_fmtargs)); |
|
90 |
|
91 // output the suffix |
|
92 if (log_fmt) |
|
93 buf_ptr += str_advance(NULL, &buf_size, str_append_fmt_va(buf_ptr, buf_size, log_fmt, log_fmtargs)); |
|
94 |
|
95 // send it to the output func |
|
96 _log_output_ctx.func(buf, _log_output_ctx.arg); |
|
97 |
|
98 } |
|
99 |
|
100 void log_output_tag (enum log_level level, const char *tag, const char *func, const char *user_fmt, va_list user_fmtargs, const char *log_fmt, ...) |
|
101 { |
|
102 va_list vargs; |
|
103 |
|
104 va_start(vargs, log_fmt); |
|
105 log_output_tag_va(level, tag, func, user_fmt, user_fmtargs, log_fmt, vargs); |
|
106 va_end(vargs); |
|
107 } |
|
108 |
|
109 void _log_msg (enum log_level level, const char *func, const char *format, ...) |
|
110 { |
|
111 va_list vargs; |
|
112 |
|
113 // formatted output: no suffix |
|
114 va_start(vargs, format); |
|
115 log_output_tag(level, log_level_name(level), func, format, vargs, NULL); |
|
116 va_end(vargs); |
|
117 } |
|
118 |
|
119 void _log_msg_va2 (enum log_level level, const char *func, const char *fmt1, va_list fmtargs1, const char *fmt2, va_list fmtargs2) |
|
120 { |
|
121 log_output_tag_va(level, log_level_name(level), func, fmt1, fmtargs1, fmt2, fmtargs2); |
|
122 } |
|
123 |
|
124 void _log_err (enum log_level level, err_t err, const char *func, const char *format, ...) |
|
125 { |
|
126 va_list vargs; |
|
127 |
|
128 // formatted output: suffix error_name() |
|
129 va_start(vargs, format); |
|
130 log_output_tag(level, log_level_name(level), func, format, vargs, ": %s", error_name(err)); |
|
131 va_end(vargs); |
|
132 } |
|
133 |
|
134 void _log_error (enum log_level level, const error_t *err, const char *func, const char *format, ...) |
|
135 { |
|
136 va_list vargs; |
|
137 |
|
138 // formatted output: suffix error_msg() |
|
139 va_start(vargs, format); |
|
140 log_output_tag(level, log_level_name(level), func, format, vargs, ": %s", error_msg(err)); |
|
141 va_end(vargs); |
|
142 } |
|
143 |
|
144 void _log_perr (enum log_level level, const char *func, const char *format, ...) |
|
145 { |
|
146 va_list vargs; |
|
147 |
|
148 // formatted output: suffix strerror() |
|
149 va_start(vargs, format); |
|
150 log_output_tag(level, log_level_name(level), func, format, vargs, ": %s", strerror(errno)); |
|
151 va_end(vargs); |
|
152 } |
|
153 |
|
154 void _log_exit (enum log_level level, int exit_code, const char *func, const char *format, ...) |
|
155 { |
|
156 va_list vargs; |
|
157 |
|
158 // formatted output without any suffix |
|
159 va_start(vargs, format); |
|
160 log_output_tag(level, "EXIT", func, format, vargs, NULL); |
|
161 va_end(vargs); |
|
162 |
|
163 // exit |
|
164 exit(exit_code); |
|
165 } |
|