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