Monday, November 09, 2009

Regex for Tracing

I've been working on SwinGame, and one of the tasks has been to add tracing code to the core to make it easier to debug problems. This involves adding TraceEnter and Trace exit calls to each procedure in the code.

To avoid having to do this by hand I am using a Regular Expression in TextMate to find procedures in the code, and replace them with a version that includes the injected trace enter and exit code. The regex I am using is shown below. It will work with a maximum depth of four begin/end groups... so its not completely automatic, but is a good start.

(function |procedure )(.*?)(;(\n|.)*?begin)((\n|(begin(\n|(begin(\n|(begin(\n|(begin(\n|.)*?end)|.)*?end)|.)*?end)|.)*?end)|.)*?)(\n end;)
This is then replaced using the following replace text. The $1 values are the groups that are matched in the regular expression. This enables me to place the procedure name, parameters and return type in the traced output ($2). It also ensures that all of the code from the program is output in the right spot.
$1$2$3
{$IFDEF TRACE}
TraceEnter('sgCamera', '$2', '');
{$ENDIF}
$5
{$IFDEF TRACE}
TraceExit('sgCamera', '$2', '');
{$ENDIF}
$15
This regular expression converts the following code...
function VectorFrom(x, y: Single): Vector; overload;
begin
result := VectorFrom(x, y, false);
end;
into this code which now has the tracing details added.
function VectorFrom(x, y: Single): Vector; overload;
begin
{$IFDEF TRACE}
TraceEnter('sgCamera', 'VectorFrom(x, y: Single): Vector', '');
{$ENDIF}

result := VectorFrom(x, y, false);

{$IFDEF TRACE}
TraceExit('sgCamera', 'VectorFrom(x, y: Single): Vector', '');
{$ENDIF}
end;
This should save me some time... though a real parser trace injector would be great!