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;
~
BEGIN
<< 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"];