// SwatStack.bcpl - code for stack manipulation
// Copyright Xerox Corporation 1979, 1981, 1982
// Last modified March 21, 1982 1:55 PM by Boggs
// All you do is just...08/10/73 (ALB)
get "Swat.decl"
external
[
// outgoing procedures
StackSwapIn; StackSysIn; StackSysOut
MapStack; Frame; PrintFrame; GetRetPC
// incoming procedures from Swat
VMFetch; ReportFail; AddrToSym; OpenCell
// incoming procedures from OS
Endofs; Gets; Puts; Wss; PutTemplate
// outgoing statics
openFrame
// incoming statics
dsp; stackDubious; xmFlag
]
static
[
openFrame // currently open frame
opfnum
fnp
]
//----------------------------------------------------------------------------
let StackSwapIn() be openFrame = VMFetch(userAC2)
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
and StackSysOut(sysOut) be Puts(sysOut, openFrame)
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
and StackSysIn(sysIn) be
//----------------------------------------------------------------------------
openFrame = Endofs(sysIn)? VMFetch(userAC2), Gets(sysIn)
//----------------------------------------------------------------------------
and Frame(n) be
//----------------------------------------------------------------------------
// Dump the parameters in the nth frame, and set $
[
MapStack(n, Frame1, nil, VMFetch(userAC2))
if opfnum ne n then ReportFail("Frame not found")
for i = 1 to fnp do
PutTemplate(dsp, "$UO: $UO*N", openFrame+3+i, VMFetch(openFrame+3+i))
OpenCell(openFrame+3+fnp)
]
//----------------------------------------------------------------------------
and GetRetPC(n) = valof
//----------------------------------------------------------------------------
// Get the pc at which we jump back into the nth frame.
// Used by the "index$↑P" command.
[
MapStack(n, Frame1, nil, VMFetch(userAC2))
if opfnum ne n then ReportFail("Frame not found")
resultis VMFetch(openFrame+1) +1
]
//----------------------------------------------------------------------------
and Frame1(level, frame, numArgs, nil) be
//----------------------------------------------------------------------------
[ openFrame, opfnum, fnp = frame, level, numArgs ]
//----------------------------------------------------------------------------
and PrintFrame(level, frame, numArgs, stream) be
//----------------------------------------------------------------------------
[
let bank = 0
let retAddr = VMFetch(frame eq VMFetch(userAC2)? userPC, frame+1)
if xmFlag then
[
let retInst = VMFetch(retAddr+1)
if (retInst & xJmpInstMask) eq xJmp0 & retAddr eq (frame+xJmp-1) then
[
retAddr = VMFetch(retAddr+2) //i.e. xPC in extended frame
bank = retInst & xJmpBankMask
]
]
if level ge 1 then stackDubious = false // used in SwatResident.bcpl
PutTemplate(stream, "$2O $6UO $5UO $1O ",
level, frame, VMFetch(frame)-frame, bank)
AddrToSym(stream, retAddr, bank)
Wss(stream, "--(")
for i = 1 to numArgs do PutTemplate(stream, "$UO$S",
VMFetch(frame+3+i), (numArgs eq i? "", ", "))
Wss(stream, ")*N")
]
//----------------------------------------------------------------------------
and MapStack(lastLevel, proc, arg, root) be
//----------------------------------------------------------------------------
[
let thisLevel, thisFrame = 0, root
until thisLevel gr lastLevel do
[
let prevFrame = VMFetch(thisFrame)
let retAddr = VMFetch(prevFrame+1)
let numArgs = VMFetch(retAddr)
let prevFrameValid = valof
[
if (numArgs & 177700B) ne 0 then [ numArgs = 0; resultis false ]
if prevFrame eq 0 % prevFrame eq thisFrame %
prevFrame ugr 176777b % retAddr eq 0 resultis false
resultis true
]
proc(thisLevel, thisFrame, numArgs, arg)
unless prevFrameValid return
thisFrame = prevFrame
thisLevel = thisLevel +1
]
]