DIRECTORY Alloc USING [Top], CompilerUtil USING [AppendMobPair, AppendMobString, AppendMobUnits, EndMob, FileByteIndex, FillMobPage, ReadMobIndex, ReadMobOffset, RTTableOut, StartMob, UpdateMobUnits], ConstArith USING [FromInt], ConvertUnsafe USING [AppendRope, EqualSubStrings, SubString], MimData USING [base, codeSeg, compilerVersion, fixupLoc, importCtx, interface, linkCount, mainCtx, matched, mobSeg, moduleCtx, monitored, mtRoot, mtRootSize, nBodies, nSigCodes, objectVersion, ownSymbols, pattern, source, switches, symSeg, table, tC0, tC1, textIndex], MimosaCopier USING [FreeSymbolTable, GetSymbolTable, MapSymbols, UnmapSymbols], MimosaEvents USING [Callback, RegisterSet, Trigger], MimosaLog USING [ErrorN, ErrorSei, ErrorType, WarningRope, WarningSei, WarningSubString], MimP4 USING [AssignEntries, Attr, Bias, Body, DeclItem, DefaultBasicOps, ExpANotify, ExpBNotify, ExpCNotify, ExpInit, ExpReset, ImplicitRecord, LayoutNotify, MatchMob, OperandStruct, OpsNotify, ownGfi, StmtNotify, TypeExp, VarInit, voidAttr], MimZones USING [permUZ, tempUZ, tempZone], MobDefs USING [Mob, MobBase, CodeDesc, CTIndex, CTNull, EVHandle, EVIndex, EVNull, EVRecord, EXPIndex, EXPLink, EXPRecord, FPIndex, FTIndex, FTRecord, FTSelf, IMPIndex, IMPRecord, LFIndex, LFNull, Link, LinkOffset, ModuleIndex, MTHandle, MTIndex, MTRecord, Namee, NameRecord, NameString, NTIndex, NTRecord, nullLink, NullName, ProcIndex, procLimit, RefLitIndex, RFIndex, RFNull, SGIndex, SGRecord, SPIndex, TFIndex, TFNull, TMIndex, TMRecord, TypeIndex, TYPIndex, TYPRecord, varLimit, VersionID], OSMiscOps USING [mobFormat, bytesPerFilePage], Pass4Parms USING [links], Pass4ToPass5 USING [ImportsVisitor, ExportsVisitor], RefText USING [Append], Rope USING [Length, ROPE], SourceMap USING [Loc], Symbols USING [Base, bodyType, BTIndex, BTNull, CBTIndex, CSEIndex, CTXIndex, CTXNull, ctxType, IncludedCTXIndex, ISEIndex, ISENull, Linkage, MDIndex, MDNull, MDRecord, mdType, Name, nullFileIndex, nullName, OwnMdi, RecordSEIndex, RecordSENull, RootBti, seType, Type, typeANY, typeTYPE], SymbolOps, SymbolTable USING [Base], SymbolTablePrivate USING [SymbolTableBaseRep], SymLiteralOps USING [DescribeRefLits, DescribeTypes, EnumerateRefLits, EnumerateTypes, RefLitsVisitor, TypeIndex, TypesVisitor, UTypeId], Target: TYPE MachineParms USING [bitsPerAU], Tree USING [Base, Index, Link, nullIndex, Scan, treeType], TreeOps USING [FreeNode, GetNode, GetSe, GetTag, ListLength, NthSon, OpName, ScanList, ToLoc], Types USING [Assignable, Equivalent, Handle], TypeStrings USING [Create, TypeString]; Pass4B: PROGRAM IMPORTS Alloc, CompilerUtil, ConstArith, ConvertUnsafe, MimData, MimosaCopier, MimosaEvents, MimosaLog, MimP4, MimZones, OSMiscOps, RefText, Rope, SymbolOps, SymLiteralOps, TreeOps, Types, TypeStrings EXPORTS CompilerUtil, MimP4, Pass4ToPass5, SymbolTable = { OPEN Symbols; STB: TYPE = REF SymbolTableBaseRep; SymbolTableBaseRep: PUBLIC TYPE = SymbolTablePrivate.SymbolTableBaseRep; tb: Tree.Base; -- tree base address (local copy) seb: Symbols.Base; -- se table base address (local copy) ctxb: Symbols.Base; -- context table base address (local copy) mdb: Symbols.Base; -- body table base address (local copy) bb: Symbols.Base; -- body table base address (local copy) tTRUE: PUBLIC Tree.Link; tFALSE: PUBLIC Tree.Link; returnRecord: PUBLIC RecordSEIndex; resumeRecord: PUBLIC RecordSEIndex; implicit: PUBLIC MimP4.ImplicitRecord; nullBias: PUBLIC MimP4.Bias; -- constant bias of zero lockNode: PUBLIC Tree.Index; resident: PUBLIC BOOL; FileByteIndex: TYPE = CompilerUtil.FileByteIndex; P4Notify: MimosaEvents.Callback = { SELECT class FROM zoneReset, cleanup => { typeMap ¬ NIL; nStringREFTEXT ¬ NIL; nString ¬ NIL; Reset[]; }; relocate => { tb ¬ MimData.base[Tree.treeType]; seb ¬ MimData.base[seType]; ctxb ¬ MimData.base[ctxType]; mdb ¬ MimData.base[mdType]; bb ¬ MimData.base[bodyType]; MimP4.LayoutNotify[MimData.base]; MimP4.StmtNotify[MimData.base]; MimP4.OpsNotify[MimData.base]; MimP4.ExpANotify[MimData.base]; MimP4.ExpBNotify[MimData.base]; MimP4.ExpCNotify[MimData.base]; }; ENDCASE; }; P4Unit: PUBLIC PROC [unit: Tree.Link] = { node: Tree.Index; tTRUE ¬ MimData.tC1; tFALSE ¬ MimData.tC0; implicit.type ¬ typeANY; implicit.lb ¬ implicit.ub ¬ nullBias ¬ implicit.bias ¬ ConstArith.FromInt[0]; implicit.attr ¬ MimP4.voidAttr; implicit.sef ¬ TRUE; resumeRecord ¬ RecordSENull; MimP4.ExpInit[]; node ¬ TreeOps.GetNode[unit]; Module[node ! MimP4.VarInit => {RESUME [TRUE]}]; MimP4.ExpReset[]; TreeOps.FreeNode[node]; }; Module: PROC [node: Tree.Index] = { subNode: Tree.Index = TreeOps.GetNode[tb[node].son[6]]; saveIndex: SourceMap.Loc = MimData.textIndex; MimData.textIndex ¬ TreeOps.ToLoc[tb[subNode].info]; InitMob[tb[subNode].son[1]]; MimData.textIndex ¬ TreeOps.ToLoc[tb[node].info]; lockNode ¬ Tree.nullIndex; IF MimData.monitored THEN { lockNode ¬ TreeOps.GetNode[tb[node].son[5]]; IF tb[lockNode].name = lambda THEN { son1: Tree.Link ¬ tb[lockNode].son[1]; IF TreeOps.OpName[son1] = decl THEN MimP4.TypeExp[TreeOps.NthSon[son1, 2]]; }; }; resident ¬ tb[node].attr1; Reset[]; MimP4.AssignEntries[Symbols.RootBti]; AssignImports[tb[node].son[2]]; MimP4.DeclItem[tb[node].son[6]]; MimP4.Body[Symbols.RootBti]; TreeOps.ScanList[tb[node].son[1], DirectoryItem]; ProcessImports[tb[node].son[2]]; ProcessExports[tb[node].son[3]]; IF MimData.interface THEN { def: ISEIndex = ctxb[MimData.moduleCtx].seList; defType: CSEIndex = SymbolOps.UnderType[SymbolOps.own, seb[def].idType]; WITH d: seb[defType] SELECT FROM definition => { slots: CARDINAL ¬ 0; FOR sei: ISEIndex ¬ ctxb[d.defCtx].seList, SymbolOps.NextSe[SymbolOps.own, sei] WHILE sei # ISENull DO mode: Linkage = SymbolOps.LinkMode[SymbolOps.own, sei]; IF mode # manifest THEN slots ¬ slots + 1; ENDLOOP; d.slots ¬ slots; }; ENDCASE => ERROR; }; FinishMob[tb[subNode].son[1]]; IF MimData.matched THEN MimData.matched ¬ MimP4.MatchMob[]; MimData.textIndex ¬ saveIndex; }; bitsPerAU: CARDINAL = Target.bitsPerAU; mobHeader: MobDefs.MobBase; mobIndex: FileByteIndex; mtIndex: FileByteIndex; permUZ: UNCOUNTED ZONE = MimZones.permUZ; tempUZ: UNCOUNTED ZONE = MimZones.tempUZ; z: ZONE = MimZones.tempZone; pageBytes: NAT = OSMiscOps.bytesPerFilePage; nString: MobDefs.NameString; nStringREFTEXT: REF TEXT; firstPorted: MDIndex = OwnMdi + MDRecord.SIZE; lastPorted: MDIndex ¬ firstPorted; -- im/exported files in [firstPorted..lastPorted) evList: MobDefs.EVHandle ¬ NIL; -- initialized in START code, below evListMax: NAT ¬ 60; -- the # of elements allocated for evList protoMTRecord: MobDefs.MTHandle; -- initialized in START code, below ImportList: TYPE = REF ImportListRep; ImportListRep: TYPE = RECORD [ mdi: Symbols.MDIndex, formal: Symbols.Name, irSei: ISEIndex, irType: CSEIndex, src: ISEIndex, link: MobDefs.Link, next: ImportList ¬ NIL ]; importHead: ImportList ¬ NIL; importTail: ImportList ¬ NIL; ExportList: TYPE = REF ExportListRep; ExportListRep: TYPE = RECORD [ mdi: Symbols.MDIndex, formal: Symbols.Name, irSei: ISEIndex, irType: CSEIndex, ts: TypeStrings.TypeString, src: ISEIndex, link: MobDefs.EXPLink, next: ExportList ¬ NIL ]; exportHead: ExportList ¬ NIL; exportTail: ExportList ¬ NIL; ModuleIndex: TYPE = MobDefs.ModuleIndex; ProcIndex: TYPE = MobDefs.ProcIndex; procLimit: CARDINAL = MobDefs.procLimit; varLimit: CARDINAL = MobDefs.varLimit; MobLink: TYPE = MobDefs.Link; ownGfi: ModuleIndex = MimP4.ownGfi; MakeEPLink: PUBLIC PROC [ep: CARDINAL, gfi: ModuleIndex] RETURNS [MobLink] = { RETURN [[tag: proc, offset: ep MOD procLimit, modIndex: gfi + ep/procLimit]]; }; MakeFrameLink: PROC [ep: CARDINAL, gfi: ModuleIndex] RETURNS [MobLink] = INLINE { RETURN [[tag: var, offset: ep MOD varLimit, modIndex: gfi + ep/varLimit]]; }; MakeTypeLink: PROC [index: MobDefs.TYPIndex] RETURNS [MobLink] = INLINE { offset: CARD ¬ LOOPHOLE[index, CARD] / MobDefs.TYPRecord.SIZE; IF offset >= MobDefs.LinkOffset.LAST THEN ERROR; RETURN [[tag: type, offset: offset]]; }; MdiForCtx: PROC [ctx: CTXIndex] RETURNS [MDIndex] = INLINE { WITH c: ctxb[ctx] SELECT FROM included => RETURN [c.module]; imported => RETURN [ctxb[c.includeLink].module]; ENDCASE => RETURN [OwnMdi] }; PortedCtx: PROC [ctx: CTXIndex] RETURNS [MobDefs.FTIndex] = INLINE { RETURN [PortedFile[MdiForCtx[ctx]]]; }; PortedFile: PROC [mdi: MDIndex] RETURNS [fti: MobDefs.FTIndex ¬ MobDefs.FTSelf] = { IF mdi # OwnMdi THEN { n: CARDINAL; IF mdi IN [firstPorted .. lastPorted) THEN n ¬ LOOPHOLE[mdi-firstPorted, CARD]/MDRecord.SIZE ELSE { n ¬ LOOPHOLE[lastPorted-firstPorted, CARD]/MDRecord.SIZE; { mdi1: MDIndex ¬ mdi; mdi2: MDIndex ¬ lastPorted; IF mdi1 # mdi2 THEN { t: MDRecord; FOR ctx: IncludedCTXIndex ¬ mdb[mdi1].ctx, ctxb[ctx].chain UNTIL ctx = CTXNull DO ctxb[ctx].module ¬ mdi2; ENDLOOP; FOR ctx: IncludedCTXIndex ¬ mdb[mdi2].ctx, ctxb[ctx].chain UNTIL ctx = CTXNull DO ctxb[ctx].module ¬ mdi1; ENDLOOP; t ¬ mdb[mdi1]; mdb[mdi1] ¬ mdb[mdi2]; mdb[mdi2] ¬ t; } }; lastPorted ¬ lastPorted + MDRecord.SIZE; }; fti ¬ MobDefs.FTIndex.FIRST + n*MobDefs.FTRecord.SIZE; }; }; EnterId: PROC [id: ConvertUnsafe.SubString, ignoreCase: BOOL] RETURNS [MobDefs.NameRecord] = { i: CARDINAL ¬ 0; s: ConvertUnsafe.SubString; s.base ¬ LOOPHOLE[nString]; UNTIL i = nString.length DO s.offset ¬ i+1; s.length ¬ nString[i].ORD; IF id.EqualSubStrings[s2: s, case: ~ignoreCase] THEN RETURN [[i]]; i ¬ i + s.length+1; REPEAT FINISHED => { len: [0..255) = id.length; nLen: NAT ¬ nString.length+(len+1); IF nLen > nString.maxLength THEN { tLen: NAT ¬ nString.maxLength + MAX[(len+1), 512]; t: REF TEXT ¬ z.NEW[TEXT[tLen]]; t ¬ RefText.Append[t, nStringREFTEXT]; z.FREE[@nStringREFTEXT]; nStringREFTEXT ¬ t; nString ¬ LOOPHOLE[nStringREFTEXT, MobDefs.NameString]; }; nString[i] ¬ VAL[len]; FOR j: CARDINAL IN [0..len) DO nString[i+1+j] ¬ id.base[id.offset+j]; ENDLOOP; nString.length ¬ i + len + 1; }; ENDLOOP; RETURN [[i]]; }; EnterSymbolId: PROC [sei: ISEIndex] RETURNS [MobDefs.NameRecord] = { s: ConvertUnsafe.SubString = SymbolOps.SubStringForName[SymbolOps.own, seb[sei].hash]; RETURN [EnterId[s, FALSE]]; }; EnterFileId: PROC [mdi: MDIndex] RETURNS [MobDefs.NameRecord] = { ext: LONG STRING = ".mob"; extLength: CARDINAL = ext.length; s: ConvertUnsafe.SubString ¬ SymbolOps.SubStringForName[SymbolOps.own, mdb[mdi].fileId]; IF s.base[s.offset+s.length-1] = '. THEN s.length ¬ s.length - 1; IF s.length > extLength THEN { s1: ConvertUnsafe.SubString ¬ [ base: s.base, offset: s.offset+s.length-extLength, length: extLength]; s2: ConvertUnsafe.SubString ¬ [base: ext, offset: 0, length: extLength]; IF ConvertUnsafe.EqualSubStrings[s1: s1, s2: s2, case: FALSE] THEN s.length ¬ s.length - extLength; }; RETURN [EnterId[s, TRUE]]; }; Reset: PUBLIC PROC = { WHILE importHead # NIL DO lag: ImportList ¬ importHead; importHead ¬ importHead.next; z.FREE[@lag]; ENDLOOP; importHead ¬ importTail ¬ NIL; FOR each: ExportList ¬ exportHead, each.next WHILE each # NIL DO IF each.ts # NIL THEN tempUZ.FREE[@each.ts]; ENDLOOP; WHILE exportHead # NIL DO lag: ExportList ¬ exportHead; exportHead ¬ exportHead.next; z.FREE[@lag]; ENDLOOP; exportHead ¬ exportTail ¬ NIL; }; VisitImports: PUBLIC PROC [visitor: Pass4ToPass5.ImportsVisitor] = { FOR each: ImportList ¬ importHead, each.next WHILE each # NIL DO visitor[each.mdi, each.formal, each.irSei, each.irType, each.src, each.link]; ENDLOOP; }; VisitExports: PUBLIC PROC [visitor: Pass4ToPass5.ExportsVisitor] = { FOR each: ExportList ¬ exportHead, each.next WHILE each # NIL DO visitor[each.mdi, each.formal, each.irSei, each.irType, each.ts, each.src, each.link]; ENDLOOP; }; DirectoryItem: Tree.Scan = { node: Tree.Index = TreeOps.GetNode[t]; sei: ISEIndex = TreeOps.GetSe[tb[node].son[1]]; type: CSEIndex = SymbolOps.UnderType[SymbolOps.own, seb[sei].idType]; WITH t: seb[type] SELECT FROM definition => [] ¬ PortedCtx[t.defCtx]; transfer => { bti: BTIndex = SymbolOps.DecodeBti[seb[sei].idInfo]; IF bti # BTNull THEN [] ¬ PortedCtx[bb[bti].localCtx]; }; ENDCASE; }; AssignImports: PUBLIC Tree.Scan = { gfi: ModuleIndex ¬ mobHeader.firstdummy ¬ ownGfi + 1; saveIndex: SourceMap.Loc = MimData.textIndex; MimData.mtRoot.modIndex ¬ ownGfi; MimData.mtRoot.entries ¬ MAX[MimData.nBodies, MimData.nSigCodes]; FOR sei: ISEIndex ¬ SymbolOps.FirstCtxSe[SymbolOps.own, MimData.importCtx], SymbolOps.NextSe[SymbolOps.own, sei] UNTIL sei = ISENull DO node: Tree.Index = SymbolOps.DecodeTreeIndex[seb[sei].idValue]; id: ISEIndex ¬ sei; formal: Symbols.Name ¬ seb[sei].hash; type: CSEIndex = SymbolOps.UnderType[SymbolOps.own, seb[sei].idType]; new: ImportList ¬ NIL; IF node # Tree.nullIndex THEN { fSon: Tree.Link = tb[node].son[1]; MimData.textIndex ¬ TreeOps.ToLoc[tb[node].info]; WITH e: fSon SELECT TreeOps.GetTag[fSon] FROM hash => formal ¬ e.index; symbol => formal ¬ seb[e.index].hash; ENDCASE; }; WITH se: seb[type] SELECT FROM definition => { slots: CARDINAL = se.slots; ctx: CTXIndex = se.defCtx; IF ctxb[ctx].seList = ISENull THEN MimosaLog.WarningSei[unusedImport, sei]; IF ~MimData.interface THEN { mdi: MDIndex ¬ MdiForCtx[ctx]; FOR sei: ISEIndex ¬ SymbolOps.FirstCtxSe[SymbolOps.own, ctx], SymbolOps.NextSe[SymbolOps.own, sei] UNTIL sei = ISENull DO IF ~seb[sei].constant THEN { ut: CSEIndex = SymbolOps.UnderType[SymbolOps.own, seb[sei].idType]; epN: CARDINAL = SymbolOps.DecodeCard[seb[sei].idValue]; link: MobLink ¬ MakeEPLink[epN, gfi]; SELECT seb[ut].typeTag FROM ref => link.tag ¬ var; transfer => link.tag ¬ proc; ENDCASE => link.tag ¬ other; seb[sei].idValue ¬ SymbolOps.EncodeLink[link]; new ¬ z.NEW[ImportListRep ¬ [ mdi: mdi, formal: formal, irSei: id, irType: type, src: sei, link: link]]; IF importTail = NIL THEN importHead ¬ new ELSE importTail.next ¬ new; importTail ¬ new; }; ENDLOOP; }; seb[sei].idInfo ¬ SymbolOps.EncodeCard[slots]; gfi ¬ gfi + 1; }; ref => { IF ~MimData.interface THEN { link: MobLink ¬ MakeEPLink[0, gfi]; seb[sei].idValue ¬ SymbolOps.EncodeLink[link]; new ¬ z.NEW[ImportListRep ¬ [ mdi: MDNull, formal: formal, irSei: id, irType: type, src: sei, link: link]]; IF importTail = NIL THEN importHead ¬ new ELSE importTail.next ¬ new; importTail ¬ new; }; gfi ¬ gfi + 1; }; ENDCASE; seb[sei].mark4 ¬ TRUE; ENDLOOP; mobHeader.nDummies ¬ gfi - mobHeader.firstdummy; MimData.textIndex ¬ saveIndex; }; ProcessSymLiterals: PUBLIC PROC = { rfOffset: CARD = CompilerUtil.ReadMobOffset[]; mobHeader.rfOffset.units ¬ rfOffset; mobHeader.lfLimit ¬ MobDefs.LFIndex.FIRST + (rfOffset - mobHeader.lfOffset.units); IF ~MimData.interface THEN { rfi: MobDefs.RefLitIndex ¬ [0]; length: CARD ¬ 0; offset: CARD ¬ 0; AppendLitItem: SymLiteralOps.RefLitsVisitor = { CompilerUtil.AppendMobUnits[@rfi, MobDefs.RefLitIndex.SIZE]; rfi ¬ [rfi + 1]; }; [offset, length] ¬ SymLiteralOps.DescribeRefLits[]; IF length # 0 THEN { MimData.mtRoot.refLiterals ¬ MobDefs.RFIndex.FIRST; CompilerUtil.AppendMobPair[offset, length]; SymLiteralOps.EnumerateRefLits[AppendLitItem]; } }; { tfOffset: CARD = CompilerUtil.ReadMobOffset[]; mobHeader.tfOffset.units ¬ tfOffset; mobHeader.rfLimit ¬ MobDefs.RFIndex.FIRST + (tfOffset-rfOffset); IF NOT MimData.interface THEN { length: CARD ¬ 0; offset: CARD ¬ 0; tfi: MobDefs.TypeIndex ¬ [0]; AppendTypeIndex: SymLiteralOps.TypesVisitor = { CompilerUtil.AppendMobUnits[@tfi, MobDefs.TypeIndex.SIZE]; tfi ¬ [tfi + 1]; }; [offset, length] ¬ SymLiteralOps.DescribeTypes[]; IF length # 0 THEN { MimData.mtRoot.types ¬ MobDefs.TFIndex.FIRST; CompilerUtil.AppendMobPair[offset, length]; SymLiteralOps.EnumerateTypes[AppendTypeIndex]; } }; mobHeader.tfLimit ¬ MobDefs.TFIndex.FIRST + (CompilerUtil.ReadMobOffset[]-tfOffset); }; }; ProcessImports: Tree.Scan = { ProcessSei: PROC [sei, tSei: ISEIndex, implicit: BOOL] = { type: CSEIndex = SymbolOps.UnderType[SymbolOps.own, seb[sei].idType]; entry: MobDefs.IMPRecord ¬ [ name: EnterSymbolId[tSei], port: interface, namedInstance: seb[sei].hash # seb[tSei].hash, modIndex: nextSlot, offset: 0]; WITH t: seb[type] SELECT FROM definition => { entry.file ¬ PortedCtx[t.defCtx]; seb[sei].idValue ¬ SymbolOps.EncodeCard[nextSlot]; nextSlot ¬ nextSlot + 1; }; ref => { rType: RecordSEIndex = LOOPHOLE[SymbolOps.UnderType[SymbolOps.own, t.refType]]; entry.port ¬ module; entry.file ¬ PortedCtx[seb[rType].fieldCtx]; nextSlot ¬ nextSlot + 1; }; ENDCASE; nImports ¬ nImports + 1; IF entry.namedInstance THEN anyNamed ¬ TRUE; CompilerUtil.AppendMobUnits[@entry, MobDefs.IMPRecord.SIZE]; }; ImportItem: Tree.Scan = { node: Tree.Index = TreeOps.GetNode[t]; ProcessSei[sei, TreeOps.GetSe[tb[node].son[2]], FALSE]; sei ¬ SymbolOps.NextSe[SymbolOps.own, sei]; }; NameItem: Tree.Scan = { node: Tree.Index = TreeOps.GetNode[t]; sei: ISEIndex = TreeOps.GetSe[tb[node].son[1]]; tSei: ISEIndex = TreeOps.GetSe[tb[node].son[2]]; entry: MobDefs.NTRecord; IF seb[sei].hash # seb[tSei].hash THEN { entry ¬ [name: EnterSymbolId[sei], item: MobDefs.Namee[0, 0, import[impi]]]; CompilerUtil.AppendMobUnits[@entry, MobDefs.NTRecord.SIZE]; }; impi ¬ impi + MobDefs.IMPRecord.SIZE; }; units: CARD ¬ mobHeader.impOffset.units ¬ CompilerUtil.ReadMobOffset[]; nImports: CARDINAL ¬ 0; impi: MobDefs.IMPIndex ¬ MobDefs.IMPIndex.FIRST; nextSlot: CARDINAL ¬ mobHeader.firstdummy; anyNamed: BOOL ¬ FALSE; sei: ISEIndex ¬ SymbolOps.FirstCtxSe[SymbolOps.own, MimData.importCtx]; TreeOps.ScanList[t, ImportItem]; UNTIL sei = ISENull DO ProcessSei[sei, sei, TRUE]; sei ¬ SymbolOps.NextSe[SymbolOps.own, sei]; ENDLOOP; mobHeader.nImports ¬ nImports; mobHeader.impLimit ¬ MobDefs.IMPIndex.FIRST + (CompilerUtil.ReadMobOffset[]-units); mobHeader.ntOffset.units ¬ units ¬ CompilerUtil.ReadMobOffset[]; IF anyNamed THEN TreeOps.ScanList[t, NameItem]; mobHeader.ntLimit ¬ MobDefs.NTIndex.FIRST + (CompilerUtil.ReadMobOffset[]-units); }; EnterEVOffset: PROC [offset: CARDINAL] RETURNS [CARDINAL] = { index: CARDINAL ¬ 0; IF offset # 0 THEN { FOR i: CARDINAL IN [1 .. evList.length] DO IF offset = evList.offsets[i] THEN RETURN [i]; ENDLOOP; index ¬ evList.length + 1; IF index >= evListMax THEN { newMax: NAT = evListMax + MIN[evListMax, 1024]; new: MobDefs.EVHandle = permUZ.NEW[MobDefs.EVRecord[newMax]]; FOR i: NAT IN [1 .. evList.length] DO new.offsets[i] ¬ evList.offsets[i]; ENDLOOP; new.pad ¬ evList.pad; permUZ.FREE[@evList]; evList ¬ new; evListMax ¬ newMax; }; evList.offsets[index] ¬ offset; evList.length ¬ index; }; RETURN [index]; }; TypeMap: TYPE = RECORD [SEQUENCE length: CARDINAL OF TypeMapEntry]; TypeMapEntry: TYPE = RECORD [opaque: MobDefs.TMRecord, concrete: MobDefs.TYPRecord]; typeMap: REF TypeMap ¬ NIL; mapIndex: CARDINAL ¬ 0; typeIndex: MobDefs.TYPIndex ¬ MobDefs.TYPIndex.FIRST; EnterType: PROC [mdi: MDIndex, offset: CARDINAL, sei: ISEIndex] RETURNS [typeId: MobDefs.TYPIndex] = { entry: MobDefs.TYPRecord = MakeTypeId[sei]; IF typeMap = NIL OR mapIndex >= typeMap.length THEN AdjustTypeMap[8]; FOR i: CARDINAL IN [0..mapIndex) DO IF typeMap[i].concrete = entry THEN GO TO matched; REPEAT matched => typeId ¬ typeMap[i].opaque.map; FINISHED => {typeId ¬ typeIndex; typeIndex ¬ typeIndex + MobDefs.TYPRecord.SIZE}; ENDLOOP; typeMap[mapIndex] ¬ [ opaque: [version: mdb[mdi].stamp, offset: offset, map: typeId], concrete: entry]; mapIndex ¬ mapIndex + 1; }; MakeTypeId: PROC [id: ISEIndex] RETURNS [MobDefs.TYPRecord] = { sei: ISEIndex ¬ id; DO next: Type = SymbolOps.DecodeType[seb[sei].idInfo]; WITH seb[next] SELECT FROM id => sei ¬ LOOPHOLE[next]; ENDCASE => { mdi: MDIndex = MdiForCtx[seb[sei].idCtx]; RETURN [[version: mdb[mdi].stamp, id: SymbolOps.DecodeInt[seb[sei].idValue]]]; }; ENDLOOP; }; AdjustTypeMap: PROC [delta: CARDINAL] = { oldN: CARDINAL = IF typeMap = NIL THEN 0 ELSE typeMap.length; newMap: REF TypeMap = z.NEW[TypeMap[oldN+delta]]; FOR i: CARDINAL IN [0 .. oldN) DO newMap[i] ¬ typeMap[i] ENDLOOP; z.FREE[@typeMap]; typeMap ¬ newMap; }; WriteTypeTable: PROC = { next: MobDefs.TYPIndex ¬ MobDefs.TYPIndex.FIRST; offset: CARD ¬ CompilerUtil.ReadMobOffset[]; mobHeader.typOffset.units ¬ offset; FOR i: CARDINAL IN [0 .. mapIndex) DO FOR j: CARDINAL IN [0..i) DO IF typeMap[i].opaque.map = typeMap[j].opaque.map THEN EXIT REPEAT FINISHED => { CompilerUtil.AppendMobUnits[@typeMap[i].concrete, MobDefs.TYPRecord.SIZE]; next ¬ next + MobDefs.TYPRecord.SIZE}; ENDLOOP; ENDLOOP; mobHeader.typLimit ¬ MobDefs.TYPIndex.FIRST + CARDINAL[CompilerUtil.ReadMobOffset[]-offset]; offset ¬ CompilerUtil.ReadMobOffset[]; mobHeader.tmOffset.units ¬ offset; FOR i: CARDINAL IN [0 .. mapIndex) DO CompilerUtil.AppendMobUnits[@typeMap[i].opaque, MobDefs.TMRecord.SIZE]; ENDLOOP; mobHeader.tmLimit ¬ MobDefs.TMIndex.FIRST + (CompilerUtil.ReadMobOffset[]-offset); }; ExportItem: Tree.Scan = { node: Tree.Index = TreeOps.GetNode[t]; saveIndex: SourceMap.Loc = MimData.textIndex; son1: Tree.Link = tb[node].son[1]; son2: Tree.Link = tb[node].son[2]; expType: CSEIndex = MimP4.OperandStruct[son2, FALSE]; MimData.textIndex ¬ TreeOps.ToLoc[tb[node].info]; WITH se: seb[expType] SELECT FROM definition => { id: ISEIndex = TreeOps.GetSe[son2]; ctx: IncludedCTXIndex = IF ctxb[se.defCtx].ctxType = included THEN LOOPHOLE[se.defCtx] ELSE ERROR; mdi: MDIndex = ctxb[ctx].module; iBase: STB = MimosaCopier.GetSymbolTable[mdi]; IF iBase # NIL THEN { expHeader: LONG POINTER TO MobDefs.EXPRecord ¬ NIL; size: NAT ¬ 0; epN: CARDINAL ¬ 0; typeExported: BOOL ¬ FALSE; used: BOOL ¬ FALSE; formal: Symbols.Name ¬ nullName; WITH e: son1 SELECT TreeOps.GetTag[son1] FROM hash => formal ¬ e.index; symbol => formal ¬ seb[e.index].hash; ENDCASE; FOR iSei: ISEIndex ¬ SymbolOps.FirstCtxSe[iBase, ctxb[ctx].map], SymbolOps.NextSe[iBase, iSei] UNTIL iSei = ISENull DO SELECT SymbolOps.LinkMode[iBase, iSei] FROM val, ref => size ¬ size + 1; type => {typeExported ¬ TRUE; size ¬ size + 1}; ENDCASE; ENDLOOP; expHeader ¬ permUZ.NEW[MobDefs.EXPRecord[size]]; expHeader.name ¬ EnterSymbolId[id]; expHeader.port ¬ interface; expHeader.namedInstance ¬ FALSE; expHeader.typeExported ¬ FALSE; expHeader.file ¬ PortedCtx[ctx]; FOR iSei: ISEIndex ¬ SymbolOps.FirstCtxSe[iBase, ctxb[ctx].map], SymbolOps.NextSe[iBase, iSei] UNTIL iSei = ISENull DO mode: Linkage = SymbolOps.LinkMode[iBase, iSei]; link: MobLink ¬ MobDefs.nullLink; destOffset: MobDefs.LinkOffset ¬ epN; expLink: MobDefs.EXPLink ¬ [to: destOffset, from: link]; iTarget: Type = iBase.seb[iSei].idType; iType: CSEIndex = SymbolOps.UnderType[iBase, iTarget]; sei: ISEIndex ¬ ISENull; ss: ConvertUnsafe.SubString = SymbolOps.SubStringForName[iBase, iBase.seb[iSei].hash]; name: Name ¬ SymbolOps.FindString[SymbolOps.own, ss]; IF name # nullName THEN { sei ¬ SymbolOps.SearchContext[SymbolOps.own, name, MimData.mainCtx]; IF sei = ISENull THEN sei ¬ SymbolOps.SearchContext[SymbolOps.own, name, MimData.moduleCtx]; }; IF sei # ISENull THEN { public: BOOL = seb[sei].public; type: CSEIndex = SymbolOps.UnderType[SymbolOps.own, seb[sei].idType]; warnPrivate: BOOL ¬ NOT public AND seb[sei].idCtx = MimData.mainCtx; SELECT mode FROM $val => { SELECT TRUE FROM warnPrivate => { MimosaLog.WarningSei[privateExport, sei]; GO TO noValue; }; seb[type].typeTag = definition => { GO TO noValue; }; NOT Types.Assignable[[iBase, iType], [MimData.ownSymbols, type]] => { MimosaLog.ErrorType[exportClash, [symbol[sei]], [iBase, iTarget]]; GO TO noValue; }; NOT seb[sei].constant, seb[sei].extended => { MimosaLog.ErrorSei[varExport, sei]; GO TO noValue; }; ENDCASE; SELECT SymbolOps.XferMode[SymbolOps.own, type] FROM program => link ¬ [tag: other, modIndex: 0, offset: 0]; ENDCASE => link ¬ SymbolOps.DecodeLink[seb[sei].idValue]; }; $ref => { iVType: CSEIndex ¬ iType; iConst: BOOL ¬ iBase.seb[iSei].immutable; WITH t: iBase.seb[iType] SELECT FROM ref => IF t.var THEN { iVType ¬ SymbolOps.UnderType[iBase, t.refType]; iConst ¬ t.readOnly; }; ENDCASE; SELECT TRUE FROM warnPrivate => { MimosaLog.WarningSei[privateExport, sei]; GO TO noValue; }; NOT Types.Equivalent[ [iBase, iVType], [MimData.ownSymbols, type]] => { MimosaLog.ErrorType[exportClash, [symbol[sei]], [iBase, iTarget]]; GO TO noValue; }; seb[sei].constant => { MimosaLog.ErrorSei[varExport, sei]; GO TO noValue; }; seb[sei].immutable AND ~iConst => { MimosaLog.ErrorSei[updateClash, sei]; GO TO noValue; }; ENDCASE; link ¬ MakeFrameLink[ ep: EnterEVOffset[ SymbolOps.DecodeBitAddr[seb[sei].idValue].bd/bitsPerAU], gfi: ownGfi]; }; $type => { SELECT TRUE FROM warnPrivate => { GO TO noValue; }; type # typeTYPE, SymbolOps.TypeForm[SymbolOps.own, sei] = $opaque => { MimosaLog.ErrorSei[exportClash, sei]; GO TO noValue; }; ENDCASE => { iValue: CSEIndex = SymbolOps.UnderType[iBase, iSei]; WITH it: iBase.seb[iValue] SELECT FROM opaque => IF it.lengthKnown AND ~MimP4.DefaultBasicOps[sei, it.length] THEN { MimosaLog.ErrorSei[exportAttr, sei]; GO TO noValue; }; ENDCASE => ERROR; link ¬ MakeTypeLink[EnterType[mdi, epN, sei]]; mobHeader.typeExported ¬ TRUE; }; }; $manifest => { SELECT TRUE FROM NOT public => {}; type # typeTYPE, iBase.seb[iSei].idType # typeTYPE => MimosaLog.WarningSei[voidExport, sei]; ENDCASE; GO TO noValue; }; ENDCASE => GO TO noValue; IF link # MobDefs.nullLink THEN { iT: Type = SymbolOps.DecodeType[iBase.seb[iSei].idInfo]; ts: TypeStrings.TypeString = IF mode = type THEN TypeStrings.Create[iBase, iT, tempUZ] ELSE NIL; new: ExportList; expLink.from ¬ link; new ¬ z.NEW[ExportListRep ¬ [ mdi: mdi, formal: formal, irSei: id, irType: expType, ts: ts, src: sei, link: expLink]]; IF exportTail = NIL THEN exportHead ¬ new ELSE exportTail.next ¬ new; exportTail ¬ new; used ¬ TRUE; }; EXITS noValue => {}; }; IF mode # $manifest THEN { expHeader[epN] ¬ expLink; epN ¬ epN + 1; }; ENDLOOP; CompilerUtil.AppendMobUnits[expHeader, MobDefs.EXPRecord[size].SIZE]; permUZ.FREE[@expHeader]; MimosaCopier.FreeSymbolTable[iBase]; IF ~used THEN MimosaLog.WarningSei[unusedExport, id]; }; }; ENDCASE; MimData.textIndex ¬ saveIndex; }; ProcessExports: PROC [t: Tree.Link] = { offset: CARD ¬ CompilerUtil.ReadMobOffset[]; mobHeader.expOffset.units ¬ offset; mobHeader.nExports ¬ TreeOps.ListLength[t]; evList.length ¬ evList.pad ¬ 0; typeIndex ¬ MobDefs.TYPIndex.FIRST; mapIndex ¬ 0; typeMap ¬ NIL; TreeOps.ScanList[t, ExportItem]; mobHeader.expLimit ¬ MobDefs.EXPIndex.FIRST + (CompilerUtil.ReadMobOffset[]-offset); mobHeader.evOffset.units ¬ offset ¬ CompilerUtil.ReadMobOffset[]; SELECT evList.length FROM 0 => MimData.mtRoot.variables ¬ MobDefs.EVNull; ENDCASE => { units: NAT = SIZE[MobDefs.EVRecord[evList.length]]; MimData.mtRoot.entries ¬ MAX[MimData.mtRoot.entries, evList.length+1]; MimData.mtRoot.variables ¬ MobDefs.EVIndex.FIRST; CompilerUtil.AppendMobUnits[evList, units]; }; mobHeader.evLimit ¬ MobDefs.EVIndex.FIRST + (CompilerUtil.ReadMobOffset[]-offset); WriteTypeTable[]; typeMap ¬ NIL; }; InitMob: PUBLIC PROC [ids: Tree.Link] = { nIds: CARDINAL ¬ TreeOps.ListLength[ids]; IF nIds > 1 AND ~MimData.interface THEN {MimosaLog.ErrorN[listLong, nIds-1]; nIds ¬ 1}; lastPorted ¬ firstPorted; nStringREFTEXT ¬ z.NEW[TEXT[pageBytes-4]]; nString ¬ LOOPHOLE[nStringREFTEXT, MobDefs.NameString]; nString[MobDefs.NullName] ¬ 0C; nString.length ¬ MobDefs.NullName + 1; mdb[OwnMdi].stamp ¬ MimData.objectVersion; -- update from DIRECTORY processing CompilerUtil.StartMob[]; mobHeader.versionIdent ¬ MobDefs.VersionID; mobHeader.format ¬ OSMiscOps.mobFormat; mobHeader.version ¬ MimData.objectVersion; mobHeader.creator ¬ MimData.compilerVersion; mobHeader.sourceVersion ¬ MimData.source.version; mobHeader.nConfigs ¬ 0; mobHeader.nModules ¬ nIds; mobHeader.nImports ¬ mobHeader.nExports ¬ 0; mobHeader.definitions ¬ MimData.interface; mobHeader.typeExported ¬ FALSE; mobHeader.repackaged ¬ FALSE; mobHeader.inlineFloat ¬ MimData.switches['f]; mobHeader.versions ¬ FALSE; mobHeader.extended ¬ TRUE; mobHeader.mappingStarted ¬ FALSE; mobHeader.mappingFinished ¬ FALSE; mobHeader.ctOffset.units ¬ 0; mobHeader.ctLimit ¬ MobDefs.CTIndex.FIRST; mobHeader.spOffset.units ¬ 0; mobHeader.spLimit ¬ MobDefs.SPIndex.FIRST; mobHeader.fpOffset.units ¬ 0; mobHeader.fpLimit ¬ MobDefs.FPIndex.FIRST; { source: Rope.ROPE = MimData.source.locator; len: [0..255] ¬ Rope.Length[source]; nString[nString.length] ¬ VAL[len]; nString.length ¬ nString.length + 1; ConvertUnsafe.AppendRope[to: LOOPHOLE[nString], from: source]; }; mobIndex ¬ CompilerUtil.ReadMobIndex[]; CompilerUtil.AppendMobUnits[mobHeader, MobDefs.Mob.SIZE]; MimData.fixupLoc ¬ CompilerUtil.ReadMobIndex[]; mobHeader.sgOffset.units ¬ CompilerUtil.ReadMobOffset[]; CompilerUtil.AppendMobUnits[@MimData.codeSeg, MobDefs.SGRecord.SIZE]; CompilerUtil.AppendMobUnits[@MimData.symSeg, MobDefs.SGRecord.SIZE]; mobHeader.mtOffset.units ¬ CompilerUtil.ReadMobOffset[]; mtIndex ¬ CompilerUtil.ReadMobIndex[]; mobHeader.sgLimit ¬ MobDefs.SGIndex.FIRST + (mobHeader.mtOffset.units - mobHeader.sgOffset.units); MimData.mtRootSize ¬ MobDefs.MTRecord.SIZE; MimData.mtRoot ¬ protoMTRecord; MimData.mtRoot.links ¬ (IF MimData.interface THEN MobDefs.LFNull ELSE MobDefs.LFIndex.FIRST); MimData.mtRoot.refLiterals ¬ MobDefs.RFNull; MimData.mtRoot.types ¬ MobDefs.TFNull; FOR i: CARDINAL IN [0..nIds) DO CompilerUtil.AppendMobUnits[MimData.mtRoot, MimData.mtRootSize] ENDLOOP; mobHeader.lfOffset.units ¬ CompilerUtil.ReadMobOffset[]; mobHeader.mtLimit ¬ MobDefs.MTIndex.FIRST + (mobHeader.lfOffset.units-mobHeader.mtOffset.units); }; FinishMob: PUBLIC PROC [ids: Tree.Link] = { unitsPerPage: CARDINAL = OSMiscOps.bytesPerFilePage / BYTES[UNIT]; Alignment: CARDINAL = 4; -- Code Segments must start at 0 MOD Alignment nLinks: CARDINAL = MimData.linkCount; codeLinks: BOOL = FALSE; embeddedLinks: BOOL ¬ Pass4Parms.links.embedded; gfType: RecordSEIndex = bb[RootBti].type; mtRoot: MobDefs.MTHandle = MimData.mtRoot; IF TreeOps.ListLength[ids] > 1 THEN { inner: Tree.Scan = {[] ¬ EnterSymbolId[TreeOps.GetSe[t]]}; TreeOps.ScanList[ids, inner]; }; mtRoot.name ¬ EnterSymbolId[bb[RootBti].id]; mtRoot.namedInstance ¬ FALSE; mtRoot.initial ¬ TRUE; { fti: MobDefs.FTIndex = PortedCtx[MimData.mainCtx]; mtRoot.file ¬ fti; MimData.mobSeg.file ¬ fti; MimData.codeSeg.file ¬ fti; MimData.symSeg.file ¬ fti; }; MimData.mobSeg.base.units ¬ 0; mtRoot.linkLoc ¬ SELECT TRUE FROM embeddedLinks => inFrame, codeLinks => codePrefix, ENDCASE => framePrefix; mtRoot.config ¬ MobDefs.CTNull; mtRoot.code ¬ MobDefs.CodeDesc[ sgi: MobDefs.SGIndex.FIRST, packed: FALSE, linkspace: codeLinks, offset: (IF codeLinks AND nLinks # 0 AND NOT embeddedLinks THEN (nLinks+1) + (Alignment-1 - (nLinks MOD Alignment)) ELSE 0), length: 0]; -- will be updated mtRoot.sseg ¬ MobDefs.SGIndex.FIRST + MobDefs.SGRecord.SIZE; IF seb[gfType].hints.refField THEN { mtRoot.frameRefs ¬ TRUE; mtRoot.frameType ¬ SymLiteralOps.TypeIndex[gfType]; } ELSE { mtRoot.frameRefs ¬ seb[gfType].hints.refField; mtRoot.frameType ¬ [0]; }; mtRoot.framesize ¬ 0; -- will be updated mtRoot.inlineFloat ¬ MimData.switches['f]; mtRoot.residentFrame ¬ resident; mtRoot.boundsChecks ¬ MimData.switches['b]; mtRoot.nilChecks ¬ MimData.switches['n]; mtRoot.packageable ¬ TRUE; { limit: MDIndex = Alloc.Top[MimData.table, mdType]; EnterCanonicalFile: SymLiteralOps.TypesVisitor = { IF NOT canonical THEN { mdi: MDIndex; [mdi, ] ¬ SymLiteralOps.UTypeId[type]; IF mdi # MDNull THEN [] ¬ PortedFile[mdi]; }; }; offset: CARD = CompilerUtil.ReadMobOffset[]; FOR mdi: MDIndex ¬ lastPorted, mdi + MDRecord.SIZE UNTIL mdi = limit DO IF mdb[mdi].file # nullFileIndex THEN [] ¬ PortedFile[mdi]; ENDLOOP; mobHeader.ftOffset.units ¬ offset; SymLiteralOps.EnumerateTypes[EnterCanonicalFile]; FOR mdi: MDIndex ¬ firstPorted, mdi + MDRecord.SIZE UNTIL mdi = lastPorted DO ftEntry: MobDefs.FTRecord ¬ [name: EnterFileId[mdi], version: mdb[mdi].stamp]; CompilerUtil.AppendMobUnits[@ftEntry, MobDefs.FTRecord.SIZE]; ENDLOOP; mobHeader.ftLimit ¬ MobDefs.FTIndex.FIRST + (CompilerUtil.ReadMobOffset[]-offset); }; mobHeader.ssOffset.units ¬ CompilerUtil.ReadMobOffset[]; CompilerUtil.AppendMobString[LOOPHOLE[nString]]; mobHeader.ssLimit.units ¬ (CompilerUtil.ReadMobOffset[]-mobHeader.ssOffset.units); IF MimData.interface THEN { mobHeader.rtOffset.units ¬ 0; mobHeader.rtLimit.units ¬ 0; } ELSE { CompilerUtil.FillMobPage[]; mobHeader.rtOffset.units ¬ CompilerUtil.ReadMobOffset[]; CompilerUtil.RTTableOut[MimData.table]; mobHeader.rtLimit.units ¬ CompilerUtil.ReadMobOffset[] - mobHeader.rtOffset.units; }; mobHeader.nBytes ¬ CompilerUtil.ReadMobIndex[]; CompilerUtil.UpdateMobUnits[mobIndex, mobHeader, MobDefs.Mob.SIZE]; MimData.mobSeg.base.units ¬ 0; MimData.mobSeg.units ¬ [domestic[unitsPerPage]]; IF MimData.interface AND TreeOps.ListLength[ids] > 1 THEN { index: FileByteIndex ¬ mtIndex; saveName: MobDefs.NameRecord = mtRoot.name; UpdateMDEntry: Tree.Scan = { mtRoot.name ¬ EnterSymbolId[TreeOps.GetSe[t]]; CompilerUtil.UpdateMobUnits[index, mtRoot, MimData.mtRootSize]; index ¬ index + (MimData.mtRootSize)*BYTES[UNIT]; }; TreeOps.ScanList[ids, UpdateMDEntry]; mtRoot.name ¬ saveName; }; CompilerUtil.EndMob[]; z.FREE[@nStringREFTEXT]; nString ¬ NIL; }; MatchMob: PUBLIC PROC RETURNS [matched: BOOL ¬ FALSE] = { oldSymbols: SymbolTable.Base = MimosaCopier.MapSymbols[MimData.pattern]; IF oldSymbols = NIL THEN MimosaLog.WarningRope[fileName, MimData.pattern.locator] ELSE { matched ¬ MatchedBodies[ [oldSymbols, RootBti], [MimData.ownSymbols, RootBti] ! Unmatched => { stb: STB ¬ id.stb; n: Symbols.Name ¬ SymbolOps.NameForSe[SymbolOps.own, id.sei]; d: ConvertUnsafe.SubString ¬ SymbolOps.SubStringForName[stb, n]; SELECT attr FROM $strings => MimosaLog.WarningSubString[replString, d]; $id => MimosaLog.WarningSubString[replId, d]; ENDCASE; RESUME}]; MimosaCopier.UnmapSymbols[oldSymbols]; }; }; IdHandle: TYPE = RECORD [ stb: SymbolTable.Base, sei: Symbols.ISEIndex]; MatchedNames: PROC [id1, id2: IdHandle] RETURNS [BOOL] = { IF id1.sei = ISENull OR id2.sei = ISENull THEN RETURN [FALSE] ELSE { b1: STB = id1.stb; b2: STB = id2.stb; ss1: ConvertUnsafe.SubString = SymbolOps.SubStringForName[b1, b1.seb[id1.sei].hash]; ss2: ConvertUnsafe.SubString = SymbolOps.SubStringForName[b2, b2.seb[id2.sei].hash]; RETURN [ConvertUnsafe.EqualSubStrings[ss1, ss2]]; }; }; MatchMode: PROC [id: IdHandle] RETURNS [Linkage] = { b: STB = id.stb; IF b.seb[id.sei].idType = typeTYPE AND b.seb[id.sei].public THEN RETURN [$type]; IF b.seb[id.sei].constant THEN SELECT SymbolOps.XferMode[b, b.seb[id.sei].idType] FROM proc, program, signal, error => RETURN [$val]; ENDCASE => RETURN [$manifest]; RETURN [$ref]; }; MatchedAttrs: PROC [idL, idR: IdHandle] RETURNS [BOOL] = { bL: STB = idL.stb; bR: STB = idR.stb; typeL: CSEIndex = SymbolOps.UnderType[bL, bL.seb[idL.sei].idType]; mode: Linkage = MatchMode[idL]; matched: BOOL; IF idR.sei # ISENull THEN { typeR: CSEIndex = SymbolOps.UnderType[bR, bR.seb[idR.sei].idType]; matched ¬ (SELECT mode FROM $val => Types.Assignable[[bL, typeL], [bR, typeR]] AND (bL.seb[idL.sei].idValue = bR.seb[idR.sei].idValue), $ref => Types.Equivalent[[bL, typeL], [bR, typeR]] AND (bL.seb[idL.sei].idValue = bR.seb[idR.sei].idValue) -- offsets AND (bL.seb[idL.sei].idInfo = bR.seb[idR.sei].idInfo), -- sizes $type => (bR.seb[idR.sei].idType = typeTYPE) AND (bR.seb[idR.sei].public) AND Types.Equivalent[ [bL, SymbolOps.UnderType[bL, idL.sei]], [bR, SymbolOps.UnderType[bR, idR.sei]]], ENDCASE => TRUE); } ELSE matched ¬ (mode = manifest); IF ~matched THEN SIGNAL Unmatched[$id, idL]; RETURN [matched]; }; CTXHandle: TYPE = RECORD [ stb: SymbolTable.Base, ctx: CTXIndex]; MatchedContexts: PROC [ctxL, ctxR: CTXHandle] RETURNS [BOOL] = { bL: STB = ctxL.stb; bR: STB = ctxR.stb; n: CARDINAL ¬ 0; FOR sei: ISEIndex ¬ SymbolOps.FirstCtxSe[bL, ctxL.ctx], SymbolOps.NextSe[bL, sei] UNTIL sei = ISENull OR n > 4 DO IF bL.seb[sei].hash # nullName THEN { ss: ConvertUnsafe.SubString = SymbolOps.SubStringForName[bL, bL.seb[sei].hash]; seiR: Symbols.ISEIndex = SymbolOps.SearchContext[bR, SymbolOps.FindString[bR, ss], ctxR.ctx]; IF ~MatchedAttrs[ [ctxL.stb, sei], [ctxR.stb, seiR]] THEN n ¬ n+1; }; ENDLOOP; RETURN [n = 0]; }; RecordHandle: TYPE = RECORD [ stb: SymbolTable.Base, sei: RecordSEIndex]; MatchedRecords: PROC [recL, recR: RecordHandle] RETURNS [BOOL] = { bL: STB = recL.stb; bR: STB = recR.stb; IF recL.sei = RecordSENull OR recR.sei = RecordSENull THEN RETURN [recL.sei = recR.sei]; RETURN [MatchedContexts[[bL, bL.seb[recL.sei].fieldCtx], [bR, bR.seb[recR.sei].fieldCtx]]]; }; MatchedArgLists: PROC [argL, argR: Types.Handle] RETURNS [BOOL] = { bL: STB = argL.stb; bR: STB = argR.stb; inL, inR, outL, outR: RecordSEIndex; [inL, outL] ¬ SymbolOps.TransferTypes[bL, argL.sei]; [inR, outR] ¬ SymbolOps.TransferTypes[bR, argR.sei]; IF NOT MatchedRecords[[bL, inL], [bR, inR]] THEN RETURN [FALSE]; IF NOT MatchedRecords[[bL, outL], [bR, outR]] THEN RETURN [FALSE]; RETURN [TRUE]; }; BodyHandle: TYPE = RECORD [ stb: SymbolTable.Base, bti: Symbols.CBTIndex]; MatchAttr: TYPE = {id, strings}; Unmatched: SIGNAL[attr: MatchAttr, id: IdHandle] = CODE; MatchedBodies: PROC [bodyL, bodyR: BodyHandle] RETURNS [BOOL] = { bL: STB = bodyL.stb; bR: STB = bodyR.stb; matched: BOOL ¬ TRUE; IF NOT bL.bb[bodyL.bti].hints.noStrings THEN { SIGNAL Unmatched[$strings, [bodyL.stb, bL.bb[bodyL.bti].id]]; matched ¬ FALSE; }; IF NOT bR.bb[bodyR.bti].hints.noStrings THEN { IF NOT matched THEN SIGNAL Unmatched[$strings, [bodyR.stb, bR.bb[bodyR.bti].id]]; matched ¬ FALSE; }; IF NOT ( MatchedNames[[bodyL.stb, bL.bb[bodyL.bti].id], [bodyR.stb, bR.bb[bodyR.bti].id]] AND (bL.bb[bodyL.bti].entryIndex = bR.bb[bodyR.bti].entryIndex) AND Types.Assignable[ [bodyL.stb, bL.bb[bodyL.bti].ioType], [bodyR.stb, bR.bb[bodyR.bti].ioType]] AND MatchedArgLists[ [bodyL.stb, bL.bb[bodyL.bti].ioType], [bodyR.stb, bR.bb[bodyR.bti].ioType]]) THEN { SIGNAL Unmatched[$id, [bodyL.stb, bL.bb[bodyL.bti].id]]; matched ¬ FALSE; }; IF NOT MatchedContexts[ [bodyL.stb, bL.bb[bodyL.bti].localCtx], [bodyR.stb, bR.bb[bodyR.bti].localCtx]] THEN matched ¬ FALSE; RETURN [matched]; }; { set: MimosaEvents.Trigger ¬ ALL[FALSE]; set[relocate] ¬ TRUE; set[zoneReset] ¬ TRUE; evList ¬ permUZ.NEW[MobDefs.EVRecord[evListMax]]; mobHeader ¬ permUZ.NEW[MobDefs.Mob]; protoMTRecord ¬ permUZ.NEW[MobDefs.MTRecord]; MimosaEvents.RegisterSet[P4Notify, ALL[TRUE]]; }; }. ¼ Pass4B.mesa Copyright Ó 1985, 1986, 1987, 1988, 1991 by Xerox Corporation. All rights reserved. Satterthwaite, June 18, 1986 12:33:20 pm PDT Russ Atkinson (RRA) June 21, 1989 1:40:46 pm PDT Exported variables intermediate result bookkeeping also see ObjectOut.mesa Formerly in Pass4 called by allocator whenever table area is repacked EXPORTED to CompilerUtil There is a type expression that needs processing Just to keep things clean formerly: ProcessDirectory[tb[node].son[1]]; Scan the context to determine the necessary size of the interface record This is passed on as the number of slots in the interface record Global types, constants & variables initialized in START code, below NOTE SHARING with nString ASSUME bitwise compatibility with LONG STRING & REF TEXT Service routines RRA: How the hell did we get so many? Formerly SwapMdi assume bitwise compatibility with LONG STRING & REF TEXT Enumerating the current exports (to later passes) Processing directory entries (to file table) Relocating imported control links RRA: this is obsolete, so we should get rid of it some day relocate the imports Writing frame fragments (link fragment written by Pass4L) Writing import records RRA: the idValue field appears to hold the assigned slot in the local world N.B. nextSlot must be regenerated to match AssignImports updated by ImportItem matches importCtx prefix Writing export records Need to expand the evList RRA: for now we leave these records indexed directly by the interface record offset. However, the definitions support a better encoding! Just in case the interface name collides with an exported item No warnings about types This is an exported item Initialization/finalization allocate the null name Must be compatible with EnterId. RRA: someday fix this up RRA: temporary until we get better parameterization of machine model fill MTRecord complete nString now Formerly in ProcessFiles add any files opened during compilation Matching for module replacement (formerly in ReplPack) LinkMode for a virtual defs module note: must resample b if any table allocations occur (none do now) note: must resample bL & bR if any table allocations occur (none do now) note: must resample bL & bR if any table allocations occur (none do now) note: must resample bL & bR if any table allocations occur (none do now) note: must resample bL & bR if any table allocations occur (none do now) note: must resample bL & bR if any table allocations occur (none do now) Initialization Ê&•NewlineDelimiter –(cedarcode) style™code™ Kšœ ÏeœI™TKšÏy,™,K™0—˜šÏk ˜ KšœŸœ˜Kšœ Ÿœ™˜«Kšœ Ÿœ ˜KšœŸœ*˜=KšœŸœÿ˜ŒKšœ Ÿœ=˜OKšœ Ÿœ"˜4Kšœ ŸœJ˜YKšœŸœç˜òKšœ Ÿœ˜*KšœŸœã˜ðKšœ Ÿœ˜.Kšœ Ÿœ ˜Kšœ Ÿœ"˜4KšœŸœ ˜KšœŸœ Ÿœ˜Kšœ Ÿœ˜KšœŸœ’˜ŸKšœ ˜ Kšœ Ÿœ˜KšœŸœ˜.KšœŸœv˜‰KšœŸœŸœ ˜,KšœŸœ0˜:KšœŸœQ˜^KšœŸœ"˜-Kšœ Ÿœ˜'K˜——headšÏnœŸ˜KšŸœÁ˜ÈKšŸœ3˜:KšŸœ ˜ K˜KšŸœŸœŸœ˜#KšœŸœŸœ)˜HK˜KšœÏc!˜0Kšœ¡%˜8Kšœ¡*˜>Kšœ¡'˜:Kšœ¡'˜9—™KšœŸœ ˜KšœŸœ ˜K˜Kšœ™K˜KšœŸœ˜#KšœŸœ˜#K˜Kšœ Ÿœ˜&Kšœ Ÿœ ¡˜5K˜Kšœ Ÿœ ˜Kšœ ŸœŸœ˜K˜šœŸœ˜1K™——™š œ˜#Kšœ3™3šŸœŸ˜šœ˜Kšœ Ÿœ˜KšœŸœ˜Kšœ Ÿœ˜Kšœ˜K˜—šœ ˜ K˜!K˜K˜K˜K˜Kšœ!˜!Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—KšŸœ˜—K˜K˜—š œŸœŸœ˜)K™K˜Kšœ˜Kšœ˜Kšœ˜KšœM˜MKšœ˜KšœŸœ˜K˜Kšœ˜K˜Kšœ ŸœŸœ˜0Kšœ˜Kšœ˜K˜K˜—š œŸœ˜#K˜7Kšœ-˜-Kšœ4˜4Kšœ˜Kšœ1˜1KšœŸ˜šŸœŸœ˜Kšœ,˜,šŸœŸœ˜$Kšœ&˜&šŸœŸ˜#K™0Kšœ'˜'—K˜—K˜—K˜˜K™—Kšœ%˜%Kšœ˜Kšœ ˜ Kšœ˜šœ1˜1Kšœ,™,—Kšœ ˜ Kšœ ˜ šŸœŸœ˜K˜/KšœH˜HšŸœŸœŸ˜ ˜K™HKšœŸœ˜šŸœMŸœŸ˜fKšœ7˜7KšŸœŸœ˜*KšŸœ˜—šœ˜K™@—K˜—KšŸœŸœ˜—K˜—Kšœ˜KšŸœŸœ$˜;Kšœ˜K˜——™#Kšœ Ÿœ˜'K˜˜K™ —Kšœ˜Kšœ˜K˜KšœŸ œŸœ˜)KšœŸ œŸœ˜)KšœŸœ˜K˜Kšœ Ÿœ˜,K˜K˜šœŸœŸœ˜šŸœŸœ ™Kš ŸœŸœŸœŸœŸ™8——K˜Kšœ)Ÿœ˜.Kšœ#¡1˜TK˜KšœŸœ¡#˜DKšœ Ÿœ¡)˜?K˜Kšœ"¡#˜EK˜Kšœ ŸœŸœ˜%šœŸœŸœ˜Kšœ˜Kšœ˜K˜K˜K˜Kšœ˜KšœŸ˜K˜—KšœŸœ˜KšœŸœ˜K˜Kšœ ŸœŸœ˜%šœŸœŸœ˜Kšœ˜Kšœ˜K˜K˜K˜K˜Kšœ˜KšœŸ˜K˜—KšœŸœ˜KšœŸœ˜—™Kšœ Ÿœ˜(Kšœ Ÿœ˜$Kšœ Ÿœ˜(Kšœ Ÿœ˜&Kšœ Ÿœ˜K˜K˜#K˜š   œŸœŸœŸœŸœ˜NKšŸœŸœ+˜MK˜K˜—š   œŸœŸœŸœ Ÿœ˜QKšŸœŸœ)˜JK˜K˜—š  œŸœŸœ Ÿœ˜IKš œŸœŸœŸœŸœ˜>šŸœŸœŸœŸœ˜0K™%—KšŸœ˜%K˜K˜—š  œŸœŸœ Ÿœ˜<šŸœŸœŸ˜Kšœ Ÿœ ˜Kšœ Ÿœ˜0KšŸœŸœ ˜—˜K˜——š  œŸœŸœŸœ˜DKšŸœ˜$K˜K˜—š  œŸœŸœ,˜SšŸœŸœ˜KšœŸœ˜ šŸœŸœ˜%šŸ˜KšœŸœŸœ Ÿ˜1—šŸœ˜KšœŸœŸœ Ÿœ˜9˜Kšœ™Kšœ˜Kšœ˜šŸœ Ÿœ˜K˜ šŸœ8ŸœŸ˜QK˜KšŸœ˜—šŸœ8ŸœŸ˜QK˜KšŸœ˜—K˜K˜K˜K˜—Kšœ˜—Kšœ#Ÿœ˜(K˜——KšœŸœŸœ˜6K˜—K˜K˜—š œŸœ+ŸœŸœ˜^KšœŸœ˜K˜šœ Ÿœ ˜K™8—šŸœŸ˜K˜KšœŸœ˜KšŸœ.ŸœŸœ˜BK˜šŸ˜šŸœ˜ K˜KšœŸœ˜#šŸœŸœ˜"KšœŸœŸœ˜2Kš œŸœŸœŸœŸœ˜ K˜&KšœŸœ˜K˜Kšœ Ÿœ%˜7K˜—Kšœ Ÿœ˜šŸœŸœŸœ Ÿ˜K˜&KšŸœ˜—K˜K˜——KšŸœ˜—KšŸœ˜ K˜K˜—š  œŸœŸœ˜DK˜VKšŸœ Ÿœ˜K˜K˜—š  œŸœŸœ˜AKšœŸœŸœ ˜Kšœ Ÿœ˜!K˜XKšŸœ"Ÿœ˜AšŸœŸœ˜˜K˜F—KšœH˜HšŸœ5ŸœŸ˜BKšœ ˜ —K˜—KšŸœ Ÿœ˜K˜——™1š œŸœŸœ˜šŸœŸœŸ˜Kšœ˜Kšœ˜KšœŸœ˜ KšŸœ˜—KšœŸœ˜šŸœ*ŸœŸœŸ˜@KšŸœ ŸœŸœŸœ ˜,KšŸœ˜—šŸœŸœŸ˜Kšœ˜Kšœ˜KšœŸœ˜ KšŸœ˜—KšœŸœ˜K˜K˜—š  œŸœŸœ+˜DšŸœ*ŸœŸœŸ˜@KšœM˜MKšŸœ˜—K˜K˜—š  œŸœŸœ+˜DšŸœ*ŸœŸœŸ˜@KšœV˜VKšŸœ˜—K˜——™,š  œ˜K˜&K˜/K˜EšŸœŸœŸ˜K˜'˜ K˜4KšŸœŸœ"˜6Kšœ˜—KšŸœ˜—K˜——™!š  œŸœ˜#˜5K™:—K˜-K˜K˜!KšœŸœ%˜AšŸœnŸœŸ˜‡K˜?Kšœ˜Kšœ%˜%K˜EKšœŸœ˜šŸœŸœ˜Kšœ"˜"Kšœ1˜1šŸœ ŸœŸ˜-Kšœ˜Kšœ%˜%KšŸœ˜—K˜—šŸœŸœŸ˜˜KšœŸœ ˜Kšœ˜KšŸœŸœ)˜KšŸœŸœ˜K™Kšœ˜šŸœ`ŸœŸ˜yšŸœŸœ˜KšœC˜CKšœŸœ*˜7Kšœ%˜%šŸœŸ˜Kšœ˜Kšœ˜KšŸœ˜—Kšœ.˜.šœŸœ˜Kšœ ˜ K˜K˜ Kšœ ˜ K˜ Kšœ ˜ —KšŸœŸœŸœŸœ˜EKšœ˜K˜—KšŸœ˜—K˜—Kšœ.˜.K˜K˜—˜šŸœŸœ˜Kšœ#˜#Kšœ.˜.šœŸœ˜Kšœ ˜ K˜K˜ Kšœ ˜ K˜ Kšœ ˜ —KšŸœŸœŸœŸœ˜EKšœ˜K˜—K˜K˜—KšŸœ˜—KšœŸœ˜KšŸœ˜—K˜0K˜K˜——™9š œŸœŸœ˜#Kšœ Ÿœ ˜.Kšœ$˜$Kšœ$Ÿœ)˜RšŸœŸœ˜K˜KšœŸœ˜KšœŸœ˜š  œ"˜/Kšœ6Ÿœ˜KšŸœŸœ ˜K˜—šŸœB˜EK˜BKšŸœŸœ ˜K˜—šŸœ*˜-K˜#KšŸœŸœ ˜K˜—KšŸœ˜—šŸœ)Ÿ˜3Kšœ7˜7KšŸœ2˜9—K˜—˜ K˜KšœŸœ˜)šŸœŸœŸ˜$˜šŸœŸœ˜K˜/K˜K˜——KšŸœ˜—šŸœŸœŸ˜šœ˜Kšœ)˜)KšŸœŸœ ˜K˜—šŸœD˜GK˜BKšŸœŸœ ˜K˜—˜K˜#KšŸœŸœ ˜K˜—šœŸœ ˜#Kšœ%˜%KšŸœŸœ ˜K˜—KšŸœ˜—˜K˜KK˜ —K˜—˜ šŸœŸœŸ˜šœ˜K™KšŸœŸœ ˜K˜—šœF˜FKšœ%˜%KšŸœŸœ ˜K˜—šŸœ˜ K˜4šŸœŸœŸ˜&˜ šŸœŸœ(Ÿœ˜CK˜$KšŸœŸœ ˜K˜——KšŸœŸœ˜—Kšœ.˜.KšœŸœ˜K˜——K˜—˜šŸœŸœŸ˜KšŸœ˜šœ5˜5Kšœ&˜&—KšŸœ˜—KšŸœŸœ ˜K˜—šŸœ˜ KšŸœŸœ ˜——šŸœŸœ˜!K™Kšœ8˜8Kš œŸœ Ÿœ'ŸœŸœ˜`Kšœ˜Kšœ˜šœŸœ˜Kšœ ˜ K˜K˜ K˜Kšœ˜K˜ Kšœ˜—KšŸœŸœŸœŸœ˜EKšœ˜KšœŸœ˜ K˜—KšŸœ˜K˜—šŸœŸœ˜Kšœ˜K˜K˜—KšŸœ˜—Kšœ?Ÿœ˜EKšœŸœ ˜K˜$KšŸœŸœ(˜5K˜—K˜—KšŸœ˜—K˜K˜K˜—š œŸœ˜'KšœŸœ ˜,K˜#K˜+K˜KšœŸœ˜#K˜ Kšœ Ÿœ˜K˜ Kšœ&Ÿœ)˜TK˜AšŸœŸ˜Kšœ/˜/šŸœ˜ KšœŸœŸœ"˜3KšœŸœ*˜FKšœ+Ÿœ˜1Kšœ+˜+K˜——Kšœ$Ÿœ)˜RK˜Kšœ Ÿœ˜K˜K˜——™š œŸœŸœ˜)KšœŸœ˜)KšŸœ ŸœŸœ0˜WK˜KšœŸœŸœ˜*Kšœ Ÿœ%˜7™K˜K˜&—Kšœ+¡#˜N˜K˜+K˜'K˜*K˜,K˜1K˜K˜K˜,K˜*KšœŸœ˜KšœŸœ˜Kšœ-˜-KšœŸœ˜KšœŸœ˜KšœŸœ˜!KšœŸœ˜"KšœCŸœ˜IKšœCŸœ˜IKšœCŸœ˜I˜K™ Kšœ Ÿœ˜+K˜$KšœŸœ˜#K˜$KšœŸœ˜>K˜——K˜'Kšœ3Ÿœ˜9šœ/˜/KšŸœ™—K˜8Kšœ?Ÿœ˜EKšœ>Ÿœ˜DK˜8K˜&Kšœ$Ÿœ8˜bKšœ&Ÿœ˜+K˜˜Kš œŸœŸœŸœŸœ˜F—K˜,K˜&šŸœŸœŸœ Ÿ˜K˜?KšŸœ˜—K˜8Kšœ$Ÿœ6˜`K˜K˜—š  œŸœŸœ˜+KšœŸœ ŸœŸœ˜BKš  œŸœ¡.˜HKšœŸœ˜%Kšœ ŸœŸœ˜šœŸœ˜0KšŸœA™D—K˜)Kšœ*˜*™ šŸœŸœ˜%K™Kšœ:˜:K˜K˜—K˜,KšœŸœ˜KšœŸœ˜˜Kšœ2˜2Kšœ˜K˜K˜K˜K˜—K˜šœŸœŸœŸ˜!K˜K˜KšŸœ˜—K˜˜KšœŸœ˜KšœŸœ˜K˜š œ Ÿœ Ÿœ ŸœŸœ˜:KšŸœ%Ÿœ ˜8KšŸœ˜—Kšœ ¡˜—KšœŸœŸœ˜<šŸœ˜šŸœ˜KšœŸœ˜Kšœ3˜3K˜—šŸœ˜K˜.Kšœ˜K˜——Kšœ¡˜(Kšœ*˜*K˜ K˜+K˜(KšœŸœ˜—˜KšÏb™K˜2š œ ˜2šŸœŸœ Ÿœ˜K˜ K˜'KšŸœŸœ˜*Kšœ˜—K˜—KšœŸœ ˜,šŸœ+ŸœŸœ Ÿ˜GšŸœŸœ˜;K™'—KšŸœ˜—K˜"K˜1šŸœ,ŸœŸœŸ˜MK˜NKšœ7Ÿœ˜=KšŸœ˜—Kšœ$Ÿœ)˜RK˜—K˜8KšœŸœ ˜0K˜RšŸœ˜šŸœ˜K˜K˜K˜—šŸœ˜K˜K˜8K˜'K˜RK˜——Kšœ/˜/Kšœ=Ÿœ˜CK˜K˜0šŸœŸœŸœ˜;Kšœ˜K˜+š  œ˜K˜.K˜?Kšœ%ŸœŸœ˜1K˜—K˜%K˜K˜—K˜KšœŸœ˜Kšœ Ÿœ˜K˜K˜—š  œŸœŸœŸœ ŸœŸœ˜9K˜HšŸœŸ˜KšŸœ9˜=šŸœ˜˜K˜4˜KšœŸœ ˜K˜=K˜@šŸœŸ˜K˜6K˜-KšŸœ˜—KšŸœ˜ ——K˜&K˜——˜K˜———™6šœ ŸœŸœ˜K˜K˜K˜—š  œŸœŸœŸœ˜:šŸœŸœ˜)KšŸœŸœŸœ˜šŸœ˜KšœŸœ ˜KšœŸœ ˜K˜TK˜TKšŸœ+˜1K˜——K˜—K˜š  œŸœŸœ˜4K™"šœŸœ ˜KšœB™B—KšŸœ!ŸœŸœŸœ ˜PšŸœŸ˜šŸœ-Ÿ˜7Kšœ Ÿœ˜.KšŸœŸœ ˜——KšŸœ˜˜K˜——š  œŸœŸœŸœ˜:KšœŸœ ˜šœŸœ ˜KšœH™H—K˜BK˜Kšœ Ÿœ˜šŸœ˜šŸœ˜K˜Bšœ ŸœŸ˜˜šœ*˜*KšŸ˜—K˜4—˜šœ*˜*KšŸ˜—šœ4¡ ˜>KšŸ˜—Kšœ3¡˜;—˜šœ$Ÿœ˜@KšŸ˜—Kšœb˜b—KšŸœŸœ˜—Kšœ˜—KšŸœ˜!—KšŸœ ŸœŸœ˜,KšŸœ ˜K˜K˜—šœ ŸœŸœ˜K˜K˜K˜—š œŸœŸœŸœ˜@KšœŸœ ˜šœŸœ ˜KšœH™H—KšœŸœ˜šŸœOŸœŸœŸ˜qšŸœŸœ˜%KšœO˜OKšœ]˜]KšŸœ3Ÿœ ˜BK˜—KšŸœ˜—KšŸœ ˜K˜K˜—šœŸœŸœ˜K˜K˜K˜—š œŸœŸœŸœ˜BKšœŸœ ˜šœŸœ ˜KšœH™H—šŸœŸœŸ˜:KšŸœ˜—KšŸœU˜[˜K˜——š œŸœŸœŸœ˜CKšœŸœ ˜šœŸœ ˜KšœH™H—K˜$Kšœ4˜4Kšœ4˜4Kš ŸœŸœ&ŸœŸœŸœ˜@Kš ŸœŸœ(ŸœŸœŸœ˜BKšŸœŸœ˜K˜K˜—šœ ŸœŸœ˜K˜K˜K˜—Kšœ Ÿœ˜ Kšœ Ÿœ"Ÿœ˜8K˜š  œŸœŸœŸœ˜AKšœŸœ ˜šœŸœ ˜KšœH™H—Kšœ ŸœŸœ˜šŸœŸœ"Ÿœ˜.KšŸœ7˜=Kšœ Ÿœ˜Kšœ˜—šŸœŸœ"Ÿœ˜.KšŸœŸœ ŸœŸœ7˜QKšœ Ÿœ˜Kšœ˜—šŸœŸœ˜KšœQŸœ=ŸœkŸœj˜ìšŸœ˜KšŸœ2˜8Kšœ Ÿœ˜Kšœ˜——šŸœŸœ˜K˜'Kšœ(Ÿœ Ÿœ˜=—KšŸœ ˜K˜——™˜KšœŸœŸœ˜'KšœŸœ˜KšœŸœ˜KšœŸœ˜1KšœŸœ˜$KšœŸœ˜-Kšœ#ŸœŸœ˜.K˜——˜K˜——…—”>ļ