-- 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.