DIRECTORY
Basics USING [ShortNumber],
FS USING [Error, OpenFile, Create, StreamFromOpenFile],
IO,
List USING [CompareProc, LORA, Sort],
Rope,
MicroDefs,
MicroGlobalVars,
MicroOps USING [FilterSyms, GetSymbol],
MicroUtils USING [FullNameWithExt];
MicroOutputImpl:
CEDAR
PROGRAM
IMPORTS
FS, IO, List, Rope,
MicroGlobalVars, MicroOps, MicroUtils
EXPORTS
MicroOps, MicroUtils
= BEGIN OPEN MicroDefs, MicroGlobalVars;
oldMemory: Memory ← NIL;
oldLoc: INTEGER ← 0;
ListingReport:
PUBLIC
PROC[msg1, msg2:
ROPE ←
NIL] = {
reportStrm.PutRope[msg1];
reportStrm.PutRope[msg2];
reportStrm.PutChar['\n];
};
WriteWord:
PUBLIC
PROC[accWord: WordSeq, mem: Memory, loc:
INTEGER] = {
write data word
IF ~writeBinaryFlag THEN RETURN;
IF binaryFile.strm =
NIL
THEN {
OpenBinary[];
oldMemory ← NIL;
};
IF mem # oldMemory
OR (loc # oldLoc+1)
THEN {
PutInteger[binaryFile.strm, MBseta];
PutInteger[binaryFile.strm, mem.memoryNum];
PutInteger[binaryFile.strm, loc];
oldMemory ← mem;
};
oldLoc ← loc;
PutInteger[binaryFile.strm, MBdata];
PutInteger[binaryFile.strm, stmtLineCount];
FOR i:
INTEGER
IN [0..accWord.length)
DO
PutWord[binaryFile.strm, accWord[i]];
ENDLOOP;
};
WriteFixup:
PUBLIC
PROC[memIndex, loc, feIndex, symIndex:
INTEGER] = {
Write a fixup
IF fixupsFileRec.strm = NIL THEN OpenOutputStream[fixupsFileRec];
PutInteger[fixupsFileRec.strm, memIndex];
PutInteger[fixupsFileRec.strm, loc];
PutInteger[fixupsFileRec.strm, feIndex];
PutInteger[fixupsFileRec.strm, symIndex];
PutInteger[fixupsFileRec.strm, labelSymIndex];
PutInteger[fixupsFileRec.strm, stmtLineCount - labelLineCount];
};
WriteSymName:
PUBLIC
PROC[symIndex:
INTEGER] =
{ SymName[MicroOps.GetSymbol[symIndex]]};
SymName:
PROC[sObj: SymbolObj] = {
Write a fixup
name: ROPE;
len: INT;
IF ~writeBinaryFlag THEN RETURN;
IF binaryFile.strm = NIL THEN OpenBinary[];
IF sObj = NIL THEN RETURN;
name ← sObj.name;
len ← name.Length[];
**** starts writing on word boundary
FOR i:
INT
IN [0..len)
DO
binaryFile.strm.PutChar[name.Fetch[i]];
ENDLOOP;
IF len
MOD 2 = 1
THEN binaryFile.strm.PutChar['\000]
ELSE PutWord[binaryFile.strm, 0]; -- end marker for name
};
WriteMemoryDef:
PUBLIC
PROC[mem: Memory] = {
write memory definition
IF ~writeBinaryFlag THEN RETURN;
IF binaryFile.strm = NIL THEN OpenBinary[];
IF mem = NIL THEN RETURN;
PutInteger[binaryFile.strm, MBmemdef];
PutInteger[binaryFile.strm, mem.memoryNum];
PutInteger[binaryFile.strm, mem.widthInBits];
WriteSymName[mem.symIndex];
};
EndListing: PUBLIC PROC[xListFlag: BOOL] = { };
EndOutput:
PUBLIC
PROC[symDumpStartIndex:
INTEGER] = {
lSyms: LIST OF SymbolObj;
SymbolCompareProc: List.CompareProc = {
s1: SymbolObj = NARROW[ref1];
s2: SymbolObj = NARROW[ref2];
RETURN[Rope.Compare[s1.name, s2.name, FALSE]];
};
IF binaryFile.strm = NIL THEN RETURN;
CopyFixups[];
lSyms ← MicroOps.FilterSyms[addressType, symDumpStartIndex];
TRUSTED
{ lSyms ← LOOPHOLE[List.Sort[LOOPHOLE[lSyms, List.LORA], SymbolCompareProc], LIST OF SymbolObj] };
FOR ls:
LIST
OF SymbolObj ← lSyms, ls.rest
UNTIL ls =
NIL
DO
sym: SymbolObj = ls.first;
mem: Memory = NARROW[MicroOps.GetSymbol[sym.sMisc].sData];
PutInteger[binaryFile.strm, MBsymbol];
PutInteger[binaryFile.strm, mem.memoryNum];
PutInteger[binaryFile.strm, sym.sVal];
SymName[sym];
ENDLOOP;
PutInteger[binaryFile.strm, MBend];
binaryFile.strm.Close[ ! IO.Error, FS.Error => CONTINUE];
binaryFile.strm ← NIL;
};
CopyFixups:
PROC = {
-- Copy fixups to output file
IF fixupsFileRec.strm = NIL THEN RETURN;
fixupsFileRec.strm.SetLength[fixupsFileRec.strm.GetIndex[]];
fixupsFileRec.strm.SetIndex[0];
UNTIL fixupsFileRec.strm.EndOf[]
DO
memIndex: INTEGER = GetInteger[fixupsFileRec.strm];
loc: INTEGER = GetInteger[fixupsFileRec.strm];
feIndex: INTEGER = GetInteger[fixupsFileRec.strm];
symIndex: INTEGER = GetInteger[fixupsFileRec.strm];
labelSymIndex: INTEGER = GetInteger[fixupsFileRec.strm];
lineCount: INTEGER = GetInteger[fixupsFileRec.strm];
memSym: SymbolObj = MicroOps.GetSymbol[memIndex];
mem: Memory = NARROW[memSym.sData];
fSym: SymbolObj = MicroOps.GetSymbol[feIndex];
sym: SymbolObj = MicroOps.GetSymbol[symIndex];
bits: INTEGER = (fSym.sMisc * 256) + fSym.sMisc + LOOPHOLE[fSym.sVal, INTEGER] - 1;
val: INTEGER;
IF sym.sType = undefnType
THEN {
PutInteger[binaryFile.strm, MBext];
PutInteger[binaryFile.strm, mem.memoryNum];
PutInteger[binaryFile.strm, loc];
PutInteger[binaryFile.strm, bits];
WriteSymName[symIndex];
LOOP;
};
IF sym.sType = addressType
OR sym.sType = integerType
THEN val ← sym.sVal
ELSE {
lSym: SymbolObj = MicroOps.GetSymbol[labelSymIndex];
reportStrm.PutF["\n** Undefined symbol %g in field %g of %g at %g",
IO.rope[sym.name], IO.rope[fSym.name], IO.rope[memSym.name],
IO.rope[lSym.name]];
SELECT
TRUE
FROM
lineCount = 0 => NULL;
lineCount > 0 => reportStrm.PutF["+%g", IO.int[lineCount]];
lineCount < 0 => reportStrm.PutF["%g", IO.int[lineCount]];
ENDCASE => NULL;
reportStrm.PutChar['\n];
LOOP;
};
PutInteger[binaryFile.strm, MBfixup];
PutInteger[binaryFile.strm, mem.memoryNum];
PutInteger[binaryFile.strm, loc];
PutInteger[binaryFile.strm, bits];
PutInteger[binaryFile.strm, val];
ENDLOOP;
fixupsFileRec.strm.SetLength[0];
fixupsFileRec.strm.Close[];
fixupsFileRec.strm ← NIL;
};
the following are exported to MicroUtils
PutWord:
PUBLIC
PROC[strm:
STREAM, val:
WORD] = {
sn: Basics.ShortNumber ← LOOPHOLE[val];
strm.PutChar[LOOPHOLE[sn.hi, CHAR]];
strm.PutChar[LOOPHOLE[sn.lo, CHAR]];
};
PutInteger:
PUBLIC
PROC[strm:
STREAM, val:
INTEGER] = {
sn: Basics.ShortNumber ← LOOPHOLE[val];
strm.PutChar[LOOPHOLE[sn.hi, CHAR]];
strm.PutChar[LOOPHOLE[sn.lo, CHAR]];
};
GetWord:
PUBLIC
PROC[strm:
STREAM]
RETURNS[val:
WORD] = {
sn: Basics.ShortNumber;
sn.hi ← LOOPHOLE[strm.GetChar[], BYTE];
sn.lo ← LOOPHOLE[strm.GetChar[], BYTE];
RETURN[LOOPHOLE[sn, WORD]];
};
GetInteger:
PUBLIC
PROC[strm:
STREAM]
RETURNS[val:
WORD] = {
sn: Basics.ShortNumber;
sn.hi ← LOOPHOLE[strm.GetChar[], BYTE];
sn.lo ← LOOPHOLE[strm.GetChar[], BYTE];
RETURN[LOOPHOLE[sn, WORD]];
};
OpenBinary:
PROC = {
binaryFile.fullName ← MicroUtils.FullNameWithExt[binaryFile.fullName, NIL, NIL, mbExtn];
OpenOutputStream[binaryFile];
};
OpenOutputStream:
PUBLIC
PROC[rec: OutputFile] = {
of: FS.OpenFile = FS.Create[name: rec.fullName, setKeep: TRUE, keep: 2];
rec.strm ← FS.StreamFromOpenFile[of, $write];
};
END.