mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
verbosity: fix the logger audit's correctness tier
The whole-tree logger audit's actionable findings, the ones that are defects rather than policy: - Xbox1 wrote the message body with wvsprintf, which takes no size: any expansion past the 256-byte stack buffer wrote off its end. Both Xbox1 and WinRT now go through bounded vsnprintf (the msvc compat header maps it for that toolchain) into a 1024-byte line, matching the generic branch's budget; truncation stays the policy on this heapless path. - The ORBIS HAVE_LOGGER va_list macros handed debugNetPrintf (tag, fmt, vp): the tag became the format string and a raw va_list rode as a value argument, and RARCH_WARN_V mapped to a different debugnet level than RARCH_WARN. The non-ORBIS logger_send spelling was two calls per line - prefix plus tag, then body - which interleave under concurrent writers, with one branch carrying a stray "[WARN] :: " prefix. All eight *_V sites now route through one bounded format-then-send helper per backend: one call per line, body formatted, levels matching the non-V spellings (debugnet has no WARN level, so warnings are INFO on both spellings). - LibNX ran mutexInit on every retro_main_log_file_init: a file->console->file cycle re-initialized a mutex another thread may hold for a write. Once per process now, and deinit still never destroys it, for the same reason. - The Android file arm logged the bare body with no tag - the one line-format inconsistency across platforms - through its own vfprintf pair. The generic branch's format-once single-write is now a shared helper, and Android's file arm goes through it: tag included, line whole under stdio's per-call lock (logcat keeps receiving the tag as a priority). - RARCH_LOG_BUFFER computed data + len before any NULL check - UB on a NULL buffer - and carried a dead 'end' from an older loop. NULL with a length returns; the leftover is gone. samples/frontend/logger_macros compiles verbosity.h under all four HAVE_LOGGER configurations (ORBIS x IS_SALAMANDER) against capturing sinks and drives the *_V macros with real va_lists: one sink call per line, body formatted, tag and prefix present, WARN_V at RARCH_WARN's level. Against the pre-fix header the logger configuration fails on exactly the audited shapes (two calls per line, tag lost, prefix lost); the harness also documents that the old macros only ever compiled with literal tags, since they pasted the tag into a string constant. The audit's policy items stay open deliberately: per-line fflush vs crash durability, macro early-outs and a compile-time RARCH_DBG, printf format attributes (a tree-wide -Wformat sweep of its own), the verbosity_get_ptr writer walk, and asl_close on the Apple client. Each changes behavior or blast radius and gets its own decision. Verified: the logger-macro harness green on all four configurations and red as stated on the pre-fix header, log_atomicity green, host syntax passes under -DHAVE_LIBNX (stubbed mutex) and -DANDROID (stubbed logcat) with implicit-function-declaration promoted to an error, five forced atomic backends, C89 gate at baseline, full build scanned clean for the warning classes, thread-read audit 0 findings / 0 allowlisted pairs, hot-function budgets and the 74-lane compile matrix.
This commit is contained in:
1 parent
56b0b748d3
commit
0205b6c016
6 files changed
+372
-111
No files matched your search
@@ -0,0 +1,10 @@
|
||||
TARGET := logger_macros_test
|
||||
|
||||
all:
|
||||
@sh ./build.sh
|
||||
|
||||
clean:
|
||||
rm -f $(TARGET)
|
||||
rm -rf dbgnet_stub
|
||||
|
||||
.PHONY: all clean
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
#!/bin/sh
|
||||
# Logger-macro capture harness: compiles verbosity.h under the four
|
||||
# HAVE_LOGGER configurations (ORBIS x IS_SALAMANDER) against
|
||||
# capturing sinks and runs each. The ORBIS builds use the stubbed
|
||||
# debugnet header beside this script.
|
||||
set -eu
|
||||
cd "$(dirname "$0")"
|
||||
CC="${CC:-gcc}"
|
||||
INC="-I../../../libretro-common/include -I../../.."
|
||||
mkdir -p dbgnet_stub
|
||||
cat > dbgnet_stub/debugnet.h <<'HDR'
|
||||
#ifndef DEBUGNET_H
|
||||
#define DEBUGNET_H
|
||||
#define DEBUGNET_NONE 0
|
||||
#define DEBUGNET_INFO 1
|
||||
#define DEBUGNET_ERROR 2
|
||||
#define DEBUGNET_DEBUG 3
|
||||
void debugNetPrintf(int level, const char *fmt, ...);
|
||||
#endif
|
||||
HDR
|
||||
for CFG in "" "-DIS_SALAMANDER" "-DORBIS -Idbgnet_stub" \
|
||||
"-DIS_SALAMANDER -DORBIS -Idbgnet_stub"; do
|
||||
$CC -std=gnu99 -Wall -Werror -g $INC $CFG \
|
||||
-o logger_macros_test logger_macros_test.c
|
||||
./logger_macros_test >/dev/null
|
||||
echo "ok: ${CFG:-plain HAVE_LOGGER}"
|
||||
done
|
||||
echo "built samples/frontend/logger_macros (all four configurations green)"
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef DEBUGNET_H
|
||||
#define DEBUGNET_H
|
||||
#define DEBUGNET_NONE 0
|
||||
#define DEBUGNET_INFO 1
|
||||
#define DEBUGNET_ERROR 2
|
||||
#define DEBUGNET_DEBUG 3
|
||||
void debugNetPrintf(int level, const char *fmt, ...);
|
||||
#endif
|
||||
@@ -0,0 +1,187 @@
|
||||
/* The HAVE_LOGGER va_list macros ship one formatted line.
|
||||
*
|
||||
* Compiles verbosity.h under the logger configurations that a
|
||||
* desktop build never sees and drives the *_V macros against
|
||||
* capturing sinks:
|
||||
*
|
||||
* ORBIS (either salamander flavour): debugNetPrintf is
|
||||
* printf-style with no va_list variant. The old macros handed it
|
||||
* (tag, fmt, vp) - the tag became the format string and a raw
|
||||
* va_list rode as a value argument - and mapped RARCH_WARN_V to a
|
||||
* different level than RARCH_WARN. The sink must now receive one
|
||||
* call per line, at the level matching the non-V spelling, with
|
||||
* the body formatted.
|
||||
*
|
||||
* logger_send (non-ORBIS): the old macros were two calls - prefix
|
||||
* plus tag, then body - which interleave under concurrent
|
||||
* writers. One call per line now, prefix, tag and formatted body
|
||||
* together, and the "[WARN] :: " oddity gone.
|
||||
*
|
||||
* Build selects the region with -DIS_SALAMANDER / -DORBIS; the
|
||||
* build script runs all four combinations.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#define HAVE_LOGGER 1
|
||||
#include "../../../verbosity.h"
|
||||
|
||||
static unsigned failures = 0;
|
||||
|
||||
#define CHECK(cond, ...) \
|
||||
do { \
|
||||
if (!(cond)) \
|
||||
{ \
|
||||
fprintf(stderr, "FAIL %s:%d: ", __FILE__, __LINE__); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fprintf(stderr, "\n"); \
|
||||
failures++; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Capturing sinks: every call lands here as one formatted string
|
||||
* plus, for debugnet, its level. */
|
||||
static unsigned sink_calls = 0;
|
||||
static int sink_level = -1;
|
||||
static char sink_text[600];
|
||||
|
||||
#ifdef ORBIS
|
||||
void debugNetPrintf(int level, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
sink_calls++;
|
||||
sink_level = level;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(sink_text, sizeof(sink_text), fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
#else
|
||||
void logger_init(void) { }
|
||||
void logger_shutdown(void) { }
|
||||
void logger_send(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
sink_calls++;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf(sink_text, sizeof(sink_text), fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
void logger_send_v(const char *fmt, va_list ap)
|
||||
{
|
||||
/* The interleave-prone second call of the old shape: with the
|
||||
* fix, nothing reaches it from the *_V macros. */
|
||||
sink_calls++;
|
||||
vsnprintf(sink_text, sizeof(sink_text), fmt, ap);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void reset(void)
|
||||
{
|
||||
sink_calls = 0;
|
||||
sink_level = -1;
|
||||
sink_text[0] = '\0';
|
||||
}
|
||||
|
||||
/* The macros take a va_list; these build one the way the function
|
||||
* wrappers do. The tag is baked in as a literal: the logger macros
|
||||
* paste it into a string constant, so a runtime tag never compiled
|
||||
* against them. */
|
||||
static void drive_log_v(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
RARCH_LOG_V("[Video]", fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void drive_warn_v(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
#ifdef ORBIS
|
||||
RARCH_WARN_V("[Audio]", fmt, ap);
|
||||
#else
|
||||
RARCH_WARN_V("[Input]", fmt, ap);
|
||||
#endif
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void drive_err_v(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
#ifdef ORBIS
|
||||
RARCH_ERR_V("[Core]", fmt, ap);
|
||||
#else
|
||||
RARCH_ERR_V("[Config]", fmt, ap);
|
||||
#endif
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* One call, formatted body present, tag present. */
|
||||
reset();
|
||||
drive_log_v("mode %ux%u set\n", 640u, 480u);
|
||||
CHECK(sink_calls == 1,
|
||||
"LOG_V made %u sink calls, want exactly 1", sink_calls);
|
||||
CHECK(strstr(sink_text, "640x480") != NULL /* %ux%u */,
|
||||
"LOG_V body not formatted: \"%.80s\"", sink_text);
|
||||
CHECK(strstr(sink_text, "[Video]") != NULL,
|
||||
"LOG_V tag missing: \"%.80s\"", sink_text);
|
||||
|
||||
#ifdef ORBIS
|
||||
CHECK(sink_level == DEBUGNET_INFO,
|
||||
"LOG_V level %d, want DEBUGNET_INFO", sink_level);
|
||||
|
||||
/* WARN_V at the same level as RARCH_WARN. */
|
||||
reset();
|
||||
RARCH_WARN("plain warn\n");
|
||||
{
|
||||
int warn_level = sink_level;
|
||||
reset();
|
||||
drive_warn_v("underrun of %d frames\n", 32);
|
||||
CHECK(sink_calls == 1,
|
||||
"WARN_V made %u sink calls, want 1", sink_calls);
|
||||
CHECK(sink_level == warn_level,
|
||||
"WARN_V level %d differs from RARCH_WARN's %d",
|
||||
sink_level, warn_level);
|
||||
}
|
||||
|
||||
reset();
|
||||
drive_err_v("load failed: %s\n", "missing file");
|
||||
CHECK(sink_level == DEBUGNET_ERROR,
|
||||
"ERR_V level %d, want DEBUGNET_ERROR", sink_level);
|
||||
CHECK(strstr(sink_text, "missing file") != NULL,
|
||||
"ERR_V body not formatted: \"%.80s\"", sink_text);
|
||||
#else
|
||||
/* No " :: " residue, and the error prefix rides the one call. */
|
||||
reset();
|
||||
drive_warn_v("pad %d gone\n", 2);
|
||||
CHECK(sink_calls == 1,
|
||||
"WARN_V made %u sink calls, want 1", sink_calls);
|
||||
CHECK(strstr(sink_text, " :: ") == NULL,
|
||||
"WARN_V still carries the :: oddity: \"%.80s\"", sink_text);
|
||||
CHECK(strstr(sink_text, "pad 2 gone") != NULL,
|
||||
"WARN_V body not formatted: \"%.80s\"", sink_text);
|
||||
|
||||
reset();
|
||||
drive_err_v("parse error at %d\n", 7);
|
||||
CHECK(sink_calls == 1,
|
||||
"ERR_V made %u sink calls, want 1", sink_calls);
|
||||
CHECK(strstr(sink_text, "[ERROR]") != NULL,
|
||||
"ERR_V prefix missing: \"%.80s\"", sink_text);
|
||||
CHECK(strstr(sink_text, "parse error at 7") != NULL,
|
||||
"ERR_V body not formatted: \"%.80s\"", sink_text);
|
||||
#endif
|
||||
|
||||
if (failures)
|
||||
{
|
||||
fprintf(stderr, "FAILURES (%u)\n", failures);
|
||||
return 1;
|
||||
}
|
||||
printf("logger_macros: all lanes passed\n");
|
||||
return 0;
|
||||
}
|
||||
+83
-55
@@ -181,12 +181,23 @@ bool *verbosity_get_ptr(void)
|
||||
void retro_main_log_file_init(const char *path, bool append)
|
||||
{
|
||||
FILE *tmp;
|
||||
#ifdef HAVE_LIBNX
|
||||
static bool mtx_inited = false;
|
||||
#endif
|
||||
|
||||
if (main_verbosity_st.initialized)
|
||||
return;
|
||||
|
||||
#ifdef HAVE_LIBNX
|
||||
mutexInit(&main_verbosity_st.mtx);
|
||||
/* Once for the process: a file->console->file cycle re-enters
|
||||
* here, and re-initializing a mutex another thread may be
|
||||
* holding for a write is exactly the race the mutex exists to
|
||||
* prevent. Deinit never destroys it for the same reason. */
|
||||
if (!mtx_inited)
|
||||
{
|
||||
mutexInit(&main_verbosity_st.mtx);
|
||||
mtx_inited = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Default to stderr; only override when a valid path is given */
|
||||
@@ -235,10 +246,71 @@ void retro_main_log_file_deinit(void)
|
||||
}
|
||||
|
||||
#if !defined(HAVE_LOGGER)
|
||||
/* Compiled for its two consumers: the Android file arm and the
|
||||
* generic branch. Xbox/WinRT formats into its own bounded buffer,
|
||||
* and the Apple arms go through their platform sinks. */
|
||||
#if defined(ANDROID) \
|
||||
|| (!defined(_XBOX1) && !defined(__WINRT__) && !defined(__APPLE__))
|
||||
/* Format tag and message into one buffer and write it with a single
|
||||
* stdio call: the per-call lock then keeps concurrent lines whole.
|
||||
* Lines wider than the stack buffer take an exact-sized heap detour
|
||||
* rather than truncating; if that allocation fails, the truncated
|
||||
* stack line ships - a shortened message over a dropped one. */
|
||||
static void rarch_log_line_write(FILE *fp, const char *tag_v,
|
||||
const char *fmt, va_list ap)
|
||||
{
|
||||
char line[1024];
|
||||
char *out = line;
|
||||
char *heap = NULL;
|
||||
int t_len = snprintf(line, sizeof(line), "%s ", tag_v);
|
||||
int b_len;
|
||||
va_list ap_cp;
|
||||
|
||||
if (t_len < 0 || t_len >= (int)sizeof(line))
|
||||
t_len = 0;
|
||||
|
||||
va_copy(ap_cp, ap);
|
||||
b_len = vsnprintf(line + t_len, sizeof(line) - (size_t)t_len,
|
||||
fmt, ap_cp);
|
||||
va_end(ap_cp);
|
||||
|
||||
if (b_len >= (int)(sizeof(line) - (size_t)t_len))
|
||||
{
|
||||
size_t need = (size_t)t_len + (size_t)b_len + 1;
|
||||
if ((heap = (char*)malloc(need)))
|
||||
{
|
||||
memcpy(heap, line, (size_t)t_len);
|
||||
vsnprintf(heap + t_len, need - (size_t)t_len, fmt, ap);
|
||||
out = heap;
|
||||
}
|
||||
}
|
||||
else if (b_len < 0)
|
||||
line[t_len] = '\0';
|
||||
|
||||
#if defined(HAVE_LIBNX)
|
||||
/* Around exactly one write and its flush; libnx newlib's stdio
|
||||
* locking history is why this exists at all. */
|
||||
mutexLock(&main_verbosity_st.mtx);
|
||||
#endif
|
||||
fputs(out, fp);
|
||||
fflush(fp);
|
||||
#if defined(HAVE_LIBNX)
|
||||
mutexUnlock(&main_verbosity_st.mtx);
|
||||
#endif
|
||||
|
||||
free(heap);
|
||||
}
|
||||
#endif
|
||||
|
||||
void RARCH_LOG_V(const char *tag, const char *fmt, va_list ap)
|
||||
{
|
||||
#if defined(_XBOX1) || defined(__WINRT__)
|
||||
char buffer[256];
|
||||
/* wvsprintf takes no size and writes past any small buffer on a
|
||||
* long expansion; vsnprintf is bounded on both targets (the msvc
|
||||
* compat header maps it for the Xbox toolchain), and 1024 matches
|
||||
* the line budget the generic branch uses. Truncation stays the
|
||||
* policy here - no heap on this target. */
|
||||
char buffer[1024];
|
||||
int _len;
|
||||
const char *tag_v = tag ? tag : FILE_PATH_LOG_INFO;
|
||||
buffer[0] = '\0';
|
||||
@@ -246,13 +318,7 @@ void RARCH_LOG_V(const char *tag, const char *fmt, va_list ap)
|
||||
"%s: %s ", FILE_PATH_PROGRAM_NAME, tag_v);
|
||||
|
||||
if (_len > 0 && _len < (int)sizeof(buffer))
|
||||
{
|
||||
#if defined(__WINRT__)
|
||||
vsnprintf(buffer + _len, sizeof(buffer) - (size_t)_len, fmt, ap);
|
||||
#else
|
||||
wvsprintf(buffer + _len, fmt, ap);
|
||||
#endif
|
||||
}
|
||||
#ifdef _DEBUG
|
||||
OutputDebugStringA(buffer);
|
||||
#endif
|
||||
@@ -267,9 +333,11 @@ void RARCH_LOG_V(const char *tag, const char *fmt, va_list ap)
|
||||
FILE *fp = main_verbosity_st.fp;
|
||||
if (main_verbosity_st.initialized && fp)
|
||||
{
|
||||
/* Already logging to file: single write path, no Android log overhead */
|
||||
vfprintf(fp, fmt, ap);
|
||||
fflush(fp);
|
||||
/* Logging to file: one formatted write, tag included -
|
||||
* the file carries the same line format as every other
|
||||
* platform (logcat gets the tag as a priority instead). */
|
||||
const char *tag_v = tag ? tag : FILE_PATH_LOG_INFO;
|
||||
rarch_log_line_write(fp, tag_v, fmt, ap);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -402,48 +470,7 @@ apple_log_done:;
|
||||
* body-call pair could interleave between threads; lines
|
||||
* wider than the stack buffer take an exact-sized heap
|
||||
* detour rather than truncating. */
|
||||
char line[1024];
|
||||
char *out = line;
|
||||
char *heap = NULL;
|
||||
int t_len = snprintf(line, sizeof(line), "%s ", tag_v);
|
||||
int b_len;
|
||||
va_list ap_cp;
|
||||
|
||||
if (t_len < 0 || t_len >= (int)sizeof(line))
|
||||
t_len = 0;
|
||||
|
||||
va_copy(ap_cp, ap);
|
||||
b_len = vsnprintf(line + t_len, sizeof(line) - (size_t)t_len,
|
||||
fmt, ap_cp);
|
||||
va_end(ap_cp);
|
||||
|
||||
if (b_len >= (int)(sizeof(line) - (size_t)t_len))
|
||||
{
|
||||
size_t need = (size_t)t_len + (size_t)b_len + 1;
|
||||
if ((heap = (char*)malloc(need)))
|
||||
{
|
||||
memcpy(heap, line, (size_t)t_len);
|
||||
vsnprintf(heap + t_len, need - (size_t)t_len, fmt, ap);
|
||||
out = heap;
|
||||
}
|
||||
/* On allocation failure the truncated stack line ships:
|
||||
* a shortened message over a dropped one. */
|
||||
}
|
||||
else if (b_len < 0)
|
||||
line[t_len] = '\0';
|
||||
|
||||
# if defined(HAVE_LIBNX)
|
||||
/* Around exactly one write and its flush; libnx newlib's
|
||||
* stdio locking history is why this exists at all. */
|
||||
mutexLock(&main_verbosity_st.mtx);
|
||||
# endif
|
||||
fputs(out, fp);
|
||||
fflush(fp);
|
||||
# if defined(HAVE_LIBNX)
|
||||
mutexUnlock(&main_verbosity_st.mtx);
|
||||
# endif
|
||||
|
||||
free(heap);
|
||||
rarch_log_line_write(fp, tag_v, fmt, ap);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -454,9 +481,11 @@ void RARCH_LOG_BUFFER(uint8_t *data, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
size_t offset = 0;
|
||||
const uint8_t *end = data + len;
|
||||
uint8_t buf[16];
|
||||
|
||||
if (!data && len)
|
||||
return;
|
||||
|
||||
RARCH_LOG("== %d-byte buffer ==================\n", (int)len);
|
||||
|
||||
/* Zero-init once; tail padding written below */
|
||||
@@ -486,7 +515,6 @@ void RARCH_LOG_BUFFER(uint8_t *data, size_t len)
|
||||
buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
|
||||
}
|
||||
RARCH_LOG("==================================\n");
|
||||
(void)end; /* suppress unused-variable warning */
|
||||
}
|
||||
|
||||
void RARCH_DBG(const char *fmt, ...)
|
||||
|
||||
+56
-56
@@ -17,6 +17,7 @@
|
||||
#define __RARCH_VERBOSITY_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <boolean.h>
|
||||
@@ -60,6 +61,25 @@ void logger_shutdown (void);
|
||||
void logger_send (const char *__format,...);
|
||||
void logger_send_v(const char *__format, va_list args);
|
||||
|
||||
/* The va_list spellings format the body first: debugNetPrintf is
|
||||
* printf-style with no va_list variant (handing it (tag, fmt, vp)
|
||||
* makes the tag the format string and passes a raw va_list as a
|
||||
* value), and two logger_send calls interleave under concurrent
|
||||
* writers. Bounded at 512; logger consoles have no heap detour. */
|
||||
#ifdef ORBIS
|
||||
#define RARCH_LOGGER_V_IMPL(level, tag, fmt, vp) do { \
|
||||
char _rarch_log_line[512]; \
|
||||
vsnprintf(_rarch_log_line, sizeof(_rarch_log_line), fmt, vp); \
|
||||
debugNetPrintf(level, "%s %s", tag, _rarch_log_line); \
|
||||
} while (0)
|
||||
#else
|
||||
#define RARCH_LOGGER_V_IMPL(prefix, tag, fmt, vp) do { \
|
||||
char _rarch_log_line[512]; \
|
||||
vsnprintf(_rarch_log_line, sizeof(_rarch_log_line), fmt, vp); \
|
||||
logger_send("%s%s %s", prefix, tag, _rarch_log_line); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef IS_SALAMANDER
|
||||
|
||||
#ifdef ORBIS
|
||||
@@ -71,33 +91,31 @@ void logger_send_v(const char *__format, va_list args);
|
||||
debugNetPrintf(DEBUGNET_INFO,"" __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_LOG_V(tag, fmt, vp) do { \
|
||||
debugNetPrintf(DEBUGNET_DEBUG,tag,fmt,vp); \
|
||||
} while (0)
|
||||
#define RARCH_LOG_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL(DEBUGNET_INFO, tag, fmt, vp)
|
||||
|
||||
#define RARCH_ERR(...) do { \
|
||||
debugNetPrintf(DEBUGNET_ERROR,"" __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_ERR_V(tag, fmt, vp) do { \
|
||||
debugNetPrintf(DEBUGNET_ERROR,tag,fmt,vp); \
|
||||
} while (0)
|
||||
#define RARCH_ERR_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL(DEBUGNET_ERROR, tag, fmt, vp)
|
||||
|
||||
#define RARCH_WARN(...) do { \
|
||||
debugNetPrintf(DEBUGNET_INFO,"" __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_WARN_V(tag, fmt, vp) do { \
|
||||
debugNetPrintf(DEBUGNET_DEBUG,tag,fmt,vp); \
|
||||
} while (0)
|
||||
/* debugnet has no WARN level: INFO on both spellings, matching
|
||||
* RARCH_WARN, instead of one INFO and one DEBUG. */
|
||||
#define RARCH_WARN_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL(DEBUGNET_INFO, tag, fmt, vp)
|
||||
|
||||
#define RARCH_LOG_OUTPUT(...) do { \
|
||||
debugNetPrintf(DEBUGNET_INFO,"" __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_LOG_OUTPUT_V(tag, fmt, vp) do { \
|
||||
debugNetPrintf(DEBUGNET_INFO,tag,fmt,vp); \
|
||||
} while (0)
|
||||
#define RARCH_LOG_OUTPUT_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL(DEBUGNET_INFO, tag, fmt, vp)
|
||||
|
||||
#else
|
||||
#define RARCH_DBG(...) do { \
|
||||
@@ -108,37 +126,29 @@ void logger_send_v(const char *__format, va_list args);
|
||||
logger_send("RetroArch Salamander: " __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_LOG_V(tag, fmt, vp) do { \
|
||||
logger_send("RetroArch Salamander: " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
#define RARCH_LOG_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL("RetroArch Salamander: ", tag, fmt, vp)
|
||||
|
||||
#define RARCH_LOG_OUTPUT(...) do { \
|
||||
logger_send("[OUTPUT] " __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_LOG_OUTPUT_V(tag, fmt, vp) do { \
|
||||
logger_send("[OUTPUT] " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
#define RARCH_LOG_OUTPUT_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL("[OUTPUT] ", tag, fmt, vp)
|
||||
|
||||
#define RARCH_ERR(...) do { \
|
||||
logger_send("[ERROR] " __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_ERR_V(tag, fmt, vp) do { \
|
||||
logger_send("[ERROR] " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
#define RARCH_ERR_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL("[ERROR] ", tag, fmt, vp)
|
||||
|
||||
#define RARCH_WARN(...) do { \
|
||||
logger_send("[WARN] " __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_WARN_V(tag, fmt, vp) do { \
|
||||
logger_send("[WARN] " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
#define RARCH_WARN_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL("[WARN] ", tag, fmt, vp)
|
||||
#endif
|
||||
#else /* IS_SALAMANDER */
|
||||
|
||||
@@ -151,33 +161,31 @@ void logger_send_v(const char *__format, va_list args);
|
||||
debugNetPrintf(DEBUGNET_INFO,"" __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_LOG_V(tag, fmt, vp) do { \
|
||||
debugNetPrintf(DEBUGNET_DEBUG,tag,fmt,vp); \
|
||||
} while (0)
|
||||
#define RARCH_LOG_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL(DEBUGNET_INFO, tag, fmt, vp)
|
||||
|
||||
#define RARCH_ERR(...) do { \
|
||||
debugNetPrintf(DEBUGNET_ERROR,"" __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_ERR_V(tag, fmt, vp) do { \
|
||||
debugNetPrintf(DEBUGNET_ERROR,tag,fmt,vp); \
|
||||
} while (0)
|
||||
#define RARCH_ERR_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL(DEBUGNET_ERROR, tag, fmt, vp)
|
||||
|
||||
#define RARCH_WARN(...) do { \
|
||||
debugNetPrintf(DEBUGNET_INFO,"" __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_WARN_V(tag, fmt, vp) do { \
|
||||
debugNetPrintf(DEBUGNET_DEBUG,tag,fmt,vp); \
|
||||
} while (0)
|
||||
/* debugnet has no WARN level: INFO on both spellings, matching
|
||||
* RARCH_WARN, instead of one INFO and one DEBUG. */
|
||||
#define RARCH_WARN_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL(DEBUGNET_INFO, tag, fmt, vp)
|
||||
|
||||
#define RARCH_LOG_OUTPUT(...) do { \
|
||||
debugNetPrintf(DEBUGNET_INFO,"" __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_LOG_OUTPUT_V(tag, fmt, vp) do { \
|
||||
debugNetPrintf(DEBUGNET_INFO,tag,fmt,vp); \
|
||||
} while (0)
|
||||
#define RARCH_LOG_OUTPUT_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL(DEBUGNET_INFO, tag, fmt, vp)
|
||||
|
||||
#else
|
||||
#define RARCH_DBG(...) do { \
|
||||
@@ -188,37 +196,29 @@ void logger_send_v(const char *__format, va_list args);
|
||||
logger_send("" __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_LOG_V(tag, fmt, vp) do { \
|
||||
logger_send("" tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
#define RARCH_LOG_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL("", tag, fmt, vp)
|
||||
|
||||
#define RARCH_ERR(...) do { \
|
||||
logger_send("[ERROR] " __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_ERR_V(tag, fmt, vp) do { \
|
||||
logger_send("[ERROR] " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
#define RARCH_ERR_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL("[ERROR] ", tag, fmt, vp)
|
||||
|
||||
#define RARCH_WARN(...) do { \
|
||||
logger_send("[WARN] " __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_WARN_V(tag, fmt, vp) do { \
|
||||
logger_send("[WARN] :: " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
#define RARCH_WARN_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL("[WARN] ", tag, fmt, vp)
|
||||
|
||||
#define RARCH_LOG_OUTPUT(...) do { \
|
||||
logger_send("[OUTPUT] " __VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define RARCH_LOG_OUTPUT_V(tag, fmt, vp) do { \
|
||||
logger_send("[OUTPUT] " tag); \
|
||||
logger_send_v(fmt, vp); \
|
||||
} while (0)
|
||||
#define RARCH_LOG_OUTPUT_V(tag, fmt, vp) \
|
||||
RARCH_LOGGER_V_IMPL("[OUTPUT] ", tag, fmt, vp)
|
||||
#endif
|
||||
#endif
|
||||
#define RARCH_LOG_BUFFER(...) do { } while (0)
|
||||
|
||||
Reference in new issue
Block a user