-- File: Dispatch.mesa edit by: -- Bruce October 21, 1980 12:46 PM -- Sandman July 30, 1980 9:47 AM DIRECTORY Actions USING [ AsciiDisplay, AsciiRead, AttachImage, AttachLoadState, CallInterpreter, CallNub, DisplayFrame, DisplayModule, DisplayStack, DoKill, DoProceed, DoQuit, FindVar, OctalRead, OctalWrite, PrintCoremap, SearchMode, SetOctalContext, SetProcessContext, StartUser, TeleDebug, TreeMode, UserScreen, WorryMode], Ascii USING [ControlC, ControlD, ControlN, ControlS, ControlT, DEL, ESC, SP], BP USING [ AttachCondition, AttachExpression, BreakAllEntries, BreakAllXits, BreakEntry, BreakExit, ClearAllBreaks, ClearAllEntries, ClearAllXits, ClearBreak, ClearCondition, ClearDefault, ClearEntryBreak, ClearEntryTrace, ClearExpression, ClearOctal, ClearXitBreak, ClearXitTrace, Conditionalize, Expressionalize, List, ListBreak, ListBreaks, OctalBreak, TraceAllEntries, TraceAllXits, TraceEntry, TraceExit], CommandList USING [Command, Error], Commands USING [ Command, Confirm, DispatchChar, Error, Execute, GetComment, GetString, GetTwoStrings, Login, ModuleBreak, Umbrella, WriteCommand, WriteError], DContext USING [ DisplayConfig, DisplayCurrent, ListConfigs, Reset, SetConfig, SetModule,SetRootConfig], DebugOps USING [ Abort, BBHandle, fileSW, InvalidateFileCache, Kill, Proceed, Quit, UserAborted], DOutput USING [Char, Decimal, EOL, Line, Text], DPsb USING [ DisplayProcess, DisplayQueue, DisplayReadyList, ListProcesses, ResetCache], DSyms USING [AttachSymbols], Dump USING [EvalStack], Frames USING [FlushFrameCache], Gf USING [DisplayGFT], Init USING [CoreSwap, FlushCaches, TopLevel], MachineDefs USING [CoPilot, FHandle, GFHandle], Nub USING [DoCommand], State USING [Get, GetGS, GSHandle, Handle, Pop, Push, top], String USING [AppendChar, LowerCase], TextSW USING [BlinkingCaret], UserInput USING [userAbort], TajoMisc USING [SetState]; Dispatch: PROGRAM IMPORTS Actions, BP, Commands, DContext, DebugOps, DOutput, DPsb, DSyms, Dump, Frames, Gf, Init, Nub, State, String, UserInput, TajoMisc, TextSW EXPORTS Commands = BEGIN OPEN Actions, Commands; Command: PUBLIC TYPE = CommandList.Command; Error: PUBLIC TYPE = CommandList.Error; GFHandle: TYPE = MachineDefs.GFHandle; FHandle: TYPE = MachineDefs.FHandle; data: State.GSHandle ← State.GetGS[]; CommandNotAllowed: PUBLIC SIGNAL = CODE; SmashedContext: ERROR = CODE; DoExp: PUBLIC PROC [param: DebugOps.BBHandle] = BEGIN IF param = NIL THEN RETURN; IF param.bt.bt = trace THEN { SendChars[SELECT param.bt.ex FROM entry => "DSP"L, exit => "DSR"L, ENDCASE => "DSV"L]; [] ← TajoMisc.SetState[on]}; IF param.exp # NIL THEN SendChars[param.exp]; END; SendChars: PROC [s: STRING] = BEGIN FOR i: CARDINAL IN [0..s.length) DO IF UserInput.userAbort THEN SIGNAL DebugOps.UserAborted; data.parse[s[i]]; ENDLOOP; END; Go: PUBLIC PROCEDURE [bb: DebugOps.BBHandle ← NIL] = BEGIN State.Push[]; data.inNub ← FALSE; IF data.StatePtr = NIL THEN data.initBCD ← TRUE; DContext.Reset[]; IF data.signal # LOOPHOLE[0] THEN Commands.Umbrella[ucs, 0]; DO Prompt[]; BEGIN ENABLE BEGIN DebugOps.Abort, ABORTED => CONTINUE; DebugOps.Kill => GOTO kill; DebugOps.Quit => IF data.inNub THEN {LeaveNub[]; CONTINUE} ELSE GOTO abort; DebugOps.Proceed => IF data.inNub THEN {LeaveNub[]; CONTINUE} ELSE EXIT; UNWIND => State.Pop[]; END; thisBreak ← bb; Commands.Umbrella[exp, bb ! ANY => {bb ← NIL; REJECT}]; bb ← NIL; [] ← TajoMisc.SetState[on]; Commands.Umbrella[notifier,NIL]; EXITS kill => BEGIN State.Pop[]; Init.CoreSwap[kill ! DebugOps.Abort => LOOP]; SIGNAL DebugOps.Abort; END; abort => BEGIN State.Pop[]; Init.CoreSwap[quit ! DebugOps.Abort => LOOP]; SIGNAL DebugOps.Abort; END; END; ENDLOOP; State.Pop[]; RETURN END; thisBreak: DebugOps.BBHandle; LeaveNub: PROC = {data.nubLevel ← data.nubLevel - 1; data.inNub ← FALSE}; DebuggingMode: PUBLIC PROC = BEGIN data.debugging ← ~data.debugging END; Invalidate: PROC = { Frames.FlushFrameCache[]; DPsb.ResetCache[]; Init.FlushCaches[flushSymbols]; DebugOps.InvalidateFileCache[]}; DisplayB: PROC [s: STRING] = { SELECT TRUE FROM s.length # 0 => {DOutput.EOL[]; BP.ListBreak[s]}; GetBreak[] => {DOutput.EOL[]; BP.List[thisBreak]}; ENDCASE}; ClearB: PROC [s: STRING] = { IF s.length # 0 THEN {BP.ClearBreak[s]; thisBreak ← NIL; RETURN}; IF GetBreak[] THEN {BP.ClearDefault[thisBreak]; thisBreak ← NIL}}; ClearC: PROC [s: STRING] = { IF s.length # 0 THEN {BP.ClearCondition[s]; RETURN}; IF GetBreak[] THEN BP.Conditionalize[thisBreak,NIL]}; ClearE: PROC [s: STRING] = { IF s.length # 0 THEN {BP.ClearExpression[s]; RETURN}; IF GetBreak[] THEN BP.Expressionalize[thisBreak,NIL]}; GetBreak: PROC RETURNS [BOOLEAN] = { IF thisBreak = NIL THEN {Commands.WriteError[notAtBreak, FALSE]; DOutput.EOL[]} ELSE {DOutput.Decimal[thisBreak.num]; DOutput.EOL[]}; RETURN[thisBreak # NIL]}; Prefix: TYPE = { ba, s, a, as, at, o, l, li, d, se, b, t, ta, top, cl, cla, cle, clx, c, re}; prefix: Prefix ← top; cs: STRING ← [4]; param: STRING; GetFrame: PROC [s: STRING] = {param ← s; IF s # NIL THEN Confirm[null, StartFrame]}; StartFrame: PROC = {StartUser[param]}; GetDebuggee: PROC [s: STRING] = {param ← s; IF s # NIL THEN Confirm[null, RemoteDebuggee]}; RemoteDebuggee: PROC = {TeleDebug[param]}; DispatchChar: PUBLIC PROCEDURE [char: CHARACTER] = BEGIN OPEN Ascii, Commands; c: CHARACTER; i: [0..4]; IF data.tool THEN RETURN; IF prefix = top THEN IF char = ESC THEN BEGIN FOR i IN [0..cs.length) DO DispatchChar[cs[i]] ENDLOOP; RETURN END ELSE cs.length ← 0; String.AppendChar[cs, char]; SELECT (c←String.LowerCase[char]) FROM 'a => SELECT prefix FROM cl => BEGIN prefix ← cla; WriteCommand[all]; DOutput.Char[' ]; END; b => BEGIN prefix ← ba; WriteCommand[all]; DOutput.Char[' ]; END; t => BEGIN prefix ← ta; WriteCommand[all]; DOutput.Char[' ]; END; top => BEGIN prefix ← a; WriteCommand[a];END; ENDCASE => GOTO what; 'b => SELECT prefix FROM d => GetString[[sId: bbNum, prompt: bbNum], DisplayB, break]; li => Confirm[breaks, BP.ListBreaks]; cl => GetString[[sId: bbNum, prompt: bbNum], ClearB, break]; cla => Confirm[breaks, BP.ClearAllBreaks]; cle => GetString[[sId: proc], BP.ClearEntryBreak, breakProc]; clx => GetString[[sId: proc], BP.ClearXitBreak, breakProc]; top => BEGIN prefix ← b; WriteCommand[break]; DOutput.Char[SP] END; ENDCASE => GOTO what; 'c => SELECT prefix FROM at => GetTwoStrings[[sId: bbNum, prompt: bbNum, resetPrompt: FALSE], [sId: exp, prompt: condition, resetPrompt: FALSE, atom: FALSE], BP.AttachCondition, Condition]; cl => GetString[[sId: bbNum, prompt: bbNum], ClearC, Condition]; d => Execute[config, DContext.DisplayConfig]; li => Confirm[configs, DContext.ListConfigs]; o => GetTwoStrings[[sId: frame, resetPrompt: FALSE], [ prompt: bytePC, sId: pc, resetPrompt: FALSE], BP.ClearOctal, clearGlobal]; se => GetString[[sId: config], DContext.SetConfig, config]; top => BEGIN prefix ← c; WriteCommand[c]; END; ENDCASE => GOTO what; 'd => SELECT prefix FROM as => GetTwoStrings[[sId: num1,resetPrompt: FALSE], [ sId: num2, prompt: n10, resetPrompt: FALSE], AsciiDisplay, display]; top => {WriteCommand[display]; DOutput.Char[SP]; prefix ← d}; ENDCASE => GOTO what; 'e => SELECT prefix FROM d => Execute[evalStack, Dump.EvalStack]; s => BEGIN WriteCommand[set]; DOutput.Char[SP]; prefix ← se END; b => GetString[[sId: proc], BP.BreakEntry, entryProc]; ba => ModuleBreak[BP.BreakAllEntries, entriesMod]; t => GetString[[sId: proc], BP.TraceEntry, entryProc]; ta => ModuleBreak[BP.TraceAllEntries, entriesMod]; cl => BEGIN WriteCommand[entry]; DOutput.Char[SP]; prefix ← cle END; cla => GetString[[sId: module], BP.ClearAllEntries, entriesMod]; ENDCASE => GOTO what; 'f => SELECT prefix FROM d => GetString[[sId: frame, resetPrompt: FALSE], DisplayFrame, frame]; top => GetString[[sId: var], FindVar, find]; ENDCASE => GOTO what; 'g => SELECT prefix FROM d => Execute[gft, Gf.DisplayGFT]; ENDCASE => GOTO what; 'i => SELECT prefix FROM at => IF MachineDefs.CoPilot THEN GOTO what ELSE GetString[[sId: image], Actions.AttachImage, image]; l => BEGIN prefix ← li; WriteCommand[list]; DOutput.Char[SP]; END; ENDCASE => GOTO what; 'k => SELECT prefix FROM at => GetTwoStrings[[sId: bbNum, prompt: bbNum, resetPrompt: FALSE], [sId: exp, prompt: expression, resetPrompt: FALSE, atom: FALSE], BP.AttachExpression, Exp]; cl => GetString[[sId: bbNum, prompt: bbNum], ClearE, Exp]; top => Confirm[kill, DoKill]; ENDCASE => GOTO what; 'l => SELECT prefix FROM c => BEGIN prefix ← cl; WriteCommand[clear]; DOutput.Char[SP]; END; at => IF MachineDefs.CoPilot THEN GOTO what ELSE GetString[[sId: image], Actions.AttachLoadState, loadstate]; top => BEGIN prefix ← l; WriteCommand[l]; END; ENDCASE => GOTO what; 'm => SELECT prefix FROM d => GetString[ [sId: module, resetPrompt: FALSE], DisplayModule, module]; se => GetString[[sId: module], DContext.SetModule, moduleCtx]; re => GetString[[sId: temp1, resetPrompt: FALSE], GetDebuggee, remote]; ENDCASE => GOTO what; 'o => SELECT prefix FROM c => IF MachineDefs.CoPilot THEN GOTO what ELSE Confirm[coremap, PrintCoremap]; l => Commands.Login[]; se => GetString[[sId: frame], SetOctalContext, octalCtx]; top => {prefix ← o; WriteCommand[octal]; DOutput.Char[SP]}; ENDCASE => GOTO what; 'p => SELECT prefix FROM d => GetString[ [sId: process, resetPrompt: FALSE], DPsb.DisplayProcess, process]; li => Confirm[processes, DPsb.ListProcesses]; se => GetString[[sId: process], SetProcessContext, processCtx]; top => Confirm[proceed, DoProceed]; ENDCASE => GOTO what; 'q => SELECT prefix FROM d => GetString[ [sId: queue, resetPrompt: FALSE], DPsb.DisplayQueue, queue]; top => Confirm[quit, DoQuit]; ENDCASE => GOTO what; 'r => SELECT prefix FROM as => GetTwoStrings[[sId: num1,resetPrompt: FALSE], [ sId: num2, prompt: n10, resetPrompt: FALSE], AsciiRead, read]; d => Execute[readyList, DPsb.DisplayReadyList, FALSE]; o => GetTwoStrings[[sId: num1, resetPrompt: FALSE], [ prompt: n10, sId: num2, resetPrompt: FALSE], OctalRead, read]; se => GetString[[sId: rconfig], DContext.SetRootConfig, rootCtx]; top => {prefix ← re; WriteCommand[re]}; ENDCASE => GOTO what; 's => SELECT prefix FROM d => Execute[stack, DisplayStack, FALSE]; o => GetTwoStrings[[sId: frame, resetPrompt: FALSE], [sId: pc, prompt: bytePC, resetPrompt: FALSE], BP.OctalBreak, breakGlobal]; a => BEGIN prefix ← as; WriteCommand[ascii]; DOutput.Char[SP] END; at => GetTwoStrings[ [prompt: symbols, sId: frame, resetPrompt: FALSE], [ sId:file, prompt:name, resetPrompt:FALSE], DSyms.AttachSymbols]; re => Confirm[reset, DContext.Reset]; top => BEGIN prefix ← s; WriteCommand[s]; END; ENDCASE => GOTO what; 't => SELECT prefix FROM top => BEGIN prefix ← t; WriteCommand[trace]; DOutput.Char[SP] END; cla => Confirm[traces, BP.ClearAllBreaks]; cle => GetString[[sId: proc], BP.ClearEntryTrace, traceProc]; clx => GetString[[sId: proc], BP.ClearXitTrace, traceProc]; s => GetString[[sId: frame, resetPrompt: FALSE], GetFrame, start]; a => BEGIN prefix ← at; WriteCommand[attach]; DOutput.Char[SP] END; ENDCASE => GOTO what; 'u => SELECT prefix FROM c => Execute[current, DContext.DisplayCurrent]; top => Confirm[userscreen, UserScreen]; ENDCASE => GOTO what; 'w => SELECT prefix FROM o => GetTwoStrings[[sId: num1, resetPrompt: FALSE], [ prompt: gets, sId: num2, resetPrompt: FALSE, colon: FALSE], OctalWrite, write]; top => BEGIN WriteCommand[worry]; Confirm[IF data.worryBreaks THEN off ELSE on, WorryMode]; END; ENDCASE => GOTO what; 'x => SELECT prefix FROM b => GetString[[sId: proc], BP.BreakExit, xitProc]; ba => ModuleBreak[BP.BreakAllXits, xitsMod]; t => GetString[[sId: proc], BP.TraceExit, xitProc]; ta => ModuleBreak[BP.TraceAllXits, xitsMod]; cl => BEGIN prefix ← clx; WriteCommand[xit]; DOutput.Char[SP]; END; cla => GetString[[sId:module], BP.ClearAllXits, xitsMod]; ENDCASE => GOTO what; ENDCASE => SELECT TRUE FROM prefix = top => SELECT char FROM ControlC => { WriteCommand[check]; Confirm[IF data.debugging THEN off ELSE on, DebuggingMode]}; ControlD => Confirm[debug, CallNub]; ControlN => Confirm[spare2, Invalidate]; ControlS => BEGIN WriteCommand[IF data.search THEN callStack ELSE oneFrame]; Confirm[null, SearchMode]; END; ControlT => BEGIN WriteCommand[treePrinting]; Confirm[IF data.tree THEN off ELSE on, TreeMode]; END; SP => CallInterpreter[TRUE]; '- => GetComment[TRUE]; '? => UnknownCommand[firstCommand, kill]; ENDCASE => GOTO what; char = '? => SELECT prefix FROM ba,ta => UnknownCommand[entriesMod, xitsMod]; re => UnknownCommand[remote, reset]; s => UnknownCommand[start, set]; a => UnknownCommand[ascii, attach]; as => UnknownCommand[adisplay, read]; at => IF MachineDefs.CoPilot THEN UnknownCommand[Symbols, Exp] ELSE UnknownCommand[image, loadstate]; o => UnknownCommand[read, clearGlobal]; l => UnknownCommand[login, list]; li => UnknownCommand[configs, breaks]; d => UnknownCommand[module, config]; se => UnknownCommand[config, rootCtx]; b,t => UnknownCommand[all, xitProc]; c => UnknownCommand[clear, IF MachineDefs.CoPilot THEN current ELSE coremap]; cl => UnknownCommand[entry, all]; cla => UnknownCommand[breaks, xitsMod]; cle => UnknownCommand[breakProc, traceProc]; clx => UnknownCommand[breakProc, traceProc]; ENDCASE => UnknownCommand[clear, current]; ENDCASE => GOTO what; RETURN EXITS what => UnknownChar[char]; END; UnknownCommand: PROCEDURE [first, last: Command] = BEGIN OPEN DOutput; i: Command; Line[" ?"L]; Text["Your options are: "L]; FOR i IN Command[first..last) DO WriteCommand[i]; Text[", "L]; ENDLOOP; WriteCommand[last]; EOL[]; Prompt[]; RETURN END; UnknownChar: PROCEDURE [char: CHARACTER] = BEGIN OPEN DOutput; IF char = Ascii.DEL THEN WriteCommand[del] ELSE {Char[char]; Char['?]}; Prompt[]; RETURN END; Prompt: PUBLIC PROCEDURE= BEGIN inNub: BOOLEAN ← data.inNub; level: CARDINAL ← IF inNub THEN data.nubLevel ELSE data.level; h: State.Handle ← State.Get[]; data.resetPrompt ← data.resetParse ← TRUE; DOutput.EOL[]; THROUGH [1..level] DO DOutput.Char[IF inNub THEN '/ ELSE '>] ENDLOOP; data.parse ← IF inNub THEN Nub.DoCommand ELSE DispatchChar; TextSW.BlinkingCaret[DebugOps.fileSW, on]; prefix ← top; Init.TopLevel[]; h.interpretContext ← SELECT h.howSet FROM none => NIL, local => h.lContext, psb => h.lContext, global => h.gContext, state => h.lContext, ENDCASE => ERROR SmashedContext; END; END.