-
Notifications
You must be signed in to change notification settings - Fork 112
/
Copy pathlog.c
125 lines (108 loc) · 3.08 KB
/
log.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
* Copyright (c) 2020 rxi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "log.h"
static struct {
void *udata;
log_lock_func_t lock;
int level;
bool quiet;
} L;
static const char *level_strings[] = {
"TRACE", "DEBUG", "INFO", "WARN", "ERROR", "FATAL",
};
#if RV32_HAS(LOG_COLOR)
static const char *level_colors[] = {
"\x1b[94m", "\x1b[36m", "\x1b[32m", "\x1b[33m", "\x1b[31m", "\x1b[35m",
};
#endif /* RV32_HAS(LOG_COLOR) */
static void stdout_callback(log_event_t *ev)
{
char buf[16];
buf[strftime(buf, sizeof(buf), "%H:%M:%S", ev->time)] = '\0';
#if RV32_HAS(LOG_COLOR)
fprintf(ev->udata, "%s %s%-5s\x1b[0m \x1b[90m%s:%d:\x1b[0m ", buf,
level_colors[ev->level], level_strings[ev->level], ev->file,
ev->line);
#else
fprintf(ev->udata, "%s %-5s %s:%d: ", buf, level_strings[ev->level],
ev->file, ev->line);
#endif /* RV32_HAS(LOG_COLOR) */
vfprintf(ev->udata, ev->fmt, ev->ap);
fprintf(ev->udata, "\n");
fflush(ev->udata);
}
static void lock(void)
{
if (L.lock)
L.lock(true, L.udata);
}
static void unlock(void)
{
if (L.lock)
L.lock(false, L.udata);
}
const char *log_level_string(int level)
{
return level_strings[level];
}
void log_set_lock(log_lock_func_t fn, void *udata)
{
L.lock = fn;
L.udata = udata;
}
void log_set_level(int level)
{
L.level = level;
}
void log_set_quiet(bool enable)
{
L.quiet = enable;
}
static void init_event(log_event_t *ev, void *udata)
{
if (!ev->time) {
time_t t = time(NULL);
ev->time = localtime(&t);
}
ev->udata = udata;
}
void log_set_stdout_stream(FILE *stream)
{
L.udata = stream;
}
void log_impl(int level, const char *file, int line, const char *fmt, ...)
{
log_event_t ev = {
.fmt = fmt,
.file = file,
.line = line,
.level = level,
};
lock();
if (!L.quiet && level >= L.level) {
init_event(&ev, L.udata ? L.udata : stdout);
va_start(ev.ap, fmt);
stdout_callback(&ev);
va_end(ev.ap);
}
unlock();
}