ListCode.mesa;
edited by Bruce; 13-Jan-81 11:00:33
edited by Sandman; September 29, 1980 9:21 AM
edited by Sweet; 26-Mar-81 12:26:01
edited by Satterthwaite; May 10, 1983 1:03 pm
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: BOOLEANFALSE] = {
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[];
}.