Files
2025-09-29 00:52:08 +02:00

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
)
*/