Program Listing for File log.hpp¶
↰ Return to documentation for file (lib/log.hpp
)
/* SPDX-License-Identifier: BSD-2-Clause */
#pragma once
#include <frg/logging.hpp>
#include <frg/spinlock.hpp>
#include <frg/string.hpp>
#include <frg/string_stub.hpp>
#include <hal/hal.hpp>
namespace Gaia {
#define ENABLE_ASSERTS 1
#if ENABLE_ASSERTS
#define ASSERT(CONDITION) \
((CONDITION) ? (void)0 \
: panic("assertion '{}' failed at {}:{}", #CONDITION, __FILE__, \
__LINE__))
#else
#define ASSERT(CONDITION) ((void)(0))
#endif
class DebugSink {
public:
void operator()(const char *str) {
while (*str) {
Hal::debug_output(*str++);
}
}
};
constexpr const char *file_name(const char *path) {
const char *file = path;
while (*path) {
if (*path++ == '/') {
file = path;
}
}
return file;
}
struct FormatWithLocation {
constexpr FormatWithLocation(char const *_format,
char const *_file = __builtin_FILE(),
int _line = __builtin_LINE())
: format{_format}, file{_file}, line{_line} {}
char const *format;
char const *file;
int line;
};
extern frg::stack_buffer_logger<DebugSink> logger;
extern frg::simple_spinlock log_lock;
template <bool locked = true, typename... T>
void log(FormatWithLocation fmt, T... args) {
#ifndef __KERNEL__
return;
#endif
if (locked) {
log_lock.lock();
}
char file_path[256];
// ok... this kinda sucks but hey it's pretty cool
memcpy(file_path, fmt.file, strlen(fmt.file));
// remove .cpp
file_path[strlen(fmt.file) - 4] = 0;
logger() << frg::fmt("\x1b[32m[{:5}.{:06d}]\x1b[0m ",
Hal::get_time_since_boot().seconds,
Hal::get_time_since_boot().milliseconds)
<< frg::fmt("\x1b[33m{}:\x1b[0m ", file_name(file_path))
<< frg::fmt(fmt.format, args...) << "\n"
<< frg::endlog;
if (locked) {
log_lock.unlock();
}
}
template <bool locked = true, typename... T>
void error(FormatWithLocation fmt, T... args) {
if (locked) {
log_lock.lock();
}
char file_path[256];
// ok... this kinda sucks but hey it's pretty cool
memcpy(file_path, fmt.file, strlen(fmt.file));
// remove .cpp
file_path[strlen(fmt.file) - 4] = 0;
logger() << frg::fmt("\x1b[31m[{:5}.{:06d}]\x1b[0m ",
Hal::get_time_since_boot().seconds,
Hal::get_time_since_boot().milliseconds)
<< frg::fmt("\x1b[33m{}:\x1b[0m ", file_name(file_path))
<< frg::fmt(fmt.format, args...) << "\n"
<< frg::endlog;
if (locked) {
log_lock.unlock();
}
}
template <typename... T>
[[noreturn]] void panic(FormatWithLocation fmt, T... args) {
char file_path[256];
memcpy(file_path, fmt.file, strlen(fmt.file));
file_path[strlen(fmt.file) - 4] = 0;
logger() << frg::fmt("\x1b[31m[{:5}.{:06d}] PANIC \x1b[0m",
Hal::get_time_since_boot().seconds,
Hal::get_time_since_boot().milliseconds)
<< frg::fmt("\x1b[33m{}:{}\x1b[0m ", file_name(file_path), fmt.line)
<< frg::fmt(fmt.format, args...) << "\x1b[0m\n"
<< frg::endlog;
#ifdef __KERNEL__
Hal::disable_interrupts();
#endif
Hal::halt();
}
} // namespace Gaia