DIRECTORY Alloc USING [Units], CompilerUtil USING [], ConvertUnsafe USING [SubString, ToRope], LiteralOps USING [StringValue], MimData USING [base, importCtx, interface, moduleCtx, monitored, objectStamp, outerCtx, stopping, switches, table, textIndex, worstAlignment], MimosaCopier USING [CopierInit, CopierReset, CreateFileTable, EnterFile, FileProblem, FileVersion, FileVersionMix, FillModule, SearchFileCtx, TableRelocated, UnknownModule], MimosaEvents USING [Callback, RegisterSet], MimosaLog USING [ErrorHti, ErrorSei, ErrorTree, WarningTree], MimP3 USING [BodyList, DeclList, DeclNotify, EnterIdList, Exp, ExpANotify, ExpCNotify, IdInit, IdReset, MakeFrameRecord, MakeIdTable, MakeRefType, mark, MiscNotify, PopCtx, PushCtx, RAttrPop, RPop, Shared, StmtNotify, UType, VRNotify], MimP3S USING [safety], MimZones USING [permZone], OSMiscOps USING [MergeStamps, Stamp, TimeToStamp], Pass3Attributes USING [TypeNotify], Rope USING [ROPE], SourceMap USING [Loc], SymbolOps USING [DecodeBti, EncodeCard, EncodeTreeIndex, FillCtxSe, FirstCtxSe, LinkMode, MakeCtxSe, MakeNonCtxSe, NameClash, NewCtx, NextSe, own, SearchContext, SubStringForName, UnderType], Symbols USING [Base, bodyType, BTNull, CBTIndex, CSEIndex, CSENull, CTXIndex, CTXNull, CTXRecord, ctxType, IncludedCTXIndex, ISEIndex, ISENull, lG, MDIndex, mdType, Name, nullName, OwnMdi, RootBti, SERecord, seType, typeANY], SymLiteralOps USING [Reset], Target: TYPE MachineParms USING [bitsPerPtr], Tree USING [Base, Index, Link, Map, Scan, Test, Null, nullIndex, treeType], TreeOps USING [GetHash, GetNode, GetTag, ListLength, ScanList, SearchList, ToLoc, UpdateList]; Pass3B: PROGRAM IMPORTS Alloc, ConvertUnsafe, LiteralOps, MimData, MimosaCopier, MimosaEvents, MimosaLog, MimP3, MimP3S, MimZones, OSMiscOps, Pass3Attributes, SymbolOps, SymLiteralOps, TreeOps EXPORTS CompilerUtil, MimP3 = { OPEN MimP3, TreeOps, Symbols; 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; -- module table base address (local copy) bb: Symbols.Base; -- body table base address (local copy) Pass3Notify: MimosaEvents.Callback = { SELECT class FROM relocate => { tb ฌ MimData.base[Tree.treeType]; seb ฌ MimData.base[seType]; ctxb ฌ MimData.base[ctxType]; mdb ฌ MimData.base[mdType]; bb ฌ MimData.base[bodyType]; Pass3Attributes.TypeNotify[MimData.base]; MimP3.DeclNotify[MimData.base]; MimP3.MiscNotify[MimData.base]; MimP3.StmtNotify[MimData.base]; MimP3.VRNotify[MimData.base]; MimP3.ExpANotify[MimData.base]; MimP3.ExpCNotify[MimData.base]; }; ENDCASE; }; lockNode: PUBLIC Tree.Index; -- lambda expr for monitor lock checkedANY: PUBLIC Symbols.CSEIndex; -- typeANY in CHECKED code P3Unit: PUBLIC PROC [unit: Tree.Link] RETURNS [Tree.Link] = { node: Tree.Index; saveIndex: SourceMap.Loc = MimData.textIndex; checkedANY ฌ Symbols.CSENull; MimP3S.safety ฌ none; node ฌ TreeOps.GetNode[unit]; MimData.textIndex ฌ TreeOps.ToLoc[tb[node].info]; MimosaCopier.CopierInit[ownTable: MimData.table, symbolCachePages: 256]; MimP3.IdInit[]; { ENABLE { MimosaCopier.FileProblem => {MimosaLog.ErrorHti[fileName, hti]; RESUME [TRUE]}; MimosaCopier.FileVersion => {MimosaLog.ErrorHti[fileWrong, hti]; RESUME [TRUE]}; MimosaCopier.FileVersionMix => { MimosaLog.WarningTree[fileVersion, [hash[index: hti]]]; RESUME}; MimosaCopier.TableRelocated => {RESUME}}; MimData.stopping ฌ FALSE; { TestShared: HashTest = { RETURN [MemberId[id, tb[node].son[3]] OR MemberId[id, tb[node].son[4]]]; }; Directory[directory: tb[node].son[1], shared: TestShared]; ScanList[tb[node].son[4], Sharing]; PushCtx[MimData.outerCtx]; PushCtx[MimData.moduleCtx]; ScanList[tb[node].son[2], ImportItem]; ScanList[tb[node].son[3], ExportItem]; PopCtx[]; PopCtx[]; }; MimP3.PushCtx[MimData.outerCtx]; MimP3.PushCtx[MimData.moduleCtx]; MimP3.PushCtx[MimData.importCtx]; lockNode ฌ IF ~MimData.monitored THEN Tree.nullIndex ELSE GetNode[tb[node].son[5]]; MimP3.DeclList[tb[node].son[6]]; MimP3.BodyList[Symbols.RootBti]; MimP3.PopCtx[]; -- import context MimP3.PopCtx[]; MimP3.PopCtx[]; MimP3.IdReset[tb[node].son[1]]; }; MimosaCopier.CopierReset[]; SymLiteralOps.Reset[pad: ~MimData.switches['s]]; MimData.textIndex ฌ saveIndex; RETURN [unit]; }; ItemLabel: PROC [node: Tree.Index] RETURNS [ISEIndex] = INLINE { t: Tree.Link ฌ tb[node].son[1]; DO WITH t SELECT GetTag[t] FROM symbol => RETURN [index]; subtree => t ฌ tb[index].son[1]; ENDCASE => ERROR; ENDLOOP; }; MemberId: PROC [id: Name, list: Tree.Link] RETURNS [found: BOOLฌFALSE] = { TestItem: Tree.Test = { DO WITH t SELECT GetTag[t] FROM hash => IF index = id THEN RETURN [found ฌ TRUE]; subtree => IF t # Tree.Null THEN {t ฌ tb[index].son[1]; LOOP}; ENDCASE; RETURN [FALSE]; ENDLOOP; }; SearchList[list, TestItem]; }; HashTest: TYPE = PROC [id: Name] RETURNS [BOOL]; Directory: PROC [directory: Tree.Link, shared: HashTest] = { bytesPerStamp: NAT = BITS[OSMiscOps.Stamp] / BITS[CHAR]; id: Name ฌ seb[bb[RootBti].id].hash; ss: ConvertUnsafe.SubString ฌ SymbolOps.SubStringForName[SymbolOps.own, id]; accumPos: [0..bytesPerStamp) ฌ 0; Long: PROC [p: LONG POINTER] RETURNS [LONG POINTER] = {RETURN[p]}; stampAccum: PACKED ARRAY [0..bytesPerStamp) OF CHAR ฌ ALL[0C]; lp: LONG POINTER TO OSMiscOps.Stamp ฌ LOOPHOLE[Long[@stampAccum]]; FOR i: NAT IN [ss.offset..ss.offset+ss.length) DO stampAccum[accumPos] ฌ ss.base[i]; IF accumPos = bytesPerStamp-1 THEN { MimData.objectStamp ฌ OSMiscOps.MergeStamps[MimData.objectStamp, lpญ]; accumPos ฌ 0} ELSE accumPos ฌ accumPos + 1; ENDLOOP; IF accumPos # 0 THEN MimData.objectStamp ฌ OSMiscOps.MergeStamps[MimData.objectStamp, lpญ]; mdb[OwnMdi].moduleId ฌ id; MakeIdTable[DirectoryScan[directory]]; DirectoryDecls[directory, shared]; }; MdiMap: TYPE = RECORD [SEQUENCE length: CARDINAL OF MDIndex]; mdiMap: REF MdiMap; DirectoryScan: PROC [t: Tree.Link] RETURNS [nLists: CARDINAL ฌ 0] = { i: CARDINAL ฌ 0; FileEntry: Tree.Scan = { node: Tree.Index = GetNode[t]; formalId: Name = seb[ItemLabel[node]].hash; typeId: Name = WITH tb[node].son[2] SELECT GetTag[tb[node].son[2]] FROM hash => index, ENDCASE => formalId; mdiMap[i] ฌ MimosaCopier.EnterFile[formalId, typeId, TreeStringValue[tb[node].son[2]] ! MimosaCopier.FileVersionMix => {IF hti = typeId THEN RESUME ELSE REJECT}]; i ฌ i + 1; IF tb[node].son[3] # Tree.Null THEN nLists ฌ nLists+1; }; n: CARDINAL = ListLength[t]; MimosaCopier.CreateFileTable[n]; MimZones.permZone.FREE[@mdiMap]; -- (just in case of a previous UNWIND) mdiMap ฌ MimZones.permZone.NEW[MdiMap[n]]; ScanList[t, FileEntry]; }; TreeStringValue: PROC [t: Tree.Link] RETURNS [Rope.ROPE] = { RETURN [WITH s: t SELECT GetTag[t] FROM string => ConvertUnsafe.ToRope[LiteralOps.StringValue[s.index]], ENDCASE => NIL] }; DirectoryDecls: PROC [directory: Tree.Link, shared: HashTest] = { i: CARDINAL ฌ 0; DirectoryItem: Tree.Scan = { node: Tree.Index = GetNode[t]; sei: ISEIndex = ItemLabel[node]; key: Name = WITH tb[node].son[2] SELECT GetTag[tb[node].son[2]] FROM hash => index, ENDCASE => seb[sei].hash; type: CSEIndex; ctx: CTXIndex; bti: CBTIndex; saveIndex: SourceMap.Loc = MimData.textIndex; MimData.textIndex ฌ ToLoc[tb[node].info]; tb[node].attr2 ฌ tb[node].attr3 ฌ MimP3.mark; MimosaCopier.FillModule[sei, key, mdiMap[i] ! MimosaCopier.UnknownModule => {MimosaLog.ErrorHti[moduleId, hti]; RESUME}]; type ฌ SymbolOps.UnderType[SymbolOps.own, seb[sei].idType]; ctx ฌ WITH t: seb[type] SELECT FROM definition => t.defCtx, transfer => IF (btiฌSymbolOps.DecodeBti[seb[sei].idInfo]) # BTNull THEN bb[bti].localCtx ELSE CTXNull, ENDCASE => CTXNull; IF ctx # CTXNull THEN { WITH c: ctxb[ctx] SELECT FROM included => { MimData.objectStamp ฌ OSMiscOps.MergeStamps[ MimData.objectStamp, OSMiscOps.TimeToStamp[mdb[c.module].stamp]]; mdb[c.module].shared ฌ shared[seb[sei].hash]}; ENDCASE; tb[node].son[3] ฌ IncludedIds[ctx, tb[node].son[3] ! MimosaCopier.FileVersionMix => {IF hti=key THEN RESUME ELSE REJECT}] }; i ฌ i + 1; MimData.textIndex ฌ saveIndex; }; ScanList[directory, DirectoryItem]; MimZones.permZone.FREE[@mdiMap]; }; IncludedIds: PROC [ctx: CTXIndex, list: Tree.Link] RETURNS [val: Tree.Link] = { includedCtx: IncludedCTXIndex; IncludedId: Tree.Map = { WITH t SELECT GetTag[t] FROM hash => { id: Name = index; found, update: BOOL; sei: ISEIndex ฌ SymbolOps.SearchContext[SymbolOps.own, id, ctx]; IF sei = ISENull THEN { [found, sei] ฌ MimosaCopier.SearchFileCtx[id, includedCtx]; update ฌ found; } ELSE { CheckDuplicate: Tree.Test = { RETURN[WITH t SELECT GetTag[t] FROM symbol => IF index = sei THEN (duplicate ฌ TRUE) ELSE FALSE, ENDCASE => TRUE]; }; duplicate: BOOL ฌ FALSE; found ฌ TRUE; update ฌ SymbolOps.LinkMode[SymbolOps.own, sei] = manifest; duplicate ฌ FALSE; SearchList[list, CheckDuplicate]; IF duplicate THEN MimosaLog.ErrorHti[duplicateId, id]; }; IF found THEN { IF ~seb[sei].public AND ~Shared[includedCtx] THEN { MimosaLog.ErrorSei[privateId, sei]; seb[sei].public ฌ TRUE; }; IF update THEN seb[sei].idCtx ฌ CTXNull; v ฌ [symbol[index: sei]]; } ELSE {MimosaLog.ErrorHti[unknownId, id]; v ฌ t}; }; ENDCASE => ERROR; }; WITH c: ctxb[ctx] SELECT FROM included => IF list # Tree.Null THEN { includedCtx ฌ LOOPHOLE[ctx]; c.restricted ฌ TRUE; val ฌ UpdateList[list, IncludedId]; EnterIdList[includedCtx, val]; } ELSE val ฌ Tree.Null; ENDCASE => ERROR; }; Sharing: Tree.Scan = { id: Name = GetHash[t]; sei: ISEIndex = SymbolOps.SearchContext[SymbolOps.own, id, MimData.moduleCtx]; IF sei = ISENull THEN MimosaLog.ErrorHti[unknownId, id] ELSE { type: CSEIndex = SymbolOps.UnderType[SymbolOps.own, seb[sei].idType]; ctx: CTXIndex ฌ CTXNull; WITH t: seb[type] SELECT FROM definition => ctx ฌ t.defCtx; transfer => IF seb[sei].mark4 AND seb[sei].constant AND t.mode = program THEN ctx ฌ bb[SymbolOps.DecodeBti[seb[sei].idInfo]].localCtx; ENDCASE; IF ctx = CTXNull AND type # typeANY THEN MimosaLog.ErrorTree[nonInterface, t]; }; }; ImportType: PROC [mdi: MDIndex] RETURNS[CSEIndex] = { sei: ISEIndex; FOR sei ฌ SymbolOps.FirstCtxSe[SymbolOps.own, MimData.moduleCtx], SymbolOps.NextSe[SymbolOps.own, sei] UNTIL sei = ISENull DO type: CSEIndex ฌ SymbolOps.UnderType[SymbolOps.own, seb[sei].idType]; WITH t: seb[type] SELECT FROM definition => WITH c: ctxb[t.defCtx] SELECT FROM imported => IF ctxb[c.includeLink].module = mdi THEN GO TO Found; ENDCASE; ENDCASE; REPEAT Found => NULL; FINISHED => { sei ฌ SymbolOps.MakeCtxSe[mdb[mdi].moduleId, CTXNull]; MimosaCopier.FillModule[sei, seb[sei].hash, mdi]; }; ENDLOOP; RETURN[SymbolOps.UnderType[SymbolOps.own, seb[sei].idType]]; }; ImportItem: Tree.Scan = { node: Tree.Index = GetNode[t]; sei: ISEIndex = ItemLabel[node]; type, vType: CSEIndex; const: BOOL; saveIndex: SourceMap.Loc = MimData.textIndex; son2: Tree.Link ฌ tb[node].son[2]; MimData.textIndex ฌ ToLoc[tb[node].info]; tb[node].attr2 ฌ tb[node].attr3 ฌ MimP3.mark; son2 ฌ tb[node].son[2] ฌ Exp[son2, typeANY]; vType ฌ UType[]; const ฌ RAttrPop[].const; WITH v: seb[vType] SELECT FROM definition => SELECT ctxb[v.defCtx].ctxType FROM included => { type ฌ ImportInstance[iType: vType, named: tb[node].attr1]; IF tb[node].attr1 AND MimData.interface THEN MimosaLog.ErrorSei[nonDefinition, sei]; }; ENDCASE => {type ฌ typeANY; MimosaLog.ErrorTree[notImExPortable, son2]}; transfer => { IF v.mode # program OR MimData.interface THEN MimosaLog.ErrorTree[notImExPortable, tb[node].son[2]]; seb[sei].immutable ฌ TRUE; type ฌ MakeRefType[MakeFrameRecord[son2], typeANY, Target.bitsPerPtr]; const ฌ FALSE; }; ENDCASE => { IF vType # typeANY THEN MimosaLog.ErrorTree[nonInterface, son2]; type ฌ typeANY; }; seb[sei].idType ฌ type; seb[sei].immutable ฌ TRUE; seb[sei].constant ฌ const; seb[sei].idInfo ฌ SymbolOps.EncodeCard[1]; seb[sei].mark3 ฌ TRUE; MimData.textIndex ฌ saveIndex; }; ImportInstance: PROC [iType: CSEIndex, named: BOOL] RETURNS [type: CSEIndex] = { WITH t: seb[iType] SELECT FROM definition => WITH c: ctxb[t.defCtx] SELECT FROM included => { ctx: CTXIndex = NewImportedCtx[LOOPHOLE[t.defCtx]]; type ฌ SymbolOps.MakeNonCtxSe[SERecord.cons.definition.SIZE]; seb[type] ฌ SERecord[mark3: TRUE, mark4: TRUE, body: cons[ align: MimData.worstAlignment, typeInfo: definition[slots: t.slots, named: named, defCtx: ctx]]]; IF ~named THEN mdb[c.module].defaultImport ฌ ctx; }; ENDCASE => ERROR; ENDCASE => type ฌ typeANY; }; NewImportedCtx: PROC [link: IncludedCTXIndex] RETURNS [ctx: CTXIndex] = { ctx ฌ (MimData.table).Units[ctxType, CTXRecord.imported.SIZE]; ctxb[ctx] ฌ CTXRecord[ level: ctxb[link].level, seList: ISENull, varUpdated: FALSE, extension: imported[includeLink: link]]; }; ExportItem: Tree.Scan = { node: Tree.Index = GetNode[t]; type: CSEIndex; saveIndex: SourceMap.Loc = MimData.textIndex; son2: Tree.Link ฌ tb[node].son[2]; MimData.textIndex ฌ ToLoc[tb[node].info]; son2 ฌ tb[node].son[2] ฌ Exp[son2, typeANY]; type ฌ UType[]; RPop[]; WITH d: seb[type] SELECT FROM definition => WITH c: ctxb[d.defCtx] SELECT FROM included => mdb[c.module].exported ฌ TRUE; ENDCASE => MimosaLog.ErrorTree[notImExPortable, son2]; ENDCASE => IF type # typeANY THEN MimosaLog.ErrorTree[nonInterface, son2]; MimData.textIndex ฌ saveIndex; }; SetDefaultImport: PUBLIC PROC [iCtx: IncludedCTXIndex, implicitOK: BOOL] = { mdi: MDIndex ฌ ctxb[iCtx].module; IF mdb[mdi].defaultImport = CTXNull THEN { sei: ISEIndex; type: CSEIndex; n: CARDINAL ฌ 0; IF MimData.importCtx = CTXNull THEN MimData.importCtx ฌ SymbolOps.NewCtx[lG]; FOR sei ฌ SymbolOps.FirstCtxSe[SymbolOps.own, MimData.importCtx], SymbolOps.NextSe[SymbolOps.own, sei] UNTIL sei = ISENull DO type ฌ SymbolOps.UnderType[SymbolOps.own, seb[sei].idType]; WITH t: seb[type] SELECT FROM definition => WITH c: ctxb[t.defCtx] SELECT FROM imported => IF ctxb[c.includeLink].module = mdi THEN { mdb[mdi].defaultImport ฌ t.defCtx; n ฌ n+1; }; ENDCASE; ENDCASE; ENDLOOP; SELECT n FROM 0 => { IF ~implicitOK THEN MimosaLog.ErrorHti[missingImport, mdb[mdi].moduleId]; sei ฌ SymbolOps.MakeCtxSe[nullName, MimData.importCtx]; SymbolOps.FillCtxSe[sei, mdb[mdi].moduleId, FALSE ! SymbolOps.NameClash => {MimosaLog.ErrorHti[missingImport, name]; RESUME}]; seb[sei].immutable ฌ seb[sei].constant ฌ TRUE; seb[sei].linkSpace ฌ seb[sei].extended ฌ FALSE; seb[sei].idType ฌ ImportInstance[iType: ImportType[mdi], named: FALSE]; seb[sei].idInfo ฌ SymbolOps.EncodeCard[1]; seb[sei].idValue ฌ SymbolOps.EncodeTreeIndex[Tree.nullIndex]; seb[sei].mark3 ฌ TRUE; seb[sei].mark4 ฌ FALSE; }; 1 => {}; ENDCASE => MimosaLog.ErrorHti[missingImport, mdb[mdi].moduleId]; IF mdb[mdi].defaultImport = CTXNull THEN mdb[mdi].defaultImport ฌ NewImportedCtx[iCtx]; }; }; MimosaEvents.RegisterSet[Pass3Notify, ALL[TRUE]]; }. : Pass3B.mesa Copyright ำ 1985, 1986, 1987, 1990, 1991 by Xerox Corporation. All rights reserved. Satterthwaite, June 18, 1986 12:21:16 pm PDT Russ Atkinson (RRA) January 23, 1990 1:13:26 pm PST called by allocator whenever table area is repacked Stuff formerly in Pass3 Exported to CompilerUtil formerly the Header procedure Process the IMPORTS clause Process the EXPORTS clause Some utilities module header directory processing Workaround for Mimosa bug: Make the version stamp depend on the module name Residual characters to consider import/export processing สv–(cedarcode) style•NewlineDelimiter ™head™ Icodešœ ฯeœI™TLšฯy,™,L™3—˜šฯk ˜ LšœŸœ ˜Lšœ Ÿœ˜LšœŸœ˜(Lšœ Ÿœ˜LšœŸœ˜ŽLšœ Ÿœ›˜ญLšœ Ÿœ˜+Lšœ Ÿœ.˜=LšœŸœเ˜๋LšœŸœ ˜Lšœ Ÿœ ˜Lšœ Ÿœ#˜2LšœŸœ˜#LšœŸœŸœ˜Lšœ Ÿœ˜Lšœ Ÿœฐ˜ฟLšœŸœี˜โLšœŸœ ˜LšœŸœŸœ˜-LšœŸœA˜KLšœŸœQ˜^——šฯnœŸ˜LšŸœฉ˜ฐLšŸœ˜LšŸœ˜L˜Lšœฯc!˜0Lšœก%˜8Lšœก*˜>Lšœก)˜LšŸœ˜—LšŸœŸœ˜LšŸœ˜—L˜—L˜L˜——™ Lš œ ŸœŸœ ŸœŸœ˜0—™š  œŸœ-˜Lš œŸœŸœŸœŸœ˜BšŸœŸœŸœ"Ÿ˜1Lšœ"˜"šŸœ˜šŸœ˜L™0LšœF˜FLšœ ˜ —LšŸœ˜—LšŸœ˜—šŸœŸ˜L™LšœF˜F—L˜L˜&L˜"L˜L˜—Lš œŸœŸœŸœ ŸœŸœ ˜=LšœŸœ˜L˜š  œŸœŸœ Ÿœ ˜ELšœŸœ˜š  œ˜L˜L˜+šœŸœŸœŸ˜GL˜LšŸœ ˜—˜ULš œ"ŸœŸœŸœŸœŸœ˜L—L˜ LšŸœŸœ˜6L˜—LšœŸœ˜L˜ LšœŸœ ก&˜GLšœŸœ ˜*L˜L˜L˜—š œŸœŸœŸœ˜<šŸœŸœŸœ Ÿ˜'L˜@LšŸœŸœ˜—˜L˜——š œŸœ-˜ALšœŸœ˜š  œ˜L˜L˜ šœ ŸœŸœŸ˜DL˜LšŸœ˜—L˜L˜L˜L˜-L˜)Lšœ-˜-˜+LšœDŸœ˜M—L˜;šœŸœŸœŸ˜#L˜šœ Ÿœ5Ÿœ˜HLšœŸœ ˜—LšŸœ ˜—šŸœŸœ˜šŸœŸœŸ˜˜ ˜,L˜A—L˜.—LšŸœ˜—˜2Lš œ"Ÿœ ŸœŸœŸœŸœ˜F—L˜—L˜ L˜L˜—L˜#LšœŸœ ˜ L˜L˜—š  œŸœ"Ÿœ˜OL˜š  œ˜šŸœŸœ Ÿ˜˜ L˜LšœŸœ˜L˜@šŸœ˜šŸœ˜L˜;L˜L˜—šŸœ˜š œ˜šŸœŸœŸœ Ÿ˜#Lš œ Ÿœ ŸœŸœŸœŸœ˜˜L˜LšœŸœ˜#L˜(—L˜L˜—š  œ˜L˜L˜L˜-L˜"L˜)L˜,L˜L˜šŸœŸœŸ˜˜ šŸœŸœŸ˜"Lšœ%Ÿœ˜*LšŸœ/˜6——LšŸœŸœŸœ)˜J—L˜L˜L˜—š œŸœŸœ&Ÿœ˜LL˜!šŸœ"Ÿœ˜*L˜L˜LšœŸœ˜LšŸœŸœ*˜MšŸœdŸœŸ˜}L˜;šŸœŸœŸ˜˜ šŸœŸœŸ˜"˜ šŸœ"Ÿœ˜*L˜"L˜L˜——LšŸœ˜——LšŸœ˜—LšŸœ˜—šŸœŸ˜ ˜LšŸœ Ÿœ6˜IL˜7šœ,Ÿ˜1LšœCŸœ˜L—Lšœ)Ÿœ˜.Lšœ)Ÿœ˜/Lšœ@Ÿœ˜GL˜*L˜=LšœŸœ˜LšœŸœ˜L˜—L˜LšŸœ9˜@—šŸœ"Ÿ˜(L˜.—L˜—L˜L˜——šœ&ŸœŸœ˜1L˜—˜L˜——…—9"Iา