DIRECTORY AMBridge USING [GetWorld, GetWorldIncarnation, GFHFromTV, IsRemote, nilRemoteGlobalFrameHandle, RemoteGFHFromTV, RemoteGlobalFrameHandle, TVForGFHReferent, TVForProc, TVForRemoteGFHReferent, TVForRemoteProc, TVToProc, TVToRemoteProc], AMFiles USING [OpenIt], AMModel USING [CharIndex, Class, Context, ContextChildren, ContextSection, Section, SectionClass, SectionObj, SectionSource, SectionVersion, Source, SourceClass, SourceFileName, SourceObj], AMModelBridge USING [LoadedSection, ContextForFrame, FrameFromContext], AMModelLocation USING [CodeLocation], AMModelPrivate USING [CharIndexToFGI, ConfigContext, EPI, EPIToFirstPC, EPIToLastPC, FGIndex, FGIToEPI, FGIToFirstPC, FGNull, FindMatchingGlobalFrames, PCOffset, ProgPCToFGI, RefTVRec, SectionRec], AMTypes USING [Error, GlobalParent, TV, TVType], BasicTime USING [FromNSTime, ToNSTime], BcdDefs USING [BcdBase, FTSelf, MTHandle, MTIndex, VersionStamp], BcdOps USING [ProcessModules], FS USING [OpenFile, nullOpenFile, GetInfo, Close], IO USING [PutFR], LoadState USING [Acquire, ConfigID, ConfigInfo, EnumerateAllModules, GlobalFrameToModule, Handle, local, ModuleIndex, ModuleInfo, nullConfig, Release], PrincOps USING [BytePC, ControlLink, EPRange, FrameCodeBase, GlobalFrameHandle, ProcDesc], PrincOpsUtils USING [GlobalFrameAndEntryPoint], RemotePrincOpsUtils USING [RemoteGlobalFrameAndEntryPoint], Rope USING [Concat, Equal, Flatten, Length, Match, ROPE], RuntimeError USING [UNCAUGHT], RTSymbolDefs USING [SymbolTableBase, SymbolTableHandle, nullHandle, nullBase], RTSymbols USING [ReleaseSTB, AcquireSTBFromSGI, AcquireSTB, GetSTHForModule], RTSymbolsPrivate USING [AcquireBCDFromVersion, ReleaseBCD], RTTypesPrivate USING [GetPc], RTTypesRemotePrivate USING [AcquireRemoteBCD, GetRemoteGFHeader, GetRemotePc, ReleaseRemoteBCD], SafeStorage USING [fhType, gfhType, Type], Table USING [Base], WorldVM USING [CurrentIncarnation, Loadstate, LocalWorld, Lock, NoWorld, ShortAddress, Unlock, World]; AMModelSourceImpl: PROGRAM IMPORTS AMBridge, AMFiles, AMModel, AMModelBridge, AMModelPrivate, AMTypes, BasicTime, BcdOps, FS, IO, LoadState, PrincOpsUtils, RemotePrincOpsUtils, Rope, RTSymbols, RTSymbolsPrivate, RTTypesPrivate, RTTypesRemotePrivate, RuntimeError, WorldVM EXPORTS AMModel, AMModelBridge, AMModelLocation, AMModelPrivate = { OPEN AMBridge, AMModel, AMModelBridge, AMModelPrivate, AMTypes, PrincOps, RTSymbolDefs, RTSymbols, RTTypesPrivate, RTTypesRemotePrivate; CodeLocation: TYPE = AMModelLocation.CodeLocation; LoadedSection: TYPE = AMModelBridge.LoadedSection; ROPE: TYPE = Rope.ROPE; Section: TYPE = REF SectionObj; SectionObj: PUBLIC TYPE = AMModelPrivate.SectionRec; TV: TYPE = AMTypes.TV; World: TYPE = WorldVM.World; fhType: SafeStorage.Type = SafeStorage.fhType; gfhType: SafeStorage.Type = SafeStorage.gfhType; FileSource: PUBLIC PROC [fileName: ROPE, class: --model, prog, interface--Class] RETURNS [s: Source _ NIL] = { f: FS.OpenFile _ FS.nullOpenFile; IF class = model THEN { IF NOT Rope.Match["*.config*", fileName, FALSE] THEN fileName _ fileName.Concat[".config"]; } ELSE { IF NOT Rope.Match["*.mesa*", fileName, FALSE] THEN fileName _ fileName.Concat[".mesa"]; }; f _ AMFiles.OpenIt[fileName].openFile; IF f # FS.nullOpenFile THEN { s _ NEW[SourceObj _ [ fileName: fileName, class: class, versionStamp: [0, 0, BasicTime.ToNSTime[FS.GetInfo[f].created]], sourceRange: entire[]]]; FS.Close[f]; }; }; SourceSection: PUBLIC PROC [source: Source, context: --worldRoot or model--Context] RETURNS [section: Section _ NIL, contexts: LIST OF --prog--Context _ NIL] = { SELECT SourceClass[source] FROM statement => { [section, contexts] _ SourceSection [ NEW[SourceObj _ [fileName: source.fileName, class: prog, versionStamp: source.versionStamp, sourceRange: entire[]]], context]; section _ NEW[SectionObj _ [statement[prog: NARROW[section], fgtIndex: SourceToFGIandEPI[source, NARROW[section]].fgi]]]; }; proc => { [section, contexts] _ SourceSection [ NEW[SourceObj _ [fileName: source.fileName, class: prog, versionStamp: source.versionStamp, sourceRange: entire[]]], context]; section _ NEW[SectionObj _ [proc[prog: NARROW[section], entryPointIndex: SourceToFGIandEPI[source, NARROW[section]].epi]]]; }; prog => { WITH context SELECT FROM tv: RefTVRec => { SELECT TVType[tv] FROM gfhType => { section _ ContextSection[context]; IF Rope.Equal[SourceFileName[source], SourceFileName[SectionSource[section]], FALSE] THEN contexts _ CONS[context, NIL] ELSE section _ NIL; RETURN; }; fhType => { [section, contexts] _ SourceSection[source, GlobalParent[tv]]; RETURN; }; ENDCASE => ERROR Error[typeFault]; }; mc: ConfigContext => { IF mc.configIndex = LoadState.nullConfig THEN { inner: PROC [name: ROPE, context: AMModel.Context] RETURNS [stop: BOOL _ FALSE] = TRUSTED { temp: Section _ AMModel.ContextSection[context]; source: AMModel.Source _ AMModel.SectionSource[temp]; IF source.versionStamp = sourceVersion THEN { contexts _ CONS[context, contexts]; IF section # NIL THEN IF SectionVersion[temp] # SectionVersion[section] THEN ERROR Error[reason: notImplemented, msg: "different sections for the same source"]; section _ temp; }; }; sourceVersion: BcdDefs.VersionStamp _ source.versionStamp; world: WorldVM.World _ mc.world; shortName: ROPE _ source.fileName; IF Rope.Match["*.mesa", shortName, FALSE] THEN shortName _ Rope.Flatten[shortName, 0, Rope.Length[shortName]-5]; IF world = NIL THEN world _ WorldVM.LocalWorld[]; [] _ AMModelPrivate.FindMatchingGlobalFrames[world, shortName, inner]; } ELSE { proc: PROC [context: Context] RETURNS [stop: BOOL _ FALSE] = { IF Rope.Equal[SourceFileName[source], SourceFileName[SectionSource[ContextSection[context]]], FALSE] THEN { SELECT TRUE FROM section = NIL => section _ ContextSection[context]; SectionVersion[ContextSection[context]] # SectionVersion[section] => { ERROR Error[reason: notImplemented, msg: "different sections for the same source"]; }; ENDCASE; contexts _ CONS[context, contexts]; }; }; [] _ ContextChildren[context, proc]; }; }; ENDCASE => ERROR }; model => ERROR AMTypes.Error[reason: notImplemented, msg: "SourceSection[model source]"]; interface => ERROR AMTypes.Error[reason: notImplemented, msg: "SourceSection[interface source]"]; ENDCASE => ERROR; IF section = NIL THEN { AMTypes.Error[noSymbols, IO.PutFR["for source file %g of %g", [rope[source.fileName]], [time[BasicTime.FromNSTime[source.versionStamp.time]]] ]]; }; }; GetModuleSTB: PUBLIC PROC [bcd: BcdDefs.BcdBase, versionStamp: BcdDefs.VersionStamp] RETURNS [stb: SymbolTableBase _ nullBase] = { FindModule: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [stop: BOOL _ FALSE] = { version: BcdDefs.VersionStamp _ IF mth.file = BcdDefs.FTSelf THEN bcd.version ELSE ftb[mth.file].version; IF version = versionStamp THEN { stb _ AcquireSTBFromSGI[bcd, mth.sseg]; RETURN[TRUE]}; }; sth: SymbolTableHandle _ nullHandle; ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset]; sth _ GetSTHForModule[versionStamp, NIL, NIL ! RuntimeError.UNCAUGHT, AMTypes.Error => CONTINUE]; IF sth = nullHandle THEN [] _ BcdOps.ProcessModules[bcd, FindModule] ELSE stb _ AcquireSTB[sth]; }; LoadedSectionForProc: PUBLIC PROC [tv: AMTypes.TV--proc--] RETURNS [ans: LoadedSection _ [NIL, NIL, [0]]] = { c: Context; s: Section; ep: CARDINAL; gf: AMTypes.TV _ AMTypes.GlobalParent[tv]; ans.context _ AMModelBridge.ContextForFrame[gf]; c _ ans.context; s _ ContextSection[c]; IF AMBridge.IsRemote[tv] THEN { world: WorldVM.World = AMBridge.GetWorld[tv]; rgfh: AMBridge.RemoteGlobalFrameHandle _ AMBridge.nilRemoteGlobalFrameHandle; gfh: PrincOps.GlobalFrameHandle; [gfh, ep] _ RemotePrincOpsUtils.RemoteGlobalFrameAndEntryPoint [world, AMBridge.TVToRemoteProc[tv].pd]; rgfh _ [world, WorldVM.CurrentIncarnation[world], LOOPHOLE[gfh]]; ans.pc _ RTTypesRemotePrivate.GetRemotePc[rgfh, ep]; } ELSE { gfh: PrincOps.GlobalFrameHandle; [gfh, ep] _ PrincOpsUtils.GlobalFrameAndEntryPoint[ LOOPHOLE[AMBridge.TVToProc[tv]]]; ans.pc _ RTTypesPrivate.GetPc[gfh, ep]; }; ans.section _ NEW[SectionObj _ [proc[prog: NARROW[s], entryPointIndex: ep, procTV: NARROW[tv]]]]; }; LoadedSectionForProgPC: PUBLIC PROC [prog: Context, pc: BytePC] RETURNS [ans: LoadedSection _ [NIL, NIL, [0]]] = { s: Section = ContextSection[prog]; ctx: TV _ AMModelBridge.FrameFromContext[prog]; ans.context _ prog; ans.section _ NEW[SectionObj _ [statement [ prog: NARROW[s], fgtIndex: AMModelPrivate.ProgPCToFGI[ctx, pc]]]]; ans.pc _ pc; }; ProcFromLoadedSection: PUBLIC PROC [proc: LoadedSection] RETURNS [AMTypes.TV] = { s: Section = proc.section; sr: REF proc SectionObj _ NARROW[s]; IF sr.procTV # NIL THEN RETURN[sr.procTV] ELSE { ctx: TV _ AMModelBridge.FrameFromContext[proc.context]; IF AMBridge.IsRemote[ctx] THEN { pd: PrincOps.ProcDesc _ PrincOps.ControlLink[procedure[gfi: 0, ep: 0, tag: TRUE]]; pd.gfi _ RTTypesRemotePrivate.GetRemoteGFHeader[AMBridge.RemoteGFHFromTV[ctx]].gfi + sr.entryPointIndex/PrincOps.EPRange; pd.ep _ sr.entryPointIndex MOD PrincOps.EPRange; RETURN[AMBridge.TVForRemoteProc[[ world: AMBridge.GetWorld[ctx], worldIncarnation: AMBridge.GetWorldIncarnation[ctx], pd: LOOPHOLE[pd]]]]; } ELSE { pd: PrincOps.ProcDesc _ PrincOps.ControlLink[procedure[gfi: 0, ep: 0, tag: TRUE]]; pd.gfi _ AMBridge.GFHFromTV[ctx].gfi + sr.entryPointIndex/PrincOps.EPRange; pd.ep _ sr.entryPointIndex MOD PrincOps.EPRange; RETURN[AMBridge.TVForProc[LOOPHOLE[pd]]]; }; }; }; EntryLocations: PUBLIC PROC [section: Section] RETURNS [world: World, list: LIST OF CodeLocation _ NIL] = { [world: world, list: list] _ GetLocations[section]; }; ExitLocations: PUBLIC PROC [section: Section] RETURNS [world: World, list: LIST OF CodeLocation _ NIL] = { [world: world, list: list] _ GetLocations[section: section, entry: FALSE]; }; GetLocations: PROC [section: Section, entry: BOOL _ TRUE] RETURNS [world: World _ WorldVM.NoWorld[], list: LIST OF CodeLocation _ NIL] = { epi: EPI; firstPC: PCOffset; progContexts: LIST OF Context _ NIL; context: Context _ NIL; version: BcdDefs.VersionStamp; SELECT SectionClass[section] FROM statement => { statementSect: REF statement SectionObj = NARROW[section]; context _ statementSect.prog.someGFHTV; IF context = NIL THEN RETURN; -- section is not loaded version _ statementSect.prog.versionStamp; world _ GetWorld[context]; { stb: SymbolTableBase _ STBforContext[context, statementSect.prog.versionStamp]; { ENABLE UNWIND => ReleaseSTB[stb]; epi _ FGIToEPI[stb, statementSect.fgtIndex]; firstPC _ FGIToFirstPC[stb, statementSect.fgtIndex]; }; ReleaseSTB[stb]; }; }; proc => { procSect: REF proc SectionObj = NARROW[section]; context _ procSect.prog.someGFHTV; IF context = NIL THEN RETURN; -- section is not loaded version _ procSect.prog.versionStamp; epi _ procSect.entryPointIndex; world _ GetWorld[context]; { stb: SymbolTableBase _ STBforContext[context, version]; { ENABLE UNWIND => ReleaseSTB[stb]; IF entry THEN firstPC _ EPIToFirstPC[stb, epi, TRUE] ELSE firstPC _ EPIToLastPC[stb, epi]; }; ReleaseSTB[stb]; }; }; ENDCASE => ERROR Error[reason: typeFault, msg: "EntryLocation misapplied"]; progContexts _ ProgContextsForVersion[world: world, version: version]; IF progContexts = NIL THEN ERROR; FOR contextList: LIST OF Context _ progContexts, contextList.rest UNTIL contextList = NIL DO codeBase: PrincOps.FrameCodeBase; pc: PrincOps.BytePC; context: Context = contextList.first; found: BOOL _ FALSE; IF IsRemote[context] THEN { codeBase _ GetRemoteGFHeader[RemoteGFHFromTV[context]].code; pc _ [firstPC + GetRemotePc[RemoteGFHFromTV[context], epi]]; } ELSE { codeBase _ GFHFromTV[context].code; pc _ [firstPC + GetPc[GFHFromTV[context], epi]]; }; FOR cll: LIST OF CodeLocation _ list, cll.rest UNTIL cll = NIL DO IF cll.first.codeBase = codeBase THEN {found _ TRUE; EXIT}; ENDLOOP; IF NOT found THEN list _ CONS[[codeBase: codeBase, pc: pc], list]; ENDLOOP; }; ProgContextsForVersion: PROC [world: World, version: BcdDefs.VersionStamp] RETURNS [contexts: LIST OF Context _ NIL] = { IF world = WorldVM.LocalWorld[] THEN { forEachModule: PROC [ci: LoadState.ConfigID, mi: LoadState.ModuleIndex] RETURNS [stop: BOOL _ FALSE] = { bcd: BcdDefs.BcdBase = LoadState.local.ConfigInfo[ci].bcd; ftb: Table.Base _ LOOPHOLE[bcd + bcd.ftOffset]; mtb: Table.Base _ LOOPHOLE[bcd + bcd.mtOffset]; gfh: GlobalFrameHandle; mti: BcdDefs.MTIndex; [gfh: gfh, mti: mti] _ LoadState.local.ModuleInfo[ci, mi]; IF NOT loadStateHeld THEN ERROR; IF (IF mtb[mti].file = BcdDefs.FTSelf THEN bcd.version ELSE ftb[mtb[mti].file].version) = version THEN contexts _ CONS[TVForGFHReferent[gfh], contexts]; }; loadStateHeld: BOOL _ FALSE; LoadState.local.Acquire[]; loadStateHeld _ TRUE; [] _ LoadState.local.EnumerateAllModules[newestFirst, forEachModule ! RuntimeError.UNCAUGHT, AMTypes.Error, UNWIND => IF loadStateHeld THEN {LoadState.local.Release[]; loadStateHeld _ FALSE}]; IF loadStateHeld THEN LoadState.local.Release[]; } ELSE { WorldVM.Lock[world]; { ENABLE UNWIND => WorldVM.Unlock[world]; forEachModule: PROC [ci: LoadState.ConfigID, mi: LoadState.ModuleIndex] RETURNS [stop: BOOL _ FALSE] = { bcd: BcdDefs.BcdBase = AcquireRemoteBCD[ world, WorldVM.CurrentIncarnation[world], newState.ConfigInfo[ci].bcd]; { ENABLE UNWIND => ReleaseRemoteBCD[bcd]; ftb: Table.Base _ LOOPHOLE[bcd + bcd.ftOffset]; mtb: Table.Base _ LOOPHOLE[bcd + bcd.mtOffset]; gfh: GlobalFrameHandle; rgfh: RemoteGlobalFrameHandle _ nilRemoteGlobalFrameHandle; mti: BcdDefs.MTIndex; [gfh: gfh, mti: mti] _ newState.ModuleInfo[ci, mi]; rgfh _ [world, WorldVM.CurrentIncarnation[world], LOOPHOLE[gfh, WorldVM.ShortAddress]]; IF NOT loadStateHeld THEN ERROR; IF (IF mtb[mti].file = BcdDefs.FTSelf THEN bcd.version ELSE ftb[mtb[mti].file].version) = version THEN contexts _ CONS[TVForRemoteGFHReferent[rgfh], contexts]; }; ReleaseRemoteBCD[bcd]; }; loadStateHeld: BOOL _ FALSE; newState: LoadState.Handle = WorldVM.Loadstate[world]; newState.Acquire[]; loadStateHeld _ TRUE; [] _ newState.EnumerateAllModules[newestFirst, forEachModule ! RuntimeError.UNCAUGHT, AMTypes.Error, UNWIND => IF loadStateHeld THEN {newState.Release[]; loadStateHeld _ FALSE}]; IF loadStateHeld THEN newState.Release[]; }; WorldVM.Unlock[world]; }; }; GetRemoteBCD: PUBLIC PROC [rgfh: RemoteGlobalFrameHandle] RETURNS [bcd: BcdDefs.BcdBase _ NIL] = { h: LoadState.Handle; WorldVM.Lock[rgfh.world]; h _ WorldVM.Loadstate[rgfh.world ! UNWIND => WorldVM.Unlock[rgfh.world]]; h.Acquire[]; { ENABLE UNWIND => {h.Release[]; WorldVM.Unlock[rgfh.world]}; gfh: GlobalFrameHandle = LOOPHOLE[rgfh.gfh]; bcd _ AcquireRemoteBCD[ rgfh.world, WorldVM.CurrentIncarnation[rgfh.world], h.ConfigInfo[h.GlobalFrameToModule[gfh].config].bcd ]; }; h.Release[]; WorldVM.Unlock[rgfh.world]; }; GetLocalBCD: PUBLIC PROC [gfh: GlobalFrameHandle] RETURNS [bcd: BcdDefs.BcdBase] = { LoadState.local.Acquire[]; { ENABLE UNWIND => LoadState.local.Release[]; bcd _ LoadState.local.ConfigInfo[LoadState.local.GlobalFrameToModule[gfh].config].bcd; }; LoadState.local.Release[]; }; SourceToFGIandEPI: PROC [source: Source, prog: REF prog SectionObj] RETURNS [fgi: FGIndex _ FGNull, epi: EPI _ 0] = { stb: SymbolTableBase; IF prog.someGFHTV # NIL THEN stb _ STBforContext[prog.someGFHTV, prog.versionStamp] ELSE { bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion[ versionStamp: prog.versionStamp, shortFileNameHint: Rope.Concat[prog.moduleName, ".bcd"]]; stb: SymbolTableBase _ GetModuleSTB[bcd, prog.versionStamp ! UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]]; RTSymbolsPrivate.ReleaseBCD[bcd]; }; { ENABLE UNWIND => ReleaseSTB[stb]; fgi _ CharIndexToFGI[stb, (WITH s: source SELECT FROM field => s.firstCharIndex ENDCASE => 0)]; epi _ FGIToEPI[stb, fgi]; }; ReleaseSTB[stb]; }; STBforContext: PROC [ctx: TV, version: BcdDefs.VersionStamp] RETURNS [stb: SymbolTableBase] = { world: World = AMBridge.GetWorld[ctx]; IF world = WorldVM.LocalWorld[] THEN { bcd: BcdDefs.BcdBase = GetLocalBCD[AMBridge.GFHFromTV[ctx]]; stb _ GetModuleSTB[bcd, version]; } ELSE { bcd: BcdDefs.BcdBase = GetRemoteBCD[AMBridge.RemoteGFHFromTV[ctx]]; stb _ GetModuleSTB[bcd, version ! UNWIND => RTTypesRemotePrivate.ReleaseRemoteBCD[bcd]]; RTTypesRemotePrivate.ReleaseRemoteBCD[bcd]; }; }; }. ®AMModelSourceImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. created by Rovner, December 12, 1983 11:12 am Russ Atkinson (RRA) November 12, 1985 2:52:54 pm PST TYPEs A LoadedSection is a convenience for clients of AMModelBridge. Each represents one of: loaded compiler output bundle for a prog module [prog, prog] loaded compiler output bundle for a proc [proc, prog] loaded compiler output bundle for a statement [statement, prog] either binder output bundle for a config, or compiler output bundle for a prog module, DEFs module, proc, or statement PROCs ... dealing with Source Use SourceSection to figure out (given a proc or statement source location) where to place a breakpoint. The list of prog Contexts returned by SourceSection is meaningful for prog, proc and statement sources. It will be ordered "most-recently-loaded first". Strictly speaking, a source can have multiple sections: one for each set of "SectionParams". Someday we'll accommodate such, but not this week. NOTE context = NIL oughta mean to find the section even though it's not loaded look thru all global frames in context for ones with the source name. Construct section for the first one found, thereafter check version stamp. For each found, cons onto contexts This context is from the given source, so we keep it We must check for multiple sections from the same source No symbols for the given source start GetModuleSTB here Formerly in AMModelBridgeImpl Formerly in AMModelLocationImpl was: progContexts _ SourceSection[SectionSource[section], RootContext[world]].contexts; could be (restrict to one gf): progContexts _ CONS[context, NIL]; want to find all gf's for the indicated section Here with epi, firstPC and all progContext loadings of the section in the specified world remote world case of ProgContextsForVersion Utilities [prog module bcd, CharIndex] => FGIndex (wrt prog module bcd) & epi Note, a loaded local bcd does not need release ÊÚ˜codešœ™Kšœ Ïmœ1™˜MKšœžœ%˜;Kšœžœ ˜KšœžœF˜`Kšœ žœ˜*Kšœžœ˜KšœžœY˜f——headšœž˜KšžœXžœžœ˜ôKšžœ8˜?Kšœžœ„˜ŒK˜—šœ™K˜Kšœžœ ˜2šœžœ˜2KšœV™VKšœ<™Kšžœ˜Kšœ˜—Kšžœžœ˜"—K˜—˜šžœ&˜(šžœ˜š œžœžœžœžœžœžœ˜[Kšœ0˜0Kšœ5˜5šžœ%žœ˜-Kšœ4™4Kšœ žœ˜#šžœ žœž˜Kšœ8™8šžœ0ž˜6KšžœN˜S——Kšœ˜K˜—K˜—Kšœ:˜:K˜ Kšœ žœ˜"šžœ!žœž˜.KšœA˜A—Kšžœ žœžœ˜1KšœF˜FKšœ˜—šžœ˜š œžœžœžœžœ˜>šžœ[žœžœ˜kšžœžœž˜Kšœ žœ&˜3šœF˜FKšžœN˜SK˜—Kšžœ˜—Kšœ žœ˜#K˜—K˜—K˜$K˜——K˜—Kšžœž˜—K˜—šœ˜KšžœK˜P—šœ ˜ KšžœO˜T—Kšžœžœ˜—šžœ žœžœ˜Kšœ™šœ˜šžœ"˜$Kšœ˜Kšœ:˜:——K˜—Kšœ˜—K˜šŸ œžœžœ<žœ&˜‚š Ÿ œžœ/žœžœžœ˜`šœ žœ˜˜>Kšœ ˜ K˜9—˜:Kšœžœ&˜.—K˜!K˜——˜Kšžœžœ˜!Kš œžœ žœžœžœ˜_Kšœ˜K˜—K˜K˜K˜—šŸ œžœžœ!žœ˜_Kšœ&˜&šžœ˜šžœ˜šœ<˜