//Mgo.bcpl	machine-independent stop, go, breakpoint stuff
//	Last edited: 1 May 1980

get "mdecl.d"
get "mcommon.d"

external [
// MASM
	DummyCall; @WssCSS

// MRGN
	AddToEveryTimeList

// MTXTBUF
	TxtBNewChar; InputTextBuffer

// MSYM
	EvalAText

// MMENU
	@WsMarkA; PrintActionTime

// MCMD
	StartCmdOverlay; StartLargeOverlay
	WnsCSS; SetAbortPure; @CmdAbortAct; ErrorAbort

// MINIT0
	MStatus

// xxACTIONS
	GoVec; DetachAct; ExitAct

// Machine dependent
	SetupIMA; OneStep; @CheckStopped; Stop; MStopped; DefaultGoMemory
	HaltFailed

//Defined here
	HaltWait; HaltWaitMenu; CollectAddr; HaltProc
	StartSetup; @QuitF; @CantContinue

// Defined here for ACTIONS
	SingleStepM; CallWithAddr; StartWithAddr; StartBigOvlWithAddr
	ProceedM; StartM
]

static [
	@QuitF; @CantContinue = 0
]

//In the action table to call SingleStepM.
let CallWithAddr(lvProc,MB,nil) be
	CollectAddr(DummyCall,lvProc,MB)


//In the action table to call StartM and OpcodeStep (D1)
and StartWithAddr(lvProc,MB,nil) be
	CollectAddr(StartCmdOverlay,lvProc,MB)


//**This has to be resident (calls StartLargeOverlay)
//In the action table to call SimGo (D1)
and StartBigOvlWithAddr(lvProc,MB,nil) be
	CollectAddr(StartLargeOverlay,lvProc,MB)


//CollectAddr collects an address argument from the command line and calls
//a procedure like DummyCall, StartCmdOverlay, or StartLargeOverlay.
//The first arg to the call is MB.  The next two args, omitted if nothing
//is on the command line, are AVec and MemX.  ErrorAbort if the input text
//is not an address.
and CollectAddr(Proc,lvCalled,MB) be
[	test InputTextBuffer!0 le 0
	ifso Proc(lvCalled,MB)
	ifnot
	[ let X,AVal = 1,vec size AVal/16
	  unless EvalAText(InputTextBuffer,lv X,AVal,false,
		DefaultGoMemory()) do ErrorAbort()
	  unless AVal>>AVal.TypeStorage eq MemTypeStorage do ErrorAbort()
	  Proc(lvCalled,MB,lv AVal>>AVal.Addr,AVal>>AVal.X)
	]
	TxtBNewChar(177B)	//Clear command line so ;G continues
]


and SingleStepM(MB,AVec,MemX; numargs NA) be
[	SetupIMA(false,AVec,MemX,NA,(NA ge 3 ? "Step at ","Next step at "),MB)
	QuitF = -1
	OneStep(GoVec>>Go.RunP); MStopped(false)
]


and StartM(MB,AVec,MemX; numargs NA) = valof
[	let Str = (MB & BottomButton) ne 0 ? "Proceed ","Go "
	SetupIMA(true,AVec,MemX,NA,(NA ge 3 ? Str,"Resume "),MB)
	OneStep(GoVec>>Go.RunP)
	MStatus>>MStatus.MachRunning = true
	resultis StartSetup(HaltWait)
]


and StartSetup(EveryTimeP,EveryTimeA) = valof
[	SetAbortPure(lv HaltProc,nil)
	QuitF = AddToEveryTimeList(EveryTimeP,EveryTimeA)
	resultis DetachMenu
]


//So that "n;P" will call SetupIMA with MB eq BottomButton
and ProceedM(MB,AVec,MemX; numargs NA) = valof
[	SetupIMA(true,AVec,MemX,NA,"Proceed ",BottomButton)
	OneStep(GoVec>>Go.RunP)
	MStatus>>MStatus.MachRunning = true
	resultis StartSetup(HaltWait)
]


and HaltWait(nil) be
[	if CheckStopped() then MStopped(true)
	PrintActionTime()
]


//This is used for keyboard halts to all the indefinitely computing
//go loops.
and HaltProc(nil,nil,nil) be
[	if not CheckStopped() then Stop()
	test CheckStopped() ne 0
	ifso
	[ WssCSS(", Aborted"); MStopped()
	]
	ifnot
	[ WssCSS(", Didn't halt"); HaltFailed()
	]
]


and HaltWaitMenu(nil,nil) be WsMarkA(CmdAbortAct)


and DetachMenu(S,nil) be
[	WsMarkA(CmdAbortAct); WsMarkA(DetachAct); WsMarkA(ExitAct)
]