<> <> <> <> DIRECTORY AMBridge, Atom, CD, CDAtomicObjects, CDCommandOps, CDDirectory, CDEvents, CDOps, CDProperties, CDSequencer, CDViewer, IO, PopUpSelection USING [Request], 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, PopUpSelection, 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] = { 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.WriteRopes[ " Look: ob, inst, design, comm, specificRef, viewer\n", " Call: Include[x]\n"]; SIGNAL debug; TerminalIO.WriteRope["debugger disabled\n"]; }; DoInclude: PROC [x: REF, comm: CDSequencer.Command] RETURNS [r: Rope.ROPE_NIL] = { <<--Implements Include, which is called interactively through the debugger>> 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] }; DebugComm: PROC [comm: CDSequencer.Command] = { 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"]; }; SELECT PopUpSelection.Request[ header: "Debug options", choice: LIST["detached debug", "locked debug"], headerDoc: "discard menu for not debugging", choiceDoc: LIST["not monitored; can still issue commands", "safe, but can't issue commands"], timeOut: 20 ] FROM 1 => ForkedBreak[]; 2 => InLineBreak[]; ENDCASE => TerminalIO.WriteRope["skipped\n"]; }; NewDesign: CDEvents.EventProc = { lastDesign _ design }; PrintObjectClass: PrintTV.TVPrintProc = TRUSTED { c: REF READONLY CD.ObjectClassRec _ NARROW[AMBridge.TVToRef[tv]]; stream.PutRope[ClassRope[c]] }; ClassRope: PROC [c: REF READONLY CD.ObjectClassRec] RETURNS [Rope.ROPE] = TRUSTED { RETURN [SELECT TRUE FROM c=NIL => "NIL class", Rope.IsEmpty[c.description] AND c.objectType#NIL => Atom.GetPName[c.objectType], ENDCASE => c.description] }; PrintInstance: PrintTV.TVPrintProc = TRUSTED { 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 }; IlLength: PROC [il: CD.InstanceList] RETURNS [l: INT_0] = { FOR cl: CD.InstanceList _ il, cl.rest WHILE cl#NIL DO l _ l+1 ENDLOOP; }; PrintCellPtr: PrintTV.TVPrintProc = TRUSTED { cp: REF READONLY CD.CellRep _ NARROW[AMBridge.TVToRef[tv]]; stream.PutF["(%g elements)", IO.int[IlLength[cp.contents]]]; }; PrintObject: PrintTV.TVPrintProc = TRUSTED { 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 }; 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 { 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]] ]; }; PrintTechnology: PrintTV.TVPrintProc = TRUSTED { t: REF READONLY CD.TechnologyRep = NARROW[AMBridge.TVToRef[tv]]; stream.PutRope[TechName[t]] ; }; Impl: PROC [] = { 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]; } }; Impl[]; END.