DIRECTORY Convert USING [IntFromRope, RealFromRope], IO USING [Backup, EndOfStream, GetChar, GetIndex, int, Put, PutChar, PutRope, real, STREAM], IP USING [Op, Vector], IPMaster USING [Error, nullToken, Rational, Reader, ReaderProcs, ReaderProcsRep, RegisterEncoding, Token, TokenType, Writer, WriterProcs, WriterProcsRep], RefText USING [Append, Find, InlineAppendChar, ObtainScratch, ReleaseScratch, TrustTextAsRope], Rope USING [Fetch, Length, ROPE], SymTab USING [Create, Fetch, Insert, Ref]; IPWrittenMasterImpl: CEDAR PROGRAM IMPORTS Convert, IO, IPMaster, RefText, Rope, SymTab ~ BEGIN OPEN IPMaster, IP; ROPE: TYPE ~ Rope.ROPE; STREAM: TYPE ~ IO.STREAM; NonDefaultingRope: TYPE ~ ROPE _; EncodeTable: TYPE ~ ARRAY Op OF NonDefaultingRope; encode: REF EncodeTable ~ NEW[EncodeTable _ [nil: NIL, get: "GET", makeveclu: "MAKEVECLU", makevec: "MAKEVEC", shape: "SHAPE", openvec: "OPENVEC", getprop: "GETPROP", getp: "GETP", mergeprop: "MERGEPROP", frame: "FRAME", fget: "FGET", fset: "FSET", poolop: "POOLOP", pool: "POOL", pget: "PGET", pset: "PSET", env: "ENV", makepool: "MAKEPOOL", nopool: "NOPOOL", makeco: "MAKECO", makesimpleco: "MAKESIMPLECO", do: "DO", dosave: "DOSAVE", dosaveall: "DOSAVEALL", dobody: "DOBODY", dosavebody: "DOSAVEBODY", dosaveallbody: "DOSAVEALLBODY", dosavesimplebody: "DOSAVESIMPLEBODY", makecompiledimage: "MAKECOMPILEDIMAGE", pop: "POP", copy: "COPY", dup: "DUP", roll: "ROLL", exch: "EXCH", mark: "MARK", unmark: "UNMARK", unmark0: "UNMARK0", count: "COUNT", nop: "NOP", error: "ERROR", if: "IF", ifelse: "IFELSE", ifcopy: "IFCOPY", loop: "LOOP", eq: "EQ", eqname: "EQNAME", gt: "GT", ge: "GE", and: "AND", or: "OR", not: "NOT", type: "TYPE", add: "ADD", sub: "SUB", neg: "NEG", abs: "ABS", floor: "FLOOR", ceiling: "CEILING", trunc: "TRUNC", round: "ROUND", mul: "MUL", div: "DIV", mod: "MOD", rem: "REM", max: "MAX", min: "MIN", sqrt: "SQRT", exp: "EXP", log: "LOG", sin: "SIN", cos: "COS", atan: "ATAN", iget: "IGET", iset: "ISET", dround: "DROUND", maket: "MAKET", opent: "OPENT", translate: "TRANSLATE", rotate: "ROTATE", scale: "SCALE", scale2: "SCALE2", concat: "CONCAT", invert: "INVERT", transform: "TRANSFORM", transformvec: "TRANSFORMVEC", roundxy: "ROUNDXY", roundxyvec: "ROUNDXYVEC", concatt: "CONCATT", move: "MOVE", trans: "TRANS", show: "SHOW", showandxrel: "SHOWANDXREL", setxy: "SETXY", setxyrel: "SETXYREL", setxrel: "SETXREL", setyrel: "SETYREL", getcp: "GETCP", getcprounded: "GETCPROUNDED", makepixelarray: "MAKEPIXELARRAY", extractpixelarray: "EXTRACTPIXELARRAY", finddecompressor: "FINDDECOMPRESSOR", makegray: "MAKEGRAY", findcolor: "FINDCOLOR", findcoloroperator: "FINDCOLOROPERATOR", findcolormodeloperator: "FINDCOLORMODELOPERATOR", makesampledcolor: "MAKESAMPLEDCOLOR", makesampledblack: "MAKESAMPLEDBLACK", setgray: "SETGRAY", moveto: "MOVETO", lineto: "LINETO", linetox: "LINETOX", linetoy: "LINETOY", curveto: "CURVETO", conicto: "CONICTO", arcto: "ARCTO", makeoutline: "MAKEOUTLINE", maskfill: "MASKFILL", maskstroke: "MASKSTROKE", maskstrokeclosed: "MASKSTROKECLOSED", maskvector: "MASKVECTOR", maskrectangle: "MASKRECTANGLE", startunderline: "STARTUNDERLINE", maskunderline: "MASKUNDERLINE", masktrapezoidx: "MASKTRAPEZOIDX", masktrapezoidy: "MASKTRAPEZOIDY", maskpixel: "MASKPIXEL", clipoutline: "CLIPOUTLINE", cliprectangle: "CLIPRECTANGLE", findfont: "FINDFONT", findfontvec: "FINDFONTVEC", modifyfont: "MODIFYFONT", setfont: "SETFONT", correctmask: "CORRECTMASK", correctspace: "CORRECTSPACE", correct: "CORRECT", setcorrectmeasure: "SETCORRECTMEASURE", setcorrecttolerance: "SETCORRECTTOLERANCE", space: "SPACE", beginBody: "{", endBody: "}", beginBlock: "BEGIN", endBlock: "END", pageInstructions: "PAGEINSTRUCTIONS", noPages: "NOPAGES", metricMaster: "METRICMASTER", environmentMaster: "ENVIRONMENTMASTER", beginVec: "[", comma: ",", endVec: "]"]]; decode: SymTab.Ref ~ BuildDecodeTable[encode]; BuildDecodeTable: PROC[encode: REF EncodeTable] RETURNS[decode: SymTab.Ref] = { decode _ SymTab.Create[mod: 101, case: FALSE]; FOR op: Op IN Op DO key: ROPE ~ encode[op]; IF key#NIL THEN { opRef: REF Op ~ NEW[Op _ op]; IF decode.Insert[key: key, val: opRef] THEN NULL ELSE ERROR; }; ENDLOOP; }; RopeFromOp: PROC[op: Op] RETURNS[ROPE] ~ { RETURN[encode[op]] }; OpFromRope: PROC[rope: ROPE] RETURNS[Op] ~ { found: BOOL; val: REF; [found: found, val: val] _ decode.Fetch[key: rope]; IF found THEN { opRef: REF Op ~ NARROW[val]; RETURN[opRef^] } ELSE RETURN[nil]; }; writtenReaderProcs: ReaderProcs ~ NEW[ReaderProcsRep _ [ getToken: WrittenGetToken, readInt: WrittenReadInt, readReal: WrittenReadReal, readRational: WrittenReadRational, readVector: WrittenReadVector ]]; WrittenGetToken: PROC[reader: Reader, flushComments: BOOL _ TRUE] ~ { stream: STREAM ~ reader.stream; token: Token _ nullToken; text: REF TEXT _ NIL; DO state: {begin, op, id, plus, minus, ast, int, den1, den2, den3, dot, frac, exp1, exp2, exp3, string, escape, com, com1, file, file1, ann, ann1} _ begin; err: {ok, illegalChar, invalidRational, invalidReal, invalidEscape} _ ok; char: CHAR; -- last character fetched got: BOOL _ TRUE; -- true if got char from stream, false if char is fake space at end esc: NAT; -- starting index of escape sequence BeginEscape: PROC ~ { esc _ text.length-1 }; EndEscape: PROC ~ { start: NAT ~ esc+1; stop: NAT ~ text.length-1; val: CARDINAL _ 0; IF stop<=start THEN err _ invalidEscape ELSE FOR i: NAT IN[start..stop) DO c: CHAR ~ text[i]; IF c IN['0..'9] THEN val _ val*10+(c-'0) ELSE { err _ invalidEscape; EXIT }; IF val>255 THEN { val _ 0; err _ invalidEscape; EXIT }; ENDLOOP; text[esc] _ 0C+val; text.length _ esc+1; }; reader.index _ stream.GetIndex[]; DO -- skip white space char _ stream.GetChar[! IO.EndOfStream => GOTO EndOfFile]; IF char IN['\041..'\176] THEN EXIT ELSE reader.index _ reader.index+1; ENDLOOP; text _ reader.buffer; text.length _ 0; DO -- scan a token text _ RefText.InlineAppendChar[text, char]; -- tentatively append char to token text { SELECT state FROM begin => SELECT char FROM IN['A..'Z] => { state _ op }; -- begin op IN['a..'z] => { state _ id }; -- begin identifier IN['0..'9] => { state _ int }; -- begin number '{ => { token.op _ beginBody; GOTO SingleOp }; '} => { token.op _ endBody; GOTO SingleOp }; '[ => { token.op _ beginVec; GOTO SingleOp }; '] => { token.op _ endVec; GOTO SingleOp }; ', => { token.op _ comma; GOTO SingleOp }; '< => { state _ string; GOTO Begin }; -- begin string '+ => { state _ plus }; -- might begin number or insertfile '- => { state _ minus }; -- might begin number or annotation '* => { state _ ast }; -- might begin comment '. => { state _ dot }; -- might begin real ENDCASE => { err _ illegalChar; GOTO Stop }; op => SELECT char FROM IN['A..'Z], IN['0..'9] => { }; -- extend op IN['a..'z], '- => { state _ id }; -- switch to id ENDCASE => { token.type _ op; GOTO Back }; -- op token id => SELECT char FROM IN['a..'z], IN['A..'Z], IN['0..'9], '- => { }; -- extend id ENDCASE => { token.type _ identifier; GOTO Back }; plus => SELECT char FROM IN['0..'9] => { state _ int }; -- first integer digit '+ => { state _ file; GOTO Begin }; -- begin insertfile ENDCASE => { err _ illegalChar; GOTO Back }; -- plus sign alone minus => SELECT char FROM IN['0..'9] => { state _ int }; -- first integer digit '- => { state _ ann; GOTO Begin }; -- begin annotation ENDCASE => { err _ illegalChar; GOTO Back }; -- minus sign alone ast => SELECT char FROM '* => { state _ com; GOTO Begin }; -- begin comment ENDCASE => { err _ illegalChar; GOTO Back }; -- asterisk alone int => SELECT char FROM IN['0..'9] => { }; -- integer digit '. => { state _ frac }; -- fraction follows '/ => { state _ den1 }; -- denominator follows 'E, 'e => { state _ exp1 }; -- exponent follows ENDCASE => { token.type _ integer; GOTO Back }; -- integer token den1 => SELECT char FROM IN['0..'9] => { state _ den3 }; -- first denominator digit '+, '- => { state _ den2 }; -- denominator sign ENDCASE => { err _ invalidRational; GOTO Back }; den2 => SELECT char FROM IN['0..'9] => { state _ den3 }; -- first denominator digit (after sign) ENDCASE => { err _ invalidRational; GOTO Back }; den3 => SELECT char FROM IN['0..'9] => { }; -- denominator digit ENDCASE => { token.type _ rational; GOTO Back }; -- rational token dot => SELECT char FROM IN['0..'9] => { state _ frac }; -- first fraction digit ENDCASE => { err _ illegalChar; GOTO Back }; -- dot alone frac => SELECT char FROM IN['0..'9] => { }; -- fraction digit 'E, 'e => { state _ exp1 }; -- exponent follows ENDCASE => { token.type _ real; GOTO Back }; -- real token (no exponent) exp1 => SELECT char FROM IN['0..'9] => { state _ exp3 }; -- first exponent digit '+, '- => { state _ exp2 }; -- exponent sign ENDCASE => { err _ invalidReal; GOTO Back }; exp2 => SELECT char FROM IN['0..'9] => { state _ exp3 }; -- first exponent digit (after sign) ENDCASE => { err _ invalidReal; GOTO Back }; exp3 => SELECT char FROM IN['0..'9] => { }; -- exponent digit ENDCASE => { token.type _ real; GOTO Back }; -- real token (with exponent) string => SELECT char FROM '> => { token.type _ string; GOTO Lop1 }; -- end string token '# => { BeginEscape[]; state _ escape }; -- begin escape sequence ENDCASE => { }; -- extend string escape => SELECT char FROM '# => { EndEscape[]; state _ string }; -- end escape sequence ENDCASE => { }; -- extend escape sequence com => SELECT char FROM '* => { state _ com1 }; -- look for second * ENDCASE => { }; -- extend comment com1 => SELECT char FROM '* => { token.type _ comment; GOTO Lop2 }; -- end comment ENDCASE => { state _ com }; -- continue comment file => SELECT char FROM '+ => { state _ file1 }; -- look for second + ENDCASE => { }; -- extend file name file1 => SELECT char FROM '+ => { token.type _ insertfile; GOTO Lop2 }; -- end insertfile ENDCASE => { state _ file }; -- continue file name ann => SELECT char FROM '- => { state _ ann1 }; -- look for second - ENDCASE => { }; -- extend annotation ann1 => SELECT char FROM '- => { token.type _ annotation; GOTO Lop2 }; -- end annotation ENDCASE => { state _ ann }; -- continue annotation ENDCASE => ERROR; -- unknown state EXITS Begin => text.length _ 0; SingleOp => { token.type _ op; EXIT }; Stop => { EXIT }; Lop1 => { text.length _ text.length-1; EXIT }; Lop2 => { text.length _ text.length-2; EXIT }; Back => { IF got THEN stream.Backup[char]; text.length _ text.length-1; EXIT }; }; char _ stream.GetChar[! IO.EndOfStream => IF got THEN { char _ ' ; got _ FALSE; CONTINUE }]; ENDLOOP; reader.text _ text; IF err#ok THEN ERROR Error[$illegalToken, SELECT err FROM illegalChar => "Illegal character.", invalidRational => "Invalid rational.", invalidReal => "Invalid real number.", invalidEscape => "Invalid escape sequence in string.", ENDCASE => NIL]; SELECT token.type FROM $nil => ERROR Error[$bug, "WrittenGetLiteral didn't set token type."]; $op => IF token.op=$nil THEN { token.op _ OpFromRope[RefText.TrustTextAsRope[text]]; IF token.op=$nil THEN token.type _ identifier; }; $comment, $annotation => IF flushComments THEN LOOP; ENDCASE; EXIT; REPEAT EndOfFile => token.type _ eof; ENDLOOP; reader.token _ token; }; ParseInt: PROC[text: REF TEXT, start: NAT _ 0, len: NAT _ NAT.LAST] RETURNS[x: INT] ~ { s: NAT ~ MIN[start, text.length]; n: NAT ~ MIN[len, text.length-s]; IF s=0 AND n=text.length THEN x _ Convert.IntFromRope[RefText.TrustTextAsRope[text]] ELSE { scratch: REF TEXT ~ RefText.ObtainScratch[n]; { ENABLE UNWIND => RefText.ReleaseScratch[scratch]; temp: REF TEXT ~ RefText.Append[to: scratch, from: text, start: s, len: n]; x _ Convert.IntFromRope[RefText.TrustTextAsRope[temp]]; }; RefText.ReleaseScratch[scratch]; }; }; ParseReal: PROC[text: REF TEXT, start: NAT _ 0, len: NAT _ NAT.LAST] RETURNS[x: REAL] ~ { s: NAT ~ MIN[start, text.length]; n: NAT ~ MIN[len, text.length-s]; IF s=0 AND n=text.length THEN x _ Convert.RealFromRope[RefText.TrustTextAsRope[text]] ELSE { scratch: REF TEXT ~ RefText.ObtainScratch[n]; { ENABLE UNWIND => RefText.ReleaseScratch[scratch]; temp: REF TEXT ~ RefText.Append[to: scratch, from: text, start: s, len: n]; x _ Convert.RealFromRope[RefText.TrustTextAsRope[temp]]; }; RefText.ReleaseScratch[scratch]; }; }; WrittenReadInt: PROC[reader: Reader] RETURNS[INT] ~ { SELECT reader.token.type FROM $shortNumber => RETURN[reader.shortNumber]; $integer => RETURN[ParseInt[reader.text]]; ENDCASE => ERROR Error[$illegalArgument, "Token is not an integer."]; }; WrittenReadReal: PROC[reader: Reader] RETURNS[REAL] ~ { SELECT reader.token.type FROM $integer, $real => RETURN[ParseReal[reader.text]]; ENDCASE => ERROR Error[$illegalArgument, "Token type is not $integer or $real."]; }; WrittenReadRational: PROC[reader: Reader] RETURNS[Rational] ~ { text: REF TEXT ~ reader.text; SELECT reader.token.type FROM $rational => { slash: NAT ~ RefText.Find[s1: text, s2: "/"]; { ENABLE Error => IF code=$overflow THEN GOTO Overflow; num: INT ~ ParseInt[text: text, len: slash]; den: INT ~ ParseInt[text: text, start: slash+1]; RETURN[[int[num: num, den: den]]]; EXITS Overflow => { num: REAL ~ ParseReal[text: text, len: slash]; den: REAL ~ ParseReal[text: text, start: slash+1]; RETURN[[real[num: num, den: den]]]; }; }; }; ENDCASE => ERROR Error[$illegalArgument, "Token is not a rational."]; }; WrittenReadVector: PROC[reader: Reader] RETURNS[Vector] ~ { type: TokenType ~ reader.token.type; SELECT reader.token.type FROM $vector => ERROR Error[$unimplemented, "Can't handle $vector yet."]; ENDCASE => ERROR Error[$illegalArgument, "Token is not a vector."]; }; writtenWriterProcs: WriterProcs ~ NEW[WriterProcsRep _ [ putOp: WrittenPutOp, putInt: WrittenPutInt, putReal: WrittenPutReal, putRational: WrittenPutRational, putIdentifier: WrittenPutIdentifier, putString: WrittenPutString, putInsertfile: WrittenPutInsertfile, putComment: WrittenPutComment, putAnnotation: WrittenPutAnnotation ]]; WrittenPutOp: PROC[writer: Writer, op: Op] = { stream: STREAM ~ writer.stream; rope: ROPE ~ RopeFromOp[op]; IF rope=NIL THEN ERROR Error[$illegalArgument, "Illegal argument to PutOp."]; stream.PutRope[rope]; stream.PutChar[' ]; }; WrittenPutInt: PROC[writer: Writer, value: INT] = { stream: STREAM ~ writer.stream; stream.Put[IO.int[value]]; stream.PutChar[' ]; }; WrittenPutReal: PROC[writer: Writer, value: REAL] = { stream: STREAM ~ writer.stream; stream.Put[IO.real[value]]; stream.PutChar[' ]; }; WrittenPutRational: PROC[writer: Writer, value: Rational] = { stream: STREAM ~ writer.stream; WITH value: value SELECT FROM int => { stream.Put[IO.int[value.num]]; stream.PutChar['/]; stream.Put[IO.int[value.den]]; stream.PutChar[' ]; }; real => WrittenPutReal[writer, value.num/value.den]; ENDCASE => ERROR; }; WrittenPutIdentifier: PROC[writer: Writer, rope: ROPE] = { stream: STREAM ~ writer.stream; ok: BOOL _ FALSE; len: INT ~ rope.Length[]; IF len=0 THEN ERROR Error[$illegalArgument]; FOR i: INT IN[0..len) DO char: CHAR ~ rope.Fetch[i]; IF i=0 THEN SELECT char FROM IN['a..'z] => ok _ TRUE; IN['A..'Z] => NULL; ENDCASE => ERROR Error[$illegalArgument] ELSE SELECT char FROM IN['a..'z], IN['0..'9], '- => ok _ TRUE; IN['A..'Z] => NULL; ENDCASE => ERROR Error[$illegalArgument]; stream.PutChar[char]; ENDLOOP; IF NOT ok AND OpFromRope[rope]#nil THEN Error[$illegalArgument]; stream.PutChar[' ]; }; WrittenPutString: PROC[writer: Writer, rope: ROPE] = { stream: STREAM ~ writer.stream; stream.PutChar['<]; FOR i: INT IN[0..rope.Length) DO char: CHAR ~ rope.Fetch[i]; SELECT char FROM '>, '#, <40C, >176C => { stream.PutChar['#]; stream.Put[IO.int[char-0C]]; stream.PutChar['#]; }; ENDCASE => stream.PutChar[char]; ENDLOOP; stream.PutChar['>]; stream.PutChar[' ]; }; WrittenPutComment: PROC[writer: Writer, rope: ROPE] = { stream: STREAM ~ writer.stream; stream.PutRope["**"]; stream.PutRope[rope]; stream.PutRope["**"]; stream.PutChar[' ]; }; WrittenPutInsertfile: PROC[writer: Writer, rope: ROPE] = { stream: STREAM ~ writer.stream; stream.PutRope["++ "]; stream.PutRope[rope]; stream.PutRope[" ++"]; stream.PutChar[' ]; }; WrittenPutAnnotation: PROC[writer: Writer, rope: ROPE] = { stream: STREAM ~ writer.stream; stream.PutRope["--"]; stream.PutRope[rope]; stream.PutRope["--"]; stream.PutChar[' ]; }; RegisterEncoding[name: "Written", version: [2, 1], readerProcs: writtenReaderProcs, writerProcs: writtenWriterProcs]; END. ^IPWrittenMasterImpl.mesa Last edited by: Doug Wyatt, February 29, 1984 5:28:06 pm PST Ê¥˜Jšœ™J™šœ™Jšœ,™,—J˜šÏk ˜ Jšœœ˜*JšœœLœ˜\Jšœœ˜Jšœ œŒ˜šJšœœR˜_Jšœœœ˜!Jšœœ˜*J˜—Jšœœ˜"Jšœ œ!˜4Jšœœœ œ˜J˜Jšœœœ˜Jšœœœœ˜J˜Jšœœœ˜!Jšœ œœœ˜2J˜JšœœœœÓ˜ˆJ˜Jšœ.˜.J˜šÏnœœ œœ˜OJšœ'œ˜.šœœ˜Jšœœ˜šœœœ˜Jšœœœ ˜Jš œ%œœœœ˜—šœœ˜JšœŸ˜#JšœŸ˜+JšœŸ˜.JšœŸ˜/Jšœœ Ÿ˜@—šœœ˜JšœŸ˜:JšœŸ˜/Jšœœ˜0—šœœ˜JšœŸ'˜GJšœœ˜0—šœœ˜JšœŸ˜'JšœœŸ˜B—šœœ˜JšœŸ˜7Jšœœ Ÿ ˜9—šœœ˜JšœŸ˜$JšœŸ˜/Jšœœ Ÿ˜H—šœœ˜JšœŸ˜7JšœŸ˜,Jšœœ˜,—šœœ˜JšœŸ$˜DJšœœ˜,—šœœ˜JšœŸ˜$Jšœœ Ÿ˜J—šœ œ˜Jšœœ Ÿ˜=Jšœ)Ÿ˜AJšœ Ÿ˜ —šœ œ˜Jšœ'Ÿ˜=Jšœ Ÿ˜)—šœœ˜JšœŸ˜,Jšœ Ÿ˜!—šœœ˜Jšœœ Ÿ˜9JšœŸ˜/—šœœ˜JšœŸ˜-Jšœ Ÿ˜#—šœ œ˜Jšœ!œ Ÿ˜?JšœŸ˜2—šœœ˜JšœŸ˜,Jšœ Ÿ˜$—šœœ˜Jšœ!œ Ÿ˜?JšœŸ˜2—JšœœŸ˜"—š˜J˜Jšœœ˜&Jšœ œ˜Jšœ'œ˜.Jšœ'œ˜.Jšœ œœ3œ˜O—J˜šœ˜Jš œœœœœ˜D—Jšœ˜—J˜š œœœœ˜9Jšœ$˜$Jšœ'˜'Jšœ&˜&Jšœ6˜6Jšœœ˜—šœ ˜Jšœœ9˜Fšœœœ˜Jšœ5˜5Jšœœ˜.Jšœ˜—Jšœœœœ˜4Jšœ˜—Jšœ˜š˜Jšœ˜—Jšœ˜—J˜J˜—J˜šžœœœœ œ œœœœœ˜WJšœœœ˜!Jšœœœ˜!Jšœœœ7˜Tšœ˜Jšœ œœ˜-šœœœ$˜3Jšœœœ=˜KJšœ7˜7J˜—Jšœ ˜ J˜—J˜J˜—šž œœœœ œ œœœœœ˜YJšœœœ˜!Jšœœœ˜!Jšœœœ8˜Ušœ˜Jšœ œœ˜-šœœœ$˜3Jšœœœ=˜KJšœ8˜8J˜—Jšœ ˜ J˜—J˜J˜—šžœœœœ˜5šœ˜Jšœœ˜+Jšœ œ˜*Jšœœ5˜E—J˜J˜—šžœœœœ˜7šœ˜Jšœœ˜2JšœœA˜Q—J˜J˜—šžœœœ˜?Jšœœœ˜šœ˜šœ˜Jšœœ#˜-š œœ œœœ ˜7Jšœœ$˜,Jšœœ(˜0Jšœ˜"šœ˜Jšœœ%˜.Jšœœ)˜2Jšœ˜#J˜—J˜—J˜—Jšœœ5˜E—J˜J˜—šžœœœ ˜;J˜$šœ˜Jšœ œ4˜DJšœœ3˜C—J˜J˜—J˜šœ"œ˜8Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšœ$˜$Jšœ˜Jšœ$˜$Jšœ˜Jšœ#˜#Jšœ˜J˜—šž œœ˜.Jšœœ˜Jšœœ˜Jšœœœœ7˜MJšœ˜Jšœ˜Jšœ˜J˜—šž œœœ˜3Jšœœ˜Jšœ œ ˜Jšœ˜Jšœ˜J˜—šžœœœ˜5Jšœœ˜Jšœ œ˜Jšœ˜Jšœ˜J˜—šžœœ%˜=Jšœœ˜šœœ˜˜Jšœ œ˜Jšœ˜Jšœ œ˜Jšœ˜J˜—Jšœ4˜4Jšœœ˜—Jšœ˜J˜—šžœœœ˜:Jšœœ˜Jšœœœ˜Jšœœ˜Jšœœœ˜,šœœœ ˜Jšœœ˜šœœœ˜Jšœœ˜Jšœ œ˜Jšœœ˜(—šœœ˜Jšœ œœ˜(Jšœ œ˜Jšœœ˜)—Jšœ˜Jšœ˜—Jšœœœœ˜@Jšœ˜Jšœ˜J˜—šžœœœ˜6Jšœœ˜Jšœ˜šœœœ˜ Jšœœ˜šœ˜˜Jšœ˜Jšœ œ˜Jšœ˜J˜—Jšœ˜ —Jšœ˜—Jšœ˜Jšœ˜Jšœ˜J˜—šžœœœ˜7Jšœœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜—šžœœœ˜:Jšœœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜—šžœœœ˜:Jšœœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜—J˜˜2J˜B—J˜Jšœ˜—…—?ŽP‘