forked from sysprog21/rv32emu
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Previously, messages were printed using both printf and fprintf, causing the information to be mixed between stdout and stderr. To address this, the log.[ch] was integrated to standardize the logging. The log.[ch]'s API are encapsulated one more layer with prefix 'rv', and included in src/common.h. The logging API uses color to differentiate messages at different levels, ensuring that logging all information to the same stdout stream does not cause confusion. The color feature is controlled by ENABLE_LOG_COLOR and is enabled by default. Note that the logging stdout stream is registered during rv_remap_stdstream() as the new stdout stream could be remapped at there. Related: sysprog21#310
- Loading branch information
1 parent
6e6cfb8
commit 57c74da
Showing
16 changed files
with
300 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,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(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <stdarg.h> | ||
#include <stdbool.h> | ||
#include <stdio.h> | ||
#include <time.h> | ||
|
||
typedef struct { | ||
va_list ap; | ||
const char *fmt; | ||
const char *file; | ||
struct tm *time; | ||
void *udata; | ||
int line; | ||
int level; | ||
} log_event_t; | ||
|
||
typedef void (*log_func_t)(log_event_t *ev); | ||
typedef void (*log_lock_func_t)(bool lock, void *udata); | ||
|
||
enum LOG_LEVEL { | ||
LOG_TRACE = 0, | ||
LOG_DEBUG, | ||
LOG_INFO, | ||
LOG_WARN, | ||
LOG_ERROR, | ||
LOG_FATAL, | ||
}; | ||
|
||
/* lowest level logging */ | ||
#define rv_log_trace(...) log_impl(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__) | ||
#define rv_log_debug(...) log_impl(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__) | ||
#define rv_log_info(...) log_impl(LOG_INFO, __FILE__, __LINE__, __VA_ARGS__) | ||
#define rv_log_warn(...) log_impl(LOG_WARN, __FILE__, __LINE__, __VA_ARGS__) | ||
#define rv_log_error(...) log_impl(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__) | ||
#define rv_log_fatal(...) log_impl(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__) | ||
/* highest level logging */ | ||
|
||
#define rv_log_level_string(...) log_level_string(__VA_ARGS__) | ||
#define rv_log_set_lock(...) log_set_lock(__VA_ARGS__) | ||
#define rv_log_set_level(...) log_set_level(__VA_ARGS__) | ||
#define rv_log_set_quiet(...) log_set_quiet(__VA_ARGS__) | ||
/* | ||
* By default, log messages are directed to stdout. However, | ||
* rv_remap_stdstream() may redirect stdout to a different target, such as a | ||
* file. Therefore, rv_log_set_stdout_stream() should be invoked within | ||
* rv_remap_stdstream() to properly handle any changes to the stdout stream. | ||
*/ | ||
#define rv_log_set_stdout_stream(...) log_set_stdout_stream(__VA_ARGS__) | ||
|
||
const char *log_level_string(int level); | ||
void log_set_lock(log_lock_func_t fn, void *udata); | ||
void log_set_level(int level); | ||
void log_set_quiet(bool enable); | ||
void log_set_stdout_stream(FILE *stream); | ||
|
||
void log_impl(int level, const char *file, int line, const char *fmt, ...); |
Oops, something went wrong.