{$MODESWITCH ADVANCEDRECORDS}
unit CallTracing;
{ --------------------------------------------------------------------------- }
INTERFACE
{ --------------------------------------------------------------------------- }
type
TROUTINE_LEVEL_RANGE = 0..511; { max call nesting }
TROUTINE_NAMES = record { prefix rn_ }
strict private
rn_index : int32; { also indent level }
rn_name : array[TROUTINE_LEVEL_RANGE] of pchar;
public
procedure rn_push(InProcName : pchar);
procedure rn_pop();
function rn_indent() : pchar;
end;
{ --------------------------------------------------------------------------- }
var
{ the variable name must be named CallStack because of the macros. it is }
{ possible to hide that fact by creating a macro to declare the variable }
CallStack : TROUTINE_NAMES; { !! global variable }
{ --------------------------------------------------------------------------- }
IMPLEMENTATION
{ --------------------------------------------------------------------------- }
const
CALL_LEVEL_INDENT = 3;
type
TSPACES_RANGE = low(TROUTINE_LEVEL_RANGE)..
CALL_LEVEL_INDENT * high(TROUTINE_LEVEL_RANGE);
{$WRITEABLECONST ON}
const
{ NOTE: the NULL field is to guarantee the array of spaces is always null }
{ terminated }
NTSPACES : record
SPACES : array[TSPACES_RANGE] of char;
NULL : DWORD;
end = (SPACES:' '; NULL:0);
{$WRITEABLECONST OFF}
{ --------------------------------------------------------------------------- }
procedure IndentLevel(InLevel : int32);
begin
{ use the array of spaces to output the indent }
if InLevel * CALL_LEVEL_INDENT < high(NTSPACES.SPACES) then
begin
NTSPACES.SPACES[InLevel * CALL_LEVEL_INDENT] := #0;
write(NTSPACES.SPACES);
NTSPACES.SPACES[InLevel * CALL_LEVEL_INDENT] := ' ';
exit;
end;
{ the indent level exceeds the maximum the code can handle, output tha }
{ maximum number of spaces (which is the most we can do) }
write(NTSPACES.SPACES);
end;
{ --------------------------------------------------------------------------- }
procedure TROUTINE_NAMES.rn_push(InProcName : pchar);
begin
rn_name[rn_index] := InProcName;
writeln;
IndentLevel(rn_index);
writeln(rn_index:1, ' >> ', InProcName);
inc(rn_index); { index of next available entry }
end;
{ --------------------------------------------------------------------------- }
function TROUTINE_NAMES.rn_indent() : pchar;
begin
IndentLevel(rn_index - 1);
result := pchar(@NTSPACES.NULL);
end;
{ --------------------------------------------------------------------------- }
procedure TROUTINE_NAMES.rn_pop();
begin
dec(rn_index);
if rn_index < low(TROUTINE_LEVEL_RANGE) then exit;
IndentLevel(rn_index);
writeln(rn_index:1, ' << ', rn_name[rn_index]);
writeln;
end;
{ --------------------------------------------------------------------------- }
procedure Init();
var
i : int32;
begin
{ one time initialization }
if NTSPACES.SPACES[high(NTSPACES.SPACES)] <> ' ' then
begin
for i := low(NTSPACES.SPACES) to high(NTSPACES.SPACES) do
begin
NTSPACES.SPACES[i] := ' ';
end;
end;
end;
{ --------------------------------------------------------------------------- }
initialization
Init();
end.
//
// end of file
// ----------------------------------------------------------------------------