DIRECTORY Alloc USING [AddNotify, Bounds, DropNotify, Handle, Notifier, Top], MobBindDefs USING [RelocHandle], MobComData USING [data], MobControlDefs USING [], MobDefs USING [CTIndex, cttype, cxtype, EXPIndex, EXPNull, exptype, FTIndex, FTNull, fttype, IMPIndex, IMPNull, IMPRecord, imptype, LFIndex, LFNull, lftype, Link, ModuleIndex, MTIndex, MTRecord, mttype, NameRecord, nullLink, NullName, sstype, sttype, treetype, unboundLink], MobErrorDefs USING [ErrorHti, ErrorInterface, ErrorSti, Error2Files, GetModule, GetSti], MobUtilDefs USING [EqVersions, GetDummyGfi, GetGfi, InstanceName, NameForSti], ConvertUnsafe USING [SubString], MobHashOps USING [FindString], MobSymbols USING [CXIndex, cxNull, HTIndex, HTNull, STIndex, stNull, STRecord], Table USING [Base], MobTree USING [Scan, null, Link], MobTreeOps USING [ScanList]; MobBind: PROGRAM IMPORTS Alloc, MobErrorDefs, MobUtilDefs, MobHashOps, MobTreeOps, MobComData EXPORTS MobControlDefs = { OPEN MobDefs, MobSymbols; BindError: PUBLIC ERROR ~ CODE; table: Alloc.Handle; tb, stb, ctb, cxb, mtb, lfb, etb, itb, ftb: Table.Base; ssb: LONG STRING; Notifier: Alloc.Notifier ~ { tb ¬ base[treetype]; stb ¬ base[sttype]; cxb ¬ base[cxtype]; ctb ¬ base[cttype]; mtb ¬ base[mttype]; lfb ¬ base[lftype]; etb ¬ base[exptype]; itb ¬ base[imptype]; ftb ¬ base[fttype]; ssb ¬ base[sstype]}; Error: PROC ~ {ERROR BindError}; ItiToIndex: PROC[impi: IMPIndex] RETURNS[CARD] ~ INLINE { RETURN[LOOPHOLE[impi, CARD]/IMPRecord.SIZE]}; relocationHead: MobBindDefs.RelocHandle; rel: MobBindDefs.RelocHandle; BindRoot: PUBLIC PROC[relocationRoot: MobBindDefs.RelocHandle] ~ { table ¬ MobComData.data.table; table.AddNotify[Notifier]; relocationHead ¬ relocationRoot; SetupGFMap[]; AssignImports[ ! MobErrorDefs.GetSti => { IF rel # NIL THEN RESUME [StiForContext[ IF rel.type = $inner THEN rel.parentcx ELSE rel.context]]}]; BindModules[]; ReleaseGFMap[]; table.DropNotify[Notifier]; table ¬ NIL}; LinkType: TYPE ~ RECORD[ SELECT tag:* FROM gfi => [gfi: ModuleIndex], import => [impi: IMPIndex], ENDCASE]; GFOffset: TYPE = INT; GFMapItem: TYPE ~ RECORD[ linkItem: LinkType, expi: EXPIndex, offset: GFOffset]; GFMap: TYPE ~ RECORD[SEQUENCE length: CARDINAL OF GFMapItem]; RelMap: TYPE ~ RECORD[SEQUENCE length: CARDINAL OF CARDINAL]; finalFirstDummy: ModuleIndex; gfMap: REF GFMap ¬ NIL; relMap: REF RelMap ¬ NIL; SetupGFMap: PROC ~ { nDummies: CARDINAL ¬ MobUtilDefs.GetDummyGfi[0]-1; nImports: CARDINAL ~ table.Bounds[imptype].size/IMPRecord.SIZE; finalFirstDummy ¬ MobUtilDefs.GetGfi[0]; IF nDummies # 0 THEN nDummies ¬ nDummies + 1; gfMap ¬ NEW[GFMap[nDummies]]; FOR i: CARDINAL IN [0..nDummies) DO gfMap[i] ¬ [[gfi[0]], EXPNull, 0] ENDLOOP; relMap ¬ NEW[RelMap[nImports]]; FOR rel: MobBindDefs.RelocHandle ¬ relocationHead, rel.link UNTIL rel = NIL DO FOR iti: IMPIndex ¬ IMPIndex.FIRST+rel.import, iti+IMPRecord.SIZE UNTIL iti = rel.importLimit DO relMap[ItiToIndex[iti]] ¬ itb[iti].modIndex + rel.dummygfi-rel.originalfirstdummy; ENDLOOP; ENDLOOP}; RelocatedGfi: PROC[iti: IMPIndex] RETURNS[CARDINAL] ~ { RETURN[IF iti = IMPNull THEN 0 ELSE relMap[ItiToIndex[iti]]]}; ReleaseGFMap: PROC ~ { gfMap ¬ NIL; relMap ¬ NIL}; NameToHti: PROC[name: NameRecord] RETURNS[hti: HTIndex] ~ { ss: ConvertUnsafe.SubString ~ [base~ssb, offset~name+1, length~ssb.text[name].ORD]; hti ¬ MobHashOps.FindString[ss]; IF hti = HTNull THEN Error[]}; ExpiForSti: PROC[sti: STIndex] RETURNS[EXPIndex] ~ { RETURN [IF sti = stNull THEN EXPNull ELSE WITH s~~stb[sti] SELECT FROM external => WITH m~~s.map SELECT FROM interface => m.expi, ENDCASE => EXPNull, ENDCASE => EXPNull] }; AssignImports: PROC ~ { saveIndex: CARDINAL ~ MobComData.data.textIndex; saveName: NameRecord ~ MobComData.data.currentName; FOR rel ¬ relocationHead, rel.link UNTIL rel = NIL DO MobComData.data.textIndex ¬ rel.textIndex; MobComData.data.currentName ¬ MobUtilDefs.NameForSti[StiForContext[rel.context]]; SELECT TRUE FROM (rel.type = $outer) => AssignOuter[rel]; (rel.parameters # MobTree.null) => AssignByPosition[rel]; ENDCASE => AssignByName[rel]; ENDLOOP; MobComData.data.textIndex ¬ saveIndex; MobComData.data.currentName ¬ saveName}; AssignOuter: PROC[rel: MobBindDefs.RelocHandle] ~ { FOR iti: IMPIndex ¬ IMPIndex.FIRST+rel.import, iti+IMPRecord.SIZE UNTIL iti = rel.importLimit DO sti: STIndex ~ LookupInstance[iti, rel.context]; IF sti = stNull THEN LOOP; IF stb[sti].impi # IMPNull THEN { stb[sti].impgfi ¬ itb[stb[sti].impi].modIndex ¬ MobUtilDefs.GetGfi[1]} ELSE MobErrorDefs.ErrorSti[$error, "is not imported by any module"L, sti]; ENDLOOP }; AssignByName: PROC[rel: MobBindDefs.RelocHandle] ~ { iti, import: IMPIndex; export: EXPIndex; defgfi: CARDINAL; sti, parentSti: STIndex; FOR iti ¬ IMPIndex.FIRST+rel.import, iti+IMPRecord.SIZE UNTIL iti = rel.importLimit DO sti ¬ IF rel.type = $inner THEN LookupInstance[iti, rel.context] ELSE LookupInterface[iti, rel.context]; IF sti = stNull THEN LOOP; defgfi ¬ stb[sti].impgfi; IF stb[sti].impi # IMPNull THEN SELECT rel.type FROM $inner => { IF (parentSti ¬ LookupInterface[iti, rel.parentcx]) = stNull THEN LOOP; import ¬ stb[parentSti].impi; export ¬ ExpiForSti[parentSti]; defgfi ¬ stb[parentSti].impgfi; sti ¬ parentSti}; ENDCASE => {import ¬ stb[sti].impi; export ¬ ExpiForSti[sti]} ELSE {import ¬ IMPNull; export ¬ ExpiForSti[sti]}; WITH s~~stb[sti] SELECT FROM external => WITH m~~s.map SELECT FROM module => AssignModule[defgfi, m.mti, iti]; interface => AssignInterface[defgfi, import, export, iti]; unknown => AssignImport[defgfi, import, iti]; ENDCASE => Error[]; unknown => AssignImport[defgfi, import, iti]; ENDCASE => Error[]; ENDLOOP }; LookupInstance: PROC[iti: IMPIndex, cxi: CXIndex] RETURNS[STIndex] ~ { RETURN[IF cxi = cxNull THEN stNull ELSE Lookup[ hti~NameToHti[IF itb[iti].namedInstance THEN MobUtilDefs.InstanceName[[0,0,import[iti]]] ELSE itb[iti].name], cxi~rel.context]] }; LookupInterface: PROC[iti: IMPIndex, cxi: CXIndex] RETURNS[STIndex] ~ { RETURN[IF cxi = cxNull THEN stNull ELSE Lookup[NameToHti[itb[iti].name], cxi]]}; AssignByPosition: PROC[rel: MobBindDefs.RelocHandle] ~ { iti: IMPIndex; TooManyParameters: ERROR ~ CODE; AssignPosition: MobTree.Scan ~ { sti: STIndex ~ NARROW[t, MobTree.Link.symbol].index; import: IMPIndex ~ stb[sti].impi; export: EXPIndex ~ ExpiForSti[sti]; defgfi: CARDINAL ~ stb[sti].impgfi; IF iti = rel.importLimit THEN ERROR TooManyParameters; WITH s~~stb[sti] SELECT FROM external => WITH m~~s.map SELECT FROM module => AssignModule[defgfi, m.mti, iti]; interface => AssignInterface[defgfi, import, export, iti]; unknown => AssignImport[defgfi, import, iti]; ENDCASE => Error[]; ENDCASE => MobErrorDefs.ErrorSti[$error, "is undeclared"L, sti]; iti ¬ iti + MobDefs.IMPRecord.SIZE}; iti ¬ IMPIndex.FIRST + rel.import; MobTreeOps.ScanList[rel.parameters, AssignPosition ! TooManyParameters => {GOTO tooMany}]; IF iti # rel.importLimit THEN GOTO tooFew; EXITS tooMany => MobErrorDefs.ErrorHti[$error, "has too many parameters"L, HtiForRelocation[rel]]; tooFew => MobErrorDefs.ErrorHti[$error, "has too few parameters"L, HtiForRelocation[rel]]}; MakeLink: PROC[defgfi: CARDINAL, import: IMPIndex, offset: CARDINAL] RETURNS[LinkType] ~ { RETURN[SELECT TRUE FROM (defgfi # 0) => [gfi[defgfi+offset]], (import = IMPNull) => [gfi[0]], ENDCASE => [import[import]]]}; AssignModule: PROC[defgfi: ModuleIndex, mti: MTIndex, iti: IMPIndex] ~ { gfi: CARDINAL ~ RelocatedGfi[iti]; IF itb[iti].port # $module OR ~MobUtilDefs.EqVersions[itb[iti].file, mtb[mti].file] THEN MobErrorDefs.Error2Files[ class~$error, s~"is required for import, but available version is"L, ft1~itb[iti].file, ft2~mtb[mti].file]; gfMap[gfi] ¬ [ linkItem~[gfi[IF defgfi # 0 THEN defgfi ELSE mtb[mti].modIndex]], expi~EXPNull, offset~0]}; AssignInterface: PROC[defgfi: ModuleIndex, import: IMPIndex, expi: EXPIndex, iti: IMPIndex] ~ { gfi: CARDINAL ~ RelocatedGfi[iti]; IF expi # EXPNull AND (itb[iti].port # etb[expi].port OR ~MobUtilDefs.EqVersions[itb[iti].file, etb[expi].file]) THEN MobErrorDefs.Error2Files[ class~$error, s~"is required for import, but available version is"L, ft1~itb[iti].file, ft2~etb[expi].file]; IF itb[iti].port = $module THEN gfMap[gfi] ¬ [ linkItem~[gfi[etb[expi].links[0].from.modIndex]], expi~EXPNull, offset~0] ELSE FOR i: GFOffset IN [0..1) DO gfMap[gfi+i] ¬ [ linkItem~MakeLink[defgfi, import, i], expi~expi, offset~i]; ENDLOOP}; AssignImport: PROC[defgfi: ModuleIndex, import: IMPIndex, iti: IMPIndex] ~ { gfi: CARDINAL ~ RelocatedGfi[iti]; IF import # IMPNull AND (itb[iti].port # itb[import].port OR ~MobUtilDefs.EqVersions[itb[iti].file, itb[import].file]) THEN MobErrorDefs.Error2Files[ class~$error, s~"is required for import, but available version is"L, ft1~itb[iti].file, ft2~itb[import].file]; FOR i: GFOffset IN [0..1) DO gfMap[gfi+i] ¬ [ linkItem~MakeLink[defgfi, import, i], expi~EXPNull, offset~i]; ENDLOOP}; Lookup: PROC[hti: HTIndex, cxi: CXIndex] RETURNS[sti: STIndex] ~ { FOR sti ¬ cxb[cxi].link, stb[sti].link UNTIL sti = stNull DO IF stb[sti].hti = hti THEN RETURN ENDLOOP; RETURN [stNull]}; StiForContext: PROC[cxi: CXIndex] RETURNS[sti: STIndex] ~ { stLimit: STIndex ~ LOOPHOLE[table.Top[sttype]]; FOR sti ¬ STIndex.FIRST, sti+STRecord.SIZE UNTIL sti = stLimit DO WITH s~~stb[sti] SELECT FROM local => IF s.context = cxi THEN RETURN; ENDCASE; ENDLOOP; RETURN [stNull]}; HtiForRelocation: PROC[rel: MobBindDefs.RelocHandle] RETURNS[HTIndex] ~ { sti: STIndex; mti: MTIndex; cti: CTIndex; IF rel.type # $file THEN { sti ¬ StiForContext[rel.context]; RETURN [stb[sti].hti]}; mti ¬ MTIndex.FIRST + rel.module; cti ¬ CTIndex.FIRST + rel.config; RETURN [NameToHti[IF mtb[mti].config = cti THEN ctb[cti].name ELSE mtb[mti].name]]}; BindModules: PROC ~ { saveIndex: CARDINAL ~ MobComData.data.textIndex; saveName: NameRecord ~ MobComData.data.currentName; mtLimit: MTIndex ~ LOOPHOLE[table.Top[mttype]]; rel ¬ relocationHead; FOR mti: MTIndex ¬ MTIndex.FIRST, (mti + MTRecord.SIZE) UNTIL mti = mtLimit DO SetRelocationForModule[mti]; FOR i: CARDINAL IN [0 .. lfb[mtb[mti].links].length) DO saveLink: MobDefs.Link ¬ lfb[mtb[mti].links].frag[i]; lfb[mtb[mti].links].frag[i] ¬ RelocateLink[saveLink ! MobErrorDefs.GetModule => {RESUME [mti, i, saveLink]}]; ENDLOOP; ENDLOOP; MobComData.data.textIndex ¬ saveIndex; MobComData.data.currentName ¬ saveName}; SetRelocationForModule: PROC[mti: MTIndex] ~ { gfi: ModuleIndex ~ mtb[mti].modIndex; FOR rel ¬ rel, rel.link UNTIL rel = NIL DO IF gfi IN [rel.firstgfi..rel.lastgfi] THEN GOTO found ENDLOOP; FOR rel ¬ relocationHead, rel.link UNTIL rel = NIL DO IF gfi IN [rel.firstgfi..rel.lastgfi] THEN GOTO found ENDLOOP; Error[]; EXITS found => { MobComData.data.textIndex ¬ rel.textIndex; MobComData.data.currentName ¬ MobUtilDefs.NameForSti[StiForContext[rel.context]]}}; BindFragment: PROC[mti: MTIndex, lfi: LFIndex] ~ { IF lfi # LFNull THEN FOR i: CARDINAL IN [0 .. lfb[lfi].length) DO saveLink: MobDefs.Link ¬ lfb[lfi].frag[i]; lfb[lfi].frag[i] ¬ RelocateLink[saveLink ! MobErrorDefs.GetModule => RESUME [mti, i, saveLink]]; ENDLOOP }; RelocateLink: PROC[cl: MobDefs.Link] RETURNS[MobDefs.Link] ~ { SELECT TRUE FROM (cl.tag = $type) => ERROR; (cl.modIndex = 0) => NULL; (cl.modIndex < rel.originalfirstdummy) => cl.modIndex ¬ cl.modIndex + rel.firstgfi-1; ENDCASE => { gfi: CARDINAL; expi: EXPIndex; map: LONG POINTER TO GFMapItem; gfi ¬ cl.modIndex + rel.dummygfi-rel.originalfirstdummy; DO map ¬ @gfMap[gfi]; IF (expi¬map.expi) # EXPNull THEN { newCl: MobDefs.Link ~ etb[expi].links[cl.offset + map.offset*0].from; IF newCl # nullLink THEN RETURN [newCl]}; WITH map.linkItem SELECT FROM m: LinkType.gfi => { IF (gfi¬m.gfi) = 0 THEN GOTO unbindable; IF gfi < finalFirstDummy AND cl.offset = 0 THEN cl ¬ [tag: $var, modIndex: 0, offset: 0]; EXIT}; m: LinkType.import => gfi ¬ RelocatedGfi[m.impi]+map.offset; ENDCASE; REPEAT unbindable => { importName: NameRecord; offset: CARDINAL; importFti: FTIndex; [importName, offset, importFti] ¬ LookupImport[cl.modIndex]; MobErrorDefs.ErrorInterface[ class~$warning, s~"is unbindable"L, import~[name~importName, fti~importFti], ep~(cl.offset + offset)]; RETURN [IF cl.tag = $var THEN nullLink ELSE unboundLink]}; ENDLOOP; cl.modIndex ¬ gfi}; RETURN [cl]}; LookupImport: PROC[gfi: ModuleIndex] RETURNS[importName: NameRecord, offset: CARDINAL, importFti: FTIndex] ~ { FOR iti: IMPIndex ¬ (IMPIndex.FIRST + rel.import), (iti + IMPRecord.SIZE) UNTIL iti = rel.importLimit DO IF gfi IN [itb[iti].modIndex..itb[iti].modIndex+1) THEN RETURN[ importName~itb[iti].name, offset~(gfi-itb[iti].modIndex)*0 <>, importFti~itb[iti].file]; ENDLOOP; RETURN[importName~NullName, offset~0, importFti~FTNull]}; }. n MobBind.mesa Copyright Σ 1985, 1989, 1991 by Xerox Corporation. All rights reserved. Satterthwaite on February 27, 1986 12:28:49 pm PST Lewis on 16-Dec-80 10:12:01 Maxwell, August 4, 1983 10:58 am Paul Rovner, September 8, 1983 5:30 pm Russ Atkinson (RRA) March 7, 1985 0:19:30 am PST Andy Litman May 11, 1988 6:13:15 pm PDT JKF July 22, 1989 3:50:17 pm PDT Κ σ–(cedarcode) style•NewlineDelimiter ™codešœ ™ Kšœ Οeœ=™HKšΟy2™2Kšž™Kšž ™ Kšž&™&K™0Kšž'™'K™ —K˜šΟk ˜ KšœŸœ8˜CKšœ Ÿœ˜ Kšœ Ÿœ˜KšœŸœ˜KšœŸœ…˜’Kšœ ŸœF˜XKšœ Ÿœ=˜NKšœŸœ ˜ Kšœ Ÿœ˜Kšœ Ÿœ?˜OKšœŸœ˜KšœŸœ˜!Kšœ Ÿœ ˜K˜—šΟnœŸ˜KšœŸœE˜NKšœŸœ˜KšŸœ˜K˜Kš  œŸœŸœŸœ˜K˜K˜K˜7KšœŸœŸœ˜K˜š œ˜K˜?K˜?K˜+K˜K˜K˜K˜—Kš œŸœŸœ ˜ K˜š   œŸœŸœŸœŸœ˜9KšŸœŸœŸœ Ÿœ˜-K˜—K˜(K˜K˜š œŸœŸœ-˜BK˜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šœ Ÿœ ˜2Kšœ Ÿœ(Ÿœ˜?K˜(KšŸœŸœ˜-KšœŸœ˜Kš ŸœŸœŸœŸœ#Ÿœ˜NKšœ Ÿœ˜šŸœ9ŸœŸœŸ˜NšŸœŸœŸ˜AšŸœŸ˜KšœR˜RKšŸœ˜——KšŸœ˜ K˜——š  œŸœŸœŸœ˜7KšŸœŸœŸœŸœ˜>K˜—š  œŸœ˜KšœŸœ˜ Kšœ Ÿœ˜K˜K˜—š  œŸœŸœ˜;KšœNŸœ˜SK˜ KšŸœŸœ ˜K˜—š  œŸœŸœ˜4šŸœŸœ ˜KšŸœ˜ šŸ˜šŸœ ŸœŸ˜Kš œ Ÿœ ŸœŸœŸœ ˜NKšŸœ ˜———šœ˜˜K˜———š  œŸœ˜Kšœ Ÿœ˜0K˜3šŸœ ŸœŸœŸ˜5K˜*K˜QšŸœŸœŸ˜K˜)K˜:KšŸœ˜—KšŸœ˜—K˜PK˜—š  œŸœ"˜3šŸœŸœŸœ˜BšŸœŸ˜K˜0KšŸœŸœŸœ˜šŸœ˜šŸœ˜KšœF˜F—KšŸœF˜J—KšŸ˜——šœ˜K˜——š  œŸœ"˜4K˜K˜KšœŸœ˜K˜š ŸœŸœŸœŸœŸ˜VšœŸœ˜KšŸœ!˜%KšŸœ#˜'—KšŸœŸœŸœ˜K˜šŸœ˜šŸ˜šŸœ Ÿ˜˜ šŸœ:˜K˜K˜—KšŸœ6˜=——KšŸœ.˜2—šŸœ ŸœŸ˜˜ šŸœ ŸœŸ˜K˜+K˜:K˜-KšŸœ ˜——K˜-KšŸœ ˜—KšŸ˜—šœ˜K˜——š œŸœŸœ ˜FšŸœŸœ ˜KšŸœ˜ šŸœ˜ šœŸœ˜'KšŸœ,˜0KšŸœ˜—K˜——˜K˜——š œŸœŸœ ˜GKšŸœŸœŸœŸœ)˜PK˜K˜—š œŸœ"˜8K˜Kš œŸœŸœ˜ K˜š œ˜ KšœŸœ˜4K˜!K˜#KšœŸœ˜#KšŸœŸœŸœ˜6šŸœ ŸœŸ˜˜ šŸœ ŸœŸ˜K˜+K˜:K˜-KšŸœ ˜——KšŸœ9˜@—KšœŸœ˜$K˜—KšœŸœ˜"˜2KšœŸœ ˜'—KšŸœŸœŸœ˜*šŸ˜˜)K˜3—˜(K˜3K˜———š œŸœ ŸœŸœ˜DKšŸœ˜šŸœŸœŸœŸ˜K˜%K˜KšŸœ˜K˜——š  œŸœ6˜HKšœŸœ˜"šŸœŸœ7Ÿ˜X˜K˜ K˜6Kšœ&˜&——˜KšœŸœ ŸœŸœ˜AK˜K˜——š œŸœJ˜_KšœŸœ˜"šŸœŸ˜šœ Ÿœ9Ÿ˜_˜K˜ K˜6Kšœ'˜'———šŸœŸ˜˜K˜1K˜——šŸœŸœ ŸœŸ˜!˜K˜%K˜—KšŸœ˜ K˜——š  œŸœ:˜LKšœŸœ˜"šŸœŸ˜šœ"Ÿ˜$šœ:Ÿ˜>˜K˜ K˜6Kšœ)˜)————šŸœ ŸœŸ˜˜K˜%K˜—KšŸœ˜ K˜——š œŸœŸœ˜BšŸœ$ŸœŸ˜—šŸœ ŸœŸœŸ˜5Kš ŸœŸœŸœŸœŸœ˜>—K˜šŸœ ˜K˜*K˜SK˜——š  œŸœ ˜2šŸœŸ˜šŸœŸœŸœŸ˜,K˜*šœ(˜(KšœŸœ˜7—KšŸ˜——šœ˜K˜——š  œŸœŸœ˜>šŸœŸœŸ˜KšœŸœ˜KšœŸœ˜K˜VšŸœ˜ KšœŸœ˜K˜KšœŸœŸœŸœ ˜K˜8šŸ˜K˜šŸœŸœ˜#K˜FKšŸœŸœŸœ ˜)—šŸœŸœŸ˜˜KšŸœŸœŸœ ˜(šŸœŸœŸœ˜0Kšœ)˜)—KšŸœ˜—K˜