Debugging TADS3 on Linux

(Also a linux dev) If you haven’t tumbled onto it yet, add -source reflect to your debug builds. This gives you access to VERY enhanced stack trace info, as well as access to the reflectionServices.valToSymbol() which dumps symbol information as printable strings (instead of needing to suss out string properties of an unknown object). Then yeah, lots of debug prints. I crafted a bare bones debug ‘module’ to give me a consolidated space to put that stuff, though inevitably some debugs require in-method print statements anyway.

#charset "us-ascii"

/*   Debug Printer...
 *
 *   Include the main header for the standard TADS 3 adventure library.
 *   Also include the US English definitions, since this game is written
 *   in English.  
 */
#include <adv3.h>
#include <en_us.h>

// some convenience debug macros.  need to define in any source
// file that wants to use them, though only v2s() likely useful
//
#define gDebug (debugMgr.debugEnabled)
#define gQuiet (debugMgr.quietEnabled)
#define v2s(Symbol) reflectionServices.valToSymbol(##Symbol)

//  QUIET function, mainly used to shut off output when
//  'FF' to debug areas deep in gamestate
// ie..  >QUIET
//       >REPLAY DEBUG.TXT
//       >QUIET
//
DefineSystemAction(Quiet)
    execSystemAction() {
		gQuiet = (gQuiet ? nil : true);  // toggle value
        if (gQuiet) {
            "##QUIET MODE ENABLED\n";
            mainOutputStream.disable();
        } else {
            mainOutputStream.enable();
            "##QUIET MODE DISABLED\n";
        }
    }
;
VerbRule(Quiet)
	('quiet') : QuietAction
	verbPhrase = 'quiet/quieting'
;
modify mainOutputStream
    outputOn = true
    enable() { outputOn = true; }
    disable() {outputOn = nil; }
    writeFromStream(txt) {
        /* if an input event was interrupted, cancel the event */
        inputManager.inputEventEnd();

        /* write the text to the console */
        if (outputOn) aioSay(txt);
    }
;

//  DEBUG function, enables every turn print of desired values
//
modify DebugAction
	execAction() {
		gDebug = (gDebug ? nil : true);
        "##DEBUG MESSAGES <<gDebug ? 'ENABLED' : 'DISABLED'>>";
        if (gDebug) new Daemon(debugMgr, &debugPrint, 1);
        else eventManager.removeMatchingEvents(debugMgr, &debugPrint);

        /* ORIG:  if the debugger is present, break into it,
         * never played with this, sorry
         * 
        if (t3DebugTrace(T3DebugCheck))
            t3DebugTrace(T3DebugBreak);
        else
            "Debugger not present. "; */
	}
;

debugMgr : Thing
    debugEnabled = nil
    quietEnabled = nil
    debugPrint() {
        // debug prints go here

        "DEBUG:  bigSword.location = <<v2s(bigSword.location)>>\n";
    }
;

Would also recommend this thread for stack trace chasing hints…

7 Likes