Making progress on util::dprintf
This commit is contained in:
@@ -1016,6 +1016,7 @@ static void init_engine_wrapper_helper(EngineWrapper *w) {
|
||||
w->replay_initialize = replaycore_initialize;
|
||||
w->replay_step = replaycore_step;
|
||||
|
||||
w->hook_dprintf = util::hook_dprintf;
|
||||
w->release = release;
|
||||
};
|
||||
|
||||
|
||||
@@ -318,7 +318,6 @@ private:
|
||||
friend class Channel;
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
@@ -227,6 +227,23 @@ struct EngineWrapper {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Hook dprintf
|
||||
//
|
||||
// The engine provides a function 'util::dprintf' to print debugging
|
||||
// messages. It does not use stderr or std::cerr, because in windows, those
|
||||
// go to the bit-bucket.
|
||||
//
|
||||
// This routine hooks dprintf to change where the output goes. Ideally,
|
||||
// the intent is to send the output somewhere easily accessible, like the
|
||||
// visual studio debug output log, or the unreal editor output log, or
|
||||
// something like that. Or, better yet, to all those places at once.
|
||||
//
|
||||
// The hook function will get passed one line of output at a time. The line
|
||||
// will only contain printable characters. The line will not contain a
|
||||
// newline - the newline is implied.
|
||||
//
|
||||
void (*hook_dprintf)(void (*func)(const char *oneline));
|
||||
|
||||
// Restore the wrapper to its initial blank state.
|
||||
//
|
||||
// Note that the wrapper must have already been initialized using
|
||||
|
||||
@@ -720,6 +720,63 @@ eng::string XYZ::debug_string() const {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
void (*dprintf_hook)(const char *oneline);
|
||||
|
||||
void hook_dprintf(void (*func)(const char *oneline)) {
|
||||
dprintf_hook = func;
|
||||
}
|
||||
|
||||
static void chop_up_dprintf(char *buffer, int size) {
|
||||
// Drop the final newline, if any. We're going
|
||||
// to automatically end with a newline and we don't
|
||||
// want to double up.
|
||||
if ((size > 0) && (buffer[size-1] == '\n')) {
|
||||
size -= 1;
|
||||
}
|
||||
|
||||
// Chop it up into lines and call the hook one line
|
||||
// at a time. Replace control characters as we go.
|
||||
const char *base = buffer;
|
||||
for (int i = 0; i <= size; i++) {
|
||||
if (buffer[i] < ' ') {
|
||||
if ((buffer[i] == '\n') || (buffer[i] == 0)) {
|
||||
buffer[i] = 0;
|
||||
if (dprintf_hook == nullptr) {
|
||||
fprintf(stderr, "%s\n", base);
|
||||
} else {
|
||||
dprintf_hook(base);
|
||||
}
|
||||
base = buffer + i + 1;
|
||||
} else {
|
||||
buffer[i] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we're sending to stderr, flush. If not, then
|
||||
// the hook routine is responsible for flushing its own
|
||||
// output.
|
||||
if (dprintf_hook == nullptr) {
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
|
||||
void dprintf(const char *format, ...) {
|
||||
char buffer[256];
|
||||
va_list args;
|
||||
va_start (args, format);
|
||||
int n = vsnprintf(buffer, 256, format, args);
|
||||
if (n <= 255) {
|
||||
chop_up_dprintf(buffer, n);
|
||||
} else {
|
||||
char *lbuffer = (char *)malloc(n + 1);
|
||||
vsnprintf(lbuffer, n+1, format, args);
|
||||
chop_up_dprintf(lbuffer, n);
|
||||
free(lbuffer);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
||||
|
||||
|
||||
@@ -357,6 +357,22 @@ inline eng::string ss(const ARGS & ... args) {
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// dprintf
|
||||
//
|
||||
// Send a debugging message to somewhere that it can be seen. This routine
|
||||
// initially just sends output to stderr. But it can be hooked to send output
|
||||
// somewhere else, like to a debug output window.
|
||||
//
|
||||
// The hook function must be a function that accepts a single line of text. The
|
||||
// hook function will always be passed one line, consisting of printable
|
||||
// characters only. There will be no control characters. The newline is
|
||||
// implied.
|
||||
//
|
||||
void dprintf(const char *format, ...);
|
||||
void hook_dprintf(void (*func)(const char *oneline));
|
||||
|
||||
// A better API than std::setfill, std::hex, std::setw, std::setprecision
|
||||
//
|
||||
// Usage examples:
|
||||
|
||||
@@ -9,6 +9,11 @@ static void if_error_print_and_exit(const std::string_view str) {
|
||||
}
|
||||
}
|
||||
|
||||
static void dprintf_callback(const char *oneline) {
|
||||
fprintf(stderr, "DPRINTF: %s\n", oneline);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
class Driver {
|
||||
public:
|
||||
enum ChanState {
|
||||
@@ -536,6 +541,7 @@ class Driver {
|
||||
// Load the DLL and gain access to its functions.
|
||||
call_init_engine_wrapper(&engw);
|
||||
engw.replay_cb_sent_outgoing = replay_cb_sent_outgoing;
|
||||
engw.hook_dprintf(dprintf_callback);
|
||||
|
||||
// If argv contains "replay <filename>", do a replay,
|
||||
// and then skip everything else.
|
||||
|
||||
Reference in New Issue
Block a user