joeylib2/src/core/debug.c

99 lines
2.6 KiB
C

// Cross-platform "where did it hang?" logger. Holds joeylog.txt open
// across calls; libc's stdio buffer absorbs writes (~4 KB) and the
// final fclose at program exit (via atexit) gets the buffer to disk.
//
// Earlier rev opened+closed per call for crash durability ("last line
// guaranteed on disk if we hang"); that cost ~1 second per call
// through GoldenGate's ProDOS FST emulation -- a 50-line UBER run
// burned ~5 minutes in IO. Even per-line fflush is too expensive
// because every fflush forces an FST WRITE, and host-OS file IO time
// isn't tracked by the IIgs VBL counter so wall-time logs underreport.
//
// Tradeoff: if the program crashes mid-run, buffered log lines may
// not reach disk. For UBER and similar batch demos that's acceptable;
// for hang-debugging where durability matters, call joeyLogFlush()
// at the suspected hang points.
#include <stdio.h>
#include <stdarg.h>
#include "joey/platform.h"
#include "joey/debug.h"
static const char *kLogPath = "joeylog.txt";
static FILE *gLogFp = NULL;
/* 16 KB is enough for UBER's full log (~5 KB) plus generous headroom,
* so the file never auto-flushes mid-run. ORCA-C / libnix default
* buffers are only ~512 bytes; with that, a 50-line log triggers ~10
* ProDOS / AmigaDOS WRITEs through the host FST, each of which is
* untracked-host-time (seconds). Buffer the whole thing in memory and
* let the atexit fclose flush once. */
#define JOEY_LOG_BUF_BYTES 16384
static char gLogBuf[JOEY_LOG_BUF_BYTES];
/* Lazy-open. Returns NULL if the open failed (silently disable). */
static FILE *logFile(void) {
if (gLogFp == NULL) {
gLogFp = fopen(kLogPath, "a");
if (gLogFp != NULL) {
(void)setvbuf(gLogFp, gLogBuf, _IOFBF, sizeof(gLogBuf));
}
}
return gLogFp;
}
void joeyLog(const char *msg) {
FILE *fp;
if (msg == NULL) {
return;
}
fp = logFile();
if (fp == NULL) {
return;
}
fputs(msg, fp);
fputc('\n', fp);
}
void joeyLogF(const char *fmt, ...) {
FILE *fp;
va_list args;
if (fmt == NULL) {
return;
}
fp = logFile();
if (fp == NULL) {
return;
}
va_start(args, fmt);
vfprintf(fp, fmt, args);
va_end(args);
fputc('\n', fp);
}
void joeyLogFlush(void) {
if (gLogFp != NULL) {
fflush(gLogFp);
}
}
void joeyLogReset(void) {
if (gLogFp != NULL) {
fclose(gLogFp);
gLogFp = NULL;
}
/* Truncate by opening for write then closing; subsequent
* joeyLog* will reopen for append. */
{
FILE *fp = fopen(kLogPath, "w");
if (fp != NULL) {
fclose(fp);
}
}
}