DIRECTORY Atom, Basics USING [RawBytes, RawChars], IO, IOUtils, Rope, RefText, RuntimeError USING [BoundsFault]; IOCommonImpl: CEDAR PROGRAM IMPORTS IO, IOUtils, Atom, RefText, RuntimeError EXPORTS IO, IOUtils SHARES IO --for representation of StreamProcs = BEGIN STREAM: TYPE = IO.STREAM; ROPE: TYPE = Rope.ROPE; UnsafeBlock: TYPE = IO.UnsafeBlock; ByteArrayPtr: TYPE = LONG POINTER TO Basics.RawBytes; CharArrayPtr: TYPE = LONG POINTER TO Basics.RawChars; StreamProcs: TYPE = IO.StreamProcs; TypeOfEraseChar: TYPE = PROC [self: STREAM, char: CHAR]; TypeOfGetLength: TYPE = PROC [self: STREAM] RETURNS [length: INT]; TypeOfSetLength: TYPE = PROC [self: STREAM, length: INT]; Error: PUBLIC ERROR [ec: IO.ErrorCode, stream: STREAM] = CODE; EndOfStream: PUBLIC ERROR [stream: STREAM] = CODE; CreateStreamProcs: PUBLIC PROC [ variety: IO.StreamVariety, class: ATOM, getChar: PROC [self: STREAM] RETURNS [CHAR], getBlock: PROC [self: STREAM, block: REF TEXT, startIndex: NAT, count: NAT] RETURNS [nBytesRead: NAT], unsafeGetBlock: UNSAFE PROC [self: STREAM, block: UnsafeBlock] RETURNS [nBytesRead: INT], endOf: PROC [self: STREAM] RETURNS [BOOL], charsAvail: PROC [self: STREAM, wait: BOOL] RETURNS [INT], backup: PROC [self: STREAM, char: CHAR], putChar: PROC [self: STREAM, char: CHAR], putBlock: PROC [self: STREAM, block: REF READONLY TEXT, startIndex: NAT, count: NAT], unsafePutBlock: PROC [self: STREAM, block: UnsafeBlock], flush: PROC [self: STREAM], reset: PROC [self: STREAM], close: PROC [self: STREAM, abort: BOOL], getIndex: PROC [self: STREAM] RETURNS [INT], setIndex: PROC [self: STREAM, index: INT], getLength: PROC [self: STREAM] RETURNS [length: INT], setLength: PROC [self: STREAM, length: INT], eraseChar: PROC [self: STREAM, char: CHAR] ] RETURNS [REF StreamProcs] = { streamProcs: REF StreamProcs _ NEW[StreamProcs _ [ variety: variety, class: class, getChar: IF getChar # NIL THEN getChar ELSE IF unsafeGetBlock # NIL THEN GetCharViaUnsafeGetBlock ELSE DefaultGetChar, getBlock: IF getBlock # NIL THEN getBlock ELSE IF unsafeGetBlock # NIL THEN GetBlockViaUnsafeGetBlock ELSE GetBlockViaGetChar, unsafeGetBlock: IF unsafeGetBlock # NIL THEN unsafeGetBlock ELSE UnsafeGetBlockViaGetChar, endOf: IF endOf = NIL THEN DefaultEndOf ELSE endOf, charsAvail: IF charsAvail = NIL THEN DefaultCharsAvail ELSE charsAvail, backup: IF backup = NIL THEN DefaultBackup ELSE backup, putChar: IF putChar # NIL THEN putChar ELSE IF unsafePutBlock # NIL THEN PutCharViaUnsafePutBlock ELSE DefaultPutChar, putBlock: IF putBlock # NIL THEN putBlock ELSE IF unsafePutBlock # NIL THEN PutBlockViaUnsafePutBlock ELSE PutBlockViaPutChar, unsafePutBlock: IF unsafePutBlock # NIL THEN unsafePutBlock ELSE UnsafePutBlockViaPutChar, flush: IF flush = NIL THEN DefaultFlush ELSE flush, reset: IF reset = NIL THEN DefaultReset ELSE reset, close: IF close = NIL THEN DefaultClose ELSE close, getIndex: IF getIndex = NIL THEN DefaultGetIndex ELSE getIndex, setIndex: IF setIndex = NIL THEN DefaultSetIndex ELSE setIndex, propList: NIL]]; IF getLength # NIL THEN IOUtils.StoreProc[streamProcs, $GetLength, NEW[TypeOfGetLength _ getLength]]; IF setLength # NIL THEN IOUtils.StoreProc[streamProcs, $SetLength, NEW[TypeOfSetLength _ setLength]]; IF eraseChar # NIL THEN IOUtils.StoreProc[streamProcs, $EraseChar, NEW[TypeOfEraseChar _ eraseChar]]; RETURN[streamProcs]; }; CreateStream: PUBLIC PROC [ streamProcs: REF StreamProcs, streamData: REF ANY, backingStream: STREAM _ NIL] RETURNS [stream: STREAM] = { RETURN[NEW[IO.STREAMRecord _ [ streamProcs: streamProcs, streamData: streamData, backingStream: backingStream] ]]; }; AddNat: PROC [a, b: NAT] RETURNS [NAT] = INLINE { RETURN [MIN[CARDINAL[a]+CARDINAL[b], NAT.LAST]]; }; DefaultGetChar: PROC [self: STREAM] RETURNS [CHAR] = { IF self.backingStream # NIL THEN RETURN[self.backingStream.GetChar[]] ELSE ERROR Error[NotImplementedForThisStream, self]; }; GetCharViaUnsafeGetBlock: PUBLIC PROC [self: STREAM] RETURNS [CHAR] = TRUSTED { buff: PACKED ARRAY [0..1] OF CHAR; bp: ByteArrayPtr = LOOPHOLE[LONG[@buff]]; IF self.streamProcs.unsafeGetBlock[self, [base: bp, startIndex: 0, count: 1]] = 0 THEN ERROR IO.EndOfStream[self]; RETURN[buff[0]] }; GetBlockViaGetChar: PUBLIC PROC [self: STREAM, block: REF TEXT, startIndex: NAT, count: NAT] RETURNS [nBytesRead: NAT] = { nBytes: NAT = MIN [block.maxLength, AddNat[startIndex, count]] - startIndex; FOR i: NAT IN [0 .. nBytes) DO block[startIndex+i] _ self.GetChar[ ! EndOfStream => { nBytesRead _ i; EXIT }]; REPEAT FINISHED => nBytesRead _ nBytes; ENDLOOP; block.length _ startIndex + nBytesRead; RETURN[nBytesRead]; }; GetBlockViaUnsafeGetBlock: PUBLIC PROC [self: IO.STREAM, block: REF TEXT, startIndex: NAT, count: NAT] RETURNS [nBytesRead: NAT] = TRUSTED { nBytesRead _ self.streamProcs.unsafeGetBlock[self, [ base: LOOPHOLE[block, ByteArrayPtr]+SIZE[TEXT[0]], startIndex: startIndex, count: MAX[MIN[INT[count], INT[block.maxLength]-startIndex], 0] ]]; block.length _ startIndex + nBytesRead; RETURN[nBytesRead]; }; UnsafeGetBlockViaGetChar: PUBLIC UNSAFE PROC [self: STREAM, block: UnsafeBlock] RETURNS [nBytesRead: INT] = UNCHECKED { nBytesRead _ 0; IF block.startIndex < 0 OR block.count < 0 THEN ERROR RuntimeError.BoundsFault; FOR i: INT IN [0 .. block.count) DO LOOPHOLE[block.base, CharArrayPtr][block.startIndex+i] _ self.GetChar[ ! IO.EndOfStream => { nBytesRead _ i; EXIT }] REPEAT FINISHED => nBytesRead _ block.count; ENDLOOP; RETURN[nBytesRead]; }; DefaultPutChar: PROC [self: STREAM, char: CHAR] = { backing: STREAM _ self.backingStream; IF backing # NIL THEN backing.streamProcs.putChar[backing, char] ELSE ERROR IO.Error[$NotImplementedForThisStream, self]; }; PutCharViaUnsafePutBlock: PUBLIC PROC [self: STREAM, char: CHAR] = TRUSTED { buff: PACKED ARRAY [0..1] OF CHAR; bp: ByteArrayPtr _ LOOPHOLE[LONG[@buff]]; buff[0] _ char; self.streamProcs.unsafePutBlock[self, [base: bp, startIndex: 0, count: 1]]; }; PutBlockViaPutChar: PUBLIC PROC [self: STREAM, block: REF READONLY TEXT, startIndex: NAT, count: NAT] = { stopIndexPlusOne: NAT _ AddNat[startIndex, count]; IF stopIndexPlusOne > block.maxLength THEN stopIndexPlusOne _ block.length; FOR i: NAT IN [startIndex .. stopIndexPlusOne) DO self.streamProcs.putChar[self, block[i]]; ENDLOOP; }; PutBlockViaUnsafePutBlock: PUBLIC PROC [ self: STREAM, block: REF READONLY TEXT, startIndex: NAT, count: NAT] = TRUSTED { stopIndexPlusOne: NAT _ AddNat[startIndex, count]; IF stopIndexPlusOne > block.maxLength THEN stopIndexPlusOne _ block.length; self.streamProcs.unsafePutBlock[self, [ base: LOOPHOLE[block,LONG POINTER]+TEXT[0].SIZE, startIndex: startIndex, count: MAX[INT[stopIndexPlusOne] - INT[startIndex], 0] ] ] }; UnsafePutBlockViaPutChar: PUBLIC PROC [self: STREAM, block: UnsafeBlock] = { IF block.startIndex < 0 OR block.count < 0 THEN ERROR RuntimeError.BoundsFault; FOR i: INT IN [block.startIndex .. block.startIndex+block.count) DO TRUSTED { self.streamProcs.putChar[self, LOOPHOLE[block.base, CharArrayPtr][i]] } ENDLOOP; }; DefaultEndOf: PROC [self: STREAM] RETURNS [BOOL] = { backing: STREAM _ self.backingStream; IF backing # NIL THEN RETURN[backing.streamProcs.endOf[backing]]; ERROR Error[NotImplementedForThisStream, self]; }; DefaultCharsAvail: PROC [self: STREAM, wait: BOOL] RETURNS [INT _ LAST[INT]] = { backing: STREAM _ self.backingStream; IF backing # NIL THEN RETURN[backing.streamProcs.charsAvail[backing, wait]]; }; DefaultFlush: PROC [self: STREAM] = { backing: STREAM _ self.backingStream; IF backing # NIL THEN backing.streamProcs.flush[backing]; }; DefaultReset: PROC [self: STREAM] = { backing: STREAM _ self.backingStream; IF backing # NIL THEN backing.streamProcs.reset[backing]; }; DefaultClose: PROC [self: STREAM, abort: BOOL _ FALSE] = { backing: STREAM; IF abort THEN self.streamProcs.reset[self] ELSE self.streamProcs.flush[self]; backing _ self.backingStream; IF backing # NIL THEN backing.streamProcs.close[backing, abort]; self.streamProcs _ closedStreamProcs; }; DefaultGetIndex: PROC [self: STREAM] RETURNS [index: INT] = { backing: STREAM _ self.backingStream; IF backing # NIL THEN RETURN[backing.streamProcs.getIndex[backing]] ELSE ERROR Error[NotImplementedForThisStream, self]; }; DefaultSetIndex: PROC [self: STREAM, index: INT] = { backing: STREAM _ self.backingStream; IF backing # NIL THEN backing.streamProcs.setIndex[backing, index] ELSE ERROR IO.Error[$NotImplementedForThisStream, self]; }; closedStreamProcs: PUBLIC REF StreamProcs _ NEW[StreamProcs _ [ variety: $inputOutput, class: $Closed, getChar: ClosedGetChar, getBlock: ClosedGetBlock, unsafeGetBlock: ClosedUnsafeGetBlock, endOf: ClosedEndOf, charsAvail: ClosedCharsAvail, backup: ClosedBackup, putChar: ClosedPutChar, putBlock: ClosedPutBlock, unsafePutBlock: ClosedUnsafePutBlock, flush: ClosedFlush, reset: ClosedReset, close: ClosedClose, getIndex: ClosedGetIndex, setIndex: ClosedSetIndex, propList: NIL]]; ClosedGetChar: PROC [self: STREAM] RETURNS [CHAR] = { ERROR IO.Error[$StreamClosed, self] }; ClosedGetBlock: PROC [self: STREAM, block: REF TEXT, startIndex: NAT, count: NAT] RETURNS [nBytesRead: NAT] = { ERROR IO.Error[$StreamClosed, self] }; ClosedUnsafeGetBlock: UNSAFE PROC [self: STREAM, block: UnsafeBlock]RETURNS [nBytesRead: INT] = { ERROR IO.Error[$StreamClosed, self] }; ClosedEndOf: PROC [self: STREAM] RETURNS [BOOL] = { ERROR IO.Error[$StreamClosed, self] }; ClosedCharsAvail: PROC [self: STREAM, wait: BOOL] RETURNS [INT] = { ERROR IO.Error[$StreamClosed, self] }; ClosedBackup: PROC [self: STREAM, char: CHAR] = { ERROR IO.Error[$StreamClosed, self] }; ClosedPutChar: PROC [self: STREAM, char: CHAR] = { ERROR Error[$StreamClosed, self] }; ClosedPutBlock: PROC [self: STREAM, block: REF READONLY TEXT, startIndex: NAT,count: NAT] = { ERROR Error[$StreamClosed, self] }; ClosedUnsafePutBlock: PROC [self: STREAM, block: UnsafeBlock] = { ERROR Error[$StreamClosed, self] }; ClosedFlush: PROC [self: STREAM] = { ERROR Error[$StreamClosed, self] }; ClosedReset: PROC [self: STREAM] = { }; ClosedClose: PROC [self: STREAM, abort: BOOL _ FALSE] = { }; ClosedGetIndex: PROC [self: STREAM] RETURNS [index: INT] = { ERROR Error[$StreamClosed, self] }; ClosedSetIndex: PROC [self: STREAM, index: INT] = { ERROR Error[$StreamClosed, self] }; GetChar: PUBLIC PROC [self: STREAM] RETURNS [CHAR] = { RETURN[self.streamProcs.getChar[self]]; }; GetBlock: PUBLIC PROC [self: STREAM, block: REF TEXT, startIndex: NAT _ 0, count: NAT _ NAT.LAST] RETURNS [nBytesRead: NAT] = { RETURN[self.streamProcs.getBlock[self, block, startIndex, count]]; }; UnsafeGetBlock: PUBLIC UNSAFE PROC [self: STREAM, block: UnsafeBlock] RETURNS [nBytesRead: INT] = UNCHECKED { RETURN[self.streamProcs.unsafeGetBlock[self, block]]; }; EndOf: PUBLIC PROC [self: STREAM] RETURNS [BOOL] = { RETURN[self.streamProcs.endOf[self]]; }; CharsAvail: PUBLIC PROC [self: STREAM, wait: BOOL _ FALSE] RETURNS [INT] = { RETURN[self.streamProcs.charsAvail[self, wait]]; }; Backup: PUBLIC PROC [self: STREAM, char: CHAR] = { self.streamProcs.backup[self, char]; }; PeekChar: PUBLIC PROC [self: STREAM] RETURNS [char: CHAR] = { char _ self.GetChar[]; self.Backup[char]; }; PutChar: PUBLIC PROC [self: STREAM, char: CHAR] = { self.streamProcs.putChar[self, char]; }; PutBlock: PUBLIC PROC [self: STREAM, block: REF READONLY TEXT, startIndex: NAT _ 0, count: NAT _ NAT.LAST] = { self.streamProcs.putBlock[self, block, startIndex, count]; }; UnsafePutBlock: PUBLIC PROC [self: STREAM, block: UnsafeBlock] = { self.streamProcs.unsafePutBlock[self, block]; }; Flush: PUBLIC PROC [self: STREAM] = { self.streamProcs.flush[self]; }; EraseChar: PUBLIC PROC [self: STREAM, char: CHAR] = { proc: REF ANY; DO IF self.streamProcs.class = $Closed THEN ERROR IO.Error[$StreamClosed, self]; proc _ InlineLookupProc[self, $EraseChar]; IF proc # NIL THEN {(NARROW[proc, REF TypeOfEraseChar])^ [self, char]; RETURN} ELSE IF self.backingStream # NIL THEN self _ self.backingStream ELSE {self.PutChar['\\]; self.PutChar[char]; RETURN}; ENDLOOP; }; Reset: PUBLIC PROC [self: STREAM] = {self.streamProcs.reset[self]}; Close: PUBLIC PROC [self: STREAM, abort: BOOL _ FALSE] = {self.streamProcs.close[self, abort]}; GetIndex: PUBLIC PROC[self: STREAM] RETURNS [index: INT] = { RETURN[self.streamProcs.getIndex[self]]}; SetIndex: PUBLIC PROC[self: STREAM, index: INT] = { self.streamProcs.setIndex[self, index]}; GetLength: PUBLIC PROC [self: STREAM] RETURNS [length: INT] = { proc: REF ANY; DO IF self.streamProcs.class = $Closed THEN ERROR IO.Error[$StreamClosed, self]; proc _ InlineLookupProc[self, $GetLength]; SELECT TRUE FROM proc # NIL => RETURN[(NARROW[proc, REF TypeOfGetLength])^ [self] ]; self.backingStream # NIL => self _ self.backingStream; ENDCASE => Error[NotImplementedForThisStream, self]; ENDLOOP; }; SetLength: PUBLIC PROC [self: STREAM, length: INT] = { proc: REF ANY; DO IF self.streamProcs.class = $Closed THEN ERROR IO.Error[$StreamClosed, self]; proc _ InlineLookupProc[self, $SetLength]; IF proc # NIL THEN {(NARROW[proc, REF TypeOfSetLength ])^ [self, length]; RETURN} ELSE IF self.backingStream # NIL THEN self _ self.backingStream ELSE ERROR IO.Error[$NotImplementedForThisStream, self]; ENDLOOP; }; GetInfo: PUBLIC PROC [stream: STREAM] RETURNS [variety: IO.StreamVariety, class: ATOM] = { RETURN [stream.streamProcs.variety, stream.streamProcs.class]; }; InlineLookupProc: PROC [self: STREAM, operation: ATOM] RETURNS [proc: REF ANY] = INLINE { FOR l: Atom.PropList _ self.streamProcs.propList, l.rest UNTIL l = NIL DO IF l.first.key = operation THEN RETURN[l.first.val]; ENDLOOP; }; AmbushStream: PUBLIC PROC [self: STREAM, streamProcs: REF StreamProcs, streamData: REF ANY, reusing: STREAM _ NIL] = { IF reusing = NIL OR reusing = self -- to prevent circularities due to bugs -- THEN reusing _ NEW[IO.STREAMRecord _ [streamProcs: NIL, streamData: NIL]]; reusing^ _ self^; self^ _ [streamProcs: streamProcs, streamData: streamData, propList: reusing.propList, backingStream: reusing]; reusing.propList _ NIL; -- keep only one copy of prop list. }; UnAmbushStream: PUBLIC PROC [self: STREAM] = { propList: Atom.PropList = self.propList; IF self.backingStream = NIL THEN RETURN; self^ _ self.backingStream^; IF self.propList # NIL THEN ERROR; -- access to the backing stream prop list was an error self.propList _ propList; }; StoreData: PUBLIC PROC [self: STREAM, key: ATOM, data: REF ANY] = { self.propList _ Atom.PutPropOnList[self.propList, key, data]; }; LookupData: PUBLIC PROC [self: STREAM, key: ATOM] RETURNS [REF ANY] = { RETURN[Atom.GetPropFromList[self.propList, key]]; }; RemoveData: PUBLIC PROC [self: STREAM, key: ATOM] = { self.propList _ Atom.RemPropFromList[self.propList, key]; }; StoreProc: PUBLIC PROC [class: REF StreamProcs, key: ATOM, procRef: REF ANY] = { class.propList _ Atom.PutPropOnList[class.propList, key, procRef]; }; LookupProc: PUBLIC PROC [self: STREAM, key: ATOM] RETURNS [procRef: REF ANY] = { RETURN[Atom.GetPropFromList[self.streamProcs.propList, key]]; }; BackupData: TYPE = REF BackupRecord; BackupRecord: TYPE = RECORD[stream: STREAM, buffer: REF TEXT]; backupProcs: REF StreamProcs = IO.CreateStreamProcs[ variety: $inputOutput, class: $BackedUp, getChar: BackupGetChar, endOf: BackupEndOf, charsAvail: BackupCharsAvail, reset: BackupReset, backup: BackupBackup ]; DefaultBackup: PROC [self: STREAM, char: CHAR] = { data: BackupData _ NARROW[IOUtils.LookupData[self, $Backup]]; IF data = NIL THEN { data _ NEW[BackupRecord _ [ stream: IO.CreateStream[NIL, NIL], buffer: RefText.New[8]]]; IOUtils.StoreData[self: self, key: $Backup, data: data] }; IF data.stream = self THEN ERROR Error[IllegalBackup, self]; -- while self in backed-up state, client performed self.backingStream.Backup[] (!) AmbushStream[self: self, streamProcs: backupProcs, streamData: data, reusing: data.stream]; self.Backup[char]; }; BackupBackup: PROC [self: STREAM, char: CHAR] = { data: BackupData = NARROW[IOUtils.LookupData[self, $Backup]]; data.buffer _ RefText.InlineAppendChar[data.buffer, char ! RuntimeError.BoundsFault => ERROR IO.Error[BufferOverflow, self]]; }; BackupGetChar: PROC [self: STREAM] RETURNS [char: CHAR] = { data: BackupData = NARROW[self.streamData]; char _ data.buffer[data.buffer.length - 1]; data.buffer.length _ data.buffer.length - 1; IF data.buffer.length = 0 THEN UnAmbushStream[self]; RETURN[char]; }; BackupEndOf: PROC [self: STREAM] RETURNS [BOOL] = { RETURN[FALSE]; }; BackupCharsAvail: PROC [self: STREAM, wait: BOOL] RETURNS [INT] = { data: BackupData = NARROW[self.streamData]; IF data.buffer.length > 0 THEN RETURN [data.buffer.length]; RETURN[self.backingStream.CharsAvail[wait]]; }; BackupReset: PROC [self: STREAM] = { data: BackupData = NARROW[self.streamData]; data.buffer.length _ 0; UnAmbushStream[self]; self.Reset[]; }; END.  IOCommonImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. MBrown on January 13, 1984 2:15 pm Paul Rovner on May 26, 1983 2:00 pm Teitelman on April 20, 1983 2:52 pm Russ Atkinson (RRA) February 2, 1985 1:35:51 pm PST Types Errors Creating streams Default Procedures: Get/Put Char/Block Default Procedures: others Closed Stream Procedures Input operations Analogous to GetBlock. Never raises EndOfStream. Returns the number of characters that can be obtained from the stream quickly (e.g. without waiting for the user to type something). If wait, does not return until it can return a nonzero value. Undoes the effect of the most recent GetChar, which returned the value char. Short for GetChar followed by Backup. Output Operations (defined for output and inputOutput streams) Analogous to PutBlock. Causes characters that have been output to stream, but not yet sent (because of buffering) to be sent Control Operations (defined for all streams) Special Control Operations (defined for file-like streams) Generic procedures with the standard implementation "Standard implementation" means "try property list, then try backing stream, then do something simple (e.g. Error[NotImplementedForThisStream])" Ambush / UnAmbush Stream Property list manipulation Default Backup implementation This is the implementation of Backup supplied by CreateStreamProcs when the client does not supply its own. This implementation ambushes the stream self. The stream created by the ambushing is saved so that it can be reused if the stream enters the backed-up state often. -- first time for this particular stream this is the implementation of Backup when a stream is in the backed-up state from a call to BackupFirstChar. Change Log Changed by MBrown on October 25, 1983 1:18 pm Added "IF NOT debugClose THEN self.streamProcs _ closedStreamProcs;" to DefaultClose (default is debugClose = TRUE because compiler and binder break otherwise ...) Changed by MBrown on November 15, 1983 5:25 pm Fixed off-by-one error in BackupGetChar. Κ²– "Cedar" style˜codešœ™Kšœ Οmœ1™Kš ‘ œŸœŸœ ŸœŸœ˜2K˜—šœ™š‘œŸœŸœ˜ Kšœ˜KšœŸœ˜ Kš œ ŸœŸœŸœŸœ˜,Kšœ ŸœŸœ ŸœŸœŸœ ŸœŸœ Ÿœ˜fKš œŸœŸœŸœŸœ Ÿœ˜YKš œŸœŸœŸœŸœ˜*Kš œ ŸœŸœŸœŸœŸœ˜:KšœŸœŸœŸœ˜(Kšœ ŸœŸœŸœ˜)Kšœ ŸœŸœ ŸœŸœŸœŸœ Ÿœ˜UKšœŸœŸœ˜8KšœŸœŸœ˜KšœŸœŸœ˜KšœŸœŸœ Ÿœ˜(Kš œ ŸœŸœŸœŸœ˜,Kšœ ŸœŸœ Ÿœ˜*Kš œ ŸœŸœŸœ Ÿœ˜5Kšœ ŸœŸœ Ÿœ˜,Kšœ ŸœŸœŸœ˜*K˜KšŸœŸœ˜šœ ŸœŸœ˜2Kšœ˜K˜ šœ Ÿœ ŸœŸœ˜&KšŸœŸœŸœŸœ˜:KšŸœ˜—šœ Ÿœ ŸœŸœ ˜)KšŸœŸœŸœŸœ˜;KšŸœ˜—šœŸœŸœŸœ˜;KšŸœ˜—Kš œŸœ ŸœŸœŸœ˜4Kš œ ŸœŸœŸœŸœ˜KKš œŸœ ŸœŸœŸœ˜7šœ Ÿœ ŸœŸœ˜&KšŸœŸœŸœŸœ˜:KšŸœ˜—šœ Ÿœ ŸœŸœ ˜)KšŸœŸœŸœŸœ˜;KšŸœ˜—šœŸœŸœŸœ˜;KšŸœ˜—Kš œŸœ ŸœŸœŸœ˜4Kš œŸœ ŸœŸœŸœ˜4Kš œŸœ ŸœŸœŸœ˜4Kš œ Ÿœ ŸœŸœŸœ ˜?Kš œ Ÿœ ŸœŸœŸœ ˜?Kšœ Ÿœ˜—šŸœ ŸœŸ˜Kšœ+Ÿœ˜M—šŸœ ŸœŸ˜Kšœ+Ÿœ˜M—šŸœ ŸœŸ˜Kšœ+Ÿœ˜M—KšŸœ˜šœ˜K˜——š‘ œŸœŸœ˜Kš œ ŸœŸœŸœŸœŸœ˜OKšŸœ Ÿœ˜šŸœŸœŸœ˜KšœS˜S—Kšœ˜K˜——šœ&™&š ‘œŸœŸœŸœŸœŸœ˜1Kš ŸœŸœŸœŸœŸœŸœ˜0K˜K˜—š ‘œŸœŸœŸœŸœ˜6KšŸœŸœŸœŸœ˜EKšŸœŸœ*˜4K˜K˜—š‘œŸœŸœŸœŸœŸœŸœ˜OKš œŸœŸœŸœŸœ˜"KšœŸœŸœ ˜)šŸœPŸ˜VKšŸœŸœ˜—KšŸœ ˜K˜K˜—š‘œŸ œŸœ ŸœŸœŸœ ŸœŸ œ Ÿœ˜zKš ΟrŸ’Πkr’œ’œ’œ ’˜Lš£’£’£’£˜Kš’G£’˜Oš£˜Kš£’˜ —Kš£’˜—Kš’'˜'Kš£’ ˜K˜K˜—š‘œŸœŸœŸœŸœ ŸœŸœŸœ ŸœŸ œ ŸœŸ’œ˜Œšœ4˜4KšœŸœŸœŸœ˜2Kšœ˜Kš œŸœŸœŸœ Ÿœ%˜C—Kš’œ ˜'KšŸœ ˜Kšœ˜—K˜š‘œŸ œŸœŸœŸœ ŸœŸ £œ˜wKš’˜š£’£’£˜/Kš£’˜—š£’£’£’£˜#š£’0˜8Kš’£’"£’˜;—š£˜KšŸœ’ œ’ œ˜%—Kš£’˜—Kš£’ œ˜Kšœ˜K˜—š‘œŸœŸœŸœ˜3Kšœ Ÿœ˜%šŸœ Ÿ˜KšŸœ+˜/KšŸœŸœŸœ+˜8—K˜K˜—š ‘œŸœŸœŸœŸœŸœ˜LKš œŸœŸœŸœŸœ˜"KšœŸœŸœ ˜)Kšœ˜KšœK˜KK˜K˜—š‘œŸœŸœŸœ ŸœŸœŸœŸœ Ÿœ˜iKš’£’œ’œ’˜2Kš £’œ’œŸœ’œ’ œ˜Kš£’£’£’"£˜1Kš’œ’œ’ ˜)Kš£’˜—K˜K˜—š‘œŸ œ˜(KšœŸœ ŸœŸœŸœŸœ ŸœŸœ˜PKš’£’œ’œ’˜2Kš £’œ’œŸœ’œ’ œ˜Kšœ'˜'Kš œŸœŸœŸœŸœŸœ˜0Kšœ˜KšœŸœ£’œŸœ˜:—K˜—K˜š‘œŸœŸœŸœ˜LKš £’£’œ’£’£’˜Oš £’£’£’-œ’£’£’œ˜MKš’œ’œ’£’ ˜GKš£’˜—K˜K˜——šœ™K˜š ‘ œŸœŸœŸœŸœ˜4Kšœ Ÿœ˜%KšŸœ ŸœŸœ%˜AKšŸœ*˜/K˜K˜—š‘œŸœŸœŸœŸœŸœŸœŸœ˜PKšœ Ÿœ˜%KšŸœ ŸœŸœ0˜LK˜K˜—š‘ œŸœŸœ˜%Kšœ Ÿœ˜%KšŸœ ŸœŸœ$˜9K˜K˜—š‘ œŸœŸœ˜%Kšœ Ÿœ˜%KšŸœ ŸœŸœ$˜9K˜K˜—š ‘ œŸœŸœ ŸœŸœ˜;Kšœ Ÿœ˜KšŸœŸœŸœ˜MKšœ˜KšŸœ ŸœŸœ+˜@Kšœ%˜%K˜K˜—š ‘œŸœŸœŸœ Ÿœ˜=Kšœ Ÿœ˜%KšŸœ ŸœŸœŸœ'˜CKšŸœŸœ*˜4K˜K˜—š‘œŸœŸœ Ÿœ˜4Kšœ Ÿœ˜%šŸœ Ÿ˜KšŸœ-˜1KšŸœŸ œ*˜8—K˜K˜——šœ™šœŸ œŸœ˜?Kšœ˜K˜Kšœ˜Kšœ˜Kšœ%˜%Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ%˜%Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ Ÿœ˜—š ‘ œŸœŸœŸœŸœ˜5KšŸœŸœ˜&—š‘œŸœŸœ ŸœŸœŸœ ŸœŸœŸœ˜oKšŸœŸœ˜&—š ‘œŸœŸœŸœŸœŸœ˜aKšŸœŸœ˜&—š ‘ œŸœŸœŸœŸœ˜3KšŸœŸœ˜&—š ‘œŸœŸœŸœŸœŸœ˜CKšŸœŸœ˜&—š‘ œŸœŸœŸœ˜1KšŸœŸœ˜&—š‘ œŸœŸœŸœ˜2KšŸœ˜#—š‘œŸœŸœ ŸœŸœŸœŸœŸœ˜]KšŸœ˜#—š‘œŸœŸœ˜AKšŸœ˜#—š‘ œŸœŸœ˜$KšŸœ˜#—Kš‘ œŸœŸœ˜'Kš ‘ œŸœŸœ ŸœŸœ˜<š ‘œŸœŸœŸœ Ÿœ˜™>K™š ‘œŸœŸœŸœŸœ˜3Kšœ%˜%Kšœ˜K˜—š‘œŸœŸœŸœ ŸœŸœŸœŸœ ŸœŸœŸœ˜nKšœ:˜:Kšœ˜K˜—š‘œŸœŸœŸœ˜BKšœ™Kšœ-˜-Kšœ˜K˜—š‘œŸœŸœŸœ˜%Kšœe™eKšœ˜Kšœ˜K™—š ‘ œŸœŸœŸœŸœ˜5KšœŸœŸœ˜šŸ˜KšŸœ"ŸœŸœŸœ˜MKšœ*˜*Kš ŸœŸœŸœŸœŸœ"Ÿœ˜NKšŸœŸœŸœŸœ˜?KšŸœ)Ÿœ˜5KšŸ˜—Kšœ˜K˜——šœ,™,K™Kš‘œŸœŸœŸœ#˜CK˜Kš ‘œŸœŸœŸœ ŸœŸœ,˜a—™K˜—šœ:™:K™š ‘œŸ œŸœŸœ Ÿœ˜K˜K˜—š‘œŸœŸœ ŸœŸœŸœŸœ˜NKšœŸœ˜ šŸœ6ŸœŸœŸ˜IKšŸœŸœŸœ˜5KšŸœ˜—K˜K˜——šœ™K™š ‘ œŸœŸœŸœŸœ ˜FKš œ ŸœŸœ ŸœŸœ˜/š Ÿœ ŸœŸœž*œŸ˜RKš œ ŸœŸœŸœŸœ˜E—K˜K˜oKšœŸœž#˜;Kšœ˜—š‘œŸœŸœŸœ˜.K˜)KšŸœŸœŸœŸœ˜(K˜Kš ŸœŸœŸœŸœž6˜YKšœ˜Kšœ˜K˜——™K™š ‘ œŸ œŸœŸœŸœŸœ˜CKšœ’œ-˜=Kšœ˜K˜—š‘ œŸ œŸœŸœŸœŸœŸœŸœ˜GKšŸœ+˜1Kšœ˜K˜—š‘ œŸ œŸœŸœ˜5Kšœ’œ)˜9Kšœ˜K˜—š ‘ œŸ œ ŸœŸœ ŸœŸœ˜PKšœ’œ1˜BKšœ˜K˜—š‘ œŸ œŸœŸœŸœ ŸœŸœŸœ˜PKšŸœ7˜=Kšœ˜—K™—™Kšœ ŸœŸœ˜$Kš œŸœŸœ Ÿœ ŸœŸœ˜>šœ ŸœŸœ˜4K˜(K˜K˜K˜K˜K˜K˜—š‘ œŸœŸœŸœ˜2Kšœ•’œx™‘KšœŸœ$˜=šŸœŸœŸœ˜Kšž'œ™(šœŸœ˜KšœŸœŸœ˜<—Kšœ:˜:—šŸœŸœŸœ˜