cosmopolitan/libc/log/log.h
Justine Tunney f554dd800e
Make it possible to log kprintf() to file
It's now possible to compile Emacs using cosmocc. However we need to
troubleshoot why it's event loop isn't working correctly at runtime.
2023-06-05 04:16:15 -07:00

233 lines
9.8 KiB
C

#ifndef COSMOPOLITAN_LIBC_LOG_LOG_H_
#define COSMOPOLITAN_LIBC_LOG_LOG_H_
#include "libc/stdio/stdio.h"
#define kLogFatal 0
#define kLogError 1
#define kLogWarn 2
#define kLogInfo 3
#define kLogVerbose 4
#define kLogDebug 5
#define kLogNoise 6
/**
* Log level for compile-time DCE.
*/
#ifndef LOGGABLELEVEL
#ifndef TINY
#define LOGGABLELEVEL kLogNoise
/* #elif IsTiny() */
/* #define LOGGABLELEVEL kLogInfo */
#else
#define LOGGABLELEVEL kLogVerbose
#endif
#endif
#ifdef TINY
#define _LOG_TINY 1
#else
#define _LOG_TINY 0
#endif
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
extern FILE *__log_file;
int __watch(void *, size_t);
void __die(void) relegated wontreturn; /* print backtrace and abort() */
void _meminfo(int); /* shows malloc statistics &c. */
void _memsummary(int); /* light version of same thing */
bool IsTerminalInarticulate(void) nosideeffect;
const char *commandvenv(const char *, const char *);
int LogKprintfToFile(const char *);
const char *GetAddr2linePath(void);
const char *GetGdbPath(void);
void ShowCrashReports(void);
int MakeProcessNice(void);
bool32 IsDebuggerPresent(bool);
bool IsRunningUnderMake(void);
const char *GetSiCodeName(int, int);
char *GetSymbolByAddr(int64_t);
void PrintGarbage(void);
void PrintGarbageNumeric(FILE *);
void CheckForMemoryLeaks(void);
#ifndef __STRICT_ANSI__
#define _LOG_UNLIKELY(x) __builtin_expect(!!(x), 0)
extern unsigned __log_level; /* log level for runtime check */
#define LOGGABLE(LEVEL) \
((!__builtin_constant_p(LEVEL) || (LEVEL) <= LOGGABLELEVEL) && \
(LEVEL) <= __log_level)
// log a message with the specified log level (not checking if LOGGABLE)
#define LOGF(LEVEL, FMT, ...) \
do { \
if (!_LOG_TINY) _log_untrace(); \
flogf(LEVEL, __FILE__, __LINE__, NULL, FMT, ##__VA_ARGS__); \
if (!_LOG_TINY) _log_retrace(); \
} while (0)
// report an error without backtrace and debugger invocation
#define FATALF(FMT, ...) \
do { \
if (!_LOG_TINY) _log_untrace(); \
flogf(kLogError, __FILE__, __LINE__, NULL, FMT, ##__VA_ARGS__); \
_log_exit(1); \
} while (0)
#define DIEF(FMT, ...) \
do { \
if (!_LOG_TINY) _log_untrace(); \
ffatalf(kLogFatal, __FILE__, __LINE__, NULL, FMT, ##__VA_ARGS__); \
unreachable; \
} while (0)
#define ERRORF(FMT, ...) \
do { \
if (LOGGABLE(kLogError)) { \
LOGF(kLogError, FMT, ##__VA_ARGS__); \
} \
} while (0)
#define WARNF(FMT, ...) \
do { \
if (LOGGABLE(kLogWarn)) { \
LOGF(kLogWarn, FMT, ##__VA_ARGS__); \
} \
} while (0)
#define INFOF(FMT, ...) \
do { \
if (LOGGABLE(kLogInfo)) { \
LOGF(kLogInfo, FMT, ##__VA_ARGS__); \
} \
} while (0)
#define VERBOSEF(FMT, ...) \
do { \
if (LOGGABLE(kLogVerbose)) { \
if (!_LOG_TINY) _log_untrace(); \
fverbosef(kLogVerbose, __FILE__, __LINE__, NULL, FMT, ##__VA_ARGS__); \
if (!_LOG_TINY) _log_retrace(); \
} \
} while (0)
#define DEBUGF(FMT, ...) \
do { \
if (_LOG_UNLIKELY(LOGGABLE(kLogDebug))) { \
if (!_LOG_TINY) _log_untrace(); \
fdebugf(kLogDebug, __FILE__, __LINE__, NULL, FMT, ##__VA_ARGS__); \
if (!_LOG_TINY) _log_retrace(); \
} \
} while (0)
#define NOISEF(FMT, ...) \
do { \
if (_LOG_UNLIKELY(LOGGABLE(kLogNoise))) { \
if (!_LOG_TINY) _log_untrace(); \
fnoisef(kLogNoise, __FILE__, __LINE__, NULL, FMT, ##__VA_ARGS__); \
if (!_LOG_TINY) _log_retrace(); \
} \
} while (0)
#define FLOGF(F, FMT, ...) \
do { \
if (LOGGABLE(kLogInfo)) { \
if (!_LOG_TINY) _log_untrace(); \
flogf(kLogInfo, __FILE__, __LINE__, F, FMT, ##__VA_ARGS__); \
if (!_LOG_TINY) _log_retrace(); \
} \
} while (0)
#define FWARNF(F, FMT, ...) \
do { \
if (LOGGABLE(kLogWarn)) { \
if (!_LOG_TINY) _log_untrace(); \
flogf(kLogWarn, __FILE__, __LINE__, F, FMT, ##__VA_ARGS__); \
if (!_LOG_TINY) _log_retrace(); \
} \
} while (0)
#define FFATALF(F, FMT, ...) \
do { \
if (!_LOG_TINY) _log_untrace(); \
flogf(kLogError, __FILE__, __LINE__, F, FMT, ##__VA_ARGS__); \
_log_exit(1); \
} while (0)
#define FDEBUGF(F, FMT, ...) \
do { \
if (_LOG_UNLIKELY(LOGGABLE(kLogDebug))) { \
if (!_LOG_TINY) _log_untrace(); \
fdebugf(kLogDebug, __FILE__, __LINE__, F, FMT, ##__VA_ARGS__); \
if (!_LOG_TINY) _log_retrace(); \
} \
} while (0)
#define FNOISEF(F, FMT, ...) \
do { \
if (_LOG_UNLIKELY(LOGGABLE(kLogNoise))) { \
if (!_LOG_TINY) _log_untrace(); \
fnoisef(kLogNoise, __FILE__, __LINE__, F, FMT, ##__VA_ARGS__); \
if (!_LOG_TINY) _log_retrace(); \
} \
} while (0)
#define LOGIFNEG1(FORM) \
({ \
int e = _log_get_errno(); \
autotype(FORM) Ax = (FORM); \
if (_LOG_UNLIKELY(Ax == (typeof(Ax))(-1)) && LOGGABLE(kLogWarn)) { \
if (!_LOG_TINY) _log_untrace(); \
_log_errno(__FILE__, __LINE__, #FORM); \
if (!_LOG_TINY) _log_retrace(); \
_log_set_errno(e); \
} \
Ax; \
})
#define LOGIFNULL(FORM) \
({ \
int e = _log_get_errno(); \
autotype(FORM) Ax = (FORM); \
if (Ax == NULL && LOGGABLE(kLogWarn)) { \
if (!_LOG_TINY) _log_untrace(); \
_log_errno(__FILE__, __LINE__, #FORM); \
if (!_LOG_TINY) _log_retrace(); \
_log_set_errno(e); \
} \
Ax; \
})
void _log_errno(const char *, int, const char *) relegated;
int _log_get_errno(void);
void _log_set_errno(int);
void _log_untrace(void);
void _log_retrace(void);
void _log_exit(int) wontreturn;
#define ARGS unsigned, const char *, int, FILE *, const char *
#define ATTR paramsnonnull((5)) printfesque(5)
#define ATTRV paramsnonnull((5))
void flogf(ARGS, ...) ATTR libcesque;
void vflogf(ARGS, va_list) ATTRV libcesque;
void fverbosef(ARGS, ...) asm("flogf") ATTR relegated libcesque;
void vfverbosef(ARGS, va_list) asm("vflogf") ATTRV relegated libcesque;
void fdebugf(ARGS, ...) asm("flogf") ATTR relegated libcesque;
void vfdebugf(ARGS, va_list) asm("vflogf") ATTRV relegated libcesque;
void fnoisef(ARGS, ...) asm("flogf") ATTR relegated libcesque;
void vfnoisef(ARGS, va_list) asm("vflogf") ATTRV relegated libcesque;
void ffatalf(ARGS, ...) asm("flogf") ATTR relegated wontreturn libcesque;
void vffatalf(ARGS, va_list) asm("vflogf") ATTRV relegated wontreturn libcesque;
#undef ARGS
#undef ATTR
#undef ATTRV
#endif /* __STRICT_ANSI__ */
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_LOG_LOG_H_ */