Remove debug_printf filtering

The filter was rarely used. The implementation was overly complex and
might have filtered out strings that should have been printed.

Tags like "FILES|" have been removed.
For the loader a macro `LOADER_LOG` has been introduced.
This commit is contained in:
phosit
2026-09-02 10:30:37 +02:00
parent a8ee3c2b92
commit a56456495c
11 changed files with 35 additions and 168 deletions
+2 -91
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -67,88 +67,6 @@ static const StatusDefinition debugStatusDefinitions[] = {
};
STATUS_ADD_DEFINITIONS(debugStatusDefinitions);
// need to shoehorn printf-style variable params into
// the OutputDebugString call.
// - don't want to split into multiple calls - would add newlines to output.
// - fixing Win32 _vsnprintf to return # characters that would be written,
// as required by C99, looks difficult and unnecessary. if any other code
// needs that, implement GNU vasprintf.
// - fixed size buffers aren't nice, but much simpler than vasprintf-style
// allocate+expand_until_it_fits. these calls are for quick debug output,
// not loads of data, anyway.
// rationale: static data instead of std::set to allow setting at any time.
// we store FNV hash of tag strings for fast comparison; collisions are
// extremely unlikely and can only result in displaying more/less text.
static const size_t MAX_TAGS = 20;
static u32 tags[MAX_TAGS];
static size_t num_tags;
void debug_filter_add(const char* tag)
{
const u32 hash = fnv_hash(tag, strlen(tag)*sizeof(tag[0]));
// make sure it isn't already in the list
for(size_t i = 0; i < MAX_TAGS; i++)
if(tags[i] == hash)
return;
// too many already?
if(num_tags == MAX_TAGS)
{
DEBUG_WARN_ERR(ERR::LOGIC); // increase MAX_TAGS
return;
}
tags[num_tags++] = hash;
}
void debug_filter_remove(const char* tag)
{
const u32 hash = fnv_hash(tag, strlen(tag)*sizeof(tag[0]));
for(size_t i = 0; i < MAX_TAGS; i++)
{
if(tags[i] == hash) // found it
{
// replace with last element (avoid holes)
tags[i] = tags[MAX_TAGS-1];
num_tags--;
// can only happen once, so we're done.
return;
}
}
}
void debug_filter_clear()
{
std::fill(tags, tags+MAX_TAGS, 0);
}
bool debug_filter_allows(const char* text)
{
size_t i;
for(i = 0; ; i++)
{
// no | found => no tag => should always be displayed
if(text[i] == ' ' || text[i] == '\0')
return true;
if(text[i] == '|' && i != 0)
break;
}
const u32 hash = fnv_hash(text, i*sizeof(text[0]));
// check if entry allowing this tag is found
for(i = 0; i < MAX_TAGS; i++)
if(tags[i] == hash)
return true;
return false;
}
#undef debug_printf // allowing #defining it out
void debug_printf(const char* fmt, ...)
{
@@ -161,16 +79,9 @@ void debug_printf(const char* fmt, ...)
debug_break(); // poor man's assert - avoid infinite loop because ENSURE also uses debug_printf
va_end(ap);
debug_puts_filtered(buf);
debug_puts(buf);
}
void debug_puts_filtered(const char* text)
{
if(debug_filter_allows(text))
debug_puts(text);
}
//-----------------------------------------------------------------------------
Status debug_WriteCrashlog(const wchar_t* text)
+3 -58
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -63,8 +63,8 @@ extern void debug_break();
//-----------------------------------------------------------------------------
/**
* write a formatted string to the debug channel, subject to filtering
* (see below). implemented via debug_puts - see performance note there.
* write a formatted string to the debug channel. implemented via debug_puts -
* see performance note there.
*
* @param fmt Format string and varargs; see printf.
**/
@@ -194,61 +194,6 @@ ErrorReaction debug_DisplayError(const wchar_t* description, size_t flags, void*
// disallow continue for the error.
#define DEBUG_DISPLAY_FATAL_ERROR(description) DEBUG_DISPLAY_ERROR_IMPL(description, DE_NO_CONTINUE)
//
// filtering
//
/**
* debug output is very useful, but "too much of a good thing can kill you".
* we don't want to require different LOGn() macros that are enabled
* depending on "debug level", because changing that entails lengthy
* compiles and it's too coarse-grained. instead, we require all
* strings to start with "tag_string|" (exact case and no quotes;
* the alphanumeric-only \<tag_string\> identifies output type).
* they are then subject to filtering: only if the tag has been
* "added" via debug_filter_add is the appendant string displayed.
*
* this approach is easiest to implement and is fine because we control
* all logging code. LIMODS falls from consideration since it's not
* portable and too complex.
*
* notes:
* - filter changes only affect subsequent debug_*printf calls;
* output that didn't pass the filter is permanently discarded.
* - strings not starting with a tag are always displayed.
* - debug_filter_* can be called at any time and from the debugger,
* but are not reentrant.
*
* in future, allow output with the given tag to proceed.
* no effect if already added.
**/
void debug_filter_add(const char* tag);
/**
* in future, discard output with the given tag.
* no effect if not currently added.
**/
void debug_filter_remove(const char* tag);
/**
* clear all filter state; equivalent to debug_filter_remove for
* each tag that was debug_filter_add-ed.
**/
void debug_filter_clear();
/**
* indicate if the given text would be printed.
* useful for a series of debug_printfs - avoids needing to add a tag to
* each of their format strings.
**/
bool debug_filter_allows(const char* text);
/**
* call debug_puts if debug_filter_allows allows the string.
**/
void debug_puts_filtered(const char* text);
/**
* write an error description and all logs into crashlog.txt
* (in unicode format).
+6 -2
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
@@ -800,7 +800,11 @@ static Status DetermineSymbolAddress(DWORD id, const SYMBOL_INFOW* sym, const Du
*pp = (const u8*)(uintptr_t)addr;
debug_printf("SYM| %s at %p flags=%X dk=%d sym->addr=%I64X fp=%I64x\n", utf8_from_wstring(sym->Name).c_str(), *pp, sym->Flags, dataKind, sym->Address, state.stackFrame->AddrFrame.Offset);
#if 0
debug_printf("Symbol: %s at %p flags=%X dk=%d sym->addr=%I64X fp=%I64x\n",
utf8_from_wstring(sym->Name).c_str(), *pp, sym->Flags, dataKind, sym->Address,
state.stackFrame->AddrFrame.Offset);
#endif
return INFO::OK;
}
+2 -2
View File
@@ -667,9 +667,9 @@ void CConsole::SaveHistory()
}
if (g_VFS->CreateFile(m_HistoryFile, {buffer.Data().get(), buffer.Size()}) == INFO::OK)
ONCE(debug_printf("FILES| Console command history written to '%s'\n", m_HistoryFile.string8().c_str()));
ONCE(debug_printf("Console command history written to '%s'\n", m_HistoryFile.string8().c_str()));
else
debug_printf("FILES| Failed to write console command history to '%s'\n", m_HistoryFile.string8().c_str());
debug_printf("Failed to write console command history to '%s'\n", m_HistoryFile.string8().c_str());
}
static bool isUnprintableChar(SDL_Keysym key)
+2 -2
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -294,7 +294,7 @@ namespace
std::ofstream OpenLogFile(const wchar_t* filePrefix, const char* logName)
{
OsPath path{psLogDir() / (filePrefix + g_UniqueLogPostfix + L".html")};
debug_printf("FILES| %s written to '%s'\n", logName, path.string8().c_str());
debug_printf("%s written to '%s'\n", logName, path.string8().c_str());
return std::ofstream{OsString(path), std::ofstream::trunc};
}
}
-2
View File
@@ -462,8 +462,6 @@ void EarlyInit()
Threading::SetMainThread();
debug_SetThreadName("main");
// add all debug_printf "tags" that we are interested in:
debug_filter_add("FILES");
timer_Init();
+1 -1
View File
@@ -316,7 +316,7 @@ void WriteSystemInfo(Renderer::Backend::IDevice* device, const utsname& un)
fclose(f);
f = 0;
debug_printf("FILES| Hardware details written to '%s'\n", pathname.string8().c_str());
debug_printf("Hardware details written to '%s'\n", pathname.string8().c_str());
}
} // anonymous namespace
+12 -3
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2025 Wildfire Games.
/* Copyright (C) 2026 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -32,6 +32,12 @@
#include <string>
#include <utility>
#if 0
#define LOADER_LOG(...) debug_printf(__VA_ARGS__)
#else
#define LOADER_LOG(...)
#endif
namespace PS::Loader
{
namespace
@@ -221,7 +227,9 @@ ProgressiveLoadResult ProgressiveLoad(double time_budget)
// either finished entirely, or failed => remove from queue.
if(!timed_out)
{
debug_printf("LOADER| completed %s in %g ms; estimate was %g ms\n", utf8_from_wstring(lr.description).c_str(), task_elapsed_time*1e3, estimated_duration*1e3);
LOADER_LOG("Loader: completed %s in %g ms; estimate was %g ms\n",
utf8_from_wstring(lr.description).c_str(), task_elapsed_time*1e3,
estimated_duration*1e3);
task_elapsed_time = 0.0;
estimated_duration_tally += estimated_duration;
load_requests.pop_front();
@@ -284,7 +292,8 @@ done:
if(!load_requests.empty())
ret.nextDescription = load_requests.front().description;
debug_printf("LOADER| returning; desc=%s progress=%d\n", utf8_from_wstring(ret.nextDescription).c_str(), ret.progressPercent);
LOADER_LOG("Loader: returning; desc=%s progress=%d\n",
utf8_from_wstring(ret.nextDescription).c_str(), ret.progressPercent);
return ret;
}
+3 -3
View File
@@ -86,7 +86,7 @@ void CReplayLogger::StartGame(JS::MutableHandleValue attribs)
Script::SetProperty(rq, attribs, "mods", mods);
m_Directory = createDateIndexSubdirectory(VisualReplay::GetDirectoryPath());
debug_printf("FILES| Replay written to '%s'\n", m_Directory.string8().c_str());
debug_printf("Replay written to '%s'\n", m_Directory.string8().c_str());
m_Stream = new std::ofstream(OsString(m_Directory / L"commands.txt"), std::ofstream::out | std::ofstream::trunc);
*m_Stream << "start " << Script::StringifyJSON(rq, attribs, false) << "\n";
@@ -137,10 +137,10 @@ void CReplayLogger::SaveMetadata(const CSimulation2& simulation)
{
stream << Script::StringifyJSON(rq, &metadata, false);
stream.close();
debug_printf("FILES| Replay metadata written to '%s'\n", fileName.string8().c_str());
debug_printf("Replay metadata written to '%s'\n", fileName.string8().c_str());
}
else
debug_printf("FILES| Failed to write replay metadata to '%s'\n", fileName.string8().c_str());
debug_printf("Failed to write replay metadata to '%s'\n", fileName.string8().c_str());
}
+2 -2
View File
@@ -590,12 +590,12 @@ void CUserReporter::SubmitReport(const std::string& type, int version, const std
std::ofstream stream(OsString(path), std::ofstream::trunc);
if (stream)
{
debug_printf("FILES| UserReport written to '%s'\n", path.string8().c_str());
debug_printf("UserReport written to '%s'\n", path.string8().c_str());
stream << dataHumanReadable << std::endl;
stream.close();
}
else
debug_printf("FILES| Failed to write UserReport to '%s'\n", path.string8().c_str());
debug_printf("Failed to write UserReport to '%s'\n", path.string8().c_str());
}
// If not initialised, discard the report
+2 -2
View File
@@ -279,10 +279,10 @@ void WriteJSONFile(const Script::Interface& scriptInterface, const std::wstring&
{
OsPath realPath;
g_VFS->GetRealPath(path, realPath, false);
debug_printf("FILES| JSON data written to '%s'\n", realPath.string8().c_str());
debug_printf("JSON data written to '%s'\n", realPath.string8().c_str());
}
else
debug_printf("FILES| Failed to write JSON data to '%s'\n", path.string8().c_str());
debug_printf("Failed to write JSON data to '%s'\n", path.string8().c_str());
}
bool DeleteCampaignSave(const CStrW& filePath)