DIRECTORY CCTypes USING[CCError, CCErrorCase], CirioButtons USING[ButtonSet, CreateButtonSet, CreateViewer, GetButtonSize, InstallLabelButton, InstallRule, InstallShowFrameButton, InstallSourceLanguageButton, InstallSourcePositionButton, KillButtonSet, MainActionProc, MoveToY, ViewerControl, InstallCommandButton, InstallWalkStackButton], CirioBackstop USING[Protect], CirioTypes USING[CompilerContext], Commander USING[CommandProc, Register], CommanderOps USING[ParseToList], Containers USING[ChildXBound, Create], Convert USING[Error, RopeFromCard], DisassembleSPARC, IO USING[PutF, PutF1, PutRope, rope, STREAM], LocalCirio USING[AddSearchDirectory, Connection, DoUnderMonitorLock, FlushUnknownFileCache, GetConnection, GetDummyStack, GetStackForSelf, ReleaseConnection, ListSearchDirectory, ClearSearchDirectory], PFS USING[AbsoluteName, PathFromRope, RopeFromPath], Process USING[Detach], Rope USING[Cat, ROPE], RuntimeError USING[Aborted, RegisterUncaughtSignalHandler, UCSProc], SourceFileOps, StackCirio USING[ClearAllBreakPoints, ClearBreakPoint, FormatPrompt, GetBannerForDotOofCurrentFrame, InterpretTextLine, ListBreakPoints, ResetStack, SetBreakPointAtAddress, SetBreakPointAtPosition, ShowQuickSummary, Stack], WindowSystemInterface USING[GetSelectionContents], ViewerClasses USING[Viewer]; PopUpDriver2: CEDAR MONITOR LOCKS d USING d: MyViewerData IMPORTS CCTypes, CirioButtons, CirioBackstop, Commander, CommanderOps, Convert, Containers, DisassembleSPARC, LocalCirio, IO, PFS, Process, Rope, RuntimeError, SourceFileOps, StackCirio, WindowSystemInterface = BEGIN ROPE: TYPE = Rope.ROPE; CC: TYPE = CirioTypes.CompilerContext; CCE: ERROR[case: CCTypes.CCErrorCase, msg: ROPE ¬ NIL] ¬ CCTypes.CCError; MyViewerData: TYPE = REF MyViewerDataBody; MyViewerDataBody: TYPE = MONITORED RECORD[ vc: CirioButtons.ViewerControl ¬ NIL, abortFlag: BOOLEAN ¬ TRUE, lineH: CARD, genButtonsY: INTEGER ¬ 0, genButtonsAreaH: INTEGER ¬ 0, genButtonsButtonSet: CirioButtons.ButtonSet, stack: StackCirio.Stack ¬ NIL, frameLabel: ViewerClasses.Viewer, stackButtonsY: INTEGER ¬ 0, stackButtonsAreaH: INTEGER ¬ 0, stackButtonSet: CirioButtons.ButtonSet, ruleY: INTEGER ¬ 0, scriptY: INTEGER ¬ 0, connection: LocalCirio.Connection, stopFlag: REF BOOLEAN ¬ NIL ]; InterpDriver: Commander.CommandProc = { dirs: LIST OF ROPE ¬ CommanderOps.ParseToList[cmd].list; absDirs: LIST OF ROPE ¬ NIL; FOR dirs ¬ dirs, dirs.rest WHILE dirs#NIL DO absDirs ¬ CONS[ PFS.RopeFromPath[ PFS.AbsoluteName[ PFS.PathFromRope[dirs.first]]], absDirs]; ENDLOOP; IF cmd.procData.clientData # $Registrationless THEN BEGIN result: REF ANY; msg: ROPE; [result, msg] ¬ RegisterCirio[cmd]; IF result = $Failure THEN RETURN[result, msg]; END; Process.Detach[FORK ForkedInterp[absDirs]]; }; ForkedInterp: PROC [searchDirs: LIST OF ROPE] = BEGIN d: MyViewerData ¬ BasicBuildViewer[]; Protected: PROC RETURNS [ROPE] ~ { d.connection ¬ LocalCirio.GetConnection[["PopUpDriver2", "BreakPointPopUp"], d.vc.out, searchDirs]; BEGIN ENABLE UNWIND => {LocalCirio.ReleaseConnection[d.connection, d.vc.out]}; localStack: StackCirio.Stack ¬ LocalCirio.GetStackForSelf[d.connection, d.vc.out]; d.stack ¬ LocalCirio.GetDummyStack[d.connection, d.vc.out]; IO.PutF1[d.vc.out, "Cirio Of %g\N", IO.rope[StackCirio.GetBannerForDotOofCurrentFrame[localStack, d.vc.out]]]; CirioButtons.MainActionProc[d.vc]; END; LocalCirio.ReleaseConnection[d.connection, d.vc.out]; RETURN [NIL]}; err: ROPE ¬ CirioBackstop.Protect[Protected, d.vc.out]; IF err#NIL THEN d.vc.out.PutF1["%g\n", [rope[err]] ]; END; UncaughtSignalPopUp: RuntimeError.UCSProc = BEGIN IF signal = LOOPHOLE[RuntimeError.Aborted] THEN BlowAwayThread[] ELSE BEGIN d: MyViewerData ¬ BasicBuildViewer[]; Protected: PROC RETURNS [ROPE] ~ { d.connection ¬ LocalCirio.GetConnection[["PopUpDriver2", "BreakPointPopUp"], d.vc.out]; BEGIN ENABLE UNWIND => {LocalCirio.ReleaseConnection[d.connection, d.vc.out]}; d.stack ¬ LocalCirio.GetStackForSelf[d.connection, d.vc.out]; InstallStackDebugButtons[d]; IO.PutF1[d.vc.out, "Cirio Of %g\N", IO.rope[StackCirio.GetBannerForDotOofCurrentFrame[d.stack, d.vc.out]]]; CirioButtons.MainActionProc[d.vc]; END; LocalCirio.ReleaseConnection[d.connection, d.vc.out]; RETURN [NIL]}; err: ROPE ¬ CirioBackstop.Protect[Protected, d.vc.out]; IF err#NIL THEN d.vc.out.PutF1["%g\n", [rope[err]] ]; IF d.abortFlag THEN ERROR ABORTED; END; END; BlowAwayThread: PROC ~ TRUSTED MACHINE CODE { "XR_Exit" }; BreakPointPopUp: PROCEDURE [key: CARD32] = BEGIN d: MyViewerData ¬ BasicBuildViewer[]; Protected: PROC RETURNS [ROPE] ~ { d.connection ¬ LocalCirio.GetConnection[["PopUpDriver2", "BreakPointPopUp"], d.vc.out]; BEGIN ENABLE UNWIND => {LocalCirio.ReleaseConnection[d.connection, d.vc.out]}; d.stack ¬ LocalCirio.GetStackForSelf[d.connection, d.vc.out]; InstallStackDebugButtons[d]; IO.PutF1[d.vc.out, "Cirio Of %g\N", IO.rope[StackCirio.GetBannerForDotOofCurrentFrame[d.stack, d.vc.out]]]; CirioButtons.MainActionProc[d.vc]; END; LocalCirio.ReleaseConnection[d.connection, d.vc.out]; RETURN [NIL]}; err: ROPE ¬ CirioBackstop.Protect[Protected, d.vc.out]; IF err#NIL THEN d.vc.out.PutF1["%g\n", [rope[err]] ]; IF d.abortFlag THEN ERROR ABORTED; END; BasicBuildViewer: PROC RETURNS[MyViewerData] = BEGIN d: MyViewerData ¬ NEW[MyViewerDataBody]; d.lineH ¬ CirioButtons.GetButtonSize["Sample"].h+1; d.genButtonsY ¬ 1; d.genButtonsAreaH ¬ d.lineH+1; d.stackButtonsY ¬ d.genButtonsY+d.genButtonsAreaH+1; d.stackButtonsAreaH ¬ d.lineH; d.ruleY ¬ d.stackButtonsY+d.stackButtonsAreaH+1; d.scriptY ¬ d.ruleY+1; d.vc ¬ CirioButtons.CreateViewer["Cirio", d.scriptY, FormatPrompt, InterpretTextLine, ShutDown, d]; d.stopFlag ¬ NEW[BOOLEAN¬FALSE]; InstallRules[d]; InstallGeneralButtons[d]; RETURN[d] END; FormatPrompt: PROC [counter: INT, clientData: REF ANY] RETURNS [ROPE] ~ { d: MyViewerData ¬ NARROW[clientData]; IF d.stack=NIL THEN RETURN ["can't set the language without a stack"]; RETURN StackCirio.FormatPrompt[d.stack, counter]}; InterpretTextLine: PROC[line: ROPE, reports: IO.STREAM, clientData: REF ANY] RETURNS[ROPE] = BEGIN d: MyViewerData ¬ NARROW[clientData]; result: ROPE; interpret: PROC = {result ¬ StackCirio.InterpretTextLine[d.stack, line, reports]}; IF d.stack = NIL THEN BEGIN IO.PutRope[reports, "can't interpret without a stack"]; RETURN[NIL] END ELSE {LocalCirio.DoUnderMonitorLock[d.connection, interpret]; RETURN[result]}; END; InstallRules: PROC[d: MyViewerData] = BEGIN ruleButtonSet: CirioButtons.ButtonSet ¬ CirioButtons.CreateButtonSet[d.vc.self, d.vc, 0, d.ruleY, 0, d.lineH, 0]; CirioButtons.MoveToY[ruleButtonSet, d.ruleY]; CirioButtons.InstallRule[ruleButtonSet]; END; InstallGeneralButtons: PROC[d: MyViewerData] = BEGIN genButtonsViewer: ViewerClasses.Viewer ¬ Containers.Create[ info: [parent: d.vc.self, border: FALSE, scrollable: FALSE, wx: 0, wy: d.genButtonsY, ww: d.vc.self.cw, wh: d.genButtonsAreaH] ]; bs: CirioButtons.ButtonSet ¬ d.genButtonsButtonSet ¬ CirioButtons.CreateButtonSet[genButtonsViewer, d.vc, 0, 0, 0, d.lineH, 0]; Containers.ChildXBound[d.vc.self, genButtonsViewer]; [] ¬ CirioButtons.InstallCommandButton[ bs: bs, name: "SetBreak", clientData1: d, choices: LIST[[$SetBreakAtPosition, "set breakpoint at selected source position"], [$SetBreakAtAddr, "set breakpoint at selected address"]], proc1: SetBreakAction1, proc2: SetBreakAction2]; [] ¬ CirioButtons.InstallCommandButton[ bs: bs, name: "ListBreaks", clientData1: d, proc2: ListBreaksAction]; [] ¬ CirioButtons.InstallCommandButton[ bs: bs, name: "ClearBreak(s)", clientData1: d, choices: LIST[[$ThisOne, "clear the active break"], [$All, "clear all breaks"], [$All, "clear all breaks"]], proc2: ClearBreakAction]; [] ¬ CirioButtons.InstallCommandButton[ bs: bs, name: "AddDir", clientData1: d, proc1: AddDirAction1, proc2: AddDirAction2]; [] ¬ CirioButtons.InstallCommandButton[ bs: bs, name: "ListDir", clientData1: d, proc2: ListDirAction]; [] ¬ CirioButtons.InstallCommandButton[ bs: bs, name: "FlushCache", clientData1: d, proc2: FlushCacheAction]; [] ¬ CirioButtons.InstallCommandButton[ bs: bs, name: "Stop", clientData1: d, proc1: StopAction1, proc2: StopAction2]; END; SetBreakAction1: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1: REF ANY] RETURNS [clientData2: REF ANY] ~ { SELECT key FROM $SetBreakAtPosition => { pos: SourceFileOps.Position ~ SourceFileOps.GetSelection[].pos; RETURN [NEW[SourceFileOps.Position ¬ pos]]}; $SetBreakAtAddr => { addrope: ROPE ~ WindowSystemInterface.GetSelectionContents[]; RETURN[addrope]}; ENDCASE => ERROR}; SetBreakAction2: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ~ NARROW[clientData1]; SELECT key FROM $SetBreakAtPosition => { pos: REF SourceFileOps.Position ~ NARROW[clientData2]; corresp: SourceFileOps.Position ¬ pos­; set: PROC = { corresp ¬ StackCirio.SetBreakPointAtPosition[d.stack, pos­, d.vc.out, FALSE] }; IO.PutRope[d.vc.out, "Setting break ... "]; LocalCirio.DoUnderMonitorLock[d.connection, set]; IF corresp # SourceFileOps.noPosition THEN SourceFileOps.OpenSource["break set", corresp, d.vc.out]; }; $SetBreakAtAddr => { addrope: ROPE ~ NARROW[clientData2]; addr: CARD; set: PROC = { StackCirio.SetBreakPointAtAddress[d.stack, addr, d.vc.out, FALSE]; }; TRUSTED {addr ¬ DisassembleSPARC.CardFromRope[addrope !Convert.Error => { d.vc.out.PutF["Syntax error (VAL[%g]) at %g --- selection should be an unsigned number in C or Mesa syntax", [integer[reason.ORD]], [integer[index]] ]; GOTO Bail}]}; d.vc.out.PutF1["Setting break at 0x%08x ...", [cardinal[addr]] ]; LocalCirio.DoUnderMonitorLock[d.connection, set]; EXITS Bail => NULL}; ENDCASE => ERROR; IO.PutRope[d.vc.out, " done.\n"]; END; ListBreaksAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; list: PROC = {StackCirio.ListBreakPoints[d.stack, d.vc.out]}; IO.PutRope[d.vc.out, "Listing breaks ... "]; LocalCirio.DoUnderMonitorLock[d.connection, list]; IO.PutRope[d.vc.out, " done.\n"]; END; ClearBreakAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; clearAll: BOOLEAN ¬ key = $All; IF clearAll THEN BEGIN clear: PROC = {StackCirio.ClearAllBreakPoints[d.stack, d.vc.out]}; IO.PutRope[d.vc.out, "Clearing all breaks ... "]; LocalCirio.DoUnderMonitorLock[d.connection, clear]; END ELSE BEGIN clear: PROC = {StackCirio.ClearBreakPoint[d.stack, d.vc.out]}; IO.PutRope[d.vc.out, "Clearing break ... "]; LocalCirio.DoUnderMonitorLock[d.connection, clear]; END; IO.PutRope[d.vc.out, " done.\n"]; END; AddDirAction1: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1: REF ANY] RETURNS[clientData2: REF ANY] = BEGIN rope: ROPE ¬ WindowSystemInterface.GetSelectionContents[]; IF rope = NIL THEN RETURN[NIL] ELSE RETURN[NEW[RopeHolder ¬ rope]]; END; RopeHolder: TYPE = ROPE; AddDirAction2: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; ropeHolder: REF RopeHolder ¬ NARROW[clientData2]; dirPath: ROPE ¬ IF ropeHolder = NIL THEN NIL ELSE ropeHolder­; IO.PutRope[d.vc.out, "Adding search directory ... "]; LocalCirio.AddSearchDirectory[d.connection, dirPath, d.vc.out]; IO.PutRope[d.vc.out, "Added.\n"]; END; ListDirAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; IO.PutRope[d.vc.out, "Listing directories ... "]; LocalCirio.ListSearchDirectory[d.connection, d.vc.out]; IO.PutRope[d.vc.out, " done.\n"]; END; ClearDirAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; LocalCirio.ClearSearchDirectory[d.connection, d.vc.out]; END; FlushCacheAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; IO.PutRope[d.vc.out, "Flushing unknown file cache ..."]; LocalCirio.FlushUnknownFileCache[d.connection, d.vc.out]; IO.PutRope[d.vc.out, " done flushing.\n"]; END; StopAction1: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1: REF ANY] RETURNS[clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; d.stopFlag­ ¬ TRUE; RETURN[NIL] END; StopAction2: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN END; RemoveGeneralButtons: PROC[d: MyViewerData] = BEGIN d.genButtonsButtonSet ¬ CirioButtons.KillButtonSet[d.genButtonsButtonSet, FALSE]; END; InstallStackDebugButtons: PROC[d: MyViewerData] = BEGIN subViewer: ViewerClasses.Viewer ¬ Containers.Create[ info: [parent: d.vc.self, border: FALSE, scrollable: FALSE, wx: 0, wy: d.stackButtonsY, ww: d.vc.self.cw, wh: d.stackButtonsAreaH] ]; subBs: CirioButtons.ButtonSet ¬ CirioButtons.CreateButtonSet[subViewer, d.vc, 0, 0, 0, d.lineH, 0]; Containers.ChildXBound[d.vc.self, subViewer]; d.frameLabel ¬ CirioButtons.InstallLabelButton[subBs, Rope.Cat["frame: ", Convert.RopeFromCard[StackCirio.ResetStack[d.stack, d.vc.out]], " "]]; [] ¬ CirioButtons.InstallCommandButton[ bs: subBs, name: "Summary", clientData1: d, choices: LIST[[$FullSummary, "full summary"], [$ShortSummary, "short summary"]], proc2: SummaryAction]; CirioButtons.InstallWalkStackButton[subBs, d.stack, NIL, d.frameLabel]; CirioButtons.InstallShowFrameButton[subBs, d.stack]; CirioButtons.InstallSourcePositionButton[subBs, d.stack]; [] ¬ CirioButtons.InstallCommandButton[ bs: subBs, name: "Proceed", clientData1: d, proc2: ProceedAction]; [] ¬ CirioButtons.InstallCommandButton[ bs: subBs, name: "Abort", clientData1: d, proc2: AbortAction]; CirioButtons.InstallSourceLanguageButton[subBs, d.stack]; d.stackButtonSet ¬ subBs; END; SummaryAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; show: PROC = {StackCirio.ShowQuickSummary[d.stack, d.stopFlag, d.vc.out, key=$FullSummary]}; d.stopFlag­ ¬ FALSE; LocalCirio.DoUnderMonitorLock[d.connection, show]; END; ProceedAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; d.stopFlag­ ¬ FALSE; vc.destroyStarted ¬ vc.okToDestroy ¬ TRUE; -- ugh: there should be documentation in the interface that this will indeed initiate the shutdown mechanism IO.PutRope[vc.out, "proceed\N"]; d.abortFlag ¬ FALSE; END; AbortAction: PROC[button: ViewerClasses.Viewer, vc: CirioButtons.ViewerControl, key, clientData1, clientData2: REF ANY] = BEGIN d: MyViewerData ¬ NARROW[clientData1]; d.stopFlag­ ¬ FALSE; vc.destroyStarted ¬ vc.okToDestroy ¬ TRUE; -- ugh: there should be documentation in the interface that this will indeed initiate the shutdown mechanism IO.PutRope[vc.out, "abort\N"]; d.abortFlag ¬ TRUE; -- actually, this flag should already be true END; RemoveStackDebugButtons: PROC[d: MyViewerData] = BEGIN d.stackButtonSet ¬ CirioButtons.KillButtonSet[d.stackButtonSet, FALSE]; d.frameLabel ¬ NIL; END; ShutDown: PROC[clientData: REF ANY, reports: IO.STREAM] = BEGIN d: MyViewerData ¬ NARROW[clientData]; RemoveGeneralButtons[d]; RemoveStackDebugButtons[d]; END; forLockingOriginalUCS: MyViewerData ¬ NEW[MyViewerDataBody]; originalUCS: RuntimeError.UCSProc ¬ NIL; RegisterCirio: Commander.CommandProc = BEGIN Inner: PROC[d: MyViewerData] = BEGIN IF originalUCS = NIL THEN originalUCS ¬ RuntimeError.RegisterUncaughtSignalHandler[UncaughtSignalPopUp]; END; Inner[forLockingOriginalUCS]; END; DeRegisterCirio: Commander.CommandProc = BEGIN Inner: PROC[d: MyViewerData] = BEGIN IF originalUCS # NIL THEN BEGIN [] ¬ RuntimeError.RegisterUncaughtSignalHandler[originalUCS]; originalUCS ¬ NIL; END; END; Inner[forLockingOriginalUCS]; END; Commander.Register["Interpreter", InterpDriver, "* --- create a local debugger tool"]; Commander.Register["RegistrationlessInterpreter", InterpDriver, "* --- doesn't include RegisterCirio", $Registrationless]; Commander.Register["RegisterCirio", RegisterCirio, " --- to catch uncaught errors"]; Commander.Register["CirioLocal", RegisterCirio, "= RegisterCirio"]; Commander.Register["DeRegisterCirio", DeRegisterCirio]; END..  PopUpDriver2.mesa Copyright Σ 1992 by Xerox Corporation. All rights reserved. Sturgis, March 30, 1990 2:02 pm PST Linda Howe January 8, 1990 3:14:40 pm PST Spreitze, July 24, 1992 6:26 pm PDT Coolidge, June 29, 1990 12:27 pm PDT Chauser, August 27, 1990 10:34 am PDT Laurie Horton, May 22, 1991 5:17 pm PDT Udagawa, February 13, 1991 7:38 pm PST Willie-s, July 27, 1992 5:59 pm PDT Viewer related code Stolen from RemoteDriver2.mesa lets be sure Cirio is registered as the local debugger open a block to so that unwind catches can close the connection PopUp will be called by Carl (and friends) when the debuggee wants to contact the debugger, i.e. when a breakpoint is reached. [msg: WORD, signal: SIGNAL ANY RETURNS ANY, frame: POINTER] (except that at January 9, 1990 11:19:53 am PST the implementation calls with frame = NIL) I belive the following test will eventually go away, when Carl arranges to turn ABORTED into a proper UNWIND. But for the moment, we have to blow the thread away when we are called for ABORTED. This logic is adapted from /pcedar2.0/Debugger/Debugger.mesa. open a block to so that unwind catches can close the connection The address of this procedure is supplied to the breakpoint mechanism. Same world break points will call this procedure. The type of this procedure should match the type of CirioThingsImpl.CallDebugger. The behavior should mimick that of CirioThingsImpl.CallDebugger. open a block to so that unwind catches can close the connection Interpret We do not pass a stack to CreateViewer, because the remote tool will be changing stacks from time to time. So we use a call back for interpret line. Rules because we throw this away, no one will do a KillButtonSet, hence it is alright to use d.vc.self as the container. General Buttons [] _ CirioButtons.InstallCommandButton[ bs: bs, name: "ClearDir", clientData1: d, proc2: ClearDirAction]; just a no op to keep CirioButtons happy. Stack debug buttons misc Registration as uncaught signal handler and breakpoint handler Main code Κs–"cedarcode" style•NewlineDelimiter ™codešœ™Kšœ Οeœ1™Kšžœ*˜,Kšœ3˜3Kšžœ˜—Kšžœ˜!Kšžœ˜K˜—šŸ œžœQžœžœžœžœžœ˜ŒKšž˜Kšœžœ0˜:Kš žœžœžœžœžœžœ˜$Kšžœžœ˜Kšžœ˜—K˜Kšœ žœžœ˜K˜šŸ œžœ^žœžœ˜{Kšž˜Kšœžœ˜&Kšœ žœžœ˜1Kš œ žœžœžœžœžœžœ ˜>K˜Kšžœ3˜5Kšœ?˜?Kšžœ˜!Kšžœ˜—K˜šŸ œžœ^žœžœ˜{Kšž˜Kšœžœ˜&Kšžœ/˜1Kšœ7˜7Kšžœ˜!Kšžœ˜K˜—šŸœžœ^žœžœ˜|Kšž˜Kšœžœ˜&Kšœ8˜8Kšžœ˜K˜—šŸœžœ^žœžœ˜~Kšž˜Kšœžœ˜&Kšžœ6˜8Kšœ9˜9Kšžœ(˜*Kšžœ˜K˜—šŸ œžœQžœžœžœžœžœ˜ŠKšž˜Kšœžœ˜&Kšœžœ˜Kšžœžœ˜ Kšžœ˜—K˜šŸ œžœ^žœžœ˜yKšž˜K™(Kšžœ˜K˜—šŸœžœ˜-Kšž˜KšœJžœ˜QKšžœ˜K˜—K™—K™™K˜šŸœžœ˜1Kšž˜˜4Kšœ"žœžœK˜…—K˜cK˜Kšœ.˜.K˜˜˜'Kšœ ˜ Kšœ˜Kšœ˜Kšœ žœC˜PKšœ˜—Kšœ4žœ˜GKšœ4˜4Kšœ9˜9˜'Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜—˜'Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜—Kšœ9˜9K˜Kšžœ˜—K˜šŸ œžœ^žœžœ˜{Kšž˜Kšœžœ˜&KšœžœR˜\Kšœžœ˜Kšœ2˜2Kšžœ˜—K˜šŸ œžœ^žœžœ˜{Kšž˜Kšœžœ˜&Kšœžœ˜Kšœ%žœΟcl˜—Kšžœ˜ Kšœžœ˜Kšžœ˜—K˜šŸ œžœ^žœžœ˜yšž˜Kšœžœ˜&Kšœžœ˜Kšœ%žœ l˜—Kšžœ˜Kšœžœ -˜AKšžœ˜—K˜—K˜šŸœžœ˜0Kšž˜Kšœ@žœ˜GKšœžœ˜Kšžœ˜—K˜—™K™—˜š Ÿœžœ žœžœ žœžœ˜9Kšž˜Kšœžœ ˜%Kšœ˜K˜Kšžœ˜——K™K˜K˜™>K˜Kšœ&žœ˜