OD: Commander.CommandProc =
TRUSTED {
inputSTREAM: IO.STREAM;
outputSTREAM: IO.STREAM;
inputFileName: Rope.ROPE;
outputFileName: Rope.ROPE;
outputRadix: NAT;
createViewer: BOOL ← FALSE;
argv: CommandTool.ArgumentVector;
bytesRead: NAT;
buffer: REF TEXT ← NEW[TEXT[256]];
argIndex: NAT ← 1;
token: Rope.ROPE;
filePos: INT ← 0;
words: BOOL ← FALSE;
word: CARDINAL;
chars: STRING ← [16];
out: IO.STREAM ← cmd.out;
NextToken:
PROC
RETURNS [t: Rope.
ROPE] = {
IF argIndex >= argv.argc THEN RETURN [NIL];
t ← argv[argIndex];
argIndex ← argIndex + 1;
};
Case:
PROC [c: Rope.
ROPE]
RETURNS [
BOOL] = {
RETURN [Rope.Equal[c, token, FALSE]];
};
OutByte:
PROC [c:
CHAR] = {
IF (filePos MOD 16) = 0 THEN outputSTREAM.PutF[IF filePos > LAST[CARDINAL] THEN " %08x" ELSE " %04x", IO.card[filePos]];
chars[filePos MOD 16] ← IF c IN [40C..176C] THEN c ELSE '.;
IF words THEN word ← word * 256 + LOOPHOLE[c, CARDINAL];
SELECT
TRUE
FROM
words AND (filePos MOD 2) = 1 => outputSTREAM.PutF[" %04x", IO.card[word]];
NOT words => outputSTREAM.PutF[" %02x", IO.card[LOOPHOLE[c, CARDINAL]]];
ENDCASE;
IF (filePos
MOD 16) = 15
THEN {
outputSTREAM.PutF[" "];
FOR j: NAT IN [0..16) DO outputSTREAM.PutChar[chars[j]]; ENDLOOP;
outputSTREAM.PutChar['\n];
};
filePos ← filePos + 1;
};
chars.length ← 16;
argv ← CommandTool.Parse[cmd ! CommandTool.Failed => {msg ← errorMsg; CONTINUE; }];
IF argv = NIL THEN RETURN[$Failure, msg];
DO
token ← NextToken[];
IF token.Length[]=0 THEN EXIT;
SELECT
TRUE
FROM
Case["-if"] => inputFileName ← NextToken[];
Case["-of"] => outputFileName ← NextToken[];
Case["-base"] => outputRadix ← Convert.IntFromRope[NextToken[]];
Case["-bytes"] => words ← FALSE;
Case["-words"] => words ← TRUE;
Case["-viewer"] => createViewer ← TRUE;
ENDCASE => {
out.PutF["Unknown switch token: %s\n", IO.rope[token]];
LOOP;
};
ENDLOOP;
{
ENABLE {
IO.EndOfStream => {
out.PutChar['\n];
CONTINUE;
};
};
IF inputFileName.Length[] = 0 OR outputFileName.Length[] = 0 THEN RETURN;
inputSTREAM ← FS.StreamOpen[fileName: inputFileName, streamOptions: [FALSE, TRUE, TRUE, TRUE, TRUE]];
outputSTREAM ← FS.StreamOpen[fileName: outputFileName, accessOptions: $create];
DO
bytesRead ← inputSTREAM.GetBlock[buffer];
FOR i: NAT IN [0..bytesRead) DO OutByte[buffer[i]]; ENDLOOP;
IF bytesRead # 256 THEN EXIT;
ENDLOOP;
};
IF inputSTREAM#NIL THEN inputSTREAM.Close[];
IF outputSTREAM#NIL THEN outputSTREAM.Close[];
};
}.