-- File: WiskOperations.mesa -- last edit by Smokey on Sep 16, 1980 3:45 PM -- last edit by Sandman on July 28, 1980 9:08 AM -- last edit by Bruce on October 25, 1980 7:47 PM DIRECTORY BP USING [BytePC, Fail, GFHandle, Insert, Remove], Context USING [Create, Data, Destroy, Find, Type, UniqueType], Copier USING [Outer], DContext USING [GetGlobal, GetModule], DebugFormat USING [BT, EXOI], DebugOps USING [window], DSyms USING [GFHandle, GFrameMdi, NoFGT], FileSW USING [GetFile, IsIt], FileWindow USING [ Create, CreateMCR, DestroyMCR, Event, Enumerate, EnumerateProcType, LoadWindow, NotifyProcType, SetExtension, SetMinimumWindows, SetSize, SetSourceMenu, SetNotifyProc, WindowForFile], Frames USING [Invalid], Gf USING [Copied, CopiedFrame, Frame, Handle, Validate], HeapString USING [AppendChar], Init USING [], Inline USING [LongNumber], Lookup USING [Fail], MachineDefs USING [BytePC, DestroyStream, GFHandle, NullGF, SHandle], Menu USING [Create, Handle, ItemObject, MCRType], Pc USING [BytePC, CacheCBti, EntryPC, EVRange, ExitPC, GetPc], Profile USING [bitmap], Segments USING [FHandle, FileNameProblem, NewFile, Read], Selection USING [Clear, Convert], Source USING [ BreakRec, FileMissing, GetGF, GFHandle, Handle, LittleParser, LoadWindow, Open, PcToSource, SC, SetGF, Validate], Storage USING [Free, FreeString, Node], Streams USING [CreateStream, Handle], String USING [EqualString], Strings USING [AppendString], Symbols USING [BTIndex, CBTIndex, MDIndex, RootBti], SymbolTable USING [Base, Missing], Table USING [Base], TextSW USING [GetPosition, GetSelection, SetSelection], --, RemoveSecondarySelection, SecondarySelectionFromPosition, SetSecondarySelection], ToolWindow USING [GetName, Handle, SetName, WindowForSubwindow], UserTerminal USING [BlinkDisplay], Window USING [Dims, Handle]; WiskOperations: PROGRAM IMPORTS BP, Context, Copier, DContext, DebugOps, DSyms, FileSW, FileWindow, Frames, Gf, HeapString, Lookup, MachineDefs, Menu, Pc, Profile, Segments, Selection, Source, Storage, Streams, String, Strings, SymbolTable, TextSW, ToolWindow, UserTerminal EXPORTS Init, Source = BEGIN OPEN MachineDefs, Symbols; RelPC: TYPE = [0..LAST[CARDINAL]/2]; -- Define Menu and related data sourceItemsCount: CARDINAL = 6; sourceItems: ARRAY [0..sourceItemsCount) OF Menu.ItemObject _ [ ["Create", FileWindow.CreateMCR], ["Destroy", FileWindow.DestroyMCR], ["Attach", AttachMCR], ["Set Break", BreakMCR], ["Set Trace", TraceMCR], ["Clr Break", ClearMCR]]; sourceMenu: Menu.Handle = Menu.Create[DESCRIPTOR[sourceItems], "SourceOps", TRUE]; -- Debugger Menu Command Routines AttachMCR: Menu.MCRType = { item: ItemHandle _ FindItem[window]; IF item = NIL THEN UserTerminal.BlinkDisplay[] ELSE item.trustTime _ TRUE}; BreakMCR: Menu.MCRType = BEGIN SetUp[window,set,break] END; ClearMCR: Menu.MCRType = BEGIN SetUp[window,clear,break] END; TraceMCR: Menu.MCRType = BEGIN SetUp[window,set,trace] END; -- Public stuff Destroy: PUBLIC PROC [d: MachineDefs.SHandle] = {MachineDefs.DestroyStream[d]}; LoadWindow: PUBLIC PROCEDURE [ name: STRING, gf: MachineDefs.GFHandle _ MachineDefs.NullGF, file: MachineDefs.SHandle _ NIL, position: LONG CARDINAL] = BEGIN w: Window.Handle = FileWindow.WindowForFile[name]; FileWindow.LoadWindow[fileName: name, position: position, s: file, sw: w]; SetGF[w, gf]; END; Open: PUBLIC PROC [s: STRING] RETURNS [stream: Streams.Handle] = BEGIN file: Segments.FHandle _ NIL; file _ Segments.NewFile[s, Segments.Read ! Segments.FileNameProblem[] => CONTINUE ]; IF file = NIL THEN SIGNAL Source.FileMissing[s]; stream _ Streams.CreateStream[file]; END; SetSize: PUBLIC PROCEDURE = BEGIN OPEN DebugOps.window.box; rootDims: Window.Dims = Profile.bitmap.dims; FileWindow.SetSize[NIL, [ place: [x: 0, y: place.y+dims.h], dims: [w: rootDims.w, h: rootDims.h - (place.y+dims.h)]] ]; END; SetupSourceWindow: PUBLIC PROCEDURE = BEGIN FileWindow.SetNotifyProc[SomethingChanged]; FileWindow.SetExtension[".mesa"L]; FileWindow.SetSourceMenu[sourceMenu]; FileWindow.SetMinimumWindows[1]; [] _ FileWindow.Create[[[x:32, y: 0], [w: 480, h: 352]]]; END; Shorten: PROC [lc: LONG CARDINAL] RETURNS [CARDINAL] = BEGIN OPEN ln: LOOPHOLE[lc,Inline.LongNumber]; RETURN [ln.lowbits] END; -- Utilities AddDollar: PROC [w: Window.Handle] = { s: STRING _ ToolWindow.GetName[w]; IF s[s.length-1] = '. THEN s[s.length-1] _ '$ ELSE HeapString.AppendChar[@s,'$]; ToolWindow.SetName[w,s]}; Break: PROC [sw: Window.Handle, br: Source.BreakRec] RETURNS [ok: BOOLEAN] = BEGIN gf: GFHandle; pc: BytePC; cbti: CBTIndex; ep: Pc.EVRange; index: CARDINAL; getfgt: BOOLEAN _ TRUE; mdi: Symbols.MDIndex; SetUp: PROC [base: SymbolTable.Base] = BEGIN startPc: BytePC; relPc: RelPC; [relPc,cbti,index] _ ExploreFGT[base, Shorten[TextSW.GetSelection[sw].left]]; IF base.bb[cbti].inline THEN ERROR BP.Fail[inInline]; ep _ base.bb[cbti].entryIndex; startPc _ Pc.GetPc[gf,ep]; pc _ [startPc+relPc]; index _ Source.PcToSource[base, gf, pc, cbti, startPc]; END; IF sw = NIL THEN RETURN[FALSE]; gf _ GetContext[sw ! Gf.CopiedFrame, Lookup.Fail, Source.FileMissing => GOTO nogood; DSyms.NoFGT => BEGIN IF ~getfgt OR br.bt.ex # entry THEN GOTO nogood; getfgt _ FALSE; CONTINUE; END; SymbolTable.Missing => GOTO nogood]; IF gf = NIL OR ~Gf.Validate[gf] OR Gf.Copied[gf] THEN RETURN[FALSE]; mdi _ DSyms.GFrameMdi[gf,getfgt ! DSyms.NoFGT => BEGIN IF ~getfgt OR br.bt.ex # entry THEN GOTO nogood; getfgt _ FALSE; RETRY; END]; Copier.Outer[mdi, SetUp ! BP.Fail => GOTO nogood]; cbti _ Pc.CacheCBti[mdi,gf,cbti]; SELECT br.bt.ex FROM entry => pc _ Pc.EntryPC[ep,gf]; exit => pc _ Pc.ExitPC[cbti]; in => NULL; ENDCASE; IF br.sc=set THEN [] _ BP.Insert[gf,pc,br.bt,TRUE ! BP.Fail => GOTO nogood] ELSE BP.Remove[gf,pc]; FixSelection[sw: sw, left: index, right: IF br.bt.ex = in THEN index + 1 ELSE Shorten[TextSW.GetSelection[sw].right], set: br.sc=set]; RETURN[TRUE]; EXITS nogood => RETURN[FALSE]; END; ClosestSource: PROC [ bti: BTIndex, index: CARDINAL, base: SymbolTable.Base] RETURNS [closest: CARDINAL, firstPc: RelPC] = BEGIN OPEN body: base.bb[bti]; i, start, length: CARDINAL; currentPc: RelPC; closest _ body.sourceIndex; currentPc _ firstPc _ 0; IF BASE[base.fgTable] = NIL THEN RETURN; WITH body.info SELECT FROM External => {start _ startIndex; length _ indexLength}; ENDCASE => RETURN; FOR i IN [start..start+length) DO WITH base.fgTable[i] SELECT FROM normal => BEGIN IF deltaSource + closest > index THEN RETURN; firstPc _ currentPc _ currentPc + deltaObject; closest _ closest + deltaSource; END; step => IF which = source THEN IF delta + closest > index THEN RETURN ELSE {firstPc _ currentPc; closest _ closest + delta} ELSE currentPc _ currentPc + delta; ENDCASE; ENDLOOP; END; ExploreFGT: PROC [base: SymbolTable.Base, index: CARDINAL] RETURNS [bestPc: RelPC, bestCbti: CBTIndex, bestSource: CARDINAL] = BEGIN CheckBti: PROC [bti: BTIndex] RETURNS [stop: BOOLEAN] = BEGIN OPEN body: base.bb[bti]; source: CARDINAL; pc: RelPC; stop _ FALSE; IF body.kind # Callable OR body.sourceIndex > index THEN RETURN; [closest: source, firstPc: pc] _ ClosestSource[bti,index, base]; IF source <= bestSource THEN RETURN; bestSource _ source; bestCbti _ LOOPHOLE[bti]; bestPc _ pc; END; bestPc _ 0; bestCbti _ Symbols.RootBti; bestSource _ 0; [] _ base.EnumerateBodies[Symbols.RootBti,CheckBti]; END; FixSelection: PROCEDURE [sw: Window.Handle, left, right: CARDINAL, set: BOOLEAN] = { OPEN TextSW; Selection.Clear[]; --IF set THEN [] _ SetSecondarySelection[sw,left,right,grayBox] --ELSE RemoveSecondarySelection[sw,SecondarySelectionFromPosition[sw,left]]}; TextSW.SetSelection[sw,left,right]}; GetContext: PROCEDURE [w: Window.Handle] RETURNS [frame: GFHandle] = BEGIN mod: STRING _ [40]; h: Source.Handle; retry: BOOLEAN _ TRUE; frame _ Source.GetGF[w]; IF frame # NIL THEN RETURN; h _ LOOPHOLE[FileSW.GetFile[w].s]; Source.LittleParser[h, mod]; IF mod.length = 0 THEN RETURN[NIL]; frame _ IF String.EqualString[mod, DContext.GetModule[]] THEN DContext.GetGlobal[] ELSE Gf.Frame[mod ! Frames.Invalid => CONTINUE]; Source.Validate[h,frame]; Source.SetGF[w,frame]; RETURN END; MakeEXOI: PROCEDURE [s: STRING] RETURNS [DebugFormat.EXOI] = BEGIN OPEN String; RETURN[SELECT TRUE FROM EqualString[s,"PROC"L] => entry, EqualString[s,"PROCEDURE"L] => entry, EqualString[s,"RETURN"L] => exit, ENDCASE => in]; END; Reload: PROC [gf: GFHandle, w: Window.Handle] = { fileId: STRING _ [40]; file: Source.Handle; Inner: PROC [base: SymbolTable.Base] = { Strings.AppendString[fileId,base.sourceFile]}; AddDollar[ToolWindow.WindowForSubwindow[w]]; Copier.Outer[DSyms.GFrameMdi[gf],Inner]; file _ Source.Open[fileId]; IF file = NIL THEN RETURN; Source.LoadWindow[fileId, gf, file, TextSW.GetPosition[w,0]]}; SetUp: PROCEDURE [w: Window.Handle, sc: Source.SC, bt: DebugFormat.BT] = BEGIN br: Source.BreakRec; text: STRING; IF ~ValidateSource[w] THEN GOTO fail; text _ Selection.Convert[string]; IF text = NIL THEN GOTO fail; br _ [sc: sc, bt: [ex: MakeEXOI[text], bt: bt]]; Storage.FreeString[text]; IF ~Break[w, br] THEN GOTO fail; EXITS fail => UserTerminal.BlinkDisplay[]; END; ValidateSource: PROC [w: Window.Handle] RETURNS [BOOLEAN] = BEGIN OPEN Selection; IF ~FileSW.IsIt[w] THEN RETURN[FALSE]; RETURN[Convert[subwindow] = w] END; -- GlobalFrame/SourceWindow correspondence stuff GetGF: PUBLIC PROCEDURE [w: Window.Handle] RETURNS [MachineDefs.GFHandle] = BEGIN item: ItemHandle _ FindItem[w]; RETURN[IF item = NIL THEN NIL ELSE item.gf]; END; GetWindow: PUBLIC PROCEDURE [gf: MachineDefs.GFHandle] RETURNS [w: Window.Handle] = BEGIN proc: FileWindow.EnumerateProcType = BEGIN item: ItemHandle _ FindItem[sw]; IF item # NIL AND item.gf = gf THEN w _ sw; RETURN[IF w = NIL THEN continue ELSE stop]; END; w _ NIL; FileWindow.Enumerate[proc]; RETURN[w] END; IgnoreTimeStamp: PUBLIC PROCEDURE [w: Window.Handle] RETURNS [BOOLEAN] = BEGIN item: ItemHandle _ FindItem[w]; RETURN[IF item = NIL THEN FALSE ELSE item.trustTime]; END; ResetFrames: PUBLIC PROCEDURE = BEGIN proc: FileWindow.EnumerateProcType = BEGIN ResetGF[sw]; RETURN[continue] END; FileWindow.Enumerate[proc]; END; SetGF: PUBLIC PROCEDURE [w: Window.Handle, gf: MachineDefs.GFHandle] = BEGIN item: ItemHandle; AddItem[w, gf]; item _ FindItem[w]; IF item # NIL THEN item.trustTime _ TRUE; -- not clear how it could = NIL but... END; myContext: Context.Type = Context.UniqueType[]; ItemHandle: TYPE = POINTER TO Item; Item: TYPE = RECORD [ trustTime: BOOLEAN, gf: MachineDefs.GFHandle]; AddItem: PROCEDURE [sw: Window.Handle, gf: MachineDefs.GFHandle] = BEGIN item: ItemHandle _ FindItem[sw]; IF item # NIL THEN {item.gf _ gf; item.trustTime _ FALSE; RETURN}; item _ Storage.Node[SIZE[Item]]; item^ _ [gf: gf, trustTime: FALSE]; Context.Create[myContext, item, DestroyItem, sw]; RETURN END; DeleteItem: PROCEDURE [sw: Window.Handle] = INLINE BEGIN Context.Destroy[myContext, sw]; END; DestroyItem: PROCEDURE [item: Context.Data, sw: Window.Handle] = BEGIN Storage.Free[item]; END; FindItem: PROCEDURE [sw: Window.Handle] RETURNS [item: ItemHandle] = INLINE { RETURN[IF sw # NIL THEN Context.Find[myContext, sw] ELSE NIL]}; ResetGF: PROC [w: Window.Handle] = BEGIN item: ItemHandle = FindItem[w]; IF item # NIL THEN BEGIN item.gf _ MachineDefs.NullGF; -- forget old one (else funny breakpoints) item.trustTime _ FALSE; END; END; SomethingChanged: FileWindow.NotifyProcType = BEGIN SELECT event FROM create => AddItem[sw, MachineDefs.NullGF]; destroy => DeleteItem[sw]; load => ResetGF[sw]; edit => ResetGF[sw]; reset => ResetGF[sw]; store => ResetGF[sw]; ENDCASE => ERROR; END; END.