UNSAFE MODULE; IMPORT JunoRT AS RT, JunoByteCode AS BC, JunoMarshal AS Marshal, JunoValue; IMPORT Wr, Fmt, Thread; PROCEDURE JunoDisassem P (bs: RT.ByteStream; wr: Wr.T) RAISES {Wr.Failure, Thread.Alerted} = VAR a: UNTRACED REF RT.ByteCode := ADR(bs[0]); firstaddr := ADR(bs[0]); lastaddr := firstaddr + NUMBER(bs^); globalUsed := NEW(REF ARRAY OF BOOLEAN, 20); <* INLINE *> PROCEDURE Txt(t: TEXT) RAISES {Wr.Failure, Thread.Alerted} = BEGIN Wr.PutText(wr, t) END Txt; <* INLINE *> PROCEDURE Num(n: INTEGER) RAISES {Wr.Failure, Thread.Alerted} = BEGIN Txt(Fmt.Int(n)) END Num; <* INLINE *> PROCEDURE RealNum(r: JunoValue.Real) RAISES {Wr.Failure, Thread.Alerted} = BEGIN Txt(Fmt.Real(r)) END RealNum; <* INLINE *> PROCEDURE Label(offset: INTEGER) RAISES {Wr.Failure, Thread.Alerted} = BEGIN Txt("L"); Txt(Fmt.Int(offset + (a - firstaddr))) END Label; PROCEDURE Var(index: INTEGER) RAISES {Wr.Failure, Thread.Alerted} = BEGIN Wr.PutChar(wr, VAL(ORD('a') + index MOD 26, CHAR)); IF index > 26 THEN Num(index DIV 26) END END Var; <* INLINE *> PROCEDURE Func(t: TEXT; v: INTEGER) RAISES {Wr.Failure, Thread.Alerted} = BEGIN Txt(t); Txt("("); Var(v); Txt(")") END Func; PROCEDURE MarkGlobal(index: CARDINAL) = BEGIN IF index > LAST(globalUsed^) THEN VAR new := NEW(REF ARRAY OF BOOLEAN, 2 * index); BEGIN SUBARRAY(new^, 0, NUMBER(globalUsed^)) := globalUsed^; globalUsed := new END END; globalUsed[index] := TRUE END MarkGlobal; PROCEDURE DoSolve (VAR a: UNTRACED REF RT.ByteCode) RAISES {Wr.Failure, Thread.Alerted} = VAR ins, inouts, nc: Marshal.UShort; c := 0; BEGIN ins := Marshal.ReadUShort(a); inouts := Marshal.ReadUShort(a); nc := Marshal.ReadUShort(a); Num(ins); Txt(", "); Num(inouts); Txt(", "); Num(nc); Txt(": \n"); (* package constraints *) WHILE c < nc DO VAR n: BC.ConRange := a^; x, y, z: Marshal.UShort; BEGIN INC(a); x := Marshal.ReadUShort(a); IF n < BC.REAL_C THEN y := Marshal.ReadUShort(a) END; IF n < BC.EQUAL_C THEN z := Marshal.ReadUShort(a) END; Txt("\t "); CASE n OF <* NOWARN *> | BC.CONS_C => Var(x); Txt("=("); Var(y); Txt(","); Var(z); Txt(")") | BC.SUM_C => Var(x); Txt("="); Var(y); Txt("+"); Var(z) | BC.PROD_C => Var(x); Txt("="); Var(y); Txt("*"); Var(z) | BC.ATAN_C => Var(x); Txt("=ATAN(");Var(y);Txt(",");Var(z);Txt(")") | BC.EQUAL_C => Var(x); Txt("="); Var(y) | BC.SIN_C => Var(x); Func("=SIN", y) | BC.COS_C => Var(x); Func("=COS", y) | BC.EXP_C => Var(x); Func("=EXP", y) | BC.REAL_C => Func("IS-REAL", x) | BC.TEXT_C => Func("IS-TEXT", x) END; INC(c); IF c < nc THEN Txt("\n") END END END END DoSolve; (* P *) BEGIN FOR i := 0 TO LAST(globalUsed^) DO globalUsed[i] := FALSE END; WHILE a # lastaddr DO VAR bc := a^; BEGIN Txt("L"); Num(a - firstaddr); Txt("\t"); Txt(BC.names[bc]); Txt(" "); INC(a); CASE bc OF | BC.PUSHL, BC.POPL => Num(Marshal.ReadShort(a)) | BC.PUSHG, BC.POPG => VAR index := Marshal.ReadULong(a); BEGIN Num(index); MarkGlobal(index) END | BC.INCSP, BC.DECSP, BC.PUSHM3NIL, BC.ERROR, BC.FERROR => Num(a^); INC(a) | BC.PUSHNUM => RealNum(Marshal.ReadReal(a)) | BC.JUMP, BC.TJUMP, BC.FJUMP, BC.UJUMP, BC.ADD, BC.SUBTRACT, BC.MULTIPLY, BC.DIVIDE, BC.DIV_, BC.MOD_, BC.NEGATE, BC.ABS_, BC.FLOOR_, BC.CEILING_, BC.ROUND_, BC.MAX_, BC.MIN_, BC.ATAN, BC.SIN, BC.COS, BC.LN, BC.EXP, BC.REL, BC.CAR, BC.CDR, BC.CAR_CDR, BC.CONCAT => Label(Marshal.ReadShort(a)) | BC.CALL, BC.CALLEXT, BC.NEWCL, BC.NEWEXTCL => Num(Marshal.ReadULong(a)) | BC.LIST => Num(Marshal.ReadUShort(a)) | BC.CLOSE => Num(Marshal.ReadUShort(a)); Txt(", "); Label(Marshal.ReadShort(a)) | BC.APPLY => Num(Marshal.ReadUShort(a)); Txt(", "); Num(Marshal.ReadUShort(a)); Txt(", "); Num(Marshal.ReadUShort(a)); Txt(", "); Label(Marshal.ReadShort(a)) | BC.SOLVE => DoSolve(a) ELSE (* SKIP *) END; Txt("\n") END END; VAR first := TRUE; BEGIN FOR i := 0 TO LAST(globalUsed^) DO IF globalUsed[i] AND RT.value_tbl[i] # NIL THEN IF first THEN Txt("\n"); first := FALSE END; Txt("V"); Num(i); Txt("\t"); JunoValue.Unparse(wr, RT.value_tbl[i]); Txt("\n") END END END END P; BEGIN END JunoDisassem.