DIRECTORY
BcdDefs: TYPE USING [Base, MTIndex],
BcdOps: TYPE USING [BcdBase, MTHandle],
CommanderOps: TYPE USING [AddCommand, CommandBlockHandle],
Environment: TYPE USING [Byte, PageCount],
FileSegment: TYPE USING [Pages],
FileStream: TYPE USING [Create, EndOf, SetIndex],
Format: TYPE USING [NumberFormat],
Heap: TYPE USING [systemZone],
Inline: TYPE USING [BITOR],
ListerDefs:
TYPE
USING [
IncorrectVersion, Load, LoadFromConfig, MapPages, NoCode, NoFGT, NoFile,
NoSymbols, SetRoutineSymbols, WriteFileID, WriteString],
Mopcodes:
TYPE
USING [
zJ2, zJ9, zJEQ2, zJEQ9, zJIB, zJIW, zJNE2, zJNE9, zLI0, zLI6, zLIB, zLIW, zRF,
zRFC, zRFL, zRIGP, zRIGPL, zRILP, zRILPL, zRXGPL, zRXLP, zRXLPL, zWF, zWFL,
zWIGPL, zWILP, zWILPL, zWSF, zWXGPL, zWXLP, zWXLPL],
OpTableDefs: TYPE USING [InstAligned, InstLength, InstName, PopStack, PushStack],
OSMiscOps: TYPE USING [FileError, FindFile],
OutputDefs:
TYPE
USING [
CloseOutput, OpenOutput, PutChar, PutNumber, PutString, PutLongSubString],
PrincOps:
TYPE
USING [
CSegPrefix, EntryVectorItem, FrameHandle, FrameVec, InstWord],
Space: TYPE USING [Handle, LongPointer, Delete],
Stream: TYPE USING [Delete, GetChar, Handle],
Strings: TYPE USING [AppendString, SubStringDescriptor],
Symbols:
TYPE
USING [
BodyInfo, BodyRecord, BTIndex, BTNull, CBTIndex, HTIndex, HTNull, ISEIndex,
SENull],
SymbolSegment: TYPE USING [FGTEntry],
SymbolTable: TYPE USING [Base, Acquire, Release, SetCacheSize];
ListCode:
PROGRAM
IMPORTS
CommanderOps, FileStream, Heap, Inline, ListerDefs, OpTableDefs,
OSMiscOps, OutputDefs, Space, Stream, Strings, SymbolTable = {
OPEN OutputDefs;
MTIndex: TYPE = BcdDefs.MTIndex;
FrameHandle: TYPE = PrincOps.FrameHandle;
NumberFormat: TYPE = Format.NumberFormat;
PageCount: TYPE = Environment.PageCount;
BYTE: TYPE = Environment.Byte;
opcode: TYPE = BYTE;
JumpOp: TYPE = [Mopcodes.zJ2..Mopcodes.zJIW];
FineGrainInfo:
TYPE =
RECORD [
firstSource, lastSource: CARDINAL ← nullSource,
pc: CARDINAL,
procEnd: BOOLEAN,
bti: Symbols.CBTIndex];
FGT:
TYPE =
RECORD [
length: NAT,
info: SEQUENCE maxLength: NAT OF FineGrainInfo];
FGHandle: TYPE = LONG POINTER TO FGT;
nullSource: CARDINAL = LAST[CARDINAL]; -- if lastSource, causes to EOF
myFGT: FGHandle;
DigestFGT:
PROC = {
OPEN s: symbols;
bti, prev: Symbols.BTIndex;
cspp: LONG POINTER TO PrincOps.CSegPrefix = codebase;
AddMyEntry:
PROC [
source: CARDINAL←nullSource, object: CARDINAL, procEnd: BOOLEAN←FALSE] = {
IF n = myFGTSize
THEN {
oldFGT: FGHandle ← myFGT;
myFGTSize ← myFGTSize + 10;
SetupMyFGT[];
FOR i:
NAT
IN [0..oldFGT.maxLength)
DO
myFGT[i] ← oldFGT[i] ENDLOOP;
(Heap.systemZone).FREE[@oldFGT]};
myFGT[n] ←
[firstSource: source, pc: object, procEnd: procEnd, bti: LOOPHOLE[bti]];
myFGT.length ← n ← n + 1};
AddBodyFGT:
PROC [bti: Symbols.CBTIndex] = {
OPEN s: symbols;
procstart: CARDINAL = cspp.entry[s.bb[bti].entryIndex].initialpc*2;
info: Symbols.BodyInfo[External] = NARROW[s.bb[bti].info, Symbols.BodyInfo[External]];
fgLast: CARDINAL = info.startIndex + info.indexLength - 1;
lastSource: CARDINAL ← s.bb[bti].sourceIndex;
lastObject: CARDINAL ← procstart;
FOR i:
CARDINAL
IN [info.startIndex..fgLast]
DO
f: SymbolSegment.FGTEntry = s.fgTable[i];
WITH f
SELECT
FROM
normal => {
lastSource ← lastSource + deltaSource;
lastObject ← lastObject + deltaObject;
AddMyEntry[source: lastSource, object: lastObject]};
step =>
IF which = source THEN lastSource ← lastSource + delta
ELSE lastObject ← lastObject + delta;
ENDCASE;
ENDLOOP;
AddMyEntry[object: procstart + info.bytes, procEnd: TRUE]};
SetupMyFGT:
PROC =
INLINE {
myFGT ← (Heap.systemZone).NEW[FGT[myFGTSize] ← [length: 0, info: NULL]]};
BySource:
PROC [r1, r2:
LONG
POINTER
TO FineGrainInfo]
RETURNS [
BOOLEAN] = {
IF r1.firstSource > r2.firstSource THEN RETURN [TRUE];
IF r1.firstSource = r2.firstSource THEN RETURN [r1.pc > r2.pc];
RETURN [FALSE]};
ByPC:
PROC [r1, r2:
LONG
POINTER
TO FineGrainInfo]
RETURNS [
BOOLEAN] = {
IF r1.pc > r2.pc THEN RETURN [TRUE];
IF r1.pc < r2.pc THEN RETURN [FALSE];
IF r1.procEnd THEN RETURN [FALSE];
IF r2.procEnd THEN RETURN [TRUE];
RETURN [r1.firstSource > r2.firstSource]};
Sort:
PROC [
n: CARDINAL,
greater: PROC [r1, r2: LONG POINTER TO FineGrainInfo] RETURNS [BOOLEAN]] = {
i: CARDINAL;
temp: FineGrainInfo;
SiftUp:
PROC [l, u:
CARDINAL] = {
s: CARDINAL;
key: FineGrainInfo ← myFGT[l-1];
DO
s ← l*2;
IF s > u THEN EXIT;
IF s < u AND greater[@myFGT[s+1-1], @myFGT[s-1]] THEN s ← s+1;
IF greater[@key, @myFGT[s-1]] THEN EXIT;
myFGT[l-1] ← myFGT[s-1];
l ← s;
ENDLOOP;
myFGT[l-1] ← key};
FOR i DECREASING IN [2..n/2] DO SiftUp[i, n]; ENDLOOP;
FOR i
DECREASING
IN [2..n]
DO
SiftUp[1, i];
temp ← myFGT[1-1];
myFGT[1-1] ← myFGT[i-1];
myFGT[i-1] ← temp;
ENDLOOP};
n: CARDINAL ← 0;
myFGTSize: CARDINAL ← (3*LENGTH[s.fgTable])/2;
SetupMyFGT[];
bti ← FIRST[Symbols.BTIndex];
IF s.bb[bti].sourceIndex # 0
THEN
AddMyEntry[source: 0, object: cspp.entry[0].initialpc*2];
DO
WITH s.bb[bti]
SELECT
FROM
Callable => IF ~inline THEN AddBodyFGT[LOOPHOLE[bti]];
ENDCASE;
IF s.bb[bti].firstSon # Symbols.BTNull THEN bti ← s.bb[bti].firstSon
ELSE
DO
prev ← bti;
bti ← s.bb[bti].link.index;
IF bti = Symbols.BTNull THEN GO TO Done;
IF s.bb[prev].link.which # parent THEN EXIT;
ENDLOOP;
REPEAT Done => NULL;
ENDLOOP;
Sort[n, BySource];
FOR i:
CARDINAL
DECREASING
IN [0..n - 1)
DO
IF myFGT[i].firstSource = nullSource THEN LOOP;
IF myFGT[i].firstSource = myFGT[i+1].firstSource
THEN {
myFGT[i].lastSource ← myFGT[i+1].lastSource;
myFGT[i+1].firstSource ← myFGT[i+1].lastSource}
ELSE myFGT[i].lastSource ← myFGT[i + 1].firstSource;
ENDLOOP;
Sort[n, ByPC]};
offset: CARDINAL;
codebase: LONG POINTER;
codepages: PageCount;
symbols: SymbolTable.Base;
Tinst, Tbytes, Pinst, Pbytes: CARDINAL ← 0;
number formats (initialized by Octify)
decimal: NumberFormat = NumberFormat[
base: 10, columns: 1, zerofill: FALSE, unsigned: TRUE];
decimal3: NumberFormat = NumberFormat[
base: 10, columns: 3, zerofill: FALSE, unsigned: TRUE];
hoctal3: NumberFormat;
hoctal3z: NumberFormat;
hoctal5: NumberFormat;
hoctal6: NumberFormat;
hoctal1: NumberFormat;
set base for listings
Hexify:
PROC = {
hoctal3 ← NumberFormat[base: 16, columns: 3, zerofill: FALSE, unsigned: TRUE];
hoctal3z ← NumberFormat[
base: 16, columns: 3, zerofill: FALSE, unsigned: TRUE];
hoctal5 ← NumberFormat[base: 16, columns: 5, zerofill: FALSE, unsigned: TRUE];
hoctal6 ← NumberFormat[base: 16, columns: 6, zerofill: FALSE, unsigned: TRUE];
hoctal1 ← NumberFormat[base: 16, columns: 1, zerofill: FALSE, unsigned: TRUE]};
Octify:
PROC = {
hoctal3 ← NumberFormat[base: 8, columns: 3, zerofill: FALSE, unsigned: TRUE];
hoctal3z ← NumberFormat[base: 8, columns: 3, zerofill: TRUE, unsigned: TRUE];
hoctal5 ← NumberFormat[base: 8, columns: 5, zerofill: FALSE, unsigned: TRUE];
hoctal6 ← NumberFormat[base: 8, columns: 6, zerofill: FALSE, unsigned: TRUE];
hoctal1 ← NumberFormat[base: 8, columns: 1, zerofill: FALSE, unsigned: TRUE]};
generate list of opcode lengths
OpcodeLengths:
PROC [root:
STRING] = {
OPEN OpTableDefs;
digit: STRING = "0123456789"L;
OpenOutput[root, ".list"L];
PutString[" OpcodeLengths: PACKED ARRAY [0..255] OF [0..3] = ["L];
FOR i: opcode
IN opcode
DO
IF i MOD 32 = 0 THEN PutString["\n "L];
PutChar[digit[InstLength[i]]];
IF i # LAST[opcode] THEN PutChar[',];
ENDLOOP;
PutString["];\n"L];
CloseOutput[]};
generate list of opcodes
OpcodeList:
PROC [root:
STRING] = {
OPEN OpTableDefs;
digit: STRING = "0123456789"L;
OpenOutput[root, ".list"L];
PutString["-- Mesa Opcodes\n"L];
PutString["-- Format: name hoctal(decimal)push,pop,length,aligned\n\n"L];
FOR i: opcode
IN opcode
DO
op: STRING ← InstName[i];
length: [0..3] = InstLength[i];
IF length = 0 THEN op.length ← 0;
PutString[op];
THROUGH (op.length..8] DO PutChar[' ] ENDLOOP;
PutNumber[i, hoctal3];
PutChar['(]; PutNumber[i, decimal3]; PutChar[')];
PutChar[digit[PushStack[i]]]; PutChar[',];
PutChar[digit[PopStack[i]]]; PutChar[',];
PutChar[digit[length]]; PutChar[',];
PutChar[IF InstAligned[i] THEN 'T ELSE 'F];
PutString[IF i MOD 4 = 3 THEN ";\n"L ELSE "; "L];
ENDLOOP;
CloseOutput[]};
source file procedures
source: Stream.Handle;
sourceAvailable: BOOLEAN;
outcheck:
PROC [xfirst:
CARDINAL, xlast:
CARDINAL] = {
nextchar: CHARACTER;
lastcr: CARDINAL;
IF ~sourceAvailable THEN RETURN;
FOR lastcr ← xfirst, lastcr - 1
UNTIL lastcr = 0
DO
FileStream.SetIndex[source, lastcr];
IF source.GetChar[] = '\n THEN EXIT;
ENDLOOP;
THROUGH (lastcr..xfirst) DO PutChar[' ] ENDLOOP;
FileStream.SetIndex[source, xfirst];
WHILE xfirst # xlast
DO
IF FileStream.EndOf[source] THEN GOTO eof;
nextchar ← source.GetChar[];
xfirst ← xfirst + 1;
IF nextchar = '\032
THEN
-- Bravo trailer
WHILE nextchar # '\n
DO
IF FileStream.EndOf[source] THEN GOTO eof;
nextchar ← source.GetChar[];
xfirst ← xfirst + 1;
ENDLOOP;
PutChar[nextchar];
REPEAT eof => NULL;
ENDLOOP;
IF nextchar # '\n THEN PutChar['\n]};
setupsource:
PROC = {
sourceAvailable ← TRUE;
source ← FileStream.Create[
OSMiscOps.FindFile[symbols.sourceFile
! OSMiscOps.FileError => {sourceAvailable ← FALSE; CONTINUE}]]};
closesource: PROC = {IF sourceAvailable THEN Stream.Delete[source]};
PrintBodyName:
PROC [bti: Symbols.BTIndex] = {
OPEN symbols;
sei: Symbols.ISEIndex;
hti: Symbols.HTIndex;
ss: Strings.SubStringDescriptor;
IF sourceAvailable THEN RETURN;
WITH bb[bti]
SELECT
FROM
Callable =>
IF (sei ← id) = Symbols.SENull OR (hti ← seb[sei].hash) = Symbols.HTNull THEN RETURN;
ENDCASE => RETURN;
SubStringForName[@ss, hti];
PutLongSubString[@ss];
PutString[":\n"L]};
EvenUp:
PROC [n:
CARDINAL]
RETURNS [
CARDINAL] =
INLINE {
Round up to an even number
RETURN [n + n MOD 2]};
getbyte:
PROC [pc:
CARDINAL]
RETURNS [
BYTE] = {
pc is a byte address
w: LONG POINTER TO PrincOps.InstWord = codebase + pc/2;
RETURN [IF pc MOD 2 = 0 THEN w.evenbyte ELSE w.oddbyte]};
getword:
PROC [pc:
CARDINAL]
RETURNS [
WORD] =
INLINE {
pc is a word address
RETURN [(codebase + pc)^]};
jumpaddress:
PROC [jop: opcode, arg:
INTEGER]
RETURNS [
CARDINAL] = {
given a jump operator and its argument, return its target address
OPEN Mopcodes;
SELECT OpTableDefs.InstLength[
jop] FROM
1 =>
SELECT jop
FROM
IN [zJ2..zJ9] => arg ← jop - zJ2 + 2;
IN [zJEQ2..zJEQ9] => arg ← jop - zJEQ2 + 2;
IN [zJNE2..zJNE9] => arg ← jop - zJNE2 + 2;
ENDCASE => ERROR;
2 => {
IF arg > 177B THEN arg ← Inline.BITOR[arg, 177400B];
arg ← arg - 1};
ENDCASE => arg ← arg - 2;
RETURN [INTEGER[offset] + arg]};
outwjtab:
PROC [
tabstart, tablength: CARDINAL, octal: BOOLEAN, stripped: BOOLEAN] = {
Pbytes ← Pbytes + tablength*2;
FOR pc:
CARDINAL
IN [tabstart..tabstart + tablength)
DO
w: INTEGER = getword[pc];
PutString["\n\t\t"L];
IF stripped THEN {PutNumber[w, hoctal5]; LOOP};
IF octal THEN PutString["\t\t"L];
PutString[" ("L];
PutNumber[jumpaddress[Mopcodes.zJIW, w], hoctal5];
PutChar[')];
ENDLOOP};
outbjtab:
PROC [
tabstart, tablength: CARDINAL, octal: BOOLEAN, stripped: BOOLEAN] = {
Pbytes ← Pbytes + EvenUp[tablength];
FOR pc:
CARDINAL
IN [tabstart*2..tabstart*2 + tablength)
DO
b: BYTE = getbyte[pc];
PutString["\n\t\t"L];
IF stripped THEN {PutNumber[b, hoctal5]; LOOP};
IF octal THEN PutString["\t\t"L];
PutString[" ("L];
PutNumber[jumpaddress[Mopcodes.zJIB, b], hoctal5];
PutChar[')];
ENDLOOP};
PutPair:
PROC [byte:
CARDINAL] = {
a: CARDINAL = byte/16;
b: CARDINAL = byte MOD 16;
IF a < 8 AND b < 8 THEN PutChar[' ];
PutChar['[];
PutNumber[a, hoctal1];
PutChar[',];
PutNumber[b, hoctal1];
PutChar[']]};
printcode:
PROC [
startcode, endcode: CARDINAL, octal: BOOLEAN, stripped: BOOLEAN] = {
list opcodes for indicated segment of code
OPEN Mopcodes;
lastconstant: INTEGER;
FOR offset
IN [startcode..endcode)
DO
inst: BYTE = getbyte[offset];
il: [0..3] = OpTableDefs.InstLength[inst];
loginst[inst];
Pinst ← Pinst + 1;
PutChar['\t];
IF ~stripped
THEN {
IF octal
THEN {
PutNumber[offset/2, hoctal5];
PutString[(IF offset MOD 2 = 0 THEN ",E "L ELSE ",O "L)]};
PutNumber[offset, hoctal5];
PutChar[':]};
IF octal
THEN {
PutString["\t["L]; PutNumber[inst, hoctal3z]; PutChar[']]};
PutChar['\t];
PutString[OpTableDefs.InstName[inst]];
SELECT il
FROM
0, 1 => {
Pbytes ← Pbytes + 1;
IF inst IN [zLI0..zLI6] THEN lastconstant ← inst - zLI0
ELSE
IF inst
IN JumpOp
AND ~stripped
THEN {
PutString["\t ("L];
PutNumber[jumpaddress[inst, 0], hoctal1];
PutChar[')]}};
2 => {
byte: BYTE = getbyte[(offset ← offset + 1)];
Pbytes ← Pbytes + 2;
PutChar['\t];
SELECT inst
FROM
zRILP, zWILP, zRXLP, zWXLP, zRIGP, zRXLPL, zWXLPL, zRXGPL, zWXGPL,
zRILPL, zWILPL, zRIGPL, zWIGPL => PutPair[byte];
ENDCASE => PutNumber[byte, hoctal6];
IF inst = zLIB THEN lastconstant ← byte
ELSE
IF inst
IN JumpOp
AND ~stripped
THEN {
PutString[" ("L];
PutNumber[jumpaddress[inst, byte], hoctal1];
PutChar[')]}};
3 => {
ab: RECORD [first, second: BYTE];
Pbytes ← Pbytes + 3;
ab.first ← getbyte[(offset ← offset + 1)];
ab.second ← getbyte[(offset ← offset + 1)];
PutChar['\t];
SELECT inst
FROM
zRF, zWF, zWSF, zRFC, zRFL, zWFL => {
PutNumber[ab.first, hoctal6];
PutString[", "L];
PutPair[ab.second]};
ENDCASE => {
v: INTEGER = ab.first*256 + ab.second;
PutNumber[v, hoctal6];
SELECT inst
FROM
zJIB => outbjtab[v, lastconstant, octal, stripped];
zJIW => outwjtab[v, lastconstant, octal, stripped];
zLIW => lastconstant ← v;
IN JumpOp =>
IF ~stripped
THEN {
PutString[" ("L];
PutNumber[jumpaddress[inst, v], hoctal1];
PutChar[')]};
ENDCASE}};
ENDCASE;
PutChar['\n];
ENDLOOP};
ListFile:
PROC [root:
STRING, octal, stripped:
BOOLEAN] = {
OPEN symbols;
cseg, sseg, bcdseg: FileSegment.Pages;
bcdFile: STRING ← [40];
Strings.AppendString[bcdFile, root];
FOR i:
CARDINAL
IN [0..root.length)
DO
IF root[i] = '. THEN EXIT;
REPEAT FINISHED => Strings.AppendString[bcdFile, ".bcd"L];
ENDLOOP;
[cseg, sseg, bcdseg] ← ListerDefs.Load[bcdFile];
DoCodeListing[root, cseg, sseg, bcdseg, FIRST[MTIndex], octal, stripped]};
ListModInConfig:
PROC [config, module:
STRING, octal, stripped:
BOOLEAN] = {
OPEN symbols;
cseg, sseg, bcdseg: FileSegment.Pages;
bcdFile: STRING ← [40];
mti: BcdDefs.MTIndex;
Strings.AppendString[bcdFile, config];
FOR i:
CARDINAL
IN [0..config.length)
DO
IF config[i] = '. THEN EXIT;
REPEAT FINISHED => Strings.AppendString[bcdFile, ".bcd"L];
ENDLOOP;
[cseg, sseg, bcdseg, mti] ← ListerDefs.LoadFromConfig[bcdFile, module];
DoCodeListing[module, cseg, sseg, bcdseg, mti, octal, stripped]};
ShowTotals:
PROC = {
PutString["Instructions: "L];
PutNumber[Pinst, decimal];
PutString[", Bytes: "L];
PutNumber[Pbytes ← EvenUp[Pbytes], decimal];
PutString["\n\n"L];
Tinst ← Tinst + Pinst;
Pinst ← 0;
Tbytes ← Tbytes + Pbytes;
Pbytes ← 0};
DoCodeListing:
PROC [
root: STRING, cseg, sseg, bcdseg: FileSegment.Pages, mti: MTIndex,
octal, stripped: BOOLEAN] = {
OPEN BcdDefs, Symbols;
cspp: LONG POINTER TO PrincOps.CSegPrefix;
ff: FineGrainInfo;
bcdSpace, codeSpace: Space.Handle;
bcd: BcdOps.BcdBase;
mth: BcdOps.MTHandle;
prevBti: BTIndex ← BTNull;
bcdSpace ← ListerDefs.MapPages[bcdseg];
bcd ← bcdSpace.LongPointer;
mth ← @LOOPHOLE[bcd + bcd.mtOffset, Base][mti];
codeSpace ← ListerDefs.MapPages[cseg];
codebase ← codeSpace.LongPointer + mth.code.offset;
codepages ← cseg.span.pages;
cspp ← codebase;
IF cspp.header.info.altoCode
THEN {
ListerDefs.WriteString["Cannot list Alto code"L]; RETURN};
SymbolTable.SetCacheSize[0]; -- clear cache
symbols ← SymbolTable.Acquire[sseg];
ListerDefs.SetRoutineSymbols[symbols];
setupsource[];
OpenOutput[root, ".cl"L];
ListerDefs.WriteFileID[];
IF mth.crossJumped THEN PutString["Cross jumped\n"L];
PutString["Global frame size: "L];
PutNumber[mth.framesize, decimal];
PutString["\n\n"L];
Space.Delete[bcdSpace];
Tbytes ← Tinst ← 0;
DigestFGT[];
FOR i:
CARDINAL
IN [0..myFGT.length)
DO
ff ← myFGT[i];
IF ff.bti # prevBti AND prevBti # BTNull THEN ShowTotals[];
IF ff.firstSource # nullSource
THEN
IF ff.lastSource = ff.firstSource THEN PutChar['\n]
ELSE outcheck[ff.firstSource, ff.lastSource];
IF ff.bti # prevBti
THEN {
ep: CARDINAL = symbols.bb[ff.bti].entryIndex;
evi: LONG POINTER TO PrincOps.EntryVectorItem = @cspp.entry[ep];
fsize: CARDINAL = PrincOps.FrameVec[evi.info.framesize];
PrintBodyName[ff.bti];
IF octal THEN PutChar['\t];
PutString[" Entry point: "L];
PutNumber[ep, decimal];
PutString[", Frame size: "L];
PutNumber[fsize, decimal];
PutChar['\n]};
IF ~ff.procEnd THEN printcode[ff.pc, myFGT[i + 1].pc, octal, stripped];
PutChar['\n];
prevBti ← ff.bti;
ENDLOOP;
IF prevBti # Symbols.BTNull THEN ShowTotals[];
(Heap.systemZone).FREE[@myFGT];
SymbolTable.Release[symbols];
Space.Delete[codeSpace];
closesource[];
PutChar['\n];
IF octal THEN PutChar['\t];
PutString["Total instructions: "L];
PutNumber[Tinst, decimal];
PutString[", Bytes: "L];
PutNumber[Tbytes, decimal];
PutChar['\n];
CloseOutput[]};
LCode:
PROC [name:
STRING, octal, stripped:
BOOLEAN] = {
OPEN ListerDefs;
ListFile[name, octal, stripped
! NoCode => {ListerDefs.WriteString["Code not available"L];
CONTINUE};
NoSymbols => {ListerDefs.WriteString["Symbols not available"L]; CONTINUE};
NoFGT, IncorrectVersion => {ListerDefs.WriteString["Bad format"L]; CONTINUE};
NoFile => {ListerDefs.WriteString["File not found"L]; CONTINUE}]};
Code: PROC [name: STRING] = {LCode[name, FALSE, FALSE]};
OctalCode: PROC [name: STRING] = {LCode[name, TRUE, FALSE]};
StrippedCode: PROC [name: STRING] = {LCode[name, FALSE, TRUE]};
LCodeInConfig:
PROC [config, name:
STRING, octal, stripped:
BOOLEAN] = {
OPEN ListerDefs;
ListModInConfig[config, name, octal, stripped
! NoCode => {ListerDefs.WriteString["Code not available"L];
CONTINUE};
NoSymbols => {ListerDefs.WriteString["Symbols not available"L]; CONTINUE};
NoFGT, IncorrectVersion => {ListerDefs.WriteString["Bad format"L]; CONTINUE};
NoFile => {ListerDefs.WriteString["File not found"L]; CONTINUE}]};
CodeInConfig:
PROC [config, name:
STRING] = {
LCodeInConfig[config, name, FALSE, FALSE]};
OctalCodeInConfig:
PROC [config, name:
STRING] = {
LCodeInConfig[config, name, TRUE, FALSE]};
StrippedCodeInConfig:
PROC [config, name:
STRING] = {
LCodeInConfig[config, name, FALSE, TRUE]};
Init:
PROC = {
command: CommanderOps.CommandBlockHandle;
Octify[];
command ← CommanderOps.AddCommand["Hexify", LOOPHOLE[Hexify], 0];
command ← CommanderOps.AddCommand["Octify", LOOPHOLE[Octify], 0];
command ←
CommanderOps.AddCommand["OpcodeLengths", LOOPHOLE[OpcodeLengths], 1];
command.params[0] ← [type: string, prompt: "Filename"];
command ← CommanderOps.AddCommand["OpcodeList", LOOPHOLE[OpcodeList], 1];
command.params[0] ← [type: string, prompt: "Filename"];
command ← CommanderOps.AddCommand["OctalCode", LOOPHOLE[OctalCode], 1];
command.params[0] ← [type: string, prompt: "Filename"];
command ← CommanderOps.AddCommand["Code", LOOPHOLE[Code], 1];
command.params[0] ← [type: string, prompt: "Filename"];
command ← CommanderOps.AddCommand["StrippedCode", LOOPHOLE[StrippedCode], 1];
command.params[0] ← [type: string, prompt: "Filename"];
command ← CommanderOps.AddCommand[
"OctalCodeInConfig", LOOPHOLE[OctalCodeInConfig], 2];
command.params[0] ← [type: string, prompt: "ConfigName"];
command.params[1] ← [type: string, prompt: "ModName"];
command ← CommanderOps.AddCommand["CodeInConfig", LOOPHOLE[CodeInConfig], 2];
command.params[0] ← [type: string, prompt: "ConfigName"];
command.params[1] ← [type: string, prompt: "ModName"];
command ← CommanderOps.AddCommand[
"StrippedCodeInConfig", LOOPHOLE[StrippedCodeInConfig], 2];
command.params[0] ← [type: string, prompt: "ConfigName"];
command.params[1] ← [type: string, prompt: "ModName"]};
Init[];
}.