Game Development Community

Script - get the list of params to the current script function ?

by Orion Elenzil · in Torque Game Engine · 11/24/2008 (2:55 pm) · 7 replies

Howdy!

for producing quality debugging statements,
it would be handy to have a way to get the list of parameters which were passed in to the current function. (or even better, to the parent function).

any pointers ?

i'd like to be able to do something like this:

function foo([an unknown set of arguments])
{
   // getCallParams() would return an Array() object of [param, value] pairs.
   // see http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=4711
   printCallParams(getCallParams());
}

function printCallParams(%params)
{
   %line = "";
   %line = %line @ getScopeName(-1); // the name of the calling function. see http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=12426
   %line = %line @ " -";
   for (%n = 0; %n < %params.count(); %n++)
   {
      %line = %line SPC %params.getKey(%n) SPC "= \"" @ %params.getValue(%n) @ "\"";
   }
   
   echo(%line);
}

#1
11/25/2008 (6:26 pm)
It would be nice to have this sort of introspection in Torque.

You would need to write a new console function that pokes at callArgc and callArgv inside of Codeblock::exec. I suspect you could make...

static U32 *smCurrentArgc;
static const char ***smCurrentCallArgv; // get a load of my pointers!

... then in Codeblock::exec you could do...

U32 callArgc;
   const char **callArgv;

   smCurrentArgc = &callArgc;
   smCurrentCallArgv= &callArgv;

The problem here is that these values are only correct for the current top of the callstack. It would be more useful if this info was kept for every call stack entry... then it can even be queried from the debugger watch window in Torsion.
#2
11/25/2008 (6:37 pm)
Tom,
that's exactly the sort of thing i was after, thank you.

CodeBlock::exec() looks like it only has one exit point,
so it might be fairly simple to push argc & argv onto a stack at the beginning and pop 'em off at the end. assuming argv is not destroyed during the execution of CodeBlock::exec(), of course.

.. somehow that seems a little too simple to be true! ;)

i'm going offline for the holiday, but i'll try to look into this next week.

aye, displaying this stuff from torsion would be really nice.

cheers,
orion
#3
11/25/2008 (6:38 pm)
Forgive my ignorance,
but is torsion intrusive into the engine,
or does it try to do everything through the telnet connection and script ?
#4
11/25/2008 (6:45 pm)
Torsion works via the telnet debugger connection and a little automatic script modification to main.cs in order to enabled the telnet debugger automatically.

AKA... no engine modifications.
#5
11/25/2008 (7:10 pm)
This could be cool.
here's a quick proof-of-concept source & output:

source added near the top of CodeBlock::exec():
if (argc > 0)
   {
      U32 bufSize = 0;
      char delim[] = ", ";
      for (U32 n = 0; n < argc; n++)
      {
         bufSize += dStrlen(argv[n]);  // the arg value itself
         bufSize += sizeof(delim);     // comma and a space
      }
      bufSize += 1;                    // EOS
      

      char* buf = new char[bufSize];
      buf[0] = '[[6280e7a724bb9]]';

      for (U32 n = 1; n < argc; n++)
      {
         if (n > 1)
            dStrcat(buf, delim);
         dStrcat(buf, argv[n]);
      }

      if (thisNamespace != NULL && thisNamespace->getName() != NULL)
         Con::printf("%s::%s(%s)", thisNamespace->getName(), argv[0], buf);
      else
         Con::printf(    "%s(%s)",                           argv[0], buf);

      delete [] buf;
   }

.. and output:
[11/25/2008 19:02:09][Inf][General] AnimCtrl::addFrame(8948, platform/client/ui/pulse/bracket_11.png)
[11/25/2008 19:02:09][Inf][General] AnimCtrl::addFrame(8948, platform/client/ui/pulse/bracket_12.png)
[11/25/2008 19:02:09][Inf][General] AnimCtrl::addFrame(8948, platform/client/ui/pulse/bracket_13.png)
[11/25/2008 19:02:09][Inf][General] HudTabs::fillTabs(HudTabs)
[11/25/2008 19:02:09][Inf][General] HudTabs::fillMusicTab(HudTabs)
[11/25/2008 19:02:09][Inf][General] TabControl::getTabWithName(HudTabs, music)
[11/25/2008 19:02:09][Inf][General] TabControl::getTabIndexWithName(HudTabs, music)
[11/25/2008 19:02:09][Inf][General] MusicTabToggleSoundTxt::updateText(8969)
[11/25/2008 19:02:09][Inf][General] ratingControl::Initialize(8976, 5, 19 19, platform/client/buttons/star)
#6
11/25/2008 (7:20 pm)
But isn't this pretty much what trace( true ) does?

Maybe its worth extending trace to include times and arguments.
#7
11/25/2008 (8:33 pm)
Trace is great, and i generally include a trace of the current script call stack in error messages
(actually an extended version of getScopeName),
but i'd like to extend that to include the args.

eg

if (%error)
{
echo("oh nos! error X happened!" SPC callStackWithParams());
return;
}


i'd like to make it as easy as possible for the programmer to provide helpful debugging info in the log so that when an error occurs in the wild it's easier to track it down.

ie the difference between seeing this in your server log:
oh nos! error X happened!
and this:
oh nos! error X happened! foo(arg, arg) <- bar(arg, arg, arg) <- bim(arg, arg) <- bam(arg)


with stock TGE it's possible of course to implement the innermost part in the callstack there: foo(arg, arg),
but the reality is that programmers are lazy, and the easier it is to provide that deugging info, the more likely we are to do it.