DIRECTORY
AMBridge USING [ TVToProc ],
AMEvents USING [ CallDebugger ],
AMTypes USING [ Error, TV ],
Atom USING [ PutProp, GetPName, GetProp, PropList ],
BasicTime USING [ GMT, Now, Unpack, Unpacked ],
Commander USING [ CommandProc, GetProperty, Handle, Register ],
FS USING [ StreamOpen, Error ],
Interpreter USING [ Evaluate ],
IO,
Log,
PrincOps USING [ BytePC, FrameHandle, GFTIndex ],
PrincOpsUtils USING [ LongCOPY, GetReturnFrame ],
ProcessProps USING [ GetPropList ],
RefTab USING [ Create, Fetch, Ref, Store ],
Rope USING [ Flatten, InlineLength, ROPE, Text ],
SpyTypes USING [ DoWriteDataProc, IsActiveProc, WriteTraceProc ]
;
Reporting and Suspending
WP: TYPE = REF WPRec;
WPRec:
TYPE =
RECORD [
proc: WhereProc,
fixedWhereData: REF,
defaultIfNotFound: Log.DNFProc←NIL
];
RegisterWhereToReport:
PUBLIC
PROC[
proc: WhereProc, where: WhereToReport, fixedWhereData: REF,
defaultIfNotFound: Log.DNFProc] = {
Atom.PutProp[$ReportStreams, where, NEW[WPRec←[proc: proc, fixedWhereData: fixedWhereData, defaultIfNotFound: defaultIfNotFound]]];
};
FindWhere:
PUBLIC
PROC[where: WhereToReport, whereData:
REF]
RETURNS [s:
IO.
STREAM] = {
wp: WP;
IF where=NIL THEN RETURN[pd.sysOut];
wp ← NARROW[Atom.GetProp[$ReportStreams, where]];
IF wp=NIL THEN RETURN[pd.sysOut];
s←wp.proc[wp.fixedWhereData, whereData];
IF s#NIL THEN RETURN[s];
RETURN[IF s#NIL THEN s ELSE IF wp.defaultIfNotFound=NIL OR wp.defaultIfNotFound[where, whereData] THEN pd.sysOut ELSE NIL];
};
Report:
PUBLIC
PROC[remark:
ROPE, where: WhereToReport, whereData:
REF ←
NIL] = {
reportS: STREAM ← FindWhere[where, whereData];
seconds: INT;
IF remark=NIL OR reportS = NIL THEN RETURN;
seconds ← LogTime[reportS, where];
reportS.PutF[" %02d: %s\n", int[seconds], rope[remark]]; -- wish I could affort looking up caller.
};
ReportFR:
PUBLIC
PROC[remark:
ROPE, where: WhereToReport, whereData:
REF,
a1, a2: IO.Value] = {
Report[IO.PutFR[remark, a1, a2], where, whereData];
};
Problem:
PUBLIC PROC[
remark: ROPE, where: WhereToReport, whereData: REF] = TRUSTED {
IF remark=NIL THEN remark←"Unspecified problem";
Report[remark, where, whereData];
IF pd.attended THEN AMEvents.CallDebugger[remark];
};
ProblemFR:
PUBLIC PROC[
remark: ROPE, where: WhereToReport, whereData: REF, a1, a2: IO.Value] = TRUSTED {
Problem[IO.PutFR[remark, a1, a2], where, whereData];
};
ProblemBool:
PUBLIC PROC[
remark: ROPE, where: WhereToReport, bool: BOOL, whereData: REF]
RETURNS[sameBool: BOOL] = {
sameBool𡤋ool;
Problem[remark, where, whereData];
};
ProblemHandle:
PUBLIC PROC[ remark:
ROPE, where: WhereToReport,
handle: ThHandle, whereData: REF]
RETURNS[sameHandle: ThHandle] = {
sameHandle←handle;
Problem[remark, where, whereData];
};
CmdWhere: WhereProc = {
pl: Atom.PropList ← ProcessProps.GetPropList[];
ch: Commander.Handle;
IF pl=NIL THEN RETURN[NIL];
ch ← NARROW[Commander.GetProperty[$CommanderHandle, pl]];
IF ch=NIL THEN RETURN[NIL];
RETURN[ch.err];
};
SetAttended: Commander.CommandProc = {
pd.attended ← TRUE;
Report["Attended[TRUE]", $Cmd, NIL];
};
ClearAttended: Commander.CommandProc = {
pd.attended ← FALSE;
Report["Attended[FALSE]", $Cmd, NIL];
};
LogTime:
PROC[s:
IO.
STREAM, where:
ATOM]
RETURNS [seconds:
INT] = {
oldT: REF BasicTime.Unpacked ← NARROW[RefTab.Fetch[logTimes, where].val];
now: BasicTime.GMT ← BasicTime.Now[];
nowU: BasicTime.Unpacked ← BasicTime.Unpack[now];
seconds ← nowU.second;
nowU.second ← 0;
nowU.secondsThisYear ← 0;
IF oldT=
NIL
THEN {
oldT←NEW[BasicTime.Unpacked];
[]←RefTab.Store[logTimes, where, oldT];
};
IF nowU=oldT^ THEN RETURN;
oldT^ ← nowU;
s.PutF["%g\n", time[now]];
};
logTimes: RefTab.Ref ← RefTab.Create[];
Associates Where atoms with print times.
Procedures for performance monitoring and debugging
loggingGroups: PUBLIC CARDINAL𡤀
Noop: PUBLIC PROC = {NULL};
RealLogInfo:
TYPE =
RECORD [
logD1: LONG CARDINAL,
logD2: LONG CARDINAL,
length: CARDINAL,
logCode: PACKED SEQUENCE maxLength: CARDINAL OF CHAR
];
rli: REF RealLogInfo ← NEW[RealLogInfo];
WriteTrace: WriteTraceProc ← NIL;
DoWriteData: DoWriteDataProc ← NIL;
IsActive: IsActiveProc ← NIL;
WriteData:
PUBLIC
PROC[info: Log.LogInfo] =
TRUSTED {
logCode: Rope.Text;
nbytes: NAT;
IF loggingGroups=0 OR info.logCode =NIL THEN RETURN;
logCode←Rope.Flatten[Atom.GetPName[info.logCode]];
rli.logD1←info.logD1;
rli.logD2←info.logD2;
nbytes ← MIN[logCode.InlineLength[], 20];
rli.length←nbytes;
PrincOpsUtils.LongCOPY[
from:
LOOPHOLE[logCode,
LONG
POINTER]+2,
to: LOOPHOLE[rli, LONG POINTER]+6, nwords: (nbytes+1)/2];
DoWriteData[type: CODE[RealLogInfo], size: SIZE[RealLogInfo[nbytes]], data: LOOPHOLE[rli]];
};
Here:
PUBLIC
PROC =
TRUSTED {
frame: PrincOps.FrameHandle;
IF loggingGroups=0 OR ~IsActive[] THEN RETURN;
frame ← PrincOpsUtils.GetReturnFrame[];
IF frame=NIL THEN RETURN;
WriteTrace[frame.accesslink.gfi, frame.pc];
};
DoLog:
PUBLIC
PROC[groups:
CARDINAL] = {
IF WriteTrace=
NIL
THEN {
WriteTrace ← NARROW[FetchBinding[$WriteTrace], REF WriteTraceProc]^;
DoWriteData ← NARROW[FetchBinding[$WriteData], REF DoWriteDataProc]^;
IsActive ← NARROW[FetchBinding[$IsActive], REF IsActiveProc]^;
};
loggingGroups← IF WriteTrace#NIL THEN groups ELSE 0;
};
FetchBinding:
PROC[field:
ATOM]
RETURNS [
REF] = {
RETURN[Atom.GetProp[$Interfaces, field]];
};
Initialization
pd.ch ← NARROW[Commander.GetProperty[$CommanderHandle, ProcessProps.GetPropList[]]];
IF pd.ch#NIL THEN { pd.sysIn ← pd.ch.in; pd.sysOut ← pd.ch.out; };
RegisterWhereToReport[CmdWhere, $Cmd, NIL, NIL];
Commander.Register["Attended", SetAttended, "Break on errors"];
Commander.Register["Unattended", ClearAttended, "Log on errors, then muddle on."];
}.