MemoryDumpImpl.mesa
Copyright Ó 1990, 1992 by Xerox Corporation. All rights reserved.
Michael Plass, April 17, 1990 4:15 pm PDT
DIRECTORY Basics, IO, RefText, Commander, CommanderOps, VM;
MemoryDumpImpl: CEDAR PROGRAM
IMPORTS IO, RefText, Commander, CommanderOps, VM
~ BEGIN
bytesPerLine: NAT ~ 16;
<< XXXXXXXX: XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX *................* >>
Dump: PROC [out: IO.STREAM, byteAddress: CARD32, byteCount: INT] ~ {
startByteAddress: CARD32 ~ (byteAddress/bytesPerLine)*bytesPerLine;
limit: CARD32 ~ byteAddress+byteCount;
base: LONG POINTER TO Basics.RawBytes ~ LOOPHOLE[startByteAddress];
line: REF TEXT ¬ RefText.ObtainScratch[100];
Fetch: PROC [offset: CARD] RETURNS [BYTE] ~ TRUSTED INLINE {
RETURN [base[offset]]
};
PutChar: PROC [char: CHAR] ~ { line[line.length] ¬ char; line.length ¬ line.length + 1 };
PutHexit: PROC [nybble: [0..16)] ~ {
PutChar[(IF nybble < 10 THEN '0 ELSE 'A-10) + nybble];
};
PutHexByte: PROC [byte: BYTE] ~ {
PutHexit[byte/16];
PutHexit[byte MOD 16];
};
PutHexCard: PROC [num: Basics.LongNumber] ~ {
PutHexByte[num.hh];
PutHexByte[num.hl];
PutHexByte[num.lh];
PutHexByte[num.ll];
};
colon: CHAR ~ ':;
space: CHAR ~ ' ;
star: CHAR ~ '*;
dot: CHAR ~ '.;
tilde: CHAR ~ '~;
newline: CHAR ~ '\n;
Printable: TYPE ~ CHAR[' ..'~];
{ENABLE
VM.AddressFault => {
IO.PutBlock[out, line];
IO.PutRope[out, "<<< Address Fault >>>\n"];
CONTINUE;
};
FOR i: CARD ¬ 0, i+bytesPerLine WHILE (startByteAddress+i) < limit DO
FillLine: PROC ~ {
PutHexCard[[lc[startByteAddress+i]]];
PutChar[colon];
FOR j: CARD IN [0..bytesPerLine) DO
IF j MOD 4 = 0 THEN { PutChar[space]; };
IF startByteAddress+i+j IN [byteAddress..limit)
THEN { PutHexByte[Fetch[i+j]] }
ELSE { PutChar[space]; PutChar[space]; };
ENDLOOP;
PutChar[space];
PutChar[star];
FOR j: CARD IN [0..bytesPerLine) DO
IF startByteAddress+i+j IN [byteAddress..limit)
THEN {
char: CHAR ~ VAL[Fetch[i+j]];
PutChar[IF char IN Printable THEN char ELSE dot]
}
ELSE { PutChar[tilde] };
ENDLOOP;
PutChar[star];
PutChar[newline];
};
line.length ¬ 0;
NoMess[FillLine];
IO.PutBlock[out, line];
ENDLOOP;
};
RefText.ReleaseScratch[line];
};
MemoryDumpCommand: Commander.CommandProc ~ {
cmds: IO.STREAM ~ IO.RIS[cmd.commandLine];
GetNumber: PROC [default: CARD] RETURNS [CARD] ~ {
number: CARD ¬ default;
number ¬ IO.GetCard[cmds !
IO.EndOfStream => CONTINUE;
IO.Error => CommanderOps.Failed[cmd.procData.doc];
];
RETURN [number]
};
start: CARD ~ GetNumber[0];
count: CARD ~ GetNumber[40];
IF start = 0 THEN CommanderOps.Failed[cmd.procData.doc];
IO.PutF1[cmd.out, "%l", [rope["f"]]];
Dump[cmd.out, start, count];
IO.PutF1[cmd.out, "%l", [rope["F"]]];
};
GetMess: PROC RETURNS [BOOL] ~ TRUSTED MACHINE CODE {
"+extern int XR←msgFromMemerrHandler;\n";
"#define GetMessHelp() (XR←msgFromMemerrHandler)\n";
".GetMessHelp";
};
SetMess: PROC [BOOL] ~ TRUSTED MACHINE CODE {
"+#define SetMessHelp(new) XR←msgFromMemerrHandler = new\n";
".SetMessHelp";
};
NoMess: PROC [proc: PROC] ~ {
save: BOOL ~ GetMess[];
SetMess[FALSE];
proc[ ! UNWIND => SetMess[save]];
SetMess[save];
};
Commander.Register["MemoryDump", MemoryDumpCommand, "Dump local memory:\nMemoryDump startAddress [ byteCount ]\nParameters follow Cedar numeric literal syntax"];
END.