DIRECTORY Alloc: TYPE USING [Base, Handle, Notifier, AddNotify, DropNotify, Bounds], Basics: TYPE USING [bytesPerWord], BcdDefs: TYPE USING [SGRecord, VersionStamp, FTNull], ComData: TYPE USING [ compilerVersion, codeSeg, defBodyLimit, fgTable, fixupLoc, globalFrameSize, importCtx, interface, mainCtx, moduleCtx, mtRoot, mtRootSize, nBodies, nInnerBodies, objectBytes, objectVersion, ownSymbols, source, symSeg, typeAtomRecord], CompilerUtil: TYPE USING [Address], ConvertUnsafe: TYPE USING [AppendRope, SubString, SubStringToRope], FileParms: TYPE USING [Name], IO: TYPE USING [GetIndex, SetIndex, STREAM, UnsafePutBlock], Literals: TYPE USING [Base, STNull], LiteralOps: TYPE USING [CopyLiteral, ForgetEntries, StringValue, TextType], OSMiscOps: TYPE USING [FreeWords, Words], PackageSymbols: TYPE USING [OuterPackRecord, InnerPackRecord, IPIndex, IPNull], PrincOps: TYPE USING [wordsPerPage], PrincOpsUtils: TYPE USING [LongCOPY], RCMap: TYPE USING [Base], RCMapOps: TYPE USING [Acquire, Finalize, GetBase, Initialize], Rope: TYPE USING [Flatten, Length, Text], RTBcd: TYPE USING [ RefLitItem, RefLitList, RTHeader, StampIndex, StampList,TypeItem, TypeList, UTInfo, AnyStamp], Symbols: TYPE USING [ Base, HashVector, Name, Type, MDIndex, BodyInfo, BTIndex, MDNull, OwnMdi, BTNull, RootBti, lL], SymbolSegment: TYPE USING [ Base, FGHeader, FGTEntry, ExtRecord, ExtIndex, STHeader, WordOffset, VersionID, ltType, htType, ssType, seType, ctxType, mdType, bodyType, extType, constType], SymbolOps: TYPE USING [ EnumerateBodies, HashBlock, NameForSe, SiblingBti, SonBti, SubStringForName], SymLiteralOps: TYPE USING [ RefLitItem, DescribeRefLits, DescribeTypes, EnumerateRefLits, EnumerateTypes, TypeIndex, UTypeId], Table: TYPE USING [IPointer, Selector], Tree: TYPE USING [Base, Index, Link, Map, Node, Null, NullIndex, treeType], TreeOps: TYPE USING [FreeTree, NodeSize, UpdateLeaves], TypeStrings: TYPE USING [Create]; ObjectOut: PROGRAM IMPORTS Alloc, ConvertUnsafe, IO, PrincOpsUtils, OSMiscOps, LiteralOps, RCMapOps, Rope, SymbolOps, SymLiteralOps, TreeOps, TypeStrings, dataPtr: ComData EXPORTS CompilerUtil SHARES Rope = { StreamIndex: TYPE = INT; -- FileStream.FileByteIndex Address: TYPE = CompilerUtil.Address; GetShortIndex: PROC [stream: IO.STREAM] RETURNS [CARDINAL] = INLINE { RETURN [IO.GetIndex[stream]]}; stream: IO.STREAM _ NIL; zone: UNCOUNTED ZONE _ NIL; PageSize: CARDINAL = PrincOps.wordsPerPage; BytesPerWord: CARDINAL = Basics.bytesPerWord; BytesPerPage: CARDINAL = PageSize*BytesPerWord; NextFilePage: PUBLIC PROC RETURNS [CARDINAL] = { fill: ARRAY [0..8) OF WORD _ ALL[0]; r: INTEGER = (GetShortIndex[stream] MOD BytesPerPage)/BytesPerWord; m: INTEGER; IF r # 0 THEN FOR n: INTEGER _ PageSize-r, n-m WHILE n > 0 DO m _ MIN[n, fill.LENGTH]; stream.UnsafePutBlock[[fill.BASE, 0, m*BytesPerWord]]; ENDLOOP; RETURN [GetShortIndex[stream]/BytesPerPage + 1]}; WriteObjectWords: PROC [addr: Address, n: CARDINAL] = { stream.UnsafePutBlock[[addr, 0, n*BytesPerWord]]}; RewriteObjectWords: PROC [index: StreamIndex, addr: Address, n: CARDINAL] = { saveIndex: StreamIndex = IO.GetIndex[stream]; IO.SetIndex[stream, index]; stream.UnsafePutBlock[[addr, 0, n*BytesPerWord]]; IO.SetIndex[stream, saveIndex]}; WriteTableBlock: PROC [p: Table.IPointer, size: CARDINAL] = { stream.UnsafePutBlock[[p, 0, size*BytesPerWord]]}; bcdOffset: CARDINAL; bcdIndex: StreamIndex; BCDIndex: PROC [offset: CARDINAL] RETURNS [StreamIndex] = INLINE { RETURN [bcdIndex + offset*BytesPerWord]}; StartBCD: PUBLIC PROC = { [] _ NextFilePage[]; bcdIndex _ IO.GetIndex[stream]; bcdOffset _ 0}; ReadBCDOffset: PUBLIC PROC RETURNS [CARDINAL] = {RETURN [bcdOffset]}; ReadBCDIndex: PUBLIC PROC RETURNS [StreamIndex] = { RETURN [BCDIndex[bcdOffset]]}; AppendBCDWord: PUBLIC PROC [word: UNSPECIFIED] = { stream.UnsafePutBlock[[@word, 0, 1]]; bcdOffset _ bcdOffset + 1}; AppendBCDWords: PUBLIC PROC [addr: Address, n: CARDINAL] = { WriteObjectWords[addr, n]; bcdOffset _ bcdOffset + n}; AppendBCDString: PUBLIC PROC [s: LONG STRING] = { header: StringBody _ [length: s.length, maxlength: s.length, text:]; AppendBCDWords[@header, StringBody[0].SIZE]; AppendBCDWords[@s.text, StringBody[s.length].SIZE - StringBody[0].SIZE]}; FillBCDPage: PUBLIC PROC = { IF bcdOffset MOD PageSize # 0 THEN { [] _ NextFilePage[]; bcdOffset _ bcdOffset + (PageSize - bcdOffset MOD PageSize)}}; UpdateBCDWords: PUBLIC PROC [offset: CARDINAL, addr: Address, n: CARDINAL] = { RewriteObjectWords[BCDIndex[offset], addr, n]}; EndBCD: PUBLIC PROC = {[] _ NextFilePage[]}; PageCount: PROC [words: CARDINAL] RETURNS [CARDINAL] = { RETURN [(words+(PageSize-1))/PageSize]}; SetFgt: PROC [d: SymbolSegment.WordOffset, sourceFile: FileParms.Name] RETURNS [fgBase, fgPages: CARDINAL] = { np: CARDINAL = PageCount[d]; dataPtr.symSeg.pages _ np; IF dataPtr.interface THEN { fgBase _ 0; dataPtr.symSeg.extraPages _ fgPages _ 0; dataPtr.codeSeg.file _ BcdDefs.FTNull; dataPtr.codeSeg.base _ dataPtr.codeSeg.pages _ 0; dataPtr.objectBytes _ 0; dataPtr.mtRoot.framesize _ dataPtr.globalFrameSize _ 0} ELSE { fgBase _ np; dataPtr.symSeg.extraPages _ fgPages _ PageCount[ (StringBody[sourceFile.Length[]].SIZE-StringBody[0].SIZE) + dataPtr.fgTable.LENGTH*SymbolSegment.FGTEntry.SIZE + SymbolSegment.FGHeader.SIZE]}; dataPtr.codeSeg.class _ code; dataPtr.codeSeg.extraPages _ 0; RETURN}; litBias: CARDINAL; WriteExtension: PROC [table: Alloc.Handle] RETURNS [size: CARDINAL] = { OPEN SymbolSegment; tb: Tree.Base; ltb: Literals.Base; treeLoc: Tree.Index; OutputNotify: Alloc.Notifier = { tb _ base[Tree.treeType]; ltb _ base[ltType]; seb _ base[seType]; ctxb _ base[ctxType]; extb _ base[extType]}; OutputLiteral: PROC [t: Tree.Link.literal] RETURNS [Tree.Link] = { OPEN LiteralOps; WITH lit: t.index SELECT FROM word => lit.lti _ CopyLiteral[[baseP:@ltb, index:lit]].lti-litBias; string => lit.sti _ Literals.STNull; -- temporary ENDCASE => ERROR; RETURN [t]}; SetEmpty: Tree.Map = {RETURN [Tree.Null]}; OutputTree: Tree.Map = { WITH link: t SELECT FROM literal => v _ OutputLiteral[link]; subtree => { s: Tree.Link = TreeOps.UpdateLeaves[link, OutputTree]; IF s = Tree.Null THEN v _ Tree.Null ELSE WITH s SELECT FROM subtree => { node: Tree.Index = index; nw: CARDINAL = TreeOps.NodeSize[@tb, node]; WriteTableBlock[@tb[node], nw]; [] _ TreeOps.FreeTree[TreeOps.UpdateLeaves[s, SetEmpty]]; v _ [subtree[index: treeLoc]]; treeLoc _ treeLoc + nw}; ENDCASE => v _ s}; ENDCASE => v _ link; RETURN}; extb: SymbolSegment.Base; extLimit: ExtIndex; seb, ctxb: Symbols.Base; table.AddNotify[OutputNotify]; WriteTableBlock[@tb[Tree.NullIndex], Tree.Node.SIZE]; treeLoc _ Tree.Index.FIRST + Tree.Node.SIZE; [extb, LOOPHOLE[extLimit, CARDINAL]] _ table.Bounds[extType]; FOR exti: ExtIndex _ ExtIndex.FIRST, exti + ExtRecord.SIZE UNTIL exti = extLimit DO extb[exti].tree _ IF dataPtr.interface OR extb[exti].type = value OR extb[exti].type = default THEN OutputTree[extb[exti].tree] ELSE Tree.Null; ENDLOOP; table.DropNotify[OutputNotify]; RETURN [treeLoc-Tree.Index.FIRST]}; WritePackTables: PROC [table: Alloc.Handle] = { OPEN Symbols, PackageSymbols; bb: Symbols.Base; OutputNotify: Alloc.Notifier = {bb _ base[SymbolSegment.bodyType]}; BodyLength: PROC [info: Symbols.BodyInfo] RETURNS [CARDINAL] = INLINE { RETURN [WITH info SELECT FROM External => bytes, ENDCASE => 0]}; nOuter: CARDINAL = dataPtr.nBodies - dataPtr.nInnerBodies; outer: LONG DESCRIPTOR FOR ARRAY OF OuterPackRecord _ DESCRIPTOR[OSMiscOps.Words[nOuter*OuterPackRecord.SIZE], nOuter]; next: CARDINAL _ 0; nextIP: IPIndex _ IPIndex.FIRST; OuterBody: PROC [bti: BTIndex] = { WITH body: bb[bti] SELECT FROM Callable => IF ~body.inline THEN { outer[next] _ OuterPackRecord[ hti: SymbolOps.NameForSe[body.id], entryIndex: body.entryIndex, length: BodyLength[body.info], firstSon: InnerBodies[bti], resident: body.resident]; next _ next + 1}; ENDCASE}; InnerBodies: PROC [root: BTIndex] RETURNS [origin: IPIndex] = { buffer: InnerPackRecord; ProcessBody: PROC [bti: BTIndex] RETURNS [BOOL] = { WITH body: bb[bti] SELECT FROM Callable => IF ~body.inline AND body.level > Symbols.lL THEN { IF origin # IPNull THEN WriteObjectWords[@buffer, InnerPackRecord.SIZE]; buffer _ InnerPackRecord[ entryIndex: body.entryIndex, length: BodyLength[body.info], lastSon: FALSE]; IF origin = IPNull THEN origin _ nextIP; nextIP _ nextIP + 1}; ENDCASE => NULL; RETURN [FALSE]}; origin _ IPNull; IF root # Symbols.RootBti THEN [] _ SymbolOps.EnumerateBodies[root, ProcessBody] ELSE FOR sonBti: BTIndex _ SymbolOps.SonBti[root], SymbolOps.SiblingBti[sonBti] UNTIL sonBti = BTNull DO WITH body: bb[sonBti] SELECT FROM Callable => NULL; -- processed as an outer body ENDCASE => [] _ SymbolOps.EnumerateBodies[sonBti, ProcessBody]; ENDLOOP; IF origin # IPNull THEN { buffer.lastSon _ TRUE; WriteObjectWords[@buffer, InnerPackRecord.SIZE]}; RETURN}; table.AddNotify[OutputNotify]; OuterBody[Symbols.RootBti]; FOR bti: BTIndex _ SymbolOps.SonBti[Symbols.RootBti], SymbolOps.SiblingBti[bti] UNTIL bti = BTNull DO OuterBody[bti] ENDLOOP; table.DropNotify[OutputNotify]; IF next # outer.LENGTH OR nextIP # dataPtr.nInnerBodies THEN ERROR; SortPackInfo[outer, 1, outer.LENGTH]; WriteObjectWords[outer.BASE, nOuter*OuterPackRecord.SIZE]; OSMiscOps.FreeWords[outer.BASE]}; SortPackInfo: PROC [ a: LONG DESCRIPTOR FOR ARRAY OF PackageSymbols.OuterPackRecord, l, u: CARDINAL] = { h, i, j, k: CARDINAL; key: Symbols.Name; t: PackageSymbols.OuterPackRecord; h _ u - l; DO h _ h/2; FOR k IN [l+h .. u) DO i _ k; j _ k-h; key _ a[k].hti; t _ a[k]; WHILE key < a[j].hti DO a[i] _ a[j]; i _ j; IF j < l+h THEN EXIT; j _ j-h; ENDLOOP; a[i] _ t; ENDLOOP; IF h <= 1 THEN EXIT; ENDLOOP}; StartObjectFile: PUBLIC PROC [ objectStream: IO.STREAM, scratchZone: UNCOUNTED ZONE] = { stream _ objectStream; zone _ scratchZone}; TableOut: PUBLIC PROC [table: Alloc.Handle] = { OPEN SymbolSegment; h: STHeader; fixupLoc: StreamIndex; d: WordOffset; nw: CARDINAL; WriteSubTable: PROC [selector: Table.Selector] = { base: Alloc.Base; size: CARDINAL; [base, size] _ table.Bounds[selector]; WriteTableBlock[base, size]}; dataPtr.symSeg.class _ symbols; dataPtr.symSeg.base _ NextFilePage[]; h.versionIdent _ SymbolSegment.VersionID; h.version _ dataPtr.objectVersion; h.sourceVersion _ dataPtr.source.version; h.creator _ dataPtr.compilerVersion; h.definitionsFile _ dataPtr.interface; h.extended _ TRUE; h.directoryCtx _ dataPtr.moduleCtx; h.importCtx _ dataPtr.importCtx; h.outerCtx _ dataPtr.mainCtx; d _ STHeader.SIZE; h.hvBlock.offset _ d; d _ d + (h.hvBlock.size _ Symbols.HashVector.SIZE); h.htBlock.offset _ d; d _ d + (h.htBlock.size _ table.Bounds[htType].size); h.ssBlock.offset _ d; d _ d + (h.ssBlock.size _ table.Bounds[ssType].size); IF dataPtr.interface THEN h.innerPackBlock _ h.outerPackBlock _ [d, 0] ELSE { h.innerPackBlock.offset _ d; d _ d + (h.innerPackBlock.size _ dataPtr.nInnerBodies*PackageSymbols.InnerPackRecord.SIZE); h.outerPackBlock.offset _ d; d _ d + (h.outerPackBlock.size _ (dataPtr.nBodies-dataPtr.nInnerBodies)*PackageSymbols.OuterPackRecord.SIZE)}; h.constBlock.offset _ d; d _ d + (h.constBlock.size _ table.Bounds[constType].size); h.seBlock.offset _ d; d _ d + (h.seBlock.size _ table.Bounds[seType].size); h.ctxBlock.offset _ d; d _ d + (h.ctxBlock.size _ table.Bounds[ctxType].size); h.mdBlock.offset _ d; d _ d + (h.mdBlock.size _ table.Bounds[mdType].size); h.bodyBlock.offset _ d; d _ d + table.Bounds[bodyType].size; h.bodyBlock.size _ dataPtr.defBodyLimit; h.epMapBlock _ h.spareBlock _ [d, 0]; IF table.Bounds[extType].size # 0 THEN fixupLoc _ IO.GetIndex[stream] ELSE { h.treeBlock _ h.litBlock _ h.sLitBlock _ h.extBlock _ [d, 0]; [h.fgRelPgBase, h.fgPgCount] _ SetFgt[d, dataPtr.source.locator]}; WriteObjectWords[@h, STHeader.SIZE]; WriteObjectWords[SymbolOps.HashBlock[], h.hvBlock.size]; WriteSubTable[htType]; WriteSubTable[ssType]; IF ~dataPtr.interface THEN WritePackTables[table]; WriteSubTable[constType]; WriteSubTable[seType]; WriteSubTable[ctxType]; WriteSubTable[mdType]; WriteSubTable[bodyType]; IF table.Bounds[extType].size # 0 THEN { litBias _ LiteralOps.ForgetEntries[]; h.treeBlock.offset _ d; h.treeBlock.size _ WriteExtension[table]; d _ d + h.treeBlock.size; h.litBlock.offset _ d; nw _ table.Bounds[ltType].size - litBias; WriteTableBlock[table.Bounds[ltType].base+litBias, nw]; d _ d + (h.litBlock.size _ nw); h.extBlock.offset _ d; h.sLitBlock _ [d, 0]; WriteSubTable[extType]; d _ d + (h.extBlock.size _ table.Bounds[extType].size); [h.fgRelPgBase, h.fgPgCount] _ SetFgt[d, dataPtr.source.locator]; RewriteObjectWords[fixupLoc, @h, STHeader.SIZE]}; IF ~dataPtr.interface THEN { fg: FGHeader; s: Rope.Text _ Rope.Flatten[dataPtr.source.locator]; [] _ NextFilePage[]; nw _ StringBody[s.length].SIZE-StringBody[0].SIZE; fg.offset _ FGHeader.SIZE + nw; fg.length _ dataPtr.fgTable.LENGTH; fg.sourceFile _ StringBody[ length: s.length, maxlength: s.length, text: -- written separately -- ]; WriteObjectWords[@fg, FGHeader.SIZE]; WriteObjectWords[@s.text, nw]; WriteObjectWords[dataPtr.fgTable.BASE, dataPtr.fgTable.LENGTH*FGTEntry.SIZE]; OSMiscOps.FreeWords[dataPtr.fgTable.BASE]}}; RTTableOut: PUBLIC PROC [table: Alloc.Handle] = { nLits: CARDINAL = SymLiteralOps.DescribeRefLits[].length; nTypes: CARDINAL = SymLiteralOps.DescribeTypes[].length; IF nLits + nTypes # 0 THEN { OPEN RTBcd; rtOffset: CARDINAL _ RTHeader.SIZE; header: RTHeader _ [ refLitTable: LOOPHOLE[rtOffset], litBase: NULL, litLength: NULL, rcMapBase: NULL, rcMapLength: NULL, stampTable: NULL, typeTable: LOOPHOLE[rtOffset + RefLitList[nLits].SIZE]]; fixupOffset: CARDINAL = ReadBCDOffset[]; textBase: LONG POINTER _ NIL; -- to a sequence of StringBody's textLimit: CARDINAL _ 0; textLoc: CARDINAL _ 0; EqText: PROC [t1, t2: LONG STRING] RETURNS [BOOL] = INLINE { IF t1.length # t2.length THEN RETURN [FALSE]; FOR i: CARDINAL IN [0..t1.length) DO IF t1[i] # t2[i] THEN RETURN [FALSE] ENDLOOP; RETURN [TRUE]}; EnterText: PROC [s: LONG STRING] RETURNS [loc: CARDINAL] = { t: LONG STRING; nw: CARDINAL; FOR loc _ 0, loc + StringBody[t.length].SIZE UNTIL loc >= textLoc DO t _ textBase + loc; IF EqText[s, t] THEN RETURN; ENDLOOP; nw _ StringBody[s.length].SIZE; WHILE textLoc + nw > textLimit DO newLimit: CARDINAL = PageCount[textLimit+MAX[MIN[textLimit/2, 512], 64]]*PageSize; newBase: LONG POINTER = OSMiscOps.Words[newLimit]; IF textBase # NIL THEN { PrincOpsUtils.LongCOPY[from: textBase, to: newBase, nwords: textLoc]; OSMiscOps.FreeWords[textBase]}; textBase _ newBase; textLimit _ newLimit; ENDLOOP; loc _ textLoc; PrincOpsUtils.LongCOPY[from: s, to: textBase+loc, nwords: nw]; textLoc _ textLoc + nw; RETURN}; stampList: LONG POINTER TO RTBcd.StampList _ NIL; nextStamp: NAT _ 1; EnterStamp: PROC [mdi: Symbols.MDIndex] RETURNS [index: RTBcd.StampIndex] = { IF mdi = Symbols.MDNull THEN index _ RTBcd.AnyStamp ELSE { stamp: BcdDefs.VersionStamp = table.Bounds[SymbolSegment.mdType].base[mdi].stamp; FOR i: NAT IN [1 .. nextStamp) DO IF stamp = stampList[i] THEN RETURN [[i]]; ENDLOOP; IF stampList = NIL OR nextStamp >= stampList.limit THEN ExpandStampList[]; index _ [nextStamp]; stampList[nextStamp] _ stamp; nextStamp _ nextStamp + 1}; RETURN}; ExpandStampList: PROC = INLINE { oldSize: NAT = nextStamp - 1; AdjustStampList[oldSize + MAX[MIN[oldSize/2, 128], 32]]}; AdjustStampList: PROC [newSize: NAT] = { oldSize: NAT = nextStamp - 1; newList: LONG POINTER TO RTBcd.StampList = zone.NEW[RTBcd.StampList[newSize]]; FOR i: NAT IN [1 .. MIN[oldSize, newSize]] DO newList[i] _ stampList[i] ENDLOOP; IF stampList # NIL THEN zone.FREE[@stampList]; stampList _ newList}; AppendBCDWords[@header, RTHeader.SIZE]; AppendBCDWord[nLits]; IF nLits # 0 THEN { WriteLitItem: PROC [item: SymLiteralOps.RefLitItem] = { info: RefLitItem; loc, chars: CARDINAL; type: Symbols.Type; WITH v: item SELECT FROM atom => { desc: ConvertUnsafe.SubString; s: LONG STRING; n: CARDINAL; desc _ SymbolOps.SubStringForName[v.pName]; n _ desc.length + (desc.length MOD 2); s _ zone.NEW[StringBody[n]]; ConvertUnsafe.AppendRope[s, ConvertUnsafe.SubStringToRope[desc]]; IF s.length < n THEN s[n-1] _ 0c; loc _ EnterText[s]; chars _ s.length; type _ dataPtr.typeAtomRecord; zone.FREE[@s]}; text => { s: LONG STRING = LiteralOps.StringValue[v.value]; loc _ EnterText[s]; chars _ s.length; type _ LiteralOps.TextType[v.value]}; ENDCASE; info _ [ referentType: SymLiteralOps.TypeIndex[type, FALSE], offset: loc, length: TEXT[chars].SIZE]; AppendBCDWords[@info, RefLitItem.SIZE]}; SymLiteralOps.EnumerateRefLits[WriteLitItem]}; AppendBCDWord[nTypes]; rtOffset _ rtOffset + RefLitList[nLits].SIZE + TypeList[nTypes].SIZE; header.rcMapBase _ LOOPHOLE[LONG[rtOffset]]; IF nTypes = 0 THEN header.rcMapLength _ 0 ELSE { EnterUT: PROC [type: Symbols.Type] RETURNS [RTBcd.UTInfo] = { mdi: Symbols.MDIndex; sei: Symbols.Type; [mdi, sei] _ SymLiteralOps.UTypeId[type]; RETURN [[version: EnterStamp[mdi], sei: sei]]}; WriteTypeItem: PROC [canonical: BOOL, type: Symbols.Type] = { s: LONG STRING _ TypeStrings.Create[dataPtr.ownSymbols, type, zone]; info: TypeItem _ [ table: dataPtr.mtRoot.sseg, sei: type, canonical: canonical, rcMap: RCMapOps.Acquire[dataPtr.ownSymbols, type], ct: [EnterText[s]], ut: EnterUT[type]]; zone.FREE[@s]; AppendBCDWords[@info, TypeItem.SIZE]}; RCMapOps.Initialize[ptr: NIL, nPages: 0, expansionZone: zone]; [] _ EnterStamp[Symbols.OwnMdi]; SymLiteralOps.EnumerateTypes[WriteTypeItem]; header.rcMapLength _ RCMapOps.GetBase[].nWords; AppendBCDWords[RCMapOps.GetBase[].base, header.rcMapLength]; rtOffset _ rtOffset + header.rcMapLength; RCMapOps.Finalize[]}; header.stampTable _ LOOPHOLE[rtOffset]; AdjustStampList[nextStamp-1]; AppendBCDWords[stampList, StampList[nextStamp-1].SIZE]; rtOffset _ rtOffset + StampList[nextStamp-1].SIZE; zone.FREE[@stampList]; header.litBase _ LOOPHOLE[rtOffset]; header.litLength _ textLoc; IF textBase # NIL THEN { AppendBCDWords[textBase, textLoc]; OSMiscOps.FreeWords[textBase]}; UpdateBCDWords[fixupOffset, @header, RTHeader.SIZE]}}; EndObjectFile: PUBLIC PROC [update: BOOL] = { IF stream # NIL AND update THEN { saveIndex: StreamIndex = IO.GetIndex[stream]; IO.SetIndex[stream, dataPtr.fixupLoc]; stream.UnsafePutBlock[[@dataPtr.codeSeg, 0, BcdDefs.SGRecord.SIZE*BytesPerWord]]; stream.UnsafePutBlock[[@dataPtr.symSeg, 0, BcdDefs.SGRecord.SIZE*BytesPerWord]]; stream.UnsafePutBlock[[dataPtr.mtRoot, 0, dataPtr.mtRootSize*BytesPerWord]]; IO.SetIndex[stream, saveIndex]}; IF dataPtr.mtRoot # NIL THEN zone.FREE[@dataPtr.mtRoot]; stream _ NIL; zone _ NIL}; }. 4file ObjectOut.Mesa last modified by Satterthwaite, June 3, 1983 10:27 am last modified by Sweet, September 2, 1980 3:05 PM Last Edited by: Maxwell, August 11, 1983 8:38 am bcd i/o -- stream.PutWord[word]; symbol table i/o tree i/o package table i/o Shell sort of a[l..u) main drivers zone.FREE[@s]; Êç˜Jšœ™Jšœ5™5Jšœ2™2J™0J˜šÏk ˜ Jšœœœ9˜JJšœœœ˜"Jšœ œœ"˜5šœ œœ˜J˜KJ˜=J˜FJ˜—Jšœœœ ˜#Jšœœœ*˜CJšœ œœ˜Jšœœœœ˜Jšœœœ˜)šœœœ˜J˜KJ˜—šœ œœ˜J˜9J˜%—šœœœ˜J˜OJ˜O—šœ œœ˜J˜M—šœœœ˜J˜MJ˜—Jšœœœ˜'Jšœœœ;˜KJšœ œœ$˜7Jšœ œœ ˜!J˜—šœ ˜š˜Jšœœ1˜IJ˜5J˜—Jšœ ˜Jšœ ˜J˜Jšœ œœÏc˜4Jšœ œ˜%J˜šÏn œœ œœœœœ˜EJšœœ˜J˜—Jšœœœœ˜Jšœ œœœ˜J˜Jšœ œ˜+Jšœœ˜-Jšœœ˜/J˜š Ÿ œœœœœ˜0Jš œœœœœ˜$Jšœœœ˜CJšœœ˜ šœ˜ šœœœ˜/Jšœœ œ˜Jšœœ˜6Jšœ˜——Jšœ+˜1J˜—šŸœœœ˜7J˜2J˜—šŸœœ(œ˜MJšœœ˜-Jšœ˜J˜1Jšœ˜ J˜—šŸœœœ˜=J˜2J˜—Jšœ™˜Jšœ œ˜J˜J˜š Ÿœœ œœœ˜BJšœ#˜)J˜—šŸœœœ˜J˜Jšœ œ˜J˜J˜—Jš Ÿ œœœœœœ˜EJ˜šŸ œœœœ˜3Jšœ˜J˜—šŸ œœœ œ˜2Jšž™J˜AJ˜—šŸœœœœ˜Jšœ˜J˜J˜——Jšœ™˜Jšœ œ˜J˜šŸœœœœ˜GJšœ˜J˜J˜J˜J˜˜ J˜.J˜+J˜J˜—šŸ œœœ˜BJšœ ˜šœœ˜J˜CJšœ%ž ˜1Jšœœ˜—Jšœ˜ J˜—Jšœœ˜*J˜˜šœ œ˜J˜#˜ J˜6Jšœœ˜#š˜šœœ˜˜ J˜Jšœœ˜+J˜J˜9J˜8—Jšœ ˜———Jšœ ˜—Jšœ˜J˜—J˜J˜J˜J˜Jšœ/œ˜5Jšœœ œ˜,Jšœœ œ˜=š œœœœ˜S˜šœœœ˜LJšœ˜ Jšœ ˜——Jšœ˜—J˜Jšœœ˜#J˜J˜——Jšœ™˜šŸœœ˜/Jšœ˜J˜J˜J˜CJ˜š Ÿ œœœœœ˜GJš œœœœœ˜@J˜—Jšœœ*˜:š œœ œœœœ˜5Jš œ(œ ˜A—Jšœœ˜Jšœœ˜ J˜šŸ œœ˜"šœœ˜˜ šœœ˜˜J˜"J˜J˜J˜J˜—J˜——Jšœ˜ J˜——šŸ œœœ˜?J˜J˜šŸ œœœœ˜3šœœ˜˜ šœœœ˜2Jšœœ+œ˜H˜J˜J˜Jšœ œ˜—Jšœœ˜(J˜——Jšœœ˜—Jšœœ˜J˜—J˜Jšœœ2˜Pš˜šœG˜Jšœ˜šœœ˜!Jšœ œž˜/Jšœ8˜?—Jšœ˜———šœœ˜Jšœœ,œ˜H—Jšœ˜J˜—J˜J˜šœL˜Ošœ˜Jšœœ˜——J˜Jš œœœœœ˜CJšœœ˜%Jšœœœ˜:Jšœœ˜!J˜—šŸ œœ˜Jš œœ œœœœ ˜?Jšœœ˜Jšœ™Jšœ œ˜J˜J˜"J˜ š˜J˜šœœ ˜J˜,šœ˜J˜Jšœ œœ ˜Jšœ˜—J˜ Jšœ˜—Jšœœœ˜Jšœ˜ J˜J˜———Jšœ ™ ˜šŸœœœ˜Jš œœœ œœ˜9J˜+J˜J˜—šŸœœœ˜/Jšœ˜J˜ J˜J˜Jšœœ˜ J˜šŸ œœ˜2J˜Jšœœ˜J˜&J˜J˜—J˜J˜%J˜)J˜"J˜)J˜$J˜&Jšœ œ˜J˜#J˜ J˜Jšœ œ˜˜Jšœ-œ˜3—J˜LJ˜LJšœœ-˜Fšœ˜J˜JšœUœ˜[J˜˜ JšœFœ˜M——J˜UJ˜LJ˜QJ˜LJ˜=J˜(J˜%Jšœ œ œ˜Ešœ˜J˜=J˜B—Jšœœ˜$J˜8J˜J˜Jšœœ˜2J˜J˜J˜J˜J˜šœ œ˜(J˜%J˜J˜)J˜J˜J˜)J˜7J˜J˜J˜J˜J˜7J˜AJšœ*œ˜1—šœœ˜J˜ Jšœ4˜4J˜Jšœœœ˜2Jšœœ˜Jšœœ˜#˜J˜J˜Jšœžœ˜!—Jšœœ˜%J˜Jšœ!œœ œ˜MJšœœ™Jšœ$œ˜,J˜J˜J˜——šŸ œœœ˜1Jšœœ*˜9Jšœœ(˜8šœœ˜Jšœ˜ Jšœ œ œ˜#˜Jšœ œ ˜ Jšœ œ˜Jšœ œ˜Jšœ œ˜Jšœ œ˜Jšœ œ˜Jšœ œœ˜8—Jšœ œ˜(J˜J˜Jšœ œœœž ˜?Jšœ œ˜Jšœ œ˜J˜šŸœœ œœœœœ˜˜>J˜Jšœ˜J˜J˜—Jš œ œœœœ˜1Jšœ œ˜J˜šŸ œœœ˜MJšœœ˜3šœ˜J˜Qšœœœ˜!Jšœœœ˜*Jšœ˜ —Jšœ œœœ˜JJ˜P—Jšœ˜J˜—šŸœœœ˜ Jšœ œ˜Jšœœœ˜9J˜—šŸœœ œ˜(Jšœ œ˜šœ œœœ˜+Jšœœ˜#—Jš œœœœœœ˜PJšœ œœœ ˜.J˜J˜J˜—Jšœ!œ˜'J˜Jšœ œ˜˜šŸ œœ%˜7J˜Jšœ œ˜J˜šœ œ˜˜ Jšœ˜Jšœœœ˜Jšœœ˜ J˜+Jšœœ˜&Jšœ œ˜JšœC˜CJšœœ ˜!J˜&J˜Jšœœ˜—˜ Jšœœœ#˜1J˜&J˜%—Jšœ˜—˜Jšœ,œ˜3Jšœœœ˜'—Jšœ!œ˜(J˜—J˜.J˜—J˜Jšœ(œœ˜EJšœœœ ˜,Jšœ œ˜)Jšœ˜˜šŸœœœ˜=J˜J˜J˜)Jšœ)˜/J˜JšŸ œœ œ˜=Jšœœœ6˜D˜J˜J˜ J˜J˜2J˜J˜—Jšœœ˜Jšœœ˜&J˜—Jšœœ"˜>J˜ J˜J˜,J˜J˜/J˜