2005/5/10

     
 

Debugging CfgScript

artefaktur

| Introduction | Start | acdkcfgscript | Language | Library | Embedding | CfgScript IDE | Debugging | Templates | Samples | Wish List |

How to debug a CfgScript.



Content of this chapter:

   Using the CfgScript debugger
     (c)ontinue
     (n)next
     (s)tep
     (q)uit
     brf (break at function)
     Set breakpoint at source line
     Set breakpoint at exception
     bt (Print BackTrace)
     (l)ist
     df or dumpframe
     de or dumpenv
     trace on/off
     (p)rint
     (i)nput
   Control debugger from source
     __script.breakToDebug()
     __script.traceOn()/__script.traceOff()
     __script.getScriptBackTrace()
   Error situation in Script
     What happens on errors
     Handle interpreter errors with code
   Unittests



 Using the CfgScript debugger


Using CfgScript interpreter in debugging mode just start the acdkcfgscript interpreter with the -csfdebug option.


0:
1:
! int i = 0;
> 
In the debugger the statement, which will executed next will marked with !.
Type ? at the prompt and you will receive a short help:


Debugging commands:
running:
c|continue           continue running
n|next               execute next line
s|step               next statement (step into functions)
r|return             run until return
q|quit               quit debugging/interpreter

Breakpoints:
br[f|l|e] <cmd> [<substr>] break at function, line or exception
    cmd: new|list|delete

View Data:
bt                   print backtrace
l|list               view source
df|dumpframe [frame] dump current scope or scope of frame number
de|dumpenv           dump current environment
trace [on|off]       activate or deactivate tracing

view/modify:
p|print <expr>       print expression
i|input              interactive mode

(Please refer to the CfgScript handbook for more information)

> 


 (c)ontinue

When break into the debugger with c the program will continue running until next breakpoint.

 (n)next

When break into the debugger with n will execute the script until next statement will be reached. This command will not step into function calls or block statements.

 (s)tep

When break into the debugger with s will execute the script until next statement will be reached. This command will step into function calls of CfgScript class methods.

 (q)uit

When break into the debugger with q will stop the execution the script and quits.

 brf (break at function)

With the brf command a breakpoint can be list, set or remove at a method of a CfgScript class.
With brf new a new breakpoint can be inserted.

The argument is simply a substring of the method signature.
  • foo( stops at any CfgScript method named foo
  • MyClass. stops at any method of the CfgScript class MyClass
  • MyClass.foo( stops at any MyClass method named foo
  • MyClass.foo() stops at the MyClass foo method, which has no arguments.
  • MyClass stops at any CfgScript method, either owned by MyClass or has MyClass as return value or parameter.
To delete a breakpoint enter for example:
brf delete foo(
If no argument at brf delete is given, all breakpoints will be deleted.

 Set breakpoint at source line

With brl it is possible to insert a break point at a source line. brl has the same commands as brf, but the argument will be parsed following way:
  • <number> it will break at source line in any source
  • <sourcefile>:<number> will break at line of given csf source. The source file must only a substring of the fully qualified source file name.

 Set breakpoint at exception

With bre it is possible to insert a break point just before an exception will be thrown. brl has the same commands as brf.
If the optional argument is not given (in case bre new) the interpreter will break to debugger if any exception will be thrown.
Otherwise the argument will check if it is a substring of the class name (for example "acdk/lang/IndexOutOfBoundsException") of the thrown exception.

 bt (Print BackTrace)

Print the current stack backtrace.
The current stack frame is at top.

> bt
cfg/csf/tests/8_misc/DebuggingTest.csf(14):     __script.traceOff();
static  void DebuggingTestClass.foo()
cfg/csf/tests/8_misc/DebuggingTest.csf(20):     foo();
static  void DebuggingTestClass.baz(int i)
cfg/csf/tests/8_misc/DebuggingTest.csf(26):     baz(i);
static  void DebuggingTestClass.bar(int i)
cfg/csf/tests/8_misc/DebuggingTest.csf(38): DebuggingTestClass.bar(3);

See also  __script.getScriptBackTrace().

 (l)ist

View the source at the current position.
The possition of the next executed statement will be marked with a !.

> vs
8:   {
9:     int i = 42;
10:     String s = "asdf";
11:     out.println(__script.getScriptBackTrace());
12:     __script.breakToDebug();
! __script.traceOff();
14: i = i + 10;
15: out.println("After debug");
16: }
17: static void baz(int i)

 df or dumpframe

Dump all variables in current stack frame.
Optional the frame number can given with integer argument.

 de or dumpenv

Dump all variables, visible from current point.

 trace on/off

With trace on all code lines are printed, which are executed.

See also  __script.traceOn()/__script.traceOff().

 (p)rint

The print command expects an argument, which should be an CfgScript expression.
The result of this expression will be printed.


> print 42 * 3
126

 (i)nput

With i code can be inserted and executed.
Finish code input with a input line with single . (point).
After finish the input the source code, it will be executed in a nested scope.


0:
! __script.traceOn();
> i
enter code and end it with a single . in the line
out.println("Hello");
. 

Hello
>

 Control debugger from source

 __script.breakToDebug()

Insert the __script.breakToDebug(); statement in our code. When executed the interpreter breaks to the debugger.

 __script.traceOn()/__script.traceOff()

With the __script.traceOn(); statement each line will be printed to standard out before executed.
With __script.traceOff(); the trace will be switched off.

 __script.getScriptBackTrace()

The __script.getScriptBackTrace(); statement gives you a textual representation of the the current call stack.


out.println(__script.getScriptBackTrace());

 Error situation in Script


 What happens on errors

Whenever an error happens in the Script and the script terminates because either a unhandled thrown exception or a syntax/semantic error the stack trace of the script will be dumped.

Sample output:
507$/artefaktur/acdk/acdk_core>../bin/acdkcfgscript_d.exe cfg/csf/tests/8_misc/20_ScriptBackTrace.csf 
unhandled exception:
don't call this, Go Away!
In:
c:\d\artefaktur\acdk\acdk_core\cfg\csf\tests\8_misc\TestIncludeBackTrace.csf(7):     throw new Exception("don't call this, Go Away!");
static  void IncludedClass.foo()
c:\d\artefaktur\acdk\acdk_core\cfg\csf\tests\8_misc\TestIncludeBackTrace.csf(11):     foo();
static  void IncludedClass.bar(int i)
cfg/csf/tests/8_misc/20_ScriptBackTrace.csf(10):     IncludedClass.bar(42);
static  void AClass.foo()
cfg/csf/tests/8_misc/20_ScriptBackTrace.csf(18):     foo();
static  AClass AClass.bar(int i)
cfg/csf/tests/8_misc/20_ScriptBackTrace.csf(22): AClass.bar(2);


 Handle interpreter errors with code


If the CfgScript error encounter an error it throws an exception. Because the exception handling in CfgScript using C++ exceptions the interpreter thrown exceptions can also be handled inside the script.


/*
  first example try to use a variable, which is not
  not defined.
*/ 
try {
  new StringBuffer(this_variable_doesn_exists);
  out.println("TEST FAILED");
} catch (acdk.cfgscript.ScriptException ex) {
  out.println("Caught script error in script: " + ex.getMessage());
}
/*
  second example tries to invoke a method, which doesn't exists.
*/
try {
  num = 3;
  // try to call non existent method
  num.foobaz();
} catch (acdk.lang.NoSuchMethodException ex) {
  out.println("Caught script error in script: " + ex.getMessage());
}
/*
  it is also possibe - as long the curled brackets {} are balanced - 
  to handle really ugly syntax error
*/
try {
  num = 3;
  // syntax error
  if num = 3 then num = 4;
  p- alsjd8u usdyfiu]'lu1e // more garbage
} catch (acdk.cfgscript.ScriptException ex) {
  out.println("Caught script error in script: " + ex.getMessage());
}

 Unittests

CfgScript files can also be used as plugins for the  ACDK Unit Tests framework.
Please refer to  Using CfgScript as Unit Tests.