153 lines
4.0 KiB
Plaintext
Executable File
153 lines
4.0 KiB
Plaintext
Executable File
|
|
-- RsDebugStack.ms
|
|
-- Functions for extracting useful info from the Maxscript debug-stack text-stream
|
|
--
|
|
-- Neal D Corbett (R* Leeds, 04/2014)
|
|
|
|
global gRsDebugStack
|
|
struct RsDebugStack
|
|
(
|
|
--------------------------------------------------------------------------
|
|
-- GetStackInfo:
|
|
-- Returns list of info-items per recursion-stack level
|
|
-- Or info for a specific level if 'Level' is set:
|
|
--------------------------------------------------------------------------
|
|
fn GetStackInfo Level: GetLocals:True =
|
|
(
|
|
local StackItems = #()
|
|
local AllLevels = (not isKindOf Level Number)
|
|
|
|
struct RsDebugStackLevel
|
|
(
|
|
CallLine,
|
|
StackString
|
|
)
|
|
|
|
-- Get stack-text as stream:
|
|
local StackStream = StringStream ""
|
|
Stack ShowLocals:GetLocals To:StackStream
|
|
|
|
-- Seek to line in stack-level text referring to this current function:
|
|
Seek StackStream 0
|
|
skipToString StackStream "GetStackInfo();"
|
|
|
|
-- Find stack-level header referring to function that called 'GetStackInfo':
|
|
skipToString StackStream "[stack level:"
|
|
|
|
if (eof StackStream) do (return #())
|
|
skipToNextLine StackStream
|
|
|
|
local StackLevel = 0
|
|
|
|
-- Parse stack-text:
|
|
while (not eof StackStream) and (AllLevels or (StackLevel < Level)) do
|
|
(
|
|
StackLevel += 1
|
|
|
|
if AllLevels or (StackLevel == Level) do
|
|
(
|
|
-- Collect text up to next dividing-line, referring to current stack-level:
|
|
local LevelString = StringStream ""
|
|
local ThisLine = (readLine StackStream)
|
|
while (not eof StackStream) and (not matchPattern ThisLine pattern:"*\t------------------------------------------------------") do
|
|
(
|
|
format "%\n" ThisLine To:LevelString
|
|
ThisLine = (readLine StackStream)
|
|
)
|
|
|
|
-- Parse the 'LevelString' stream
|
|
-- (unless we've reached the bottom of stack-text)
|
|
if (not eof StackStream) do
|
|
(
|
|
-- Rewind 'LevelString' stream back to beginning:
|
|
seek LevelString 0
|
|
|
|
-- Get function-name for this stack-level:
|
|
skipToString LevelString "\t"
|
|
CallLine = readDelimitedString LevelString "\n"
|
|
|
|
-- Add parsed data to return-array:
|
|
local NewItem = (DataPair CallLine:CallLine StackString:(LevelString as string))
|
|
append StackItems NewItem
|
|
)
|
|
)
|
|
|
|
-- Find next stack-level header:
|
|
if (not eof StackStream) do
|
|
(
|
|
skipToString StackStream "[stack level:"
|
|
skipToNextLine StackStream
|
|
)
|
|
)
|
|
|
|
-- Return items for all stack-levels, or for a specific stack-level:
|
|
if AllLevels then
|
|
(
|
|
return StackItems
|
|
)
|
|
else
|
|
(
|
|
return StackItems[1]
|
|
)
|
|
),
|
|
|
|
------------------------------------------------------------------------------
|
|
-- GetCallLine:
|
|
-- Returns function/script/line that called 'GetCallLine':
|
|
------------------------------------------------------------------------------
|
|
fn GetCallLine Default:"undefined" Level:1 =
|
|
(
|
|
-- No need to get local values:
|
|
local Caller = GetStackInfo GetLocals:False Level:Level
|
|
|
|
if (Caller == undefined) then
|
|
(
|
|
return Default
|
|
)
|
|
else
|
|
(
|
|
return Caller.CallLine
|
|
)
|
|
),
|
|
|
|
--------------------------------------------------------------------------
|
|
-- PrintLine:
|
|
-- Returns string describing the function/line/script that
|
|
-- that 'GetThisLine' is called from:
|
|
--------------------------------------------------------------------------
|
|
fn GetThisLine Level:3 =
|
|
(
|
|
return (GetCallLine Level:Level)
|
|
),
|
|
|
|
--------------------------------------------------------------------------
|
|
-- GetCallerLine:
|
|
-- Returns string describing the function/line/script that
|
|
-- calling function was called from, if 'DebugActive' is true.
|
|
--------------------------------------------------------------------------
|
|
fn GetCallerLine =
|
|
(
|
|
return (GetThisLine Level:5)
|
|
)
|
|
)
|
|
gRsDebugStack = RsDebugStack()
|
|
|
|
|
|
-- HERE IS A TEST:
|
|
/*
|
|
(
|
|
fn TestB =
|
|
(
|
|
print (gRsDebugStack.GetThisLine())
|
|
print (gRsDebugStack.GetCallerLine())
|
|
)
|
|
|
|
fn TestA =
|
|
(
|
|
TestB()
|
|
)
|
|
|
|
TestA()
|
|
OK
|
|
)
|
|
*/ |