-- File: CommandActions.mesa edit by: -- Mark Apr 16, 1980 7:41 PM -- Bruce October 11, 1980 2:24 PM -- Johnsson July 16, 1980 8:23 AM DIRECTORY Actions USING [DumpFrame], Ascii USING [BS, ControlA, ControlH, ControlQ, ControlV, ControlW, CR, DEL, ESC, SP], ComData USING [typeCARDINAL, typeINT], CommandList USING [Command, Error], Commands USING [Command, CommandRec, Prompt, TermProc], CommandTable USING [CSRptr], CompilerUtil USING [error, LockTableSegment, UnlockTableSegment], DContext USING [SetOctal, SetProcess], DebugFormat USING [LongSubStringDescriptor], DebugOps USING [ fileSW, Foo, FooProc, Interpret, InvalidCharacter, InvalidNumber, Kill, LongREAD, ParseError, Proceed, Quit, ShortREAD, ShortWRITE, StringExpToOctal, SyntaxError], DI USING [Error, GetValue, MakeLongType, Number, NumberType, SetDefaultRadix, Words], DOutput USING [Char, EOL, Line, Octal, LongSubString, Text], Dump USING [Char], Event USING [Notify, Vetoed], Gf USING [Name], Init USING [CheckSymTabLength, CoreSwap], MachineDefs USING [FHandle, GFHandle, StartDP], SDDefs USING [sAlternateBreak, sBreak, SD], State USING [Get, GetGS, GetString, GSHandle, SetParse, SetString, strings, WritePrompt], Storage USING [ExpandString, String], String USING [ AppendChar, AppendOctal, InvalidNumber, StringToNumber, StringToLongNumber], Table USING [Overflow], TajoUtility USING [CheckVeto], TextSW USING [BlinkingCaret], UserInput USING [ResetUserAbort, userAbort]; CommandActions: PROGRAM IMPORTS Actions, com: ComData, Commands, CompilerUtil, DContext, DebugOps, DI, DOutput, Dump, Event, Gf, Init, State, Storage, String, Table, TajoUtility, TextSW, UserInput EXPORTS Actions, Commands, DebugOps = BEGIN OPEN Commands; Command: PUBLIC TYPE = CommandList.Command; Error: PUBLIC TYPE = CommandList.Error; GFHandle: TYPE = MachineDefs.GFHandle; FHandle: TYPE = MachineDefs.FHandle; data: State.GSHandle _ State.GetGS[]; WriteCommand: PUBLIC PROCEDURE [code: Command] = BEGIN base: CommandTable.CSRptr _ CompilerUtil.LockTableSegment[CompilerUtil.error]; ss: DebugFormat.LongSubStringDescriptor; IF code = null THEN RETURN; ss _ [ base: @base[base.stringOffset], offset: base.CommandStrings[code].offset, length: base.CommandStrings[code].length]; DOutput.LongSubString[@ss]; CompilerUtil.UnlockTableSegment[CompilerUtil.error]; END; WriteError: PUBLIC PROCEDURE [error: Error, eof: BOOLEAN _ TRUE] = BEGIN base: CommandTable.CSRptr _ CompilerUtil.LockTableSegment[CompilerUtil.error]; ss: DebugFormat.LongSubStringDescriptor _ [ base: @base[base.stringOffset], offset: base.ErrorMessages[error].offset, length: base.ErrorMessages[error].length]; IF eof THEN DOutput.EOL[]; DOutput.LongSubString[@ss]; CompilerUtil.UnlockTableSegment[CompilerUtil.error]; END; GetConfirm: PROCEDURE [char: CHARACTER] = BEGIN IF UserInput.userAbort THEN BEGIN UserInput.ResetUserAbort[]; WriteError[aborted]; Commands.Prompt[]; END; SELECT char FROM 'y, 'Y, Ascii.CR => BEGIN DOutput.Char[Ascii.CR]; Call0[]; Commands.Prompt[]; END; Ascii.DEL => BEGIN WriteCommand[del]; Commands.Prompt[]; END; ENDCASE => BEGIN DOutput.Char['?]; State.SetParse[ThrowAway] END; RETURN END; Confirm: PUBLIC PROCEDURE [code: Command, call: PROCEDURE] = BEGIN WriteCommand[code]; WriteCommand[confirm]; data.call0 _ call; State.SetParse[GetConfirm]; RETURN END; ThrowAway: PROCEDURE [c: CHARACTER] = BEGIN SELECT c FROM Ascii.DEL => BEGIN WriteCommand[del]; Commands.Prompt[]; END; ENDCASE => DOutput.Char['?]; END; GetComment: PUBLIC PROC [printDash: BOOLEAN] = { IF printDash THEN DOutput.Char['-]; State.Get[].h.reentrantParse _ data.parse; GetLine[[sId: comment, colon: FALSE, resetPrompt: printDash, resetParse: printDash], Comment, comment ! UNWIND => NULL; ANY => {data.resetParse _ data.resetPrompt _ TRUE; REJECT}] }; ModuleBreak: PUBLIC PROC [proc: PROCEDURE [STRING,STRING], prompt: Command]= BEGIN WriteCommand[prompt]; data.call2 _ proc; GetText[[sId: module, resetPrompt: FALSE],GotBreakParam,IsTerm] END; invisible: BOOLEAN; Login: PUBLIC PROC = BEGIN WriteCommand[login]; GetString[[sId: user, resetPrompt: FALSE],GotUser,user]; END; GetLine: PUBLIC PROC [com: CommandRec, call: PROCEDURE [STRING], prompt: Command _ null] = BEGIN WriteCommand[prompt]; GetText[com,call,IsCR] END; GetString: PUBLIC PROC [com: CommandRec, call: PROCEDURE [STRING], prompt: Command _ null] = BEGIN WriteCommand[prompt]; GetText[com,call,IF com.atom THEN IsAtom ELSE IsCR] END; GetText: PUBLIC PROCEDURE [ com: CommandRec, call: PROCEDURE [STRING], term: TermProc] = BEGIN s: STRING _ State.GetString[(data.currentId _ com.sId)]; IF s = NIL THEN {s _ Storage.String[10]; State.SetString[com.sId,s]}; WriteCommand[com.prompt]; IF com.colon THEN DOutput.Text[": "L]; data.resetPrompt _ com.resetPrompt; data.resetParse _ com.resetParse; data.call1 _ call; data.term _ term; data.firstChar _ TRUE; data.currentString _ s; invisible _ FALSE; State.SetParse[CollectString]; END; GotBreakParam: PROC [s: STRING] = BEGIN IF data.cr THEN {data.call2[s,NIL]; data.resetPrompt _ TRUE} ELSE {data.s1 _ s; GetString[[prompt: expression, sId: exp], GotBoth]}; END; ready, owrite: BOOLEAN _ FALSE; GetTwoStrings: PUBLIC PROC [ com1, com2: CommandRec, proc: PROCEDURE[STRING, STRING], prompt: Command _ null] = BEGIN WriteCommand[prompt]; data.call2 _ proc; data.com2 _ com2; ready _ prompt = write; GetString[com1, GotOne]; END; GotUser: PROC [s: STRING] = BEGIN Event.Notify[setDefaults]; GetString[[sId: password, resetPrompt: FALSE], GotPassword, password]; invisible _ TRUE; END; GotOne: PROC [s: STRING] = { owrite _ ready; data.s1 _ s; GetString[data.com2, GotBoth]}; Write: PROC [val: STRING] = { lp: LONG POINTER _ LOOPHOLE[StringExpToLOctal[data.s1]]; IF val = NIL OR val.maxlength < 10 THEN BEGIN Storage.ExpandString[@val,10]; data.currentString _ val; State.strings[data.currentId] _ val; END; val.length _ 0; String.AppendOctal[val,IF data.inNub THEN lp^ ELSE DebugOps.LongREAD[lp]]; DOutput.Text[val]}; GotPassword: PROC [password: STRING] = BEGIN data.resetPrompt _ TRUE; invisible _ FALSE; Event.Notify[setDefaults]; END; GotBoth: PROC [s2: STRING] = BEGIN Call2[data.s1, s2]; data.resetPrompt _ TRUE; END; Append: PROCEDURE [s: STRING, c: CHARACTER] = BEGIN quoted: BOOLEAN _ s.length # 0 AND s[s.length-1] = Ascii.ControlV; IF ~quoted AND data.term[c] THEN {Call1[s]; State.WritePrompt[]} ELSE BEGIN IF quoted THEN s.length _ s.length - 1; IF s = NIL OR s.length = s.maxlength THEN BEGIN Storage.ExpandString[@s,10]; data.currentString _ s; State.strings[data.currentId] _ s; END; String.AppendChar[s, c]; IF c # Ascii.ControlV THEN DOutput.Char[IF invisible THEN '* ELSE c]; END; RETURN END; ResetFirst: PROC RETURNS [first: BOOLEAN] = {first _ data.firstChar; IF first THEN data.firstChar _ FALSE}; CollectString: PROCEDURE [char: CHARACTER] = BEGIN OPEN Ascii; s: STRING _ data.currentString; SELECT char FROM ESC => SELECT TRUE FROM ~ResetFirst[] => Append[s, char]; owrite => { Write[s ! UNWIND => owrite _ ready _ FALSE]; owrite _ ready _ FALSE}; invisible => THROUGH [0..s.length) DO DOutput.Char['*] ENDLOOP ENDCASE => DOutput.Text[s]; DEL => BEGIN WriteCommand[del]; invisible _ FALSE; IF data.resetParse THEN Commands.Prompt[] ELSE OtherPrompt[]; END; ControlA, ControlH, BS => BEGIN IF s.length = 0 THEN RETURN; s.length _ s.length-1; DOutput.Char[char]; END; ControlW, ControlQ => BEGIN state: {ti, v, li} _ ti; i: CARDINAL; FOR i DECREASING IN [0..s.length) DO SELECT s[i] FROM IN ['A..'Z], IN ['a..'z], IN ['0..'9] => IF state = ti THEN state _ v; ENDCASE => IF state = v THEN state _ li; IF state = li THEN GOTO Done; DOutput.Char[BS]; REPEAT Done => s.length _ i+1; FINISHED => s.length _ 0; ENDLOOP; END; ENDCASE => BEGIN IF ResetFirst[] THEN s.length _ 0; Append[s,char]; END; RETURN END; Execute: PUBLIC PROC [ code: Command, call: PROC, resetPrompt: BOOLEAN _ TRUE] = BEGIN TextSW.BlinkingCaret[DebugOps.fileSW, off]; WriteCommand[code]; data.resetPrompt _ resetPrompt; call[]; State.WritePrompt[]; END; Call0: PROC = BEGIN TextSW.BlinkingCaret[DebugOps.fileSW, off]; data.call0[ ! Table.Overflow => {Init.CheckSymTabLength[]; RETRY}] END; Call1: PROC [s1: STRING] = BEGIN TextSW.BlinkingCaret[DebugOps.fileSW, off]; data.call1[s1 ! Table.Overflow => {Init.CheckSymTabLength[]; RETRY}] END; Call2: PROC [s1: STRING, s2: STRING] = BEGIN TextSW.BlinkingCaret[DebugOps.fileSW, off]; data.call2[s1, s2 ! Table.Overflow => {Init.CheckSymTabLength[]; RETRY}] END; IsAtom: PUBLIC PROCEDURE [c: CHARACTER] RETURNS [BOOLEAN] = BEGIN RETURN[c = Ascii.SP OR c = Ascii.CR] END; IsCR: PUBLIC PROCEDURE [c: CHARACTER] RETURNS [BOOLEAN] = BEGIN RETURN[c = Ascii.CR] END; IsTerm: PROC [c: CHARACTER] RETURNS [BOOLEAN] = BEGIN RETURN [(data.cr _ c = Ascii.CR) OR c = Ascii.SP] END; -- Utilities Numeric: PUBLIC PROC [s: STRING] RETURNS [BOOLEAN] = { IF s = NIL OR s.length = 0 THEN RETURN[FALSE]; FOR i: CARDINAL IN [0..s.length) DO SELECT s[i] FROM IN ['0..'9] => NULL; '- => IF i # 0 OR s.length = 1 THEN RETURN[FALSE]; 'b,'B,'d,'D => IF s.length = 1 OR i # s.length-1 THEN RETURN[FALSE]; ENDCASE => RETURN[FALSE]; ENDLOOP; RETURN[TRUE]}; StringExpToNum: PUBLIC PROC [exp: STRING, radix: CARDINAL] RETURNS [u: UNSPECIFIED] = BEGIN OPEN DebugOps; Result: FooProc = BEGIN u _ ProcessNum[f, one].n.u END; IF Numeric[exp] THEN RETURN[String.StringToNumber[exp,radix ! String.InvalidNumber => ERROR DebugOps.InvalidNumber[NIL]]]; DI.SetDefaultRadix[radix]; Interpret[exp, Result, IF radix = 8 THEN com.typeCARDINAL ELSE com.typeINT ! ParseError, SyntaxError, InvalidCharacter => ERROR InvalidNumber[NIL]; UNWIND => DI.SetDefaultRadix[10]]; DI.SetDefaultRadix[10]; END; StringExpToLNum: PUBLIC PROC [exp: STRING, radix: CARDINAL] RETURNS [u: LONG UNSPECIFIED] = BEGIN OPEN DebugOps; Result: FooProc = BEGIN u _ ProcessNum[f, two].n.lu END; IF Numeric[exp] THEN RETURN[String.StringToLongNumber[exp,radix ! String.InvalidNumber => ERROR DebugOps.InvalidNumber[NIL]]]; DI.SetDefaultRadix[radix]; Interpret[exp, Result, DI.MakeLongType[IF radix = 8 THEN com.typeCARDINAL ELSE com.typeINT] ! ParseError, SyntaxError, InvalidCharacter => ERROR InvalidNumber[NIL]; UNWIND => DI.SetDefaultRadix[10]]; DI.SetDefaultRadix[10]; END; StringExpToOctal: PUBLIC PROC [s: STRING] RETURNS [CARDINAL] = BEGIN RETURN[StringExpToNum[s,8]] END; StringExpToLOctal: PUBLIC PROC [s: STRING] RETURNS [LONG CARDINAL] = BEGIN RETURN[StringExpToLNum[s,8]] END; StringExpToDecimal: PUBLIC PROC [s: STRING] RETURNS [INTEGER] = BEGIN RETURN[StringExpToNum[s,10]] END; StringExpToLDecimal: PUBLIC PROC [s: STRING] RETURNS [LONG INTEGER] = BEGIN RETURN[StringExpToLNum[s,10]] END; ProcessNum: PROC [f: DebugOps.Foo, size: DI.NumberType] RETURNS [n: DI.Number]= BEGIN i: DI.NumberType; p: LONG POINTER TO DI.Words; IF f.bits # 0 OR f.addr.offset # 0 THEN GOTO invalid; n.type _ LOOPHOLE[f.words]; SELECT n.type FROM size => NULL; one => IF size # two THEN GOTO invalid; two => {IF size = one THEN DI.Error[sizeMismatch]; GOTO invalid}; ENDCASE => GOTO invalid; DI.GetValue[f]; p _ f.addr.base; FOR i IN [nogood..n.type) DO n.w[i] _ p[i]; ENDLOOP; IF n.type # size THEN n.w[one] _ 0; RETURN; EXITS invalid => SIGNAL DebugOps.InvalidNumber[f] END; module: STRING _ [40]; StringToModule: PUBLIC PROC [in: STRING] RETURNS [STRING] = { IF Numeric[in] THEN { module.length _ 0; Gf.Name[module,LOOPHOLE[StringExpToOctal[in]]]; RETURN[module]} ELSE RETURN[in]}; -- actions CallInterpreter: PUBLIC PROC [resetPrompt: BOOLEAN _ FALSE] = BEGIN State.Get[].h.reentrantParse _ data.parse; GetLine[[ sId:di, colon:FALSE, resetPrompt:resetPrompt, resetParse:resetPrompt], IntString, di ! UNWIND => NULL; ANY => {data.resetParse _ data.resetPrompt _ TRUE; REJECT}]; END; IntString: PROC [s: STRING] = BEGIN DOutput.EOL[]; DebugOps.Interpret[s ! Table.Overflow => {Init.CheckSymTabLength[]; RETRY}; DebugOps.InvalidCharacter => BEGIN DOutput.Text[" !"L]; Dump.Char[s[index]]; DOutput.Line[" is an invalid character"L]; CONTINUE END; DebugOps.SyntaxError => BEGIN DOutput.Text[" ! Syntax error at ["L]; DOutput.Octal[errorLoc]; DOutput.Line["]."L]; CONTINUE END; DebugOps.ParseError => BEGIN DOutput.Text[" ! Parse error at ["L]; DOutput.Octal[errorLoc]; DOutput.Line["]."L]; CONTINUE END]; DOutput.EOL[]; IF data.resetPrompt THEN RETURN ELSE OtherPrompt[]; END; OtherPrompt: PROC = BEGIN data.parse _ State.Get[].h.reentrantParse; DOutput.Text[" >"L]; TextSW.BlinkingCaret[DebugOps.fileSW, on]; END; CallNub: PUBLIC PROC = {data.inNub _ TRUE; data.nubLevel _ data.nubLevel+1}; Comment: PUBLIC PROC [STRING] = {IF data.resetPrompt THEN RETURN ELSE OtherPrompt[]}; DisplayFrame: PUBLIC PROC [s: STRING] = BEGIN Actions.DumpFrame[DebugOps.StringExpToOctal[s]] END; DoKill: PUBLIC PROC = {IF OkToLeave[] THEN SIGNAL DebugOps.Kill}; DoProceed: PUBLIC PROC = {SIGNAL DebugOps.Proceed}; DoQuit: PUBLIC PROC = {IF OkToLeave[] THEN SIGNAL DebugOps.Quit}; OkToLeave: PROC RETURNS [ok: BOOLEAN] = { ok _ TRUE; TajoUtility.CheckVeto[abortSession ! Event.Vetoed => {ok _ FALSE; CONTINUE}] }; SetOctalContext: PUBLIC PROC [s: STRING] = BEGIN DContext.SetOctal[LOOPHOLE[DebugOps.StringExpToOctal[s]]] END; SetProcessContext: PUBLIC PROC [s: STRING] = BEGIN DContext.SetProcess[LOOPHOLE[DebugOps.StringExpToOctal[s]]] END; StartUser: PUBLIC PROC [gf: STRING] = BEGIN OPEN DebugOps; IF data.worryEntry THEN { DOutput.Line[" not permitted in worry mode!"L]; RETURN}; ShortWRITE[@LOOPHOLE[ data.ESV.parameter,MachineDefs.StartDP].frame,StringExpToOctal[gf]]; Init.CoreSwap[start]; END; SearchMode: PUBLIC PROC = BEGIN data.search _ ~data.search END; TreeMode: PUBLIC PROC = BEGIN data.tree _ ~data.tree END; WorryMode: PUBLIC PROC = BEGIN OPEN SDDefs; temp: UNSPECIFIED = DebugOps.ShortREAD[SD+sBreak]; data.worryBreaks _ ~data.worryBreaks; DebugOps.ShortWRITE[SD+sBreak,DebugOps.ShortREAD[SD+sAlternateBreak]]; DebugOps.ShortWRITE[SD+sAlternateBreak,temp]; END; UserScreen: PUBLIC PROC = BEGIN Init.CoreSwap[showscreen] END; END.