
<<M2Impl.mesa>>
<<Last Edited by: Gutknecht, October 2, 1985 3:00:03 pm PDT>>
    <<Satterthwaite December 9, 1985 5:38:18 pm PST>>

DIRECTORY
Rope: TYPE USING [ROPE],
FS: TYPE USING [StreamOpen, Error],
ViewerIO: TYPE USING [CreateViewerStreams],
IO: TYPE USING [STREAM, GetChar, PutChar, Put, char, card, int, real, rope, Close],
Commander: TYPE USING [Handle, Register],
CommandTool: TYPE USING [ArgumentVector, Parse, Failed],
M2P: TYPE USING [InitP];

M2Impl: CEDAR PROGRAM
IMPORTS FS, ViewerIO, IO, Commander, CommandTool, M2P =

BEGIN

M2: PROC [cmd: Commander.Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] =
{ arg: CommandTool.ArgumentVector =
CommandTool.Parse [cmd: cmd ! CommandTool.Failed => msg _ "failed"];
FOR i: NAT IN [1..arg.argc) DO
(cmd.out).Put [IO.rope ["[ "], IO.rope [arg[i]], IO.char [' ]];
M2P.InitP [cmd.out, arg[i]]; (cmd.out).Put [IO.char[']], IO.char['\n]]
ENDLOOP;
(cmd.out).PutChar ['\n] };

Decode: PROC [cmd: Commander.Handle] RETURNS [result: REF _ NIL, msg: Rope.ROPE _ NIL] =

{ OBJFILE: CARDINAL = 220;
mnem: PACKED ARRAY [0..34*48) OF CHAR;
id: CARDINAL _ 0;

Enter: PROC [s: REF TEXT] = {
FOR i: CARDINAL IN [0..48) DO mnem[id] _ s[i]; id _ id+1 ENDLOOP };

DecodeFile: PROC [file, outmed: Rope.ROPE] =
{ f, g: IO.STREAM; ch, ch1, ch2, ch3: CHAR; opened: BOOLEAN _ TRUE;
n: LONG CARDINAL; N, i, j, k: CARDINAL; pc: CARDINAL _ 0; len: REAL;

nextno: PROC RETURNS [CARDINAL] =
{ ch: CHAR = f.GetChar; ch1: CHAR = f.GetChar;
RETURN [ch.ORD*256 + ch1.ORD] };

PutTab: PROC =
{ N: CARDINAL = nextno [];
FOR n: CARDINAL IN [0..N) DO
ch: CHAR = f.GetChar; ch1: CHAR = f.GetChar;
g.Put [IO.card[ch.ORD*256 + ch1.ORD], IO.char['\n]];
ENDLOOP;
g.PutChar ['\n] };

f _ FS.StreamOpen [file ! FS.Error => { opened _ FALSE; CONTINUE }];
IF opened THEN
{ IF outmed # "*" THEN g _ FS.StreamOpen [outmed, $create]
ELSE [out: g] _ ViewerIO.CreateViewerStreams ["Decode Files"];
g.Put [IO.rope[file], IO.char['\n], IO.char['\n]];
IF nextno [] = OBJFILE THEN
{ g.Put [IO.rope["imports"], IO.char['\n]];
N _ nextno []; i _ 0;
WHILE i # N DO
g.Put [IO.card[nextno []], IO.card[nextno []], IO.char[' ]];
ch _ f.GetChar; j _ ch.ORD-1;
WHILE j # 0 DO g.PutChar [f.GetChar]; j _ j - 1 ENDLOOP;
g.PutChar ['\n];
i _ i + 1
ENDLOOP;
g.PutChar ['\n];
g.Put [IO.rope["code"], IO.char['\n]];
k _ 0; N _ nextno [];
WHILE pc # N DO g.Put [IO.card[pc], IO.char[' ]];
ch _ f.GetChar; i _ ch.ORD*6;
WHILE mnem[i] < 'a DO g.PutChar [mnem[i]]; i _ i+1 ENDLOOP;
g.PutChar [' ];
SELECT mnem[i] FROM
'a, 'f => { pc _ pc + 1 };
'b, 'g => { ch _ f.GetChar; g.Put [IO.card[ch.ORD]]; pc _ pc + 2 };
'c, 'l => { ch _ f.GetChar; ch1 _ f.GetChar;
        IF mnem[i] = 'l THEN g.Put [IO.int[ch.ORD*256+ch1.ORD]]
        ELSE g.Put [IO.card[ch.ORD*256+ch1.ORD]];
        pc _ pc + 3 };
'd, 'm => { ch _ f.GetChar; ch1 _ f.GetChar;
        ch2 _ f.GetChar; ch3 _ f.GetChar;
        n _ ch3.ORD+(ch2.ORD+(ch1.ORD+ch.ORD*256)*256)*256;
        IF mnem[i] = 'm THEN  { i _ 32*48 + n*6;
          WHILE mnem[i] # '. DO g.PutChar [mnem[i]]; i _ i+1 ENDLOOP }
        ELSE g.Put [IO.int[ LOOPHOLE [n, LONG INTEGER]]];
        pc _ pc + 5 };
'e => {  ch _ f.GetChar;
        g.Put [IO.int [IF ch.ORD >= 128 THEN ch.ORD - 256 ELSE ch.ORD]];
        g.PutChar [' ];
        ch _ f.GetChar; g.Put [IO.card[ch.ORD]];
        pc _ pc + 3 };
'h => { ch _ f.GetChar; g.Put [IO.card[ch.ORD], IO.char [' ]];
        ch _ f.GetChar;
        g.Put [IO.card[ch.ORD/16], IO.char [' ], IO.card[ch.ORD MOD 16]];
        pc _ pc + 3 };
'i => { ch _ f.GetChar;
        g.Put [IO.card[ch.ORD/128], IO.card[(ch.ORD/64) MOD 2]];
        g.Put [IO.card[(ch.ORD/32) MOD 2], IO.card[(ch.ORD/16) MOD 2]];
        g.PutChar [' ];
        g.Put [IO.card[ch.ORD MOD 16], IO.char [' ]];
        ch _ f.GetChar;
        g.Put [IO.card[ch.ORD/16], IO.char[' ], IO.card[ch.ORD MOD 16]];
        pc _ pc + 3 };
'j => { ch _ f.GetChar;
        g.Put [IO.card[(ch.ORD/32) MOD 2], IO.char[' ]];
        g.Put [IO.card[(ch.ORD/16) MOD 2], IO.char[' ]];
        g.Put [IO.card[ch.ORD MOD 16]];
        pc _ pc + 2 };
'k => { ch _ f.GetChar;
        g.Put [IO.card[ch.ORD/128], IO.card[(ch.ORD/64) MOD 2]];
        g.Put [IO.card[(ch.ORD/32) MOD 2], IO.card[(ch.ORD/16) MOD 2]];
        g.PutChar [' ];
        g.Put [IO.card[ch.ORD MOD 16], IO.char [' ]];
        ch _ f.GetChar;
        g.Put [IO.int[IF ch.ORD >= 128 THEN ch.ORD - 256 ELSE ch.ORD]];
        pc _ pc + 3 };
ENDCASE;
g.PutChar ['\n]; k _ k + 1
ENDLOOP;
IF k > 0 THEN { len _ N;
g.Put [IO.rope ["average instruction length "], IO.real[len/k], IO.char['\n]] };
g.PutChar ['\n];
g.Put [IO.rope["entries"], IO.char['\n]]; PutTab;
g.Put [IO.rope["linkages"], IO.char['\n]]; PutTab;
g.Put [IO.rope["data"], IO.char['\n]];
g.Put [IO.card[nextno []], IO.char['\n], IO.char['\n]]; 
g.Put [IO.rope["literals"], IO.char['\n]];
N _ nextno []; g.Put [IO.card[N], IO.char['\n]];
FOR i: CARDINAL IN [0..N) DO ch _ f.GetChar;
g.PutChar [IF ch = '\000 THEN '\n ELSE ch]
ENDLOOP;
g.PutChar ['\n];
IF outmed # "*" THEN IO.Close [g];
IO.Close [f] }
ELSE (cmd.out).Put [IO.rope ["not an obj file"], IO.char['\n]] }
ELSE (cmd.out).Put [IO.rope ["failed"], IO.char['\n]] };

arg: CommandTool.ArgumentVector =
CommandTool.Parse [cmd: cmd ! CommandTool.Failed => msg _ "failed"];
i: CARDINAL _ 1;

Enter ["XOPa  XOPa  XOPa  XOPa  XOPa  XOPa  XOPa  XOPa  "];
Enter ["XOPa  XOPa  XOPa  XOPa  XOPa  XOPa  XOPa  XOPa  "];
Enter ["XOPa  XOPa  XOPa  XOPa  XOPa  XOPa  XOPa  XOPa  "];
Enter ["XOPa  XOPa  XOPa  XOPa  XOPa  XOPa  XOPa  XOPa  "];

Enter ["XOPd  XOPd  XOPd  XOPd  XOPd  XOPd  XOPd  XOPd  "];
Enter ["XOPd  XOPd  XOPd  XOPd  XOPd  XOPd  XOPd  XOPd  "];
Enter ["XOPd  DFCd  LIQBd XOPd  XOPd  XOPd  J5d   DJd   "];
Enter ["CALLm XOPd  XOPd  XOPd  XOPd  XOPd  XOPd  XOPd  "];

Enter ["***a  ***a  RXa   BCa   ADDa  SUBa  LADDa LSUBa "];
Enter ["DUPa  DISa  EXCHa EXDISaSFCa  SFCIa RETNa XOPa  "];
Enter ["XOPa  SMULa UDIVa XOPa  KFCa  XOPa  J1a   SJa   "];
Enter ["LC0a  LC1a  LC2a  LC3a  LC4a  LC5a  LC6a  LC7a  "];

Enter ["LR0f  LR1f  LR2f  LR3f  LR4f  LR5f  LR6f  LR7f  "];
Enter ["LR8f  LR9f  LR10f LR11f LR12f LR13f LR14f LR15f "];
Enter ["SR0f  SR1f  SR2f  SR3f  SR4f  SR5f  SR6f  SR7f  "];
Enter ["SR8f  SR9f  SR10f SR11f SR12f SR13f SR14f SR15f "];

Enter ["QORj  QANDj QRXj  QBCj  QADDj QSUBj QLADDjQLSUBj"];
Enter ["ALSb  ALb   ASLb  ASb   CSTb  XOPb  RETb  RETKb "];
Enter ["LIPb  SIPb  LIBb  SFPb  ADDBb SUBBb J2b   JBb   "];
Enter ["RBb   WBb   RSBb  WSBb  PINb  POUTb XOPb  PSBb  "];

Enter ["LRI0g LRI1g LRI2g LRI3g LRI4g LRI5g LRI6g LRI7g "];
Enter ["LRI8g LRI9g LRI10gLRI11gLRI12gLRI13gLRI14gLRI15g"];
Enter ["SRI0g SRI1g SRI2g SRI3g SRI4g SRI5g SRI6g SRI7g "];
Enter ["SRI8g SRI9g SRI10gSRI11gSRI12gSRI13gSRI14gSRI15g"];

Enter ["RORi  RANDi RRXi  RBCi  RADDi RSUBi RLADDiRLSUBi"];
Enter ["RXORi ***i  RFUi  ***i  RVADDiRVSUBiRUADDiRUSUBi"];
Enter ["LGFc  LFCl  LIDBc XOPc  ADDDBcSUBDBcJ3c   JDBl  "];
Enter ["RAIh  WAIh  RRIh  WRIh  INb   OUTb  XOPh  XOPh  "];

Enter ["***k  RJEBk RJLBk RJLEBk***k  RJNEBkRJGEBkRJGBk "];
Enter ["***k  RJNEJkRJGEJkRJGBJk***k  RJEBJkRJLBJkRJLEJk"];
Enter ["JEBBe JNEBBeJEBBJeJNEBJeXOPe  XOPe  XOPe  XOPe  "];
Enter ["SHLc  SHRc  SHDc  FSDBc FLIPc FLOPc XOPc  XOPc  "];

Enter ["Trap. Move. IMul. IDiv. Mod.  RAdd. RSub. RMul. "];
Enter ["RDiv. Alloc.Dlloc.Bit.  Bits. ***.  ***.  ***.  "];

WHILE i+1 < arg.argc DO
DecodeFile [arg[i], arg[i+1]];
i _ i + 2
ENDLOOP;
IF i < arg.argc THEN DecodeFile [arg[i], "*"] };

Commander.Register [key: "modula", proc: M2, doc: "Modula-2 compiler"];
Commander.Register[key: "decode", proc: Decode, doc: "Decode Modula-2 object file"];

END.

