CDDebugCommands.mesa (part of ChipNDale)
Copyright © 1983, 1986 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, June 29, 1983 4:44 pm
Last edited by: Christian Jacobi, August 29, 1986 11:19:28 am PDT
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𡤀] = {
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.