DIRECTORY Ascii USING [CR, SP, TAB, LF, BS, ControlA, ControlX, FF, NUL, ESC, DEL, BEL], Atom USING [PropList], Basics USING [UnsafeBlock], BasicTime USING [GMT, Now, Unpacked], Rope USING [ROPE]; IO: CEDAR DEFINITIONS IMPORTS BasicTime = BEGIN ROPE: TYPE = Rope.ROPE; UnsafeBlock: TYPE = Basics.UnsafeBlock; STREAM: TYPE = REF STREAMRecord; StreamVariety: TYPE = {input, output, inputOutput}; EndOfStream: ERROR [stream: STREAM]; Error: ERROR [ec: ErrorCode, stream: STREAM]; ErrorCode: TYPE = { Null, NotImplementedForThisStream, StreamClosed, Failure, IllegalBackup, BufferOverflow, BadIndex, SyntaxError, Overflow, PFInvalidCode, PFInvalidPFProcs, PFCantBindConversionProc, PFFormatSyntaxError, PFTypeMismatch, PFUnprintableValue }; GetInfo: PROC [stream: STREAM] RETURNS [variety: StreamVariety, class: ATOM]; GetChar: PROC [self: STREAM] RETURNS [CHAR]; GetBlock: PROC [self: STREAM, block: REF TEXT, startIndex: NAT _ 0, count: NAT _ NAT.LAST] 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 _ FALSE] RETURNS [INT]; Backup: PROC [self: STREAM, char: CHAR]; PeekChar: PROC [self: STREAM] RETURNS [char: CHAR]; PutChar: PROC [self: STREAM, char: CHAR]; PutBlock: PROC [self: STREAM, block: REF READONLY TEXT, startIndex: NAT _ 0, count: NAT _ NAT.LAST]; UnsafePutBlock: PROC [self: STREAM, block: UnsafeBlock]; Flush: PROC [self: STREAM]; EraseChar: PROC [self: STREAM, char: CHAR]; Reset: PROC [self: STREAM]; Close: PROC [self: STREAM, abort: BOOL _ FALSE]; GetIndex: PROC[self: STREAM] RETURNS [index: INT]; SetIndex: PROC[self: STREAM, index: INT]; GetLength: PROC[self: STREAM] RETURNS [length: INT]; SetLength: PROC[self: STREAM, length: INT]; RIS: PROC [rope: ROPE, oldStream: STREAM _ NIL] RETURNS [stream: STREAM]; ROS: PROC [oldStream: STREAM _ NIL] RETURNS [stream: STREAM]; RopeFromROS: PROC [self: STREAM, close: BOOL _ TRUE] RETURNS [ROPE]; TIS: PROC [text: REF READONLY TEXT, oldStream: STREAM _ NIL] RETURNS [stream: STREAM]; TOS: PROC [text: REF TEXT _ NIL, oldStream: STREAM _ NIL] RETURNS [stream: STREAM]; TextFromTOS: PROC [self: STREAM] RETURNS [REF TEXT]; noWhereStream: STREAM; noInputStream: STREAM; PutRope: PROC [self: STREAM, r: ROPE]; PutText: PROC [self: STREAM, t: REF READONLY TEXT]; atom: PROC [v: ATOM] RETURNS [Value] = INLINE {RETURN[[atom[v]]]}; bool: PROC [v: BOOL] RETURNS [Value] = INLINE {RETURN[[boolean[v]]]}; card: PROC [v: LONG CARDINAL] RETURNS [Value] = INLINE {RETURN[[cardinal[v]]]}; char: PROC [v: CHAR] RETURNS [Value] = INLINE {RETURN[[character[v]]]}; int: PROC [v: INT] RETURNS [Value] = INLINE {RETURN[[integer[v]]]}; real: PROC [v: REAL] RETURNS [Value] = INLINE {RETURN[[real[v]]]}; refAny: PROC [v: REF READONLY ANY] RETURNS [Value] = INLINE {RETURN[[refAny[v]]]}; rope: PROC [v: ROPE] RETURNS [Value] = INLINE {RETURN[[rope[v]]]}; text: PROC [v: REF READONLY TEXT] RETURNS [Value] = INLINE {RETURN[[text[v]]]}; time: PROC [v: BasicTime.GMT _ BasicTime.Now[]] RETURNS [Value] = INLINE { RETURN[[time[v]]]; }; Put: PROC [stream: STREAM, v1, v2, v3: Value _ [null[]]]; Put1: PROC [stream: STREAM, value: Value _ [null[]]]; PutR: PROC [v1, v2, v3: Value _ [null[]]] RETURNS [ROPE]; PutR1: PROC [value: Value _ [null[]]] RETURNS [ROPE]; PutL: PROC [stream: STREAM, list: LIST OF Value]; PutLR: PROC [list: LIST OF Value] RETURNS [ROPE]; PutF: PROC [stream: STREAM, format: ROPE _ NIL, v1, v2, v3, v4, v5: Value _ [null[]]]; PutF1: PROC [stream: STREAM, format: ROPE _ NIL, value: Value _ [null[]]]; PutFR: PROC [format: ROPE _ NIL, v1, v2, v3, v4, v5: Value _ [null[]]] RETURNS [ROPE]; PutFR1: PROC [format: ROPE _ NIL, value: Value _ [null[]]] RETURNS [ROPE]; PutFL: PROC [stream: STREAM, format: ROPE _ NIL, list: LIST OF Value]; PutFLR: PROC [format: ROPE _ NIL, list: LIST OF Value] RETURNS [ROPE]; GetCedarToken: PROC [stream: STREAM, buffer: REF TEXT, flushComments: BOOL _ TRUE] RETURNS [tokenKind: TokenKind, token: REF TEXT, charsSkipped: INT, error: TokenError]; TokenKind: TYPE = { tokenERROR, -- token.error describes the scanning error tokenID, -- an identifier or reserved word tokenDECIMAL, -- a whole number literal expressed in decimal tokenOCTAL, -- a whole number literal expressed in octal tokenHEX, -- a whole number literal expressed in hexidecimal tokenREAL, -- a REAL literal tokenROPE, -- a ROPE, REF TEXT, or STRING literal tokenCHAR, -- a CHAR literal tokenATOM, -- an ATOM literal tokenSINGLE, -- a single-character token tokenDOUBLE, -- a double-character token tokenCOMMENT, -- a comment tokenEOF -- the end-of-file marker }; TokenError: TYPE = { none, -- no error extendedChar, -- error following backslash in char or string literal numericLiteral, charLiteral, stringLiteral, atomLiteral, -- error in parsing indicated type singleChar -- first non-whitespace char is not legal as first char of token }; GetCedarTokenRope: PROC [stream: STREAM, flushComments: BOOL _ TRUE] RETURNS [tokenKind: TokenKind, token: ROPE, charsSkipped: INT]; GetInt: PROC [stream: STREAM] RETURNS [INT]; GetCard: PROC [stream: STREAM] RETURNS [LONG CARDINAL]; GetReal: PROC [stream: STREAM] RETURNS [REAL]; GetBool: PROC [stream: STREAM] RETURNS [BOOL]; GetAtom: PROC [stream: STREAM] RETURNS [ATOM]; GetRopeLiteral: PROC [stream: STREAM] RETURNS [ROPE]; GetCharLiteral: PROC [stream: STREAM] RETURNS [CHAR]; GetID: PROC [stream: STREAM] RETURNS [ROPE]; GetTime: PROC [stream: STREAM] RETURNS [BasicTime.GMT]; GetUnpackedTime: PROC [stream: STREAM] RETURNS [BasicTime.Unpacked]; GetRefAny: PROC [stream: STREAM] RETURNS [REF ANY]; GetRefAnyLine: PROC [stream: STREAM] RETURNS [LIST OF REF ANY]; SkipWhitespace: PROC [stream: STREAM, flushComments: BOOL _ TRUE] RETURNS [charsSkipped: INT]; GetToken: PROC [ stream: STREAM, breakProc: BreakProc _ TokenProc, buffer: REF TEXT] RETURNS [token: REF TEXT, charsSkipped: INT]; BreakProc: TYPE = PROC [char: CHAR] RETURNS [CharClass]; CharClass: TYPE = {break, sepr, other}; TokenProc: BreakProc; IDProc: BreakProc; GetTokenRope: PROC [ stream: STREAM, breakProc: BreakProc _ TokenProc] RETURNS [token: ROPE, charsSkipped: INT]; GetLine: PROC [stream: STREAM, buffer: REF TEXT] RETURNS [line: REF TEXT]; GetLineRope: PROC [stream: STREAM] RETURNS [line: ROPE]; BS: CHAR = Ascii.BS; -- '\b TAB: CHAR = Ascii.TAB; -- '\t LF: CHAR = Ascii.LF; -- '\l FF: CHAR = Ascii.FF; -- '\f CR: CHAR = Ascii.CR; -- '\n NUL: CHAR = Ascii.NUL; ControlA: CHAR = Ascii.ControlA; BEL: CHAR = Ascii.BEL; ControlX: CHAR = Ascii.ControlX; ESC: CHAR = Ascii.ESC; SP: CHAR = Ascii.SP; DEL: CHAR = Ascii.DEL; CreateStreamProcs: PROC [ variety: StreamVariety, class: ATOM, getChar: PROC [self: STREAM] RETURNS[CHAR] _ NIL, getBlock: PROC [self: STREAM, block: REF TEXT, startIndex: NAT, count: NAT] RETURNS [nBytesRead: NAT] _ NIL, unsafeGetBlock: UNSAFE PROC [self: STREAM, block: UnsafeBlock] RETURNS [nBytesRead: INT] _ NIL, endOf: PROC [self: STREAM] RETURNS [BOOL] _ NIL, charsAvail: PROC [self: STREAM, wait: BOOL] RETURNS [INT] _ NIL, backup: PROC [self: STREAM, char: CHAR] _ NIL, putChar: PROC [self: STREAM, char: CHAR] _ NIL, putBlock: PROC [self: STREAM, block: REF READONLY TEXT, startIndex: NAT, count: NAT] _ NIL, unsafePutBlock: PROC [self: STREAM, block: UnsafeBlock] _ NIL, flush: PROC [self: STREAM] _ NIL, reset: PROC [self: STREAM] _ NIL, close: PROC [self: STREAM, abort: BOOL _ FALSE] _ NIL, getIndex: PROC [self: STREAM] RETURNS [INT] _ NIL, setIndex: PROC [self: STREAM, index: INT] _ NIL, getLength: PROC [self: STREAM] RETURNS [length: INT] _ NIL, setLength: PROC [self: STREAM, length: INT] _ NIL, eraseChar: PROC [self: STREAM, char: CHAR] _ NIL ] RETURNS [REF StreamProcs]; CreateStream: PROC [streamProcs: REF StreamProcs, streamData: REF ANY, backingStream: STREAM _ NIL] RETURNS [stream: STREAM]; STREAMRecord: TYPE = RECORD[ streamProcs: REF StreamProcs, -- the stream procedures streamData: REF ANY, -- instance data, type is specific to the stream class propList: Atom.PropList _ NIL, -- instance data, type is independent of the stream class backingStream: STREAM _ NIL -- distinguished instance data, used to "layer" streams ]; StreamProcs: TYPE = PRIVATE RECORD[ getChar: PROC [self: STREAM] RETURNS [CHAR], endOf: PROC [self: STREAM] RETURNS [BOOL], charsAvail: PROC [self: STREAM, wait: BOOL] RETURNS [INT], getBlock: PROC [self: STREAM, block: REF TEXT, startIndex: NAT, count: NAT] RETURNS [nBytesRead: NAT], unsafeGetBlock: UNSAFE PROC [self: STREAM, block: UnsafeBlock] RETURNS [nBytesRead: 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], propList: Atom.PropList, variety: StreamVariety, class: ATOM ]; Value: TYPE = RECORD [ SELECT type: ValueType FROM null => NULL, atom => [value: ATOM], boolean => [value: BOOL], character => [value: CHAR], cardinal => [value: LONG CARDINAL], integer => [value: INT], real => [value: REAL], refAny => [value: REF READONLY ANY], rope => [value: ROPE], text => [value: REF READONLY TEXT], time => [value: BasicTime.GMT], ENDCASE ]; ValueType: TYPE = {null, atom, boolean, character, cardinal, integer, real, refAny, rope, text, time}; END. 0ÐIO.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. MBrown on September 20, 1983 11:53 pm Andrew Birrell on June 6, 1983 10:34 am Paul Rovner on May 23, 1983 9:31 am Teitelman on January 12, 1983 3:01 pm Russ Atkinson (RRA) February 2, 1985 12:38:05 pm PST Beach, February 27, 1985 10:20:51 am PST This interface defines STREAM, the Cedar byte stream abstraction. It defines the generic operations on streams and procs for implementing a new stream class. It also contains create procs for creating certain types of streams (for instance, stream to/from rope), procs for performing output conversion and writing the results to a stream, procs for reading from a stream and performing input conversion. This interface is structured for reference use, and does not contain complete documentation. The Convert, IOUtils and IOStreams interfaces contain related procedures. See IODoc.tioga for complete documentation. An UnsafeBlock describes a sequence of bytes residing in virtual memory. If you interpret base as a LONG POINTER TO PACKED ARRAY [0..n) OF CHAR, then the byte sequence described by an UnsafeBlock is base[startIndex .. startIndex+count). STREAMRecord should be regarded as opaque by most clients. Its representation is defined below in the section "Private details". Generic stream operations and errors Calling an undefined stream operation raises ERROR Error[$NotImplementedForThisStream, self]. Calling an operation other than Reset or Close on a closed stream raises ERROR Error[$StreamClosed, self]; calling Reset or Close on a closed stream does nothing. Errors not raised by any proc this operation is not implemented by this stream this stream is closed (operation might have been valid before close) from any operation; consult class-specific proc for more detailed information detected an attempt to Backup a different character than came from GetChar attempt to Backup more than NAT.LAST characters bad index to SetIndex (e.g. past end of file) in formatted input tokenizing or conversion in formatted input conversion IOUtils.Set/Get PFCodeProc: char not IN ['A..'Z] or ['a..'z] IOUtils.Set/Get PFCodeProc: pfProcs = NIL PutF: stream (and its backing streams) does not define code proc PutF: not enough or too many '%s, no code following '% PutF: the PFCodeProc is not prepared for the supplied Value type PutF: the PFCodeProc is not able to print the particular value (e.g. overflow in real -> int conversion) General information Input Operations (defined for input and inputOutput streams) ! EndOfStream (end of input sequence has been reached) Effect is like performing GetChar, placing the characters in block beginning with block[startIndex], until block is full (meaning that block[startIndex .. MIN[startIndex+count, block.maxLength]) have been filled) or until GetChar raises EndOfStream. The result, nBytesRead, is the number of bytes returned by GetChar calls; sets block.length to startIndex+nBytesRead before returning. ! RuntimeError.BoundsFault (block.startIndex < 0 OR block.count < 0) Analogous to GetBlock. Never raises EndOfStream. Tests for the input stream being at its end 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. ! Error[self, IllegalBackup] (char is not the last byte read). 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) Puts one character to the stream Effect is like: If startIndex+count > block.maxLength, then set count _ block.length-startIndex. Then perform PutChar for each byte in block[startIndex .. startIndex+count). ! RuntimeError.BoundsFault (block.startIndex < 0 OR block.count < 0) Analogous to PutBlock. Causes characters that have been output to stream, but not yet sent (because of buffering) to be sent Erases char, which was last char put to self. For instance, erases character from display. For most stream classes, implemented as on a teletype by printing '\\ followed by char. Control Operations (defined for all streams) For input streams, has the effect of flushing all pending input, so that self.CharsAvail[] = 0. For output and input/output streams, has some class-specific effect. Makes stream unusable for further operations; any stream operation except Flush, Reset, and Close will raise ERROR Error[self, StreamClosed]. Special Control Operations (defined for file-like streams) Steam classes that interface to other data types File See FS.StreamOpen. Typescript Viewers See ViewerIO.CreateViewerStreams. ROPE The rope input stream behaves much like a file input stream: GetIndex, SetIndex, and GetLength are all defined. Gets chars from client's rope. If oldStream is non-NIL it is reused rather than allocating space for a new stream. The rope output stream behaves much like an append-only file stream: GetIndex and GetLength are defined. The sequence output so far is available as a rope. Closing the stream releases a REF TEXT buffer to the scratch TEXT pool. Applies only to the result of a ROS call. Returns the entire output sequence as a rope. If close, then close self. REF TEXT The text input stream behaves much like a file input stream: GetIndex, SetIndex, and GetLength are all defined. Gets chars from user's user's REF TEXT. If oldStream is non-NIL, it is reused rather than allocating space for a new stream. The user should not modify the text after passing it to TIS until the stream is closed. The text output stream behaves much like an append-only file stream: GetIndex and GetLength are defined. If text = NIL then TOS allocates one. Sets text.length _ 0. PutChar appends characters to text using RefText.InlineAppendChar. The user should not modify the text after passing it to TOS until the stream is closed. Applies only to the result of a TOS call. Returns the entire output sequence as a ref text. Does not close the stream, so may be called repeatedly, but same ref text may be returned several times (and is mutable). Null output stream that simply discards its characters. input stream for which CharsAvail is INT.LAST, EndOf is TRUE. Others Stream implementations exist for the Viewers message window, PUP byte streams, a subset of FTP, and the magnetic tape server. The IOStreams interface defines several stream classes that combine other streams. See IODoc.tioga. Printing IO.time[] gives the current time. In the procedures below, suffix "R" means "ToRope", "L" means "FromList", and "LR" means "FromListToRope". Put is a convenience procedure that gives the effect of (1) calling the appropriate procedure from the Convert interface to turn the Value into a character string, and (2) sending this character string down the stream. Put is relatively efficient but provides no formatting options. Use PutF, or call Convert, to get other effects. PutF is similar in spirit to the FORTRAN format interpreter. A call to PutF specifies a format (a ROPE containing text and conversion specifications) and a sequence of Cedar values. PutF replaces each conversion specification in the format with a printed representation of the corresponding Cedar value. Examples (see IODoc.tioga for a full explanation): IO.PutFR["This is %g in a 5 position field: |%5g|", IO.rope["an integer"], IO.int[17]] = "This is an integer in a 5 position field: | 17|" IO.PutFR["This is %g in a 5 position field: |%05g|", IO.rope["an integer"], IO.int[17]] = "This is an integer in a 5 position field: |00017|" IO.PutFR["This is %g in a 5 position field: |%-5g|", IO.rope["an integer"], IO.int[17]] = "This is an integer in a 5 position field: |17 |" Scanning Scanning routines that return a result are generally provided in two versions. The first version takes a REF TEXT buffer as a parameter, and may return its result in this buffer, but will allocate a larger one if the buffer fills up. Hence if each token is smaller than the buffer, only a single allocation is required to scan a sequence of tokens. The second version returns its result in a ROPE; hence at least one byte of storage is allocated for each byte of token scanned. In either case, a token cannot exceed NAT.LAST bytes in length. Scanning according to Cedar syntax ! (none) Consumes chars from stream, looking for next Cedar token. Returns the kind of token found, the characters of the token, and the number of white space characters discarded before reaching the token. If flushComments then the characters of a comment are treated as white space. The error returned is # none only for tokenKind = tokenERROR. ! EndOfStream ! Error[SyntaxError] Calls GetCedarToken. If token returned is tokenEOF or tokenERROR, raises an appropriate signal. Otherwise converts the token into a ROPE and returns it. The following convenience procedures generally call GetCedarToken (with flushComments = TRUE), check that the tokenKind is as expected, and convert the token to a Cedar value of the indicated type. They raise EndOfStream if the tokenKind is tokenEOF, raise Error[SyntaxError] if the tokenKind is not the one expected (including tokenERROR), and raise ERROR[Overflow] if there is an overflow in a conversion. GetTime and GetUnpackedTime do not follow the simple pattern just described because there is no standard Cedar syntax for time. They consume whatever looks like a time. Calls GetCedarToken to parse input stream, then converts the resulting token to a REF to a value of the appropriate type. GetRefAny recognizes no tokens of type tokenDOUBLE, and only a few tokens of type tokenSINGLE: '( starts a list (LIST OF REF ANY), ') terminates a list, '+, '- are unary operators that may precede a numeric literal, ', is ignored between elements of a list, '^ is always ignored. Calls GetRefAny repeatedly until the token found is (1) not an element of a list, and (2) is immediately followed by a CR. Creates a LIST OF REF ANY to hold the sequence of values returned, and returns this list. Is intended for use in command interpreters. Simple stream scanning The effect is to read and discard characters from stream until a non-whitespace character is read (and put back using Backup). If flushComments, treats comments as whitespace. Returns the number of characters skipped. ! EndOfStream (stream.EndOf[] AND token.IsEmpty[] when GetToken is about to return) The result token is the first sequence of characters in stream that is either a run of consecutive other characters, or a single break character. All chars preceding token, and token itself, are removed from stream. Raises EndOfStream if token would be empty and stream is empty. charsSkipped is the number of chars skipped before reaching the first char of the token. Is equivalent to {RETURN[SELECT char FROM IN [NUL .. SP], ',, ':, '; => sepr, '[, '], '(, '), '{, '}, '", '+, '-, '*, '/, '@, '_ => break, ENDCASE => other]}; s.GetToken[breakProc: TokenProc] approximates the behavior of the Cedar scanner, but discards commas, colons, and semicolons, does not handle real numbers, rope literals, two-character operators, etc. Is equivalent to {RETURN[SELECT char FROM IN [NUL .. SP], ',, ':, '; => sepr, ENDCASE => other]}; s.GetToken[IDProc] does not recognize single-character tokens, hence accepts "/indigo/cedar/top/io.df" or "Rovner.pa" as a single token. ! EndOfStream (stream.EndOf[] AND token.IsEmpty[] when GetTokenRope is about to return) Calls GetToken, converts token to ROPE, returns it. ! EndOfStream (stream.EndOf[] when GetLine is called) The result line is the sequence of characters in stream preceding the next CR or end of stream. If the line is terminated with CR, the CR is removed from stream but not included in line. Raises EndOfStream if the input stream is empty on entry. ! EndOfStream (stream.EndOf[] when GetLineRope is called) Calls GetLine, converts line to ROPE, returns it. ASCII Character constants Implementing a stream class The following procedures are used to implement a stream class. Few stream implementations require access to such aspects of the stream representation as the stream property list, the stream procs property list, and the backing stream, except through the CreateStreamProcs and CreateStream procedures below. When such access is necessary, consult the IOUtils interface for relevant procedures. Private details ÊA– "cedar" style˜codešœ™Kšœ Ïmœ1™™>K™LK™—š ¢œžœžœžœžœ˜3K™%—K˜—šœ>™>š¢œžœžœžœ˜)Kšœ ™ K˜—š¢œžœžœ žœžœžœžœ žœžœ˜dKš œ£"œ £œ£œ£%œ™®K™—š¢œžœžœ˜8Kšœ£œžœ™DKšœ £œ™K™—š¢œžœžœ˜Kšœe™eK™—š¢ œžœžœžœ˜,Kšœ´™´——šœ,™,š¢œžœžœ˜Kšœ¥™¥K™—š ¢œžœžœ žœžœ˜0Kšœmžœ™——šœ:™:Kš ¢œžœžœžœ žœ˜2Kš¢œžœžœ žœ˜)Kš ¢ œžœžœžœ žœ˜4Kš¢ œžœžœ žœ˜+——™0™Kš ™—™Kš !™!—šž™šÐbkœžœžœ žœžœžœ žœ˜IKšœ¥žœ<™ä—š ¥œžœ žœžœžœ žœ˜=Kšœ¼žœžœžœ™å—š¢ œžœžœ žœžœžœžœ˜DKšœ žœQ™t——šž™šÐknœžœžœžœžœ žœžœžœ žœ˜VKš œžœžœžœwžœ™ÇK™—š¦œžœžœžœžœ žœžœžœ žœ˜TKšœtžœžœ¤žœ™ÃK™—š ¢ œžœžœžœžœžœ˜4Kšœ žœ´™×——™šÏb œžœ˜Kš 3™3—š§ œžœ˜Kš %¡  ¡ ™>——™K™ã——šœ™Kš¢œžœžœžœ˜'Kš ¢œžœžœžœžœžœ˜3K˜Kš ¢œžœžœžœ žœžœ ˜BKš ¢œžœžœžœ žœžœ˜EKš¢œžœžœžœžœ žœžœ˜OKš ¢œžœžœžœ žœžœ˜GKš ¢œžœžœžœ žœžœ˜CKš ¢œžœžœžœ žœžœ ˜BKš¢œžœžœžœžœžœ žœžœ˜RKš ¢œžœžœžœ žœžœ ˜BKš¢œžœžœžœžœžœ žœžœ ˜Oš ¢œžœžœžœ žœ˜JKšžœ ˜Kšœ˜Kšœ!™!—K˜K™jK™Íš¢œžœ žœ!˜:Kš¢œžœ žœ˜6—š¢œžœ žœžœ˜9Kš¢œžœžœžœ˜5—Kš ¢œžœ žœžœžœ˜1Kš ¢œžœžœžœžœžœ˜1K˜šœ!žœ;žœþ™åšžœ2žœžœ ™XK™3—šžœ3žœžœ ™YK™3—šžœ3žœžœ ™YK™3——š ¢œžœ žœ žœžœ(˜VKš ¢œžœ žœ žœžœ˜J—š ¢œžœ žœžœ(žœžœ˜VKš ¢œžœ žœžœžœžœ˜J—Kš¢œžœ žœ žœžœžœžœ˜FKš¢œžœ žœžœžœžœžœžœ˜F—šœ™Kšœjžœ™žœyžœ™¡™"š¢ œžœ žœ žœžœžœžœ˜RKšžœžœžœžœ˜VKšœ™KšœÔ™Ôš¢ œžœ˜Kšœ  +˜7Kšœ  !˜*Kšœ &¡˜Kšœžœžœžœ˜!Kšœžœžœžœ˜!Kš œžœžœ žœžœžœ˜6Kš œ žœžœžœžœžœ˜2Kš œ žœžœ žœžœ˜0Kš œ žœžœžœ žœžœ˜;Kš œ žœžœ žœžœ˜2Kšœ žœžœžœž˜0K˜Kšžœžœ˜K˜—Kš¢ œžœžœžœžœžœžœž œ žœ˜}—™š¢ œžœžœ˜Kšœ žœ ˜6Kšœ žœžœ 6˜KKšœžœ 9˜XKšœžœžœ 7˜SK˜K˜—š¢ œžœžœžœ˜#Kš œ žœžœžœžœ˜,Kš œžœžœžœžœ˜*Kš œ žœžœžœžœžœ˜>Kšœ žœžœ žœžœžœ žœžœ žœ˜fKš œžœžœžœžœ žœ˜YKšœžœžœžœ˜(K˜Kšœ žœžœžœ˜)Kšœ žœžœ žœžœžœžœ žœ˜VKšœžœžœ˜8Kšœžœžœ˜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š¢ œžœW˜f—K˜Kšžœ˜—…—%\km