<> <> <> <> DIRECTORY Commander USING [CommandProc, Register], CommandTool USING [ArgumentVector, Failed, Parse], Convert: TYPE USING [IntFromRope], FS: TYPE USING [StreamOpen], IO, Rope; ODImpl: PROGRAM IMPORTS Commander, CommandTool, Convert, FS, IO, Rope = { <> 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]]; 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[]; }; <> Commander.Register["OD.~", OD, "Dump file in radix"]; }.