DIRECTORY Basics USING [BITAND, BITSHIFT, HighByte, LongNumber, LowByte, LowHalf], IO USING [card, int, PutF, STREAM], Process USING [MsecToTicks, SetTimeout], PupDefs USING [GetFreePupBuffer, MsToTocks, PupAddressLookup, PupAddressToRope, PupBuffer, PupPackageMake, PupPackageDestroy, PupRouterSendThis, PupSocket, PupSocketID, PupSocketDestroy, PupSocketMake, ReturnFreePupBuffer, SetPupContentsWords, UniqueLocalPupAddress], PupTypes USING [fillInHostID, fillInNetID, fillInPupAddress, Pair, PupAddress, PupType], PupStream USING [GetPupAddress, PupNameTrouble], Rope USING [ROPE], TeleLoad; TeleLoadImpl: MONITOR IMPORTS Basics, IO, Process, PupDefs, PupStream EXPORTS TeleLoad = BEGIN OPEN TeleLoad; BitOp: TYPE = PROC [a, b: UNSPECIFIED] RETURNS [UNSPECIFIED]; And: BitOp = INLINE { RETURN[Basics.BITAND[a,b]]; }; Shift: BitOp = INLINE { RETURN[Basics.BITSHIFT[a,b]]; }; locMaxByte: PUBLIC NAT _ 150; kingWaitTime: INT _ 200; -- Packet exchange reply wait time NameToAddress: PUBLIC SAFE PROC [name: Rope.ROPE] RETURNS [address: PupTypes.PupAddress, ok: BOOL _ TRUE] = TRUSTED { address _ PupStream.GetPupAddress[teleSwatSocket, name ! PupStream.PupNameTrouble => {ok _ FALSE; CONTINUE; }]; }; AddressToName: PUBLIC SAFE PROC [address: PupTypes.PupAddress] RETURNS [nameRope, addressRope: Rope.ROPE] = TRUSTED { nameRope _ PupDefs.PupAddressLookup[address]; addressRope _ PupDefs.PupAddressToRope[address]; }; Start: PUBLIC SAFE PROC [host: Rope.ROPE, log: IO.STREAM] RETURNS [h: Handle] = TRUSTED { sendHim: PupTypes.PupAddress; allok: BOOL; [sendHim, allok] _ NameToAddress[host]; sendHim.socket _ TeleLoad.teleSwatSocket; IF NOT allok THEN RETURN[NIL]; h _ NEW[TLObject _ [ host: host, address: sendHim, cacheSize: locMaxByte, log: log]]; RETURN[h]; }; Stop: PUBLIC SAFE PROC [h: Handle] = TRUSTED { IF h=NIL THEN RETURN; h.host _ NIL; h.log _ NIL; }; Store: PUBLIC ENTRY TeleLoadProc = TRUSTED { ENABLE UNWIND => NULL; [ok, attempts] _ GStore[h: h, requestcb: cb, type: coreStoreRequest, tries: tries]; }; Fetch: PUBLIC ENTRY TeleLoadProc = TRUSTED { ENABLE UNWIND => NULL; [ok, attempts] _ GFetch[h: h, requestcb: cb, type: coreFetchRequest, tries: tries]; }; SlaveStore: PUBLIC ENTRY TeleLoadProc = TRUSTED { ENABLE UNWIND => NULL; [ok, attempts] _ GStore[h: h, requestcb: cb, type: slaveStoreRequest, tries: tries]; }; SlaveFetch: PUBLIC ENTRY TeleLoadProc = TRUSTED { ENABLE UNWIND => NULL; [ok, attempts] _ GFetch[h: h, requestcb: cb, type: slaveFetchRequest, tries: tries]; }; Call: PUBLIC ENTRY TeleLoadProc = TRUSTED { ENABLE UNWIND => NULL; [ok, attempts] _ GExchange[h: h, requestcb: cb, type: callRequest, tries: tries]; }; Go: PUBLIC ENTRY TeleLoadProc = TRUSTED { ENABLE UNWIND => NULL; [ok, attempts] _ GStore[h: h, requestcb: cb, type: goRequest, tries: 1]; }; GoFromBreak: PUBLIC ENTRY TeleLoadProc = TRUSTED { ENABLE UNWIND => NULL; [ok, attempts] _ GStore[h: h, requestcb: cb, type: goFromBreakRequest, tries: 1]; }; SingleStep: PUBLIC ENTRY TeleLoadProc = TRUSTED { ENABLE UNWIND => NULL; [ok, attempts] _ GStore[h: h, requestcb: cb, type: singleStepRequest, tries: 1]; }; FetchState: PUBLIC ENTRY TeleLoadProc = TRUSTED { ENABLE UNWIND => NULL; [ok, attempts] _ GFetch[h: h, requestcb: cb, type: stateFetchRequest, tries: tries]; }; GoToDebugger: PUBLIC ENTRY TeleLoadProc = TRUSTED { ENABLE UNWIND => NULL; b: PupDefs.PupBuffer _ PupDefs.GetFreePupBuffer[]; replycb: CorePkt; replycb _ LOOPHOLE[@b.pupBody]; replycb.advice _ cb.advice; replycb.address _ cb.address; replycb.count _ cb.count; FOR j: CARDINAL IN [0..cb.count) DO replycb.data[j] _ cb.data[j]; ENDLOOP; PupDefs.SetPupContentsWords[b, SIZE[CorePktObject]+((cb.count+1)/2)]; b.pupID _ NewPupID[]; b.pupType _ debugRequest; KingSend[b, h.address]; }; eventServerUseCount: INT _ 0; eventServerActive: BOOL _ FALSE; eventServerProcess: PROCESS; eventServerPollingInterval: NAT _ 500; eventSocket: PupDefs.PupSocket _ NIL; eventClientProcedure: EventProc; eventClientData: REF ANY; StartEventServer: PUBLIC ENTRY SAFE PROC [proc: EventProc, clientData: REF ANY] = TRUSTED { eventServerUseCount _ eventServerUseCount + 1; IF eventServerUseCount > 1 THEN RETURN; IF eventServerActive THEN RETURN; eventClientProcedure _ proc; eventClientData _ clientData; eventServerActive _ TRUE; eventServerProcess _ FORK TeleloadEventServer[]; }; StopEventServer: PUBLIC ENTRY SAFE PROC = TRUSTED { eventServerUseCount _ MAX[0, eventServerUseCount - 1]; IF eventServerUseCount > 0 THEN RETURN; eventServerActive _ FALSE; JOIN eventServerProcess; }; TeleloadEventServer: PROC = { b: PupDefs.PupBuffer _ NIL; er: EventRecord; cp: CorePkt; PupDefs.PupPackageMake[]; eventSocket _ PupDefs.PupSocketMake[local: teleSwatSocket, remote: [PupTypes.fillInNetID, PupTypes.fillInHostID, teleSwatSocket], ticks: PupDefs.MsToTocks[eventServerPollingInterval]]; DO b _ eventSocket.get[]; IF b # NIL THEN { cp _ LOOPHOLE[@b.pupBody]; er _ LOOPHOLE[@cp^.data]; eventClientProcedure[b.source, er^, eventClientData]; PupDefs.ReturnFreePupBuffer[b]; }; IF NOT eventServerActive THEN EXIT; ENDLOOP; eventClientData _ NIL; eventClientProcedure _ NIL; PupDefs.PupSocketDestroy[eventSocket]; PupDefs.PupPackageDestroy[]; }; GStore: INTERNAL PROC [h: Handle, requestcb: CoreBlock, type: PupTypes.PupType, tries: NAT] RETURNS [a: BOOL _ TRUE, actualAttempts: NAT] = { b: PupDefs.PupBuffer _ NIL; replycb: CorePkt; IF h=NIL THEN RETURN[FALSE, 0]; FOR actualAttempts IN [1..tries] DO id: PupTypes.Pair _ NewPupID[]; IF b#NIL THEN PupDefs.ReturnFreePupBuffer[b]; b _ PupDefs.GetFreePupBuffer[]; replycb _ LOOPHOLE[@b.pupBody]; replycb.advice _ requestcb.advice; replycb.address _ requestcb.address; replycb.count _ requestcb.count; FOR j: CARDINAL IN [0..requestcb.count) DO replycb.data[j] _ requestcb.data[j]; ENDLOOP; PupDefs.SetPupContentsWords[b, SIZE[CorePktObject]+((requestcb.count+1)/2)]; b _ Exchange[h, b, type, id]; IF b=NIL THEN LOOP; replycb _ LOOPHOLE[@b.pupBody]; IF NOT Check[requestcb, replycb] THEN LOOP; requestcb.advice _ replycb.advice; EXIT; REPEAT FINISHED => a _ FALSE; ENDLOOP; IF b#NIL THEN PupDefs.ReturnFreePupBuffer[b]; }; GFetch: INTERNAL PROC [h: Handle, requestcb: CoreBlock, type: PupTypes.PupType, tries: CARDINAL] RETURNS [a: BOOL _ TRUE, actualAttempts: NAT] = { b: PupDefs.PupBuffer _ NIL; id: PupTypes.Pair _ NewPupID[]; replycb: CorePkt; IF h=NIL THEN RETURN[FALSE, 0]; FOR actualAttempts IN [1..tries] DO IF b#NIL THEN PupDefs.ReturnFreePupBuffer[b]; b _ PupDefs.GetFreePupBuffer[]; replycb _ LOOPHOLE[@b.pupBody]; replycb.advice _ requestcb.advice; replycb.address _ requestcb.address; replycb.count _ requestcb.count; PupDefs.SetPupContentsWords[b, SIZE[CorePktObject]]; b _ Exchange[h, b, type, id]; IF b=NIL THEN LOOP; replycb _ LOOPHOLE[@b.pupBody]; IF replycb.address # requestcb.address THEN LOOP; IF replycb.count # requestcb.count THEN LOOP; FOR j: CARDINAL IN [0..requestcb.count) DO requestcb.data[j] _ replycb.data[j]; ENDLOOP; requestcb.advice _ replycb.advice; EXIT; REPEAT FINISHED => a _ FALSE; ENDLOOP; IF b#NIL THEN PupDefs.ReturnFreePupBuffer[b]; }; GExchange: INTERNAL PROC [h: Handle, requestcb: CoreBlock, type: PupTypes.PupType, tries: CARDINAL] RETURNS [a: BOOL _ TRUE, actualAttempts: NAT] = { b: PupDefs.PupBuffer _ NIL; id: PupTypes.Pair _ NewPupID[]; replycb: CorePkt; IF h=NIL THEN RETURN[FALSE, 0]; FOR actualAttempts IN [1..tries] DO IF b#NIL THEN PupDefs.ReturnFreePupBuffer[b]; b _ PupDefs.GetFreePupBuffer[]; replycb _ LOOPHOLE[@b.pupBody]; replycb.advice _ requestcb.advice; replycb.address _ requestcb.address; replycb.count _ requestcb.count; FOR j: CARDINAL IN [0..requestcb.count) DO replycb.data[j] _ requestcb.data[j]; ENDLOOP; PupDefs.SetPupContentsWords[b, SIZE[CorePktObject]+((requestcb.count+1)/2)]; b.pupID _ id; b _ Exchange[h, b, type, id]; IF b=NIL THEN LOOP; replycb _ LOOPHOLE[@b.pupBody]; IF replycb.address # requestcb.address THEN LOOP; IF replycb.count # requestcb.count THEN LOOP; FOR j: CARDINAL IN [0..requestcb.count) DO requestcb.data[j] _ replycb.data[j]; ENDLOOP; requestcb.advice _ replycb.advice; EXIT; REPEAT FINISHED => a _ FALSE; ENDLOOP; IF b#NIL THEN PupDefs.ReturnFreePupBuffer[b]; }; Exchange: INTERNAL PROC [h: Handle, request: PupDefs.PupBuffer, type: PupTypes.PupType, id: PupTypes.Pair] RETURNS[PupDefs.PupBuffer] = { reply: PupDefs.PupBuffer _ NIL; request.pupID _ id; request.pupType _ type; KingSend[request, h.address]; DO IF reply#NIL THEN PupDefs.ReturnFreePupBuffer[reply]; reply _ KingGet[h.address]; IF reply = NIL THEN RETURN[NIL]; IF reply.pupType # LOOPHOLE[LOOPHOLE[type, CARDINAL]+1] THEN LOOP; IF reply.pupID # id THEN LOOP; RETURN[reply]; ENDLOOP; }; Check: INTERNAL PROC [a: CoreBlock, b: CorePkt] RETURNS [BOOL] = { IF a.address # b.address THEN RETURN[FALSE]; IF a.count # b.count THEN RETURN[FALSE]; FOR i: CARDINAL IN [0..a.count) DO IF a.data[i] # b.data[i] THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; }; Failed: PUBLIC ERROR = CODE; GetCoreBlock: PUBLIC ENTRY SAFE PROC[h: Handle, addr: CoreAddress, count: CARDINAL, addressSpace: AddressSpace _ main] RETURNS [cb: CoreBlock] = TRUSTED { ENABLE UNWIND => NULL; RETURN [GetCoreBlockInternal[h, addr, count, addressSpace]]; }; GetCoreBlockInternal: INTERNAL PROC[h: Handle, addr: CoreAddress, count: CARDINAL, addressSpace: AddressSpace] RETURNS [cb: CoreBlock] = { ok: BOOLEAN; tries: NAT; cb _ NEW[CoreBlockObject[count]]; cb.address _ addr; cb.advice _ [FALSE, FALSE, 0]; [ok, tries] _ GFetch[h, cb, IF addressSpace = main THEN coreFetchRequest ELSE slaveFetchRequest, 5]; IF NOT ok THEN { IF h.log # NIL THEN h.log.PutF[" ... %d byte read from %08x failed, (%d tries).\n", IO.card[count], IO.card[cb.address], IO.int[tries]]; cb_NIL; ERROR Failed; }; }; ReadWord: PUBLIC ENTRY SAFE PROC [h: Handle, addr: CoreAddress, addressSpace: AddressSpace _ main] RETURNS [v: CARDINAL] = TRUSTED { ENABLE UNWIND => NULL; RETURN [ReadInternal[h, addr, addressSpace] + (Shift[ReadInternal[h, addr+1, addressSpace], 8])]; }; Read: PUBLIC ENTRY SAFE PROC [h: Handle, addr: CoreAddress, addressSpace: AddressSpace _ main] RETURNS [v: CARDINAL] = TRUSTED { ENABLE UNWIND => NULL; RETURN[ReadInternal[h, addr, addressSpace]]; }; ReadInternal: INTERNAL PROC [h: Handle, addr: CoreAddress, addressSpace: AddressSpace] RETURNS [v: CARDINAL] = { temp: Basics.LongNumber; blockAddr: CoreAddress; count: NAT _ h.cacheSize; IF h.cacheSize = 0 THEN h.cacheSize _ locMaxByte; h.cacheSize _ MAX[1, MIN[h.cacheSize, locMaxByte]]; temp.lc _ addr; temp.lc _ temp.lc - (temp.lc MOD h.cacheSize); blockAddr _ temp.lc; IF h.cacheCB = NIL THEN { h.cacheCB _ GetCoreBlockInternal[h: h, addr: blockAddr, count: h.cacheSize, addressSpace: addressSpace]; h.addressSpace _ addressSpace; }; IF h.cacheCB.address # blockAddr OR h.addressSpace # addressSpace THEN { FlushWritesInternal[h]; h.cacheCB _ GetCoreBlockInternal[h: h, addr: blockAddr, count: h.cacheSize, addressSpace: addressSpace]; h.addressSpace _ addressSpace; }; RETURN[h.cacheCB.data[Basics.LowHalf[addr-blockAddr]]]; }; WriteWord: PUBLIC ENTRY SAFE PROC [h: Handle, addr: CoreAddress, value: CARDINAL, addressSpace: AddressSpace _ main] = TRUSTED { ENABLE UNWIND => NULL; WriteInternal[h, addr, And[value, 377B], addressSpace]; WriteInternal[h, addr + 1, Shift[value, -8], addressSpace]; }; Write: PUBLIC ENTRY SAFE PROC [h: Handle, addr: CoreAddress, value: CARDINAL, addressSpace: AddressSpace _ main] = TRUSTED { ENABLE UNWIND => NULL; WriteInternal[h, addr, value, addressSpace]; }; WriteInternal: INTERNAL PROC [h: Handle, addr: CoreAddress, value: CARDINAL, addressSpace: AddressSpace] = { temp: Basics.LongNumber; blockAddr: CoreAddress; [] _ ReadInternal[h, addr, addressSpace]; temp.lc _ addr; temp.lc _ temp.lc - (temp.lc MOD h.cacheSize); blockAddr _ temp.lc; h.cacheCB.data[Basics.LowHalf[addr-blockAddr]] _ value; h.dirty _ TRUE; }; FlushWrites: PUBLIC ENTRY SAFE PROC [h: Handle] = TRUSTED { ENABLE UNWIND => NULL; FlushWritesInternal[h]; }; FlushWritesInternal: INTERNAL PROC [h: Handle] = { IF h.dirty THEN { ok: BOOL; tries: NAT; [ok, tries] _ GStore[h, h.cacheCB, IF h.addressSpace = main THEN coreStoreRequest ELSE slaveStoreRequest, 5]; h.dirty _ FALSE; IF NOT ok THEN { IF h.log # NIL THEN h.log.PutF[" Write to %08x failed (%d tries), cache reset anyway.\n", IO.card[h.cacheCB.address], IO.int[tries]]; ERROR Failed; }; }; }; ResetCache: PUBLIC ENTRY SAFE PROC [h: Handle] = TRUSTED { ENABLE UNWIND => NULL; FlushWritesInternal[h]; h.cacheCB _ NIL; }; SetCacheSize: PUBLIC ENTRY SAFE PROC [h: Handle, bytes: NAT] = TRUSTED { ENABLE UNWIND => NULL; FlushWritesInternal[h]; h.cacheCB _ NIL; h.cacheSize _ IF bytes = 0 THEN locMaxByte ELSE MAX[1, MIN[locMaxByte, bytes]]; }; Swab: PUBLIC SAFE PROC [a: CARDINAL] RETURNS [b: CARDINAL] = TRUSTED { b _ Basics.BITSHIFT[Basics.LowByte[a], 8] + Basics.HighByte[a]; }; SwabState: PUBLIC SAFE PROC [state: State8086Object] RETURNS [State8086Object] = TRUSTED { FOR i: Registers8086 IN [AX..FL] DO state.Regs[i] _ Swab[state.Regs[i]]; ENDLOOP; RETURN[state]; }; SwabEvent: PUBLIC SAFE PROC [state: EventRecordObject] RETURNS [EventRecordObject] = TRUSTED { state.regs _ SwabState[state.regs]; state.reason _ Swab[state.reason]; state.clockLow _ Swab[state.clockLow]; state.clockHigh _ Swab[state.clockHigh]; state.bootSwitches _ Swab[state.bootSwitches]; state.advice _ Swab[state.advice]; state.monRelays _ Swab[state.monRelays]; state.tlNet _ Swab[state.tlNet]; state.tlHost _ Swab[state.tlHost]; state.tlImHost _ Swab[state.tlImHost]; state.localNet _ Swab[state.localNet]; RETURN[state]; }; kingUseCount: INT _ 0; kingWait: CONDITION; lastPacket: PupDefs.PupBuffer; pleaseStopKing: BOOL _ TRUE; myID: PupTypes.Pair _ [1711, 1]; king: PupDefs.PupSocket; kingProcess: PROCESS; KingGet: INTERNAL PROC [from: PupTypes.PupAddress] RETURNS [PupDefs.PupBuffer] = { b: PupDefs.PupBuffer; IF lastPacket # NIL AND lastPacket.source.net = from.net AND lastPacket.source.host = from.host THEN { b _ lastPacket; lastPacket _ NIL; RETURN[b]; }; Process.SetTimeout[condition: @kingWait, ticks: Process.MsecToTicks[kingWaitTime]]; WAIT kingWait; IF lastPacket # NIL AND lastPacket.source.net = from.net AND lastPacket.source.host = from.host THEN { b _ lastPacket; lastPacket _ NIL; RETURN[b]; }; RETURN[NIL]; }; NewPupID: INTERNAL PROC RETURNS [PupTypes.Pair] = { myID.b _ myID.b + 1; RETURN [myID]; }; KingSend: INTERNAL PROC [b: PupDefs.PupBuffer _ NIL, to: PupTypes.PupAddress] = { IF king = NIL THEN { PupDefs.ReturnFreePupBuffer[b]; RETURN; }; b.dest _ to; b.source _ king.getLocalAddress[]; PupDefs.PupRouterSendThis[b]; }; KingDaemon: PROC = { us: PupTypes.PupAddress _ PupDefs.UniqueLocalPupAddress[PupTypes.fillInPupAddress]; b: PupDefs.PupBuffer; SetKingPacket: ENTRY PROC [b: PupDefs.PupBuffer] = { IF lastPacket # NIL THEN PupDefs.ReturnFreePupBuffer[lastPacket]; lastPacket _ b; NOTIFY kingWait; }; king _ PupDefs.PupSocketMake[local: us.socket, remote: us, ticks: PupDefs.MsToTocks[500]]; DO IF pleaseStopKing THEN EXIT; b _ king.get[]; IF b # NIL THEN SetKingPacket[b]; ENDLOOP; PupDefs.PupSocketDestroy[king]; king _ NIL; SetKingPacket[NIL]; }; StartKing: PUBLIC ENTRY SAFE PROC = TRUSTED { kingUseCount _ kingUseCount + 1; IF kingUseCount > 1 THEN RETURN; IF NOT pleaseStopKing THEN RETURN; pleaseStopKing _ FALSE; kingProcess _ FORK KingDaemon[]; }; StopKing: PUBLIC SAFE PROC = TRUSTED { giveUp: BOOL _ FALSE; GetLock: ENTRY PROC = { kingUseCount _ MAX[0, kingUseCount - 1]; IF kingUseCount > 0 THEN giveUp _ TRUE; IF pleaseStopKing THEN giveUp _ TRUE; pleaseStopKing _ TRUE; }; GetLock[]; IF NOT giveUp THEN JOIN kingProcess; }; StopHimProbing: PUBLIC ENTRY SAFE PROC [h: Handle, setPointers: BOOL] = TRUSTED { replycb: CorePkt; b: PupDefs.PupBuffer _ NIL; IF h = NIL THEN RETURN; b _ PupDefs.GetFreePupBuffer[]; replycb _ LOOPHOLE[@b.pupBody]; replycb.advice _ [setPointers, FALSE, 0]; replycb.address _ 0; replycb.count _ 10; PupDefs.SetPupContentsWords[b, SIZE[CorePktObject]]; b.pupID _ NewPupID[]; b.pupType _ coreFetchRequest; KingSend[b, h.address]; }; GetEventData: PUBLIC SAFE PROC [h: Handle, setPointers: BOOL] RETURNS [event: EventRecordObject, ok: BOOL] = TRUSTED { deleteOnReturn: BOOL _ FALSE; er: EventRecord; cb: CoreBlock; IF h = NIL THEN RETURN [event: event, ok: FALSE]; cb _ NEW[CoreBlockObject[SIZE[EventRecordObject] * 2]]; cb.address _ 0DA00H; cb.advice _ [setPointers, FALSE, 0]; ok _ Fetch[h, cb, 1].ok; IF NOT ok THEN RETURN [event: event, ok: FALSE]; er _ LOOPHOLE[BASE[DESCRIPTOR[cb.data]], EventRecord]; event _ SwabEvent[er^]; RETURN [event: event, ok: TRUE]; }; END. December 30, 1981 3:14 PM, Stewart, created from AudioSocket.mesa December 22, 1982 3:17 pm, Stewart, modifications to TeleLoad April 25, 1983 11:22 am, LCS, new Event interface and locMaxByte May 28, 1983 5:47 pm, LCS, cacheSize added, in order to make alteration of running program safe! December 26, 1983 2:40 pm, LCS, patchup addresses with StripChar January 7, 1985 2:59:52 pm PST, DCS, increase packet exchange wait time, make it a global vbl. ŽTeleLoadImpl.mesa Last Edited by: Stewart, December 26, 1983 4:11 pm Last Edited by: Swinehart, January 19, 1985 3:12:13 pm PST Fires up a process to watch for unsolicited news items from debugees Communication stuff more conveniently arranged Here lives the single king socket. These variables are only touched by procedures in the monitor These variables are handled outside the monitor �ʨ˜Jšœ™Jšœ2™2J™:J˜šÏk ˜ Jšœ�œ�œ�œ*˜HJš�œ�œ�œ˜#Jšœ�œ˜(Jšœ�œþ˜‹Jšœ �œJ˜XJšœ �œ!˜0Jšœ�œ�œ˜J˜ J˜—šœ�˜Jš�œ �œ˜/Jš�œ ˜Jš�œ�œ ˜J˜Jš Ïnœ�œ�œ� œ�œ� œ˜=J˜Jšœ �œ�œ�œ ˜4Jšœ�œ�œ�œ ˜8J˜Jšœ �œ�œ˜Jšœ�œÏc"˜;J˜šž œ�œ�œ�œ �œ�œ$�œ�œ�œ˜ušœ8˜8Jšœ"�œ�œ˜6—J˜J˜—šž œ�œ�œ�œ �œ�œ�œ˜uJšœ-˜-Jšœ0˜0J˜J˜—šžœ�œ�œ�œ �œ�œ�œ�œ�œ˜YJ˜Jšœ�œ˜ J˜'J˜)Jš �œ�œ�œ�œ�œ˜šœ�œ ˜Jšœ ˜ Jšœ˜J˜Jšœ ˜ —Jš�œ˜ J˜J˜—š žœ�œ�œ�œ�œ˜.Jš�œ�œ�œ�œ˜Jšœ �œ˜ Jšœ�œ˜ J˜J˜—šœ�œ�œ�œ˜,Jš�œ�œ�œ˜J˜SJ˜J˜—šœ�œ�œ�œ˜,Jš�œ�œ�œ˜JšœS˜SJ˜J˜—šœ �œ�œ�œ˜1Jš�œ�œ�œ˜JšœT˜TJ˜J˜—šœ �œ�œ�œ˜1Jš�œ�œ�œ˜JšœT˜TJ˜J˜—šœ�œ�œ�œ˜+Jš�œ�œ�œ˜JšœQ˜QJ˜—J˜šœ�œ�œ�œ˜)Jš�œ�œ�œ˜J˜HJ˜J˜—šœ �œ�œ�œ˜2Jš�œ�œ�œ˜J˜QJ˜J˜—šœ �œ�œ�œ˜1Jš�œ�œ�œ˜J˜PJ˜J˜—šœ �œ�œ�œ˜1Jš�œ�œ�œ˜J˜TJ˜J˜—šœ�œ�œ�œ˜3Jš�œ�œ�œ˜J˜2J˜Jšœ �œ ˜J˜J˜J˜š�œ�œ�œ�˜#J˜Jš�œ˜—Jšœ�œ"˜EJ˜J˜J˜J˜J˜——JšœD™D˜Jšœ�œ˜Jšœ�œ�œ˜ Jšœ�œ˜Jšœ�œ˜&Jšœ!�œ˜%Jšœ ˜ Jšœ�œ�œ˜J˜šžœ�œ�œ�œ�œ�œ�œ�œ˜[J˜.Jš�œ�œ�œ˜'Jš�œ�œ�œ˜!J˜Jšœ˜Jšœ�œ˜Jšœ�œ˜0J˜J˜—š žœ�œ�œ�œ�œ�œ˜3Jšœ�œ˜6Jš�œ�œ�œ˜'Jšœ�œ˜Jš�œ˜J˜J˜—šžœ�œ˜Jšœ�œ˜J˜J˜ J˜J˜¸š�˜J˜š�œ�œ�œ˜Jšœ�œ ˜Jšœ�œ ˜Jšœ5˜5J˜J˜—Jš�œ�œ�œ�œ˜#Jš�œ˜—Jšœ�œ˜Jšœ�œ˜J˜&J˜J˜J˜—šžœ�œ�œB�œ�œ�œ�œ�œ˜�Jšœ�œ˜J˜Jš �œ�œ�œ�œ�œ˜š�œ�œ �˜#J˜Jš�œ�œ�œ ˜-J˜Jšœ �œ ˜J˜"J˜$J˜ š�œ�œ�œ�˜*J˜$Jš�œ˜—Jšœ�œ)˜LJ˜Jš�œ�œ�œ�œ˜Jšœ �œ ˜Jš�œ�œ�œ�œ˜+J˜"Jš�œ˜Jš�˜Jš�œ�œ˜Jš�œ˜—Jš�œ�œ�œ ˜-J˜J˜—šžœ�œ�œB�œ�œ�œ�œ�œ˜’Jšœ�œ˜J˜J˜Jš �œ�œ�œ�œ�œ˜š�œ�œ �˜#Jš�œ�œ�œ ˜-J˜Jšœ �œ ˜J˜"J˜$J˜ Jšœ�œ˜4J˜Jš�œ�œ�œ�œ˜Jšœ �œ ˜Jš�œ%�œ�œ˜1Jš�œ!�œ�œ˜-š�œ�œ�œ�˜*J˜$Jš�œ˜—J˜"Jš�œ˜Jš�˜Jš�œ�œ˜Jš�œ˜—Jš�œ�œ�œ ˜-J˜J˜—šž œ�œ�œB�œ�œ�œ�œ�œ˜•Jšœ�œ˜J˜J˜Jš �œ�œ�œ�œ�œ˜š�œ�œ �˜#Jš�œ�œ�œ ˜-J˜Jšœ �œ ˜J˜"J˜$J˜ š�œ�œ�œ�˜*J˜$Jš�œ˜—Jšœ�œ)˜LJ˜ J˜Jš�œ�œ�œ�œ˜Jšœ �œ ˜Jš�œ%�œ�œ˜1Jš�œ!�œ�œ˜-š�œ�œ�œ�˜*J˜$Jš�œ˜—J˜"Jš�œ˜Jš�˜Jš�œ�œ˜Jš�œ˜—Jš�œ�œ�œ ˜-J˜—J˜šžœ�œ�œT�œ˜‰Jšœ�œ˜Jšœ˜J˜J˜š�˜Jš�œ�œ�œ$˜5J˜Jš �œ �œ�œ�œ�œ˜ Jš �œ�œ�œ�œ�œ�œ˜BJš�œ�œ�œ˜Jš�œ˜Jš�œ˜—J˜J˜—š žœ�œ�œ�œ�œ˜BJš�œ�œ�œ�œ˜,Jš�œ�œ�œ�œ˜(š�œ�œ�œ�˜"Jš�œ�œ�œ�œ˜,Jš�œ˜—Jš�œ�œ˜ J˜—J˜J™.J˜Jšœ�œ�œ�œ˜J™šž œ�œ�œ�œ�œ&�œ%�œ�œ˜šJš�œ�œ�œ˜Jš�œ6˜