-- File: CC.mesa Last edited by Sandman on October 11, 1980 2:28 PM
DIRECTORY
Ascii USING [CR, NUL, SP],
DebugUsefulDefs USING [ShortCopyREAD, ShortREAD],
Event USING [Vetoed],
FormSW,
ImageDefs USING [RunImage, StopMesa],
Init USING [CoreSwap],
Inline USING [COPY],
OsStaticDefs USING [OsStatics],
Put USING [Char, Line, Text],
SegmentDefs USING [
DeleteFileSegment, FileSegmentHandle, MemoryConfig, NewFile,
NewFileSegment, Read, WriteAppend],
Selection USING [Clear, Convert],
State USING [GetGS],
Storage USING [
CopyString, FreePages, FreeString, Pages, String, StringLength],
StreamDefs USING [DiskHandle, FileNameError, NewByteStream, StreamError],
StringDefs USING [
AppendChar, AppendString, AppendSubString, EquivalentSubString,
MesaToBcplString, SubStringDescriptor, WordsForBcplString],
SwapperOps USING [memConfig, SystemTable],
TajoUtility USING [CheckVeto],
Tool USING [Create, Destroy, MakeFormSW, MakeSWsProc],
UserTerminal USING [BlinkDisplay],
Window USING [Box, Handle];
CC: PROGRAM
IMPORTS DebugUsefulDefs, Event, FormSW, ImageDefs, Init, Inline, Put,
SegmentDefs, Selection, State, Storage, StreamDefs, StringDefs,
SwapperOps, TajoUtility, Tool, UserTerminal =
BEGIN OPEN SegmentDefs, StreamDefs, StringDefs;
compile, bind, run: STRING ← NIL;
window, formSW, options: Window.Handle ← NIL;
compiler: STRING ← Storage.CopyString["Compiler.image"];
binder: STRING ← Storage.CopyString["Mesa.image Binder.bcd"];
runner: STRING ← Storage.CopyString["Mesa.image"];
debug: BOOLEAN ← FALSE;
nComp, nBind, nRun: STRING;
Expand: FormSW.ProcType =
BEGIN
ExpandItem[@compile, Rep[cs]];
ExpandItem[@bind, Rep[bs]];
ExpandItem[@run, Rep[rs]];
END;
Compile: FormSW.ProcType =
BEGIN
com: DiskHandle;
s: STRING ← [40];
IF Storage.StringLength[compile] = 0 THEN RETURN;
com ← StreamDefs.NewByteStream["Com.cm"L, WriteAppend];
DoGoodStuff[com, compiler, s, FALSE];
IF ~EndsInSwitches[compiler] THEN PutString[com, " /"];
PutString[com, "q; "];
PutCommand[com, compile ! FileNameError => {
Error[name]; com.destroy[com]; GOTO out}];
com.put[com, Ascii.CR];
com.destroy[com];
DoCommand[s];
EXITS out => NULL;
END;
Bind: FormSW.ProcType =
BEGIN OPEN SegmentDefs;
com: DiskHandle;
s: STRING ← [40];
IF Storage.StringLength[bind] = 0 THEN RETURN;
com ← StreamDefs.NewByteStream["Com.cm"L, WriteAppend];
DoGoodStuff[com, binder, s, FALSE];
IF ~EndsInSwitches[binder] THEN PutString[com, " /"];
PutString[com, "q; "];
PutCommand[com, bind ! FileNameError => {
Error[name]; com.destroy[com]; GOTO out}];
com.put[com, Ascii.CR];
com.destroy[com];
DoCommand[s];
EXITS out => NULL;
END;
Run: FormSW.ProcType =
BEGIN OPEN SegmentDefs;
com: DiskHandle;
system: STRING ← [40];
who: Runner;
IF Storage.StringLength[run] = 0 THEN RETURN;
com ← StreamDefs.NewByteStream["Com.cm"L, WriteAppend];
who ← CheckForImage[system, run];
IF who = bcd THEN {
[] ← CheckForImage[system, runner];
PutString[com, runner];
IF ~EndsInSwitches[runner] THEN PutString[com, " /"];
PutString[com, "q "]};
PutCommand[com, run ! FileNameError => {
Error[name]; com.destroy[com]; GOTO out}];
com.put[com, Ascii.CR];
com.destroy[com];
DoCommand[system, who = run];
EXITS out => NULL;
END;
Go: FormSW.ProcType =
BEGIN OPEN SegmentDefs;
com: DiskHandle;
standard: BOOLEAN ← TRUE;
binding, compiling, running: BOOLEAN ← FALSE;
who: Runner;
system: STRING ← [40];
IF Storage.StringLength[compile] # 0 THEN compiling ← TRUE;
IF Storage.StringLength[bind] # 0 THEN binding ← TRUE;
IF Storage.StringLength[run] # 0 THEN running ← TRUE;
IF ~compiling AND ~binding AND ~running THEN RETURN;
com ← StreamDefs.NewByteStream["Com.cm"L, WriteAppend];
IF compiling THEN
BEGIN
DoGoodStuff[com, compiler, system, FALSE];
IF ~EndsInSwitches[compiler] THEN PutString[com, " /"];
PutString[com, "q; "];
PutCommand[com, compile ! FileNameError => {
Error[name]; com.destroy[com]; GOTO out}];
com.put[com, Ascii.SP];
END;
IF binding THEN
BEGIN
s: STRING ← [40];
DoGoodStuff[com, binder, s, compiling];
IF ~EndsInSwitches[binder] THEN PutString[com, " /"];
PutString[com, "q; "];
PutCommand[com, bind ! FileNameError => {
Error[name]; com.destroy[com]; GOTO out}];
com.put[com, Ascii.SP];
IF ~compiling THEN AppendString[system, s];
END;
IF running THEN
BEGIN
s: STRING ← [40];
who ← CheckForImage[s, run];
IF who = bcd THEN {
DoGoodStuff[com, runner, s, compiling OR binding];
IF ~EndsInSwitches[runner] THEN PutString[com, " /"];
PutString[com, "q "];
PutCommand[com, run ! FileNameError => {
Error[name]; com.destroy[com]; GOTO out}]}
ELSE {
DoGoodStuff[com, run, s, compiling OR binding, TRUE];
IF ~EndsInSwitches[s] AND ~compiling AND ~binding THEN
PutString[com, " /"];
PutString[com, "q "];
PutCommand[com, run, s.length ! FileNameError => {
Error[name]; com.destroy[com]; GOTO out}]};
END;
com.put[com, Ascii.CR];
com.destroy[com];
DoCommand[
system, SELECT TRUE FROM
compiling, binding => FALSE, ENDCASE => who = run];
EXITS out => NULL;
END;
DoCommand: PROC [system: STRING, runFile: BOOLEAN ← FALSE] = {
OPEN SegmentDefs;
seg: FileSegmentHandle;
p: POINTER = OsStaticDefs.OsStatics.EventVector;
veto: BOOLEAN ← FALSE;
EVItem: TYPE = MACHINE DEPENDENT RECORD [
type: [0..7777B], length: [0..17B]];
IF debug THEN {ShowComCM[]; RETURN};
TajoUtility.CheckVeto[abortSession ! Event.Vetoed => {veto ← TRUE; CONTINUE}];
IF veto THEN RETURN;
seg ← NewFileSegment[
NewFile[system ! FileNameError => {Error[name]; GOTO out}], 1, 1, Read];
Init.CoreSwap[cleanmaplog ! UNWIND => DeleteFileSegment[seg]];
FixMemConfig[];
IF ~runFile THEN ImageDefs.RunImage[seg];
p↑ ← EVItem[6, WordsForBcplString[system.length]+1];
MesaToBcplString[system, p+1];
ImageDefs.StopMesa[];
EXITS out => NULL};
DoGoodStuff: PROC [
com: DiskHandle, command, first: STRING, rSwitch, short: BOOLEAN ← FALSE] = {
i: CARDINAL;
c: CHARACTER;
first.length ← i ← 0;
DO
SELECT (c ← command[i]) FROM
'/ => {
com.put[com, c]; IF rSwitch THEN com.put[com, 'r]; i←i+1; EXIT};
Ascii.SP => {
IF rSwitch THEN PutString[com, "/r"L];
com.put[com, c];
i←i+1;
EXIT};
ENDCASE => {AppendChar[first, c]; com.put[com, c]};
IF (i←i+1) = command.length THEN {
IF rSwitch THEN PutString[com, "/r;"L]; RETURN};
ENDLOOP;
IF short THEN RETURN;
UNTIL i = command.length DO
com.put[com, command[i]];
i ← i + 1;
ENDLOOP};
Runner: TYPE = {bcd, image, run};
ShowComCM: PROC =
BEGIN
com: DiskHandle;
com ← StreamDefs.NewByteStream["Com.cm"L, Read];
DO Put.Char[NIL, com.get[com ! StreamError => EXIT]] ENDLOOP;
Put.Char[NIL, Ascii.CR];
com.destroy[com];
END;
CheckForImage: PROC [system, cmd: STRING] RETURNS [who: Runner] =
BEGIN
dot, end: CARDINAL;
ssd: SubStringDescriptor;
image: SubStringDescriptor ←
[base: ".image"L, offset: 0, length: (".image"L).length];
run: SubStringDescriptor ←
[base: ".run"L, offset: 0, length: (".run"L).length];
dot ← LAST[CARDINAL];
end ← 0;
FOR i: CARDINAL IN [0..cmd.length) DO
IF dot = LAST[CARDINAL] AND cmd[i] = '. THEN dot ← i;
IF cmd[i] = Ascii.SP OR cmd[i] = Ascii.CR OR cmd[i] = '/ THEN
{end ← i; EXIT};
REPEAT FINISHED => end ← cmd.length;
ENDLOOP;
IF dot = LAST[CARDINAL] THEN RETURN[bcd];
ssd ← [base: cmd, offset: dot, length: end-dot];
SELECT TRUE FROM
EquivalentSubString[@ssd, @image] => {
ssd.offset ← 0;
ssd.length ← end;
AppendSubString[system, @ssd];
who ← image};
EquivalentSubString[@ssd, @run] => {
ssd.offset ← 0;
ssd.length ← end;
AppendSubString[system, @ssd];
who ← run};
ENDCASE => RETURN[bcd];
RETURN
END;
EndsInSwitches: PROC [s: STRING] RETURNS [BOOLEAN] =
BEGIN
FOR i: CARDINAL DECREASING IN [0..s.length) DO
SELECT s[i] FROM
Ascii.SP => RETURN[FALSE];
'/ => RETURN[TRUE];
ENDCASE;
ENDLOOP;
RETURN[FALSE];
END;
CheckForExtension: PROCEDURE [name, ext: STRING] =
BEGIN
FOR i: CARDINAL IN [0..name.length) DO
IF name[i] = '. THEN RETURN;
ENDLOOP;
AppendString[name, ext];
RETURN
END;
PutString: PROCEDURE [com: DiskHandle, run: STRING] = {
FOR i: CARDINAL IN [0..run.length) DO com.put[com, run[i]]; ENDLOOP};
GetProc: TYPE = PROC RETURNS [c: CHARACTER];
PutProc: TYPE = PROC [c: CHARACTER];
PutCommand: PROCEDURE [com: DiskHandle, s: STRING, ignore: CARDINAL ← 0] =
BEGIN
i: CARDINAL ← 0;
StringChar: GetProc = {
IF i >= s.length THEN c ← Ascii.NUL ELSE {c ← s[i]; i ← i + 1}};
TakeChars: PutProc = {com.put[com, c]};
PutChars[TakeChars, StringChar, ignore];
RETURN
END;
PutChars: PROC [put: PutProc, get: GetProc, ignore: CARDINAL] =
BEGIN
NUL: CHARACTER = Ascii.NUL;
SP: CHARACTER = Ascii.SP;
c: CHARACTER;
s: STRING ← [40];
stream: DiskHandle ← NIL;
StreamChar: GetProc =
BEGIN
IF stream = NIL THEN c ← Ascii.NUL
ELSE c ← stream.get[stream ! StreamError =>
{c ← NUL; stream.destroy[stream]; stream ← NIL; CONTINUE}];
RETURN
END;
DO
c ← get[];
IF ignore # 0 THEN {ignore ← ignore - 1; LOOP};
IF c = NUL THEN EXIT
ELSE IF c = '@ THEN
BEGIN
s.length ← 0;
DO c ← get[]; IF c = '@ OR c = NUL OR c = SP THEN EXIT; AppendChar[s, c]; ENDLOOP;
CheckForExtension[s, ".cm"];
stream ← NewByteStream[s, Read];
PutChars[put, StreamChar, ignore ! UNWIND => stream.destroy[stream]];
END
ELSE put[c];
ENDLOOP;
END;
Error: PROC [name: STRING] = {
Put.Char[NIL, '!];
Put.Text[NIL, name];
Put.Line[NIL, " not found"L];
UserTerminal.BlinkDisplay[]};
MaxChars: CARDINAL = 512-4;
Buffer: TYPE = RECORD [
link: POINTER TO Buffer ← NIL,
nChars: CARDINAL ← 0,
chars: PACKED ARRAY [0..MaxChars) OF CHARACTER ← NULL];
ExpandItem: PROC [s: POINTER TO STRING, index: CARDINAL] =
BEGIN OPEN Storage;
nChars: CARDINAL ← 0;
hasSelection: BOOLEAN = Selection.Convert[subwindow] = formSW;
p: POINTER TO PACKED ARRAY [0..0) OF CHARACTER;
b, list, last: POINTER TO Buffer ← NIL;
i: CARDINAL ← 0;
StringChar: GetProc = {
IF i >= s.length THEN c ← Ascii.NUL ELSE {c ← s[i]; i ← i + 1}};
TakeChars: PutProc = {
IF b = NIL THEN {
b ← Pages[1]; b↑ ← []; last.link ← b; last ← b;
IF list = NIL THEN list ← b};
b.chars[b.nChars] ← c;
IF (b.nChars ← b.nChars + 1) = MaxChars THEN b ← NIL};
FreeBuffers: PROC = {
UNTIL list = NIL DO b ← list.link; FreePages[list]; list ← b; ENDLOOP};
IF StringLength[s↑] = 0 THEN RETURN;
IF hasSelection AND FormSW.GetSelection[formSW].index = index THEN
Selection.Clear[];
PutChars[TakeChars, StringChar, 0 ! FileNameError => {
Error[name]; FreeBuffers[]; GOTO ret}];
FOR b ← list, b.link UNTIL b = NIL DO nChars ← nChars + b.nChars ENDLOOP;
FreeString[s↑];
s↑ ← String[nChars];
p ← @s.text;
FOR b ← list, b.link UNTIL b = NIL DO
Inline.COPY[from: @b.chars, to: p, nwords: (b.nChars+1)/2];
p ← p + (b.nChars+1)/2;
ENDLOOP;
s.length ← nChars;
FreeBuffers[];
FormSW.DisplayItem[formSW, index];
EXITS ret => NULL;
END;
FixMemConfig: PROCEDURE =
BEGIN OPEN SegmentDefs;
table: POINTER TO SwapperOps.SystemTable = State.GetGS[].gsh.ESV.tables;
userMemConfig: MemoryConfig;
DebugUsefulDefs.ShortCopyREAD[
from: DebugUsefulDefs.ShortREAD[@table.memConfig],
to: @userMemConfig,
nwords: SIZE[MemoryConfig]];
SwapperOps.memConfig ← userMemConfig;
END;
Parms: TYPE = {expand, compile, bind, run, go, options, cs, bs, rs};
Rep: PROC [Parms] RETURNS [CARDINAL] = MACHINE CODE BEGIN END;
MakeForm: FormSW.ClientItemsProcType =
BEGIN OPEN FormSW;
items ← AllocateItemDescriptor[Rep[LAST[Parms]]+1];
items[Rep[expand]] ←
CommandItem[tag: "Expand"L, place: [0, line0], proc: Expand];
items[Rep[compile]] ←
CommandItem[tag: "Compile"L, place: [10*7, line0], proc: Compile];
items[Rep[bind]] ←
CommandItem[tag: "Bind"L, place: [21*7, line0], proc: Bind];
items[Rep[run]] ←
CommandItem[tag: "Run"L, place: [29*7, line0], proc: Run];
items[Rep[go]] ← CommandItem[tag: "Go"L, place: [36*7, line0], proc: Go];
items[Rep[options]] ←
CommandItem[tag: "Options"L, place: [42*7, line0], proc: OptionsWindow];
items[Rep[cs]] ← StringItem[
tag: "Compile"L, place: [0,line1], string: @compile, inHeap: TRUE];
items[Rep[bs]] ← StringItem[
tag: "Bind"L, place: [0,line2], string: @bind, inHeap: TRUE];
items[Rep[rs]] ← StringItem[
tag: "Run"L, place: [0,line3], string: @run, inHeap: TRUE];
RETURN[items: items, freeDesc: TRUE];
END;
MakeSWs: Tool.MakeSWsProc =
BEGIN
formSW ← Tool.MakeFormSW[window: window, formProc: MakeForm];
END;
OptionsWindow: FormSW.ProcType =
BEGIN
box: Window.Box = window.box;
IF options = NIL THEN options ← Tool.Create[
name: "Options"L, makeSWsProc: OptionSW, initialState: active,
initialBox: [[box.place.x+15, box.place.y+100], [50*7, 5*15]] ]
ELSE {
Put.Line[NIL, "Option window already exists."L];
UserTerminal.BlinkDisplay[]};
END;
DoOptions: FormSW.ProcType =
BEGIN OPEN Storage;
IF index = 0 THEN
BEGIN
FreeString[compiler]; compiler ← CopyString[nComp];
FreeString[binder]; binder ← CopyString[nBind];
FreeString[runner]; runner ← CopyString[nRun];
END;
IF Selection.Convert[subwindow] = sw THEN Selection.Clear[];
Tool.Destroy[options];
options ← NIL;
END;
OptionSW: Tool.MakeSWsProc =
{[] ← Tool.MakeFormSW[window: window, formProc: MakeOptions]};
MakeOptions: FormSW.ClientItemsProcType =
BEGIN OPEN FormSW;
noptions: CARDINAL = 6;
nComp ← Storage.CopyString[compiler];
nBind ← Storage.CopyString[binder];
nRun ← Storage.CopyString[runner];
items ← AllocateItemDescriptor[noptions];
items[0] ← CommandItem[tag: "Apply"L, proc: DoOptions, place: [0,line0]];
items[1] ← StringItem[
tag: "Compiler"L, place: [10*7,line0], string: @nComp, inHeap: TRUE];
items[2] ← BooleanItem[tag: "Debug"L, switch: @debug, place: [0, line1]];
items[3] ← StringItem[
tag: "Binder"L, place: [10*7,line1], string: @nBind, inHeap: TRUE];
items[4] ← CommandItem[tag: "Abort"L, proc: DoOptions, place: [0,line2]];
items[5] ← StringItem[
tag: "Runner"L, place: [10*7,line2], string: @nRun, inHeap: TRUE];
RETURN[items, TRUE]
END;
-- Mainline code
window ← Tool.Create[
makeSWsProc: MakeSWs, name: "Command Central"L, initialBox: [[0,0],[400,100]]];
END...