<> <> <> <> <> DIRECTORY AMBridge, Atom, CD, CDAtomicObjects, CDCommandOps, CDDirectory, CDEvents, CDOps, CDProperties, CDSequencer, CDViewer, IO, List, PrintTV, Process USING [Detach], Rope, RuntimeError USING [UNCAUGHT], TerminalIO, UserProfile, ViewerClasses USING [Viewer]; CDDebugCommands: CEDAR PROGRAM IMPORTS AMBridge, Atom, CD, CDCommandOps, CDDirectory, CDEvents, CDOps, CDProperties, CDSequencer, CDViewer, IO, List, PrintTV, Process, Rope, RuntimeError, TerminalIO, UserProfile = BEGIN lastDesign: CD.Design; -- last created or debugged design; accessable from debugger debug: SIGNAL = CODE; BreakProc: PROC [comm: CDSequencer.Command] = BEGIN ENABLE ABORTED => TerminalIO.WriteRope["debugger aborted\n"]; Include: PROC [x: REF_NIL] RETURNS [Rope.ROPE] = {--called from debugger RETURN [DoInclude[x, comm]] }; design: CD.Design _ comm.design; ob: CD.Object _ NIL; inst: CD.Instance _ CDOps.SelectedInstance[design].first; specificRef: REF _ NIL; viewer: ViewerClasses.Viewer _ CDViewer.GetViewer[comm]; IF inst#NIL THEN {ob _ inst.ob; specificRef _ ob.specificRef}; lastDesign _ design; TerminalIO.WriteRope[" Look: ob, inst, design, comm, specificRef, viewer\n"]; TerminalIO.WriteRope[" Call: Include[x]\n"]; SIGNAL debug; TerminalIO.WriteRope["debugger disabled\n"]; END; DoInclude: PROC [x: REF, comm: CDSequencer.Command] RETURNS [r: Rope.ROPE_NIL] = <<--Implements Include, which is called interactively through the debugger>> BEGIN WITH x SELECT FROM ob: CD.Object => { TerminalIO.WriteRope[r _ CDOps.ObjectInfo[ob]]; TerminalIO.WriteRope[" put down from interpreter\n"]; CDOps.IncludeObjectI[comm.design, ob, comm.pos]; }; inst: CD.Instance => { TerminalIO.WriteRope[r _ CDOps.ObjectInfo[inst.ob]]; TerminalIO.WriteRope[" put down from interpreter\n"]; CDOps.IncludeInstance[comm.design, inst]; }; rob: REF CD.Object => RETURN[DoInclude[rob^, comm]]; rrob: REF REF CD.Object => RETURN[DoInclude[rrob^^, comm]]; rinst: REF CD.Instance => RETURN[DoInclude[rinst^, comm]]; rrinst: REF REF CD.Instance => RETURN[DoInclude[rrinst^^, comm]]; ENDCASE => { r _ Rope.Cat[ IF x=NIL THEN "NIL" ELSE CDCommandOps.ToRope[x, "unknown"], "; not included" ]; }; CDOps.DoTheDelayedRedraws[comm.design] END; DebugComm: PROC [comm: CDSequencer.Command] = BEGIN ForkedBreak: PROC = TRUSTED { TerminalIO.WriteRope["**open detached debugger view\n"]; Process.Detach[FORK BreakProc[comm]] }; InLineBreak: PROC = { TerminalIO.WriteRope["**open locked debugger view\n"]; BreakProc[comm]; TerminalIO.WriteRope["lock released\n"]; }; n: INT_0; n _ TerminalIO.RequestSelection[ label: "Debug options", choice: LIST["detached debug", "locked debug"], timeOut: 5 ]; SELECT n FROM 1 => ForkedBreak[]; 2 => InLineBreak[]; ENDCASE => TerminalIO.WriteRope["skipped\n"]; END; NewDesign: CDEvents.EventProc = { lastDesign _ design }; PrintObjectClass: PrintTV.TVPrintProc = TRUSTED BEGIN c: REF READONLY CD.ObjectClassRec _ NARROW[AMBridge.TVToRef[tv]]; stream.PutRope[ClassRope[c]] END; ClassRope: PROC [c: REF READONLY CD.ObjectClassRec] RETURNS [Rope.ROPE] = TRUSTED BEGIN IF c=NIL THEN RETURN ["NIL CLASS"] ELSE IF Rope.IsEmpty[c.description] THEN RETURN [Atom.GetPName[c.objectType]] ELSE RETURN [c.description] END; PrintInstance: PrintTV.TVPrintProc = TRUSTED BEGIN ENABLE RuntimeError.UNCAUGHT => GOTO someErr; x: REF; i: REF READONLY CD.InstanceRep _ NARROW[AMBridge.TVToRef[tv]]; IF i=NIL THEN RETURN [useOld_TRUE]; stream.PutRope["{ob: "]; PrintTV.Print[AMBridge.TVForReferent[i.ob], stream, 1]; IF depth>0 THEN { stream.PutF[", at: [%g, %g]", IO.int[i.location.x], IO.int[i.location.y]]; IF i.orientation#CD.original THEN stream.PutF[", orient: %g", IO.int[i.orientation]]; IF i.selected THEN stream.PutRope[", S"]; x _ CDProperties.GetListProp[i.properties, $SignalName]; IF x#NIL THEN stream.PutF[", SignalName: %g", IO.refAny[x]]; x _ CDProperties.GetListProp[i.properties, $InstanceName]; IF x#NIL THEN stream.PutF[", InstanceName: %g", IO.refAny[x]]; }; stream.PutChar['}]; EXITS someErr => useOld_TRUE END; PrintCellPtr: PrintTV.TVPrintProc = TRUSTED { cp: REF READONLY CD.CellRep _ NARROW[AMBridge.TVToRef[tv]]; stream.PutF["(%g elements)", IO.int[List.Length[LOOPHOLE[cp.contents]]]]; }; PrintObject: PrintTV.TVPrintProc = TRUSTED BEGIN ENABLE RuntimeError.UNCAUGHT => GOTO someErr; o: REF READONLY CD.ObjectRep _ NARROW[AMBridge.TVToRef[tv]]; IF o=NIL OR o.class=NIL THEN RETURN [useOld_TRUE]; stream.PutChar['{]; IF o.class.inDirectory THEN { stream.PutF1["name: %g, ", IO.rope[CDDirectory.Name[LOOPHOLE[o]]]]; }; stream.PutRope[ClassRope[o.class]]; IF depth>=1 THEN { stream.PutF[", size: [%g, %g]", IO.int[o.size.x], IO.int[o.size.y]]; IF CD.LayerTechnology[o.layer]#NIL OR o.class.wireTyped THEN stream.PutF[", layer: %g", IO.rope[CDOps.LayerName[o.layer]]]; IF ~o.class.wireTyped AND ~ISTYPE[o.specificRef, CDAtomicObjects.AtomicObsPtr] AND o.specificRef#NIL THEN { stream.PutRope[", "]; PrintTV.Print[AMBridge.TVForReferent[o.specificRef], stream, depth-1]; } }; stream.PutChar['}]; EXITS someErr => useOld_TRUE END; TechName: PROC [t: REF READONLY CD.TechnologyRep] RETURNS [Rope.ROPE] = { IF t=NIL THEN RETURN ["NIL"] ELSE IF t.name#NIL THEN RETURN [t.name] ELSE RETURN [Atom.GetPName[t.key]] }; PrintDesign: PrintTV.TVPrintProc = TRUSTED BEGIN d: REF READONLY CD.DesignRec _ NARROW[AMBridge.TVToRef[tv]]; IF d=NIL THEN RETURN [useOld_TRUE]; stream.PutF["{name: %g, technology: %g}", IO.rope[IF Rope.Length[d.name]>0 THEN d.name ELSE "(no name)"], IO.rope[TechName[d.technology]] ]; END; PrintTechnology: PrintTV.TVPrintProc = TRUSTED { t: REF READONLY CD.TechnologyRep = NARROW[AMBridge.TVToRef[tv]]; stream.PutRope[TechName[t]] ; }; Impl: PROC [] = BEGIN CDSequencer.ImplementCommand[$Debug, DebugComm]; CDEvents.RegisterEventProc[$CreateNewDesign, NewDesign]; IF UserProfile.Boolean["ChipNDale.RegisterTVPrintProcs", TRUE] THEN { PrintTV.RegisterTVPrintProc[type: CODE[CD.CellPtr], proc: PrintCellPtr]; PrintTV.RegisterTVPrintProc[type: CODE[CD.Instance], proc: PrintInstance]; PrintTV.RegisterTVPrintProc[type: CODE[CD.Object], proc: PrintObject]; PrintTV.RegisterTVPrintProc[type: CODE[CD.Design], proc: PrintDesign]; PrintTV.RegisterTVPrintProc[type: CODE[CD.Technology], proc: PrintTechnology]; } END; Impl[]; END.