-- JaMTajoImpl.mesa -- Last changed by Doug Wyatt, 24-Feb-82 18:13:55 DIRECTORY JaMBasic, JaMInternal, JaMOps, JaMTajo, JaMVM, JaMFnsDefs USING [PushInteger], StreamDefs, Ascii USING [CR], Directory USING [Error, Lookup], File USING [Capability], Heap USING [systemZone], Process USING [Abort, Detach, EnableAborts], Runtime USING [CallDebugger, ConfigError, GetBcdTime, IsBound, LoadConfig], Storage USING [String, FreeString], Time USING [Append, Unpack], TTY USING [PutString], PilotLoaderOps USING [VersionMismatch], Exec USING [AddCommand, commandLine, w], Tool, ToolWindow, FormSW, TTYSW, Put, UserInput, Window; JaMTajoImpl: MONITOR IMPORTS JaMOps, JaMVM, JaMFnsDefs, Directory, Heap, Process, Runtime, Storage, Time, TTY, PilotLoaderOps, Exec, Tool, ToolWindow, FormSW, TTYSW, Put, UserInput EXPORTS JaMTajo, StreamDefs = { OPEN TajoPut:Put, StreamDefs, JaMOps, JaMInternal, JaMBasic; Button: TYPE = JaMTajo.Button; zone: UNCOUNTED ZONE = Heap.systemZone; version: STRING _ "JaM of dd-mmm-yy hh:mm "; prompt,start,badfile,badname,badversion: name Object; buttonName: ARRAY Button OF name Object; myframe: Frame _ NIL; State: TYPE = {idle, busy}; state: State _ idle; readyForInput: CONDITION; somethingToDo: CONDITION; objectToDo: Object; -- the object to be executed tool: Window.Handle _ NIL; formSW,ttySW: Window.Handle _ NIL; dsObject: StreamObject _ [reset: DReset, get: DGet, putback: DPutback, put: DPut, endof: DEndof, destroy: DDestroy, data: NIL]; ds: StreamHandle _ @dsObject; GetDefaultDisplayStream: PUBLIC PROC RETURNS[StreamHandle] = { RETURN[ds] }; DReset: PROC[StreamHandle] = { }; DGet: PROC[StreamHandle] RETURNS[CHARACTER] = { RETURN[0C] }; DPutback: PROC[StreamHandle,CHARACTER] = { }; DPut: PROC[s: StreamHandle, c: CHARACTER] = { IF ttySW#NIL THEN TajoPut.Char[ttySW,c] }; DEndof: PROC[StreamHandle] RETURNS[BOOLEAN] = { RETURN[FALSE] }; DDestroy: PROC[StreamHandle] = { }; line: STRING _ NIL; lineIndex: CARDINAL _ 0; LReset: PROC[s: StreamHandle] = { lineIndex _ 0 }; LGet: PROC[s: StreamHandle] RETURNS[UNSPECIFIED] = { i: CARDINAL _ lineIndex; IF i0 THEN lineIndex _ lineIndex - 1 }; LEndof: PROC[s: StreamHandle] RETURNS[BOOLEAN] = { RETURN[lineIndex>=line.length] }; LPut: PROC[s: StreamHandle, x: UNSPECIFIED] = { }; LDestroy: PROC[s: StreamHandle] = { }; lineObject: StreamObject _ [reset: LReset, get: LGet, putback: LPutback, endof: LEndof, put: LPut, destroy: LDestroy, data: NIL]; lineStream: StreamHandle _ @lineObject; jamStarted: BOOLEAN _ FALSE; JaMExecCommand: PROC = { OPEN Exec; IF jamStarted THEN { TTY.PutString[w,"JaM has already been started."L]; RETURN; }; jamStarted _ TRUE; -- Allocate line, and grab the rest of the command line now, before it goes away line _ Storage.String[MAX[200,commandLine.s.length-commandLine.i]]; WHILE commandLine.ifname.maxlength THEN GOTO BadName ELSE StringText[string,fname]; file _ Directory.Lookup[fname ! Directory.Error => SELECT type FROM fileNotFound => IF extended THEN GOTO BadName ELSE { Append[fname,ext]; extended _ TRUE; RETRY }; ENDCASE => GOTO BadName]; prog _ Runtime.LoadConfig[file: file, offset: 1 ! Runtime.ConfigError => GOTO BadFile; PilotLoaderOps.VersionMismatch => { Push[frame.opstk,MakeString[name]]; -- push name of offending interface Push[frame.opstk,MakeString[fname]]; -- push name of file being loaded GOTO BadVersion}]; IF debug THEN { message: STRING _ [100]; Append[message,"JaM: Just loaded "]; Append[message,fname]; Runtime.CallDebugger[message]; }; IF Runtime.IsBound[prog] THEN START prog; EXITS BadFile => ERROR Error[badfile]; BadName => ERROR Error[badname]; BadVersion => ERROR Error[badversion,FALSE]; }; JPrint: PROC[frame: Frame] = { string: string Object _ PopString[frame.opstk]; Proc: PROC[c: CHARACTER] RETURNS[BOOLEAN] = { abort: BOOLEAN _ GetAbort[frame]; IF NOT abort THEN ds.put[ds,c]; RETURN[abort] }; IF tool=NIL THEN RETURN; -- running on cedar side StringForAll[string,Proc]; }; InstallJaMPilot: PROC[why: InstallReason, frame: Frame] = { SELECT why FROM register => { found: BOOLEAN; badfile _ MakeName[".badfile"L]; badname _ MakeName[".badname"L]; badversion _ MakeName[".badversion"L]; prompt _ MakeName[".prompt"L]; start _ MakeName[".start"L]; buttonName[rd] _ MakeName[".reddown"L]; buttonName[ru] _ MakeName[".redup"L]; buttonName[yd] _ MakeName[".yellowdown"L]; buttonName[yu] _ MakeName[".yellowup"L]; buttonName[bd] _ MakeName[".bluedown"L]; buttonName[bu] _ MakeName[".blueup"L]; RegisterExplicit[frame,".print"L,JPrint]; RegisterExplicit[frame,".loadbcd"L,LoadBCD]; RegisterExplicit[frame,".debugbcd"L,DebugBCD]; RegisterExplicit[frame,".calldebugger"L,CallDebugger]; RegisterExplicit[frame,".quit"L,Quit]; Def[frame,prompt,MakeString["(*).print"L,X]]; Def[frame,MakeName[".version"L],MakeString[version]]; Def[frame, undefname, MakeString["(Undefined name - .undefname: ).print ( ).cvis .print"L,X]]; [found,] _ TryToLoad[frame,start]; IF NOT found THEN Def[frame,start,MakeString[".version .print ( ).print"L,X]]; }; ENDCASE; }; RunJaM: PROC = { WaitForSomethingToDo: ENTRY PROC = { WHILE state=idle DO WAIT somethingToDo ENDLOOP; }; NotifyReadyForMore: ENTRY PROC = { state _ idle; BROADCAST readyForInput; }; lineLoop: PROCESS _ NIL; StartJaM[vmname: "JaM.VM"L, maxPages: 2000]; myframe _ defaultFrame; quit _ FALSE; -- do start macro Execute[myframe,start !ABORTED => CONTINUE]; -- do command line IF line.length>0 THEN { objectToDo _ MakeStream[lineStream,X]; Execute[myframe,objectToDo !ABORTED => CONTINUE]; line.length _ 0; }; Process.Detach[lineLoop _ FORK LineLoop[]]; state _ idle; UNTIL quit DO WaitForSomethingToDo[]; Execute[myframe,objectToDo !ABORTED => CONTINUE]; NotifyReadyForMore[]; ENDLOOP; Process.Abort[lineLoop]; myframe _ NIL; StopJaM[]; Storage.FreeString[line]; IF tool# NIL THEN ToolWindow.Destroy[tool]; }; Do: ENTRY PROC[ob: Object] = { UNTIL state=idle DO WAIT readyForInput ENDLOOP; objectToDo _ ob; state _ busy; BROADCAST somethingToDo; UNTIL state=idle DO WAIT readyForInput ENDLOOP; }; LineLoop: PROC = { EndLine: PROC[c: CHARACTER] RETURNS[BOOLEAN] = { IF c=Ascii.CR THEN RETURN[LineComplete[line]] ELSE RETURN[FALSE] }; UNTIL quit OR ttySW=NIL DO Do[prompt]; [] _ TTYSW.GetEditedString[ttySW,line,EndLine,TRUE ! TTYSW.LineOverflow => IF s=line THEN { new: STRING _ Storage.String[s.maxlength+s.maxlength/2]; FOR i: CARDINAL IN[0..s.length) DO new[i] _ s[i] ENDLOOP; new.length _ s.length; line _ new; Storage.FreeString[s]; RESUME[new] }; TTYSW.Rubout => { TajoPut.Line[ttySW," XXX"L]; line.length _ 0; CONTINUE }; ANY => EXIT]; IF quit THEN EXIT; TajoPut.CR[ttySW]; lineIndex _ 0; Do[MakeStream[lineStream,X]]; ENDLOOP; }; MouseProc: TYPE = JaMTajo.MouseProc; mouseProc: MouseProc _ DefaultMouseProc; DefaultMouseProc: PROC[x,y: INTEGER] = { JaMFnsDefs.PushInteger[x]; JaMFnsDefs.PushInteger[y]; }; SetMouseProc: PUBLIC PROC[new: MouseProc] RETURNS[MouseProc] = { old: MouseProc _ mouseProc; mouseProc _ new; RETURN[old]; }; DoButton: PUBLIC ENTRY PROC[button: Button, x,y: INTEGER] = { IF state#idle THEN RETURN; -- ignore buttons if not idle mouseProc[x,y]; -- push transformed coordinates objectToDo _ buttonName[button]; state _ busy; BROADCAST somethingToDo; }; -- Tajo stuff InitTool: PROC = { -- IF TajoCedarSwap.WhereAmI[] = cedar THEN RETURN; tool _ Tool.Create[ makeSWsProc: MakeSWs, initialState: active, clientTransition: ClientTransition, name: version, initialBox: [[500, 40], [464, 380]]]; ToolWindow.SetTinyName[tool,"JaM"L]; }; AcceptTypeInFrom: PUBLIC PROC[w: Window.Handle] = { IF ttySW=NIL THEN RETURN; UserInput.CreateIndirectStringInOut[from: w, to: ttySW]; UserInput.SetKeyPNR[w, keyboard, UserInput.TypeInPNR]; UserInput.SetCursorPNR[w, UserInput.TypeInCursorPNR]; }; ClientTransition: ToolWindow.TransitionProcType = { IF old=active AND new#active THEN JaMVM.Check[]; }; logName: STRING _ [20]; MakeSWs: Tool.MakeSWsProc = { Tool.UnusedLogName[unused: logName, root: "JaM.log"L]; formSW _ Tool.MakeFormSW[window: window, formProc: MakeForm]; ttySW _ Tool.MakeTTYSW[window: window, name: logName]; }; MakeForm: FormSW.ClientItemsProcType = { OPEN FormSW; nItems: CARDINAL = 3; items _ AllocateItemDescriptor[nItems]; items[0] _ CommandItem[tag: "Interrupt"L, place: newLine, proc: InterruptButton]; items[1] _ CommandItem[tag: "CheckVM"L, place: nextPlace, proc: CheckVMButton]; items[2] _ StringItem[tag: "Logged on"L, place: nextPlace, string: @logName, readOnly: TRUE]; RETURN[items: items, freeDesc: TRUE]; }; InterruptButton: FormSW.ProcType = { IF myframe#NIL THEN SetAbort[myframe,TRUE]; }; CheckVMButton: FormSW.ProcType = { JaMVM.Check[]; }; -- Initialization version.length _ 7; Time.Append[version, Time.Unpack[Runtime.GetBcdTime[]]]; Install[InstallJaMPilot]; Process.EnableAborts[@somethingToDo]; InitTool[]; Exec.AddCommand["JaM"L,JaMExecCommand]; }. Wyatt 7-Nov-81 14:20:34 add CheckVM button ENABLE ABORTED for all of main loop in RunJaM Wyatt 19-Feb-82 10:57:40 better handling of VersionMismatch specify initialBox for Tool.Create Wyatt 24-Feb-82 18:13:12 no longer refers to TajoCedarSwap