DIRECTORY Ascii: TYPE USING [CR, DEL, ESC, NUL, SP], CommanderOps: TYPE USING [ CommandBlock, CommandBlockHandle, CommandParam, ParamType], Exec: TYPE, Frame: TYPE USING [MyLocalFrame], Inline: TYPE USING [BITAND, BITOR], PrincOps: TYPE USING [StateVector], Runtime: TYPE USING [CallDebugger], Storage: TYPE USING [Node, String, CopyString, Free], String: TYPE USING [ AppendChar, AppendString, EquivalentString, InvalidNumber,StringBoundsFault], Time: TYPE USING [AppendCurrent], TTY: TYPE, UserTerminal: TYPE; CommanderImpl: PROGRAM IMPORTS Exec, Frame, Inline, Runtime, Storage, String, Time, TTY, UserTerminal EXPORTS CommanderOps = { OPEN String, CommanderOps, Ascii; CommandItem: TYPE = RECORD [ cb: CommandBlockHandle, link: POINTER TO CommandItem]; StringItem: TYPE = RECORD [link: POINTER TO StringItem, string: STRING]; commandHead: POINTER TO CommandItem _ NIL; stringHead: POINTER TO StringItem _ NIL; SyntaxError: ERROR = CODE; Help: SIGNAL = CODE; BadName: ERROR = CODE; BadParam: ERROR [type: ParamType] = CODE; GetDebugger: PROC = {Runtime.CallDebugger[NIL]}; ExtensionIs: PROC [name, ext: STRING] RETURNS [BOOL] = { t: STRING _ [40]; i: CARDINAL; IF name.length <= ext.length THEN RETURN[FALSE]; FOR i IN [name.length - ext.length..name.length) DO String.AppendChar[t, name[i]] ENDLOOP; RETURN [String.EquivalentString[t, ext]]}; CheckForExtension: PROC [name, ext: STRING] = { i: CARDINAL; FOR i IN [0..name.length) DO IF name[i] = '. THEN RETURN ENDLOOP; String.AppendString[name, ext]}; AddCommand: PUBLIC PROC [name: STRING, proc: PROC, numargs: CARDINAL] RETURNS [CommandBlockHandle] = { OPEN Storage; c: POINTER TO CommandItem _ Node[SIZE[CommandItem]]; cb: CommandBlockHandle _ Node[ SIZE[CommandBlock] + numargs*SIZE[CommandParam]]; c^ _ CommandItem[cb: cb, link: commandHead]; commandHead _ c; cb.name _ name; cb.proc _ proc; cb.nparams _ numargs; RETURN [cb]}; NewString: PROC [s: STRING] RETURNS [ns: STRING] = { OPEN Storage; si: POINTER TO StringItem _ Node[SIZE[StringItem]]; si^ _ StringItem[link: stringHead, string: ns _ CopyString[s]]; stringHead _ si; RETURN}; FreeStrings: PROC = { OPEN Storage; next: POINTER TO StringItem; WHILE stringHead # NIL DO next _ stringHead.link; Free[stringHead.string]; Free[stringHead]; stringHead _ next; ENDLOOP}; WriteEOL: PROC = {IF ~TTY.NewLine[Exec.w] THEN TTY.PutCR[Exec.w]}; firstCommand: BOOL _ TRUE; interactive: BOOL _ FALSE; SetupCom: PROC [c: POINTER TO Exec.CommandLine _ @Exec.commandLine] RETURNS [BOOL] = {RETURN[~(c.s = NIL OR c.i >= c.s.length)]}; SkipToken: PROC [c: POINTER TO Exec.CommandLine _ @Exec.commandLine] = { foundToken: BOOL _ FALSE; ch: CHAR; DO IF c.i >= c.s.length THEN EXIT; ch _ c.s[c.i]; c.i _ c.i + 1; SELECT ch FROM Ascii.SP, Ascii.CR => IF foundToken THEN EXIT; ENDCASE => foundToken _ TRUE; ENDLOOP}; line: STRING _ NIL; lineTerminator: CHAR; Lindex: CARDINAL; AppendStringToLine: PROC [s: STRING] = { UNTIL (s.length + line.length) <= line.maxlength DO AddToLine[]; ENDLOOP; AppendString[line, s]}; AppendCharToLine: PROC [c: CHAR] = { IF line.length = line.maxlength THEN AddToLine[]; AppendChar[line, c]}; ReadUserLine: PROC [newstring: BOOL] = { IF line = NIL THEN line _ Storage.String[80]; [] _ TTY.GetEditedString[Exec.w, line, LineMonitor, newstring ! resume => {newstring _ FALSE; RETRY}]; Lindex _ 0}; resume: SIGNAL = CODE; LineMonitor: PROC [c: CHAR] RETURNS [BOOL] = { SELECT c FROM CR => RETURN[TRUE]; '? => { WriteChar['?]; IF line.length = 0 THEN SIGNAL Help; PromptCompletions[]; SIGNAL resume; ERROR}; ESC => {ExtendLine[]; SIGNAL resume; ERROR}; ENDCASE => RETURN [FALSE]}; PromptCompletions: PROC = { id: STRING = [40]; atLeastOne: BOOL _ FALSE; p: POINTER TO CommandItem; IF GetLastID[id] THEN FOR p _ commandHead, p.link UNTIL p = NIL DO IF PrefixString[prefix: id, of: p.cb.name] THEN { IF ~atLeastOne THEN WriteEOL[]; WriteChar[SP]; WriteChar[SP]; WriteString[p.cb.name]; atLeastOne _ TRUE}; ENDLOOP; IF atLeastOne THEN ReTypeLine[] ELSE UserTerminal.BlinkDisplay[]}; ExtendLine: PROC = { i: CARDINAL; id: STRING = [40]; match: STRING = [40]; moreThanOne, atLeastOne: BOOL _ FALSE; p: POINTER TO CommandItem; IF GetLastID[id] THEN { FOR p _ commandHead, p.link UNTIL p = NIL DO IF PrefixString[prefix: id, of: p.cb.name] THEN IF ~atLeastOne THEN { AppendString[match, p.cb.name]; atLeastOne _ TRUE} ELSE {AndString[match, p.cb.name]; moreThanOne _ TRUE}; ENDLOOP}; IF atLeastOne AND id.length # match.length THEN { FOR i IN [id.length..match.length) DO AppendCharToLine[match[i]]; WriteChar[match[i]]; ENDLOOP; IF moreThanOne THEN UserTerminal.BlinkDisplay[]} ELSE UserTerminal.BlinkDisplay[]}; PrefixString: PROC [prefix, of: STRING] RETURNS [BOOL] = { IF prefix.length > of.length THEN RETURN[FALSE]; FOR i: CARDINAL IN [0..prefix.length) DO IF ~EquivalentChar[prefix[i], of[i]] THEN RETURN[FALSE] ENDLOOP; RETURN [TRUE]}; AndString: PROC [accum, s: STRING] = { FOR i: CARDINAL IN [0..s.length) DO IF ~EquivalentChar[accum[i], s[i]] THEN BEGIN accum.length _ i; RETURN END; ENDLOOP; accum.length _ s.length}; GetLastID: PROC [id: STRING] RETURNS [BOOL] = { i, start: CARDINAL; c: CHAR; IF line.length = 0 THEN RETURN[FALSE]; start _ line.length; FOR i DECREASING IN [0..line.length) DO IF AlphaNumeric[c _ line[i]] THEN start _ i ELSE IF c = '] OR c = SP THEN EXIT ELSE RETURN[FALSE]; ENDLOOP; FOR i IN [start..line.length) DO id[i - start] _ line[i] ENDLOOP; id.length _ line.length - start; RETURN [id.length # 0]}; AlphaNumeric: PROC [c: CHAR] RETURNS [BOOL] = { RETURN [Alphabetic[c] OR Digit[c]]}; Alphabetic: PROC [c: CHAR] RETURNS [BOOL] = { RETURN [Inline.BITAND[c, 337b] IN [100b..132b]]}; Digit: PROC [c: CHAR] RETURNS [BOOL] = { RETURN [c IN ['0..'9]]}; EquivalentChar: PROC [c, d: CHAR] RETURNS [BOOL] = { RETURN [Inline.BITOR[c, 40b] = Inline.BITOR[d, 40b]]}; AddToLine: PROC = INLINE {line _ Storage.CopyString[line, 80]}; ReTypeLine: PROC = {WriteEOL[]; WriteString[line]}; command: STRING = [100]; executing: BOOL _ FALSE; Cindex: CARDINAL; currentChar: CHAR; EndOfString: SIGNAL = CODE; GetChar: PROC RETURNS [CHAR] _ GetCommandChar; PutBackChar: PROC _ PutBackCommandChar; GetCommandChar: PROC RETURNS [CHAR] = { IF Cindex >= command.length THEN currentChar _ NUL ELSE BEGIN currentChar _ command[Cindex]; Cindex _ Cindex + 1; END; RETURN [currentChar]}; PutBackCommandChar: PROC = { IF currentChar = NUL THEN RETURN; IF Cindex = 0 THEN ERROR; Cindex _ Cindex - 1}; CommandOverFlow: SIGNAL = CODE; SetUpCommand: PROC RETURNS [BOOL] = { BEGIN ENABLE StringBoundsFault => SIGNAL CommandOverFlow; RETURN [IF interactive THEN CopyFromLine[] ELSE CopyFromExecCommand[]]; END}; CopyFromLine: PROC RETURNS [BOOL] = { c: CHAR _ NUL; DO IF Lindex >= line.length THEN RETURN [FALSE]; c _ line[Lindex]; Lindex _ Lindex + 1; IF c # SP AND c # CR THEN EXIT; ENDLOOP; command.length _ 0; DO AppendChar[command, c]; IF c = '] OR Lindex >= line.length THEN EXIT; c _ line[Lindex]; Lindex _ Lindex + 1; ENDLOOP; Cindex _ 0; RETURN [TRUE]}; SkipExecBlanks: PROC [c: POINTER TO Exec.CommandLine _ @Exec.commandLine] RETURNS [ch: CHAR] = { UNTIL c.i >= c.s.length DO ch _ c.s[c.i]; c.i _ c.i + 1; IF ch # SP AND ch # CR THEN EXIT; ENDLOOP}; WriteChar: PROC [ch: CHAR] = {TTY.PutChar[Exec.w, ch]}; WriteString: PROC [s: STRING] = {TTY.PutString[Exec.w, s]}; WriteLine: PROC [s: STRING] = {TTY.PutLine[Exec.w, s]}; EndOf: PROC [c: POINTER TO Exec.CommandLine _ @Exec.commandLine] RETURNS [BOOL] = { RETURN [c.s = NIL OR c.i >= c.s.length]}; CopyFromExecCommand: PROC [c: POINTER TO Exec.CommandLine _ @Exec.commandLine] RETURNS [BOOL] = { ch: CHAR; IF ~SetupCom[c] THEN {interactive _ TRUE; RETURN [FALSE]}; ch _ SkipExecBlanks[c]; IF EndOf[c] THEN IF firstCommand THEN {interactive _ TRUE; RETURN [FALSE]} ELSE SIGNAL CommandExit; command.length _ 0; WriteEOL[]; WriteChar['<]; WriteChar['>]; DO AppendChar[command, ch]; WriteChar[ch]; IF ch = '] OR EndOf[c] THEN EXIT; ch _ c.s[c.i]; c.i _ c.i + 1; ENDLOOP; WriteEOL[]; Cindex _ 0; RETURN [TRUE]}; GetName: PROC [n: STRING] = { n.length _ 0; DO IF AlphaNumeric[GetChar[]] THEN AppendChar[n, currentChar] ELSE EXIT; ENDLOOP; PutBackChar[]; SkipBlanks[]; IF GetChar[] # '[ THEN SE[]}; SkipBlanks: PROC = { DO IF GetChar[] # SP THEN {PutBackChar[]; RETURN} ENDLOOP}; ParseCommand: PROC [state: POINTER TO PrincOps.StateVector] = { proc: STRING = [40]; cb: CommandBlockHandle; i: CARDINAL; GetName[proc]; cb _ FindProc[proc].cb; FOR i IN [0..cb.nparams) DO state.stk[i] _ GetArg[cb, cb.params[i].type]; IF GetChar[] # (IF i = cb.nparams - 1 THEN '] ELSE ',) THEN SE[]; ENDLOOP; state.dest _ LOOPHOLE[cb.proc]; state.stkptr _ cb.nparams}; FindProc: PROC [name: STRING] RETURNS [p: POINTER TO CommandItem] = { FOR p _ commandHead, p.link UNTIL p = NIL DO IF EquivalentString[name, p.cb.name] THEN RETURN; ENDLOOP; ERROR BadName}; GetArg: PROC [cb: CommandBlockHandle, t: ParamType] RETURNS [a: UNSPECIFIED] = { s: STRING = [100]; SkipBlanks[]; SELECT GetChar[] FROM '" => { IF t # string THEN ERROR BadParam[t]; DO IF GetChar[] = '" AND GetChar[] # '" THEN {PutBackChar[]; EXIT}; IF executing THEN AppendChar[s, currentChar]; ENDLOOP; IF executing THEN a _ NewString[s]}; '' => {IF t # character THEN ERROR BadParam[t]; a _ GetChar[]}; IN ['0..'9], '(, '- => { IF t # numeric THEN ERROR BadParam[t]; PutBackChar[]; a _ ExpressionToNumber[]}; IN ['a..'z], IN ['A..'Z] => { SELECT t FROM boolean => IF currentChar = 'T THEN a _ GetTRUE[t] ELSE IF currentChar = 'F THEN a _ GetFALSE[t]; string => { DO SELECT currentChar FROM ',, '], CR, NUL => {PutBackChar[]; EXIT}; ENDCASE => IF executing THEN AppendChar[s, currentChar]; [] _ GetChar[]; ENDLOOP; IF executing THEN a _ NewString[s]}; ENDCASE => ERROR BadParam[t]}; ENDCASE => ERROR BadParam[t]; SkipBlanks[]; RETURN}; GetTRUE: PROC [t: ParamType] RETURNS [BOOL_TRUE] = { IF GetChar[] # 'R THEN ERROR BadParam[t]; IF GetChar[] # 'U THEN ERROR BadParam[t]; IF GetChar[] # 'E THEN ERROR BadParam[t]}; GetFALSE: PROC [t: ParamType] RETURNS [BOOL_FALSE] = { IF GetChar[] # 'A THEN ERROR BadParam[t]; IF GetChar[] # 'L THEN ERROR BadParam[t]; IF GetChar[] # 'S THEN ERROR BadParam[t]; IF GetChar[] # 'E THEN ERROR BadParam[t]}; ParsePromptedCommand: PROC = { proc: STRING = [40]; cb: CommandBlockHandle; IF GetLastID[proc] THEN { cb _ FindProc[proc].cb; GetPromptedArgs[cb]; Confirm[]; RETURN}; lineTerminator _ CR}; CRFound: PROC [c: CHAR] RETURNS [BOOL] = {RETURN [c = CR]}; GetPromptedArgs: PROC [cb: CommandBlockHandle] = { i: CARDINAL; cindex: CARDINAL; cstring: STRING = [100]; GetArgChar: PROC RETURNS [c: CHAR] = { IF cindex >= cstring.length THEN currentChar _ NUL ELSE BEGIN currentChar _ cstring[cindex]; cindex _ cindex + 1; END; RETURN [currentChar]}; PutBackArgChar: PROC = { IF currentChar = NUL THEN RETURN; IF cindex = 0 THEN ERROR; cindex _ cindex - 1}; GetChar _ GetArgChar; PutBackChar _ PutBackArgChar; AppendCharToLine['[]; FOR i IN [0..cb.nparams) DO WriteString["\n "L]; WriteString[cb.params[i].prompt]; WriteChar[':]; WriteChar[' ]; [] _ TTY.GetEditedString[Exec.w, cstring, CRFound, TRUE]; cindex _ 0; [] _ GetArg[cb, cb.params[i].type]; AppendStringToLine[cstring]; AppendCharToLine[',]; ENDLOOP; IF cb.nparams # 0 THEN line[line.length - 1] _ '] ELSE AppendCharToLine[']]; GetChar _ GetCommandChar; PutBackChar _ PutBackCommandChar}; Confirm: PROC = { char: CHAR; WriteString[" [confirm]"L]; DO char _ TTY.GetChar[Exec.w]; SELECT char FROM DEL => SIGNAL TTY.Rubout; CR => {WriteEOL[]; EXIT}; SP => {WriteString["\n <>"L]; EXIT}; ENDCASE => WriteChar['?]; ENDLOOP; lineTerminator _ char}; symbol: Symbol; Symbol: TYPE = RECORD [ body: SELECT tag: * FROM num => [val: INTEGER], delim => [char: CHAR], ENDCASE]; Num: TYPE = num Symbol; SE: PROC = {ERROR SyntaxError}; Scan: PROC = { v8, v10, radix, number: CARDINAL; digits: ARRAY CHAR ['0..'9] OF CARDINAL = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; firstchar: BOOL _ TRUE; v8 _ v10 _ 0; SkipBlanks[]; DO SELECT GetChar[] FROM IN ['0..'9] => { v8 _ v8*8 + digits[currentChar]; v10 _ v10*10 + digits[currentChar]}; 'M => { IF ~firstchar THEN SE[]; IF ~(GetChar[] = 'O AND GetChar[] = 'D) THEN SE[]; IF ~Alphabetic[GetChar[]] THEN PutBackChar[] ELSE SE[]; symbol _ [delim['!]]; RETURN}; 'b, 'B => {number _ v8; radix _ 8; GOTO exponent}; 'd, 'D => {number _ v10; radix _ 10; GOTO exponent}; SP => GOTO done; NUL => IF ~firstchar THEN GOTO done ELSE {symbol _ nul; RETURN}; '(, '/, '*, '+, '-, '), '], ', => IF firstchar THEN {symbol _ [delim[currentChar]]; RETURN} ELSE {PutBackChar[]; GOTO done}; ENDCASE => SIGNAL InvalidNumber; firstchar _ FALSE; REPEAT done => {symbol _ [num[v10]]; RETURN}; exponent => { IF firstchar THEN SE[]; v10 _ 0; WHILE Digit[GetChar[]] DO v10 _ v10*10 + digits[currentChar]; REPEAT FINISHED => PutBackChar[]; -- took one too many ENDLOOP; THROUGH [1..v10] DO number _ number*radix ENDLOOP; symbol _ [num[number]]; RETURN}; ENDLOOP}; nul: Symbol = [delim[NUL]]; Primary: PROC RETURNS [n: Num] = { WITH s: symbol SELECT FROM delim => { IF s.char # '( THEN SE[]; Scan[]; n _ Exp[]; WITH symbol SELECT FROM delim => IF char = ') THEN {Scan[]; RETURN}; ENDCASE; SE[]}; num => {n _ s; Scan[]; RETURN}; ENDCASE}; Factor: PROC RETURNS [n: Num] = { WITH symbol SELECT FROM delim => IF char = '- THEN {Scan[]; n _ Primary[]; n.val _ -n.val; RETURN}; ENDCASE; RETURN [Primary[]]}; Product: PROC RETURNS [n: Num] = { x: Num; n _ Factor[]; DO WITH symbol SELECT FROM delim => SELECT char FROM '* => {Scan[]; n.val _ Factor[].val*n.val}; '/ => {Scan[]; x _ Factor[]; n.val _ n.val/x.val}; '! => {Scan[]; x _ Factor[]; n.val _ n.val MOD x.val}; ENDCASE => EXIT; ENDCASE => EXIT; ENDLOOP; RETURN}; Exp: PROC RETURNS [n: Num] = { n _ Product[]; DO WITH symbol SELECT FROM delim => SELECT char FROM '+ => {Scan[]; n.val _ Product[].val + n.val}; '- => {Scan[]; n.val _ n.val - Product[].val}; '], ', => {PutBackChar[]; EXIT}; NUL, ') => EXIT; ENDCASE => SE[]; ENDCASE => EXIT; ENDLOOP; RETURN}; ExpressionToNumber: PROC RETURNS [INTEGER] = { Scan[]; RETURN[Exp[].val]}; ShowSE: PROC = { IF ~executing THEN {WriteChar['?]; RETURN}; WriteEOL[]; IF interactive THEN WriteString[command]; WriteEOL[]; THROUGH [1..(Cindex + (IF interactive THEN 0 ELSE 2))) DO WriteChar['.]; ENDLOOP; WriteChar['^]}; Driver: PROC = { state: --lst-- PrincOps.StateVector; newline: BOOL; ci: POINTER TO CommandItem; i: CARDINAL; BEGIN ENABLE { SyntaxError, InvalidNumber, StringBoundsFault => { ShowSE[]; GO TO abort}; CommandOverFlow => { WriteEOL[]; WriteString["Command too long!"L]; GO TO abort}; BadName => {ShowSE[]; WriteString[" not found!"L]; GO TO abort}; BadParam => { ShowSE[]; WriteString[" expected "L]; SELECT type FROM string => WriteString["string"L]; character => WriteString["character"L]; numeric => WriteString["numerical"L]; ENDCASE; WriteString[" parameter"L]; GO TO abort}; TTY.Rubout => {WriteString[" XXX"L]; GO TO abort}; Help => { WriteEOL[]; FOR ci _ commandHead, ci.link UNTIL ci = NIL DO WriteString[ci.cb.name]; WriteChar['[]; FOR i IN [0..ci.cb.nparams) DO IF i # 0 THEN WriteChar[',]; SELECT ci.cb.params[i].type FROM string => WriteChar['"]; character => WriteChar['']; ENDCASE; WriteString[ci.cb.params[i].prompt]; SELECT ci.cb.params[i].type FROM string => WriteChar['"]; ENDCASE; ENDLOOP; WriteChar[']]; IF ci.link # NIL THEN BEGIN WriteChar[',]; WriteChar[' ]; END; ENDLOOP; GO TO abort}; UNWIND => FreeStrings[]}; newline _ TRUE; executing _ FALSE; IF interactive THEN { WriteEOL[]; WriteChar['<]; WriteChar['>]; DO ENABLE StringBoundsFault => {AddToLine[]; RESUME [line]}; ReadUserLine[newline]; newline _ FALSE; ParsePromptedCommand[]; IF lineTerminator = CR THEN EXIT; ENDLOOP}; GetChar _ GetCommandChar; PutBackChar _ PutBackCommandChar; executing _ TRUE; WHILE SetUpCommand[] DO ParseCommand[@state]; state.instbyte _ 0; state.source _ LOOPHOLE[Frame.MyLocalFrame[]]; firstCommand _ FALSE; TRANSFER WITH state; state _ STATE; ENDLOOP; executing _ FALSE; EXITS abort => NULL; END; FreeStrings[]}; Quit: PROC = {SIGNAL CommandExit}; WriteHerald: PROC = { time: STRING _ [22]; WriteEOL[]; IF h # NIL THEN WriteLine[h]; Time.AppendCurrent[time]; time.length _ time.length - 3; WriteLine[time]}; h: STRING _ NIL; InitCommander: PUBLIC PROC [herald: STRING] = { h _ herald; [] _ AddCommand["Quit", Quit, 0]; [] _ AddCommand["Debug", GetDebugger, 0]}; CommandExit: SIGNAL = CODE; WaitCommands: PUBLIC PROC = { IF h = NIL THEN InitCommander[NIL]; executing _ interactive _ FALSE; firstCommand _ TRUE; WriteHerald[]; DO Driver[ ! CommandExit => EXIT]; ENDLOOP}; }. CommandLine ::= PromptedCommandList | NonPromptedCommandList ; NonPromptedCommandList PromptedCommandList ::= PromptedCommand | Command | CommandList Command | CommandList PromptedCommand NonPromptedCommandList ::= Command | CommandList Command Command ::= ID [ ParamList ] PromptedCommand ::= ID PromptedParamList ParamList ::= Param | ParamList , Param PromptedParamList ::= Param | PromptedParamList Param Param ::= " STRING " | ' CHAR | Expression | Expression ::= Product | Expression + Product | Expression - Product Product ::= Factor | Product * Factor | Product / Factor | Product MOD Factor Factor ::= - Primary | Primary Primary ::= NUM | ( Expression ) úfile CommanderImpl.mesa edited by Johnsson, 9-Sep-80 20:35:49 edited by Sweet, 20-Apr-81 14:44:22 edited by Bruce, 10-Jan-81 15:32:29 edited by Satterthwaite, September 20, 1982 1:33 pm code to get a line from the user, handling ESC and ?; stuffs it in line read line from user; also handles and '? for input from user code to handle characters code to parse user command code to parse user commands in interactive mode parsing arithmetic expressions Here is the grammar for the command line Ê©˜Jšœ™Jšœ&™&Jšœ#™#Jšœ#™#Jšœ3™3J˜šÏk ˜ Jšœœœœœœœœ˜*šœœœ˜J˜;—Jšœœ˜ Jšœœœ˜!Jš œœœœœ˜#Jšœ œœ˜#Jšœ œœ˜#Jšœ œœ"˜5šœœœ˜J˜M—Jšœœœ˜!Jšœœ˜ Jšœœ˜J˜—šœ˜Jšœ6œ˜NJšœ˜Jšœ˜!J˜šœ œœ˜Jšœœœ˜6J˜—Jš œ œœœœœ˜HJ˜Jšœ œœœ˜*Jšœ œœœ˜(J˜Jšœ œœ˜Jšœœœ˜Jšœ œœ˜Jšœ œœ˜)J˜JšÏn œœœ˜0J˜š ž œœ œœœ˜8Jšœœ˜Jšœœ˜ Jšœœœœ˜0šœœ)˜3Jšœœ˜&—Jšœ$˜*J˜—šžœœ œ˜/Jšœœ˜ Jšœœœœœœœ˜AJ˜ J˜—š ž œœœœœ œ˜EJšœ˜ Jšœ ˜ Jšœœœœ˜4˜Jšœœ˜1—J˜,J˜J˜J˜J˜Jšœ˜ J˜—š ž œœœœœ˜4Jšœ ˜ Jšœœœœ˜3J˜?J˜Jšœ˜J˜—šž œœ˜Jšœ ˜ Jšœœœ ˜šœœ˜J˜J˜J˜J˜Jšœ˜ J˜——Jš žœœœœœœ˜BJ˜Jšœœœ˜Jšœ œœ˜J˜š žœœœœ'œœ˜TJšœœ œœ˜,J˜—šž œœœœ*˜HJšœ œœ˜Jšœœ˜ š˜Jšœœœ˜J˜šœ˜Jš œœœœ œœ˜.Jšœœ˜—Jšœ˜ J˜——JšœG™GJ˜Jšœœœ˜Jšœœ˜Jšœœ˜J˜šžœœœ˜(Jšœ,œœ˜IJ˜J˜—šžœœœ˜$Jšœœ ˜1J˜J˜—šž œœ œ˜(JšœB™BJšœœœ˜-šœœ7˜?Jšœœœ˜&—J˜ J˜—Jšœœœ˜J˜š ž œœœœœ˜.šœ˜ Jšœœœ˜˜J˜Jšœœœ˜$J˜Jšœ˜Jšœ˜—Jšœœ œ˜,Jšœœœ˜J˜——šžœœ˜Jšœœ˜Jšœ œœ˜Jšœœœ ˜šœ˜šœœœ˜,šœ)œ˜1Jšœ œ ˜Jšœ œ˜Jšœ œ˜J˜Jšœ œ˜—Jšœ˜——Jšœ œœ˜BJ˜—šž œœ˜Jšœœ˜ Jšœœ˜Jšœœ˜Jšœœœ˜&Jšœœœ ˜šœœ˜šœœœ˜,šœ)˜/šœ œ˜Jšœ-œ˜2—Jšœ-œ˜7—Jšœ˜ ——šœ œœ˜1šœœ˜%Jšœ1œ˜9—Jšœ œ˜0—Jšœ˜"J˜—š ž œœœœœ˜:Jšœœœœ˜0šœœœ˜(Jš œ#œœœœ˜@—Jšœœ˜J˜—šž œœ œ˜&šœœœ˜#Jš œ!œœœœ˜KJšœ˜—J˜J˜—š ž œœœœœ˜/Jšœ œ˜Jšœœ˜Jšœœœœ˜&J˜šœ œœ˜'Jšœœ ˜+Jšœœœœœœœœœ˜6Jšœ˜—Jšœœœœ˜AJ˜ Jšœ˜J˜—š ž œœœœœ˜/Jšœœ ˜$J˜—š ž œœœœœ˜-Jšœ œ œ˜1J˜—š žœœœœœ˜(Jšœœ ˜J˜—š žœœœœœ˜4Jšœ œœ ˜6J˜—Jšž œœœ'˜?J˜Jšž œœ#˜3J˜Jšœ™J˜Jšœ œ ˜Jšœ œœ˜Jšœœ˜Jšœ œ˜J˜Jšœ œœ˜J˜Jšžœœœœ˜.J˜Jšž œœ˜'J˜šžœœœœ˜'Jšœœ˜2Jšœœ5œ˜CJšœ˜J˜—šžœœ˜Jšœœœœ˜!Jšœ œœ˜J˜J˜—Jšœœœ˜J˜šž œœœœ˜%Jš˜Jšœœ˜3Jšœœ œœ˜GJšœ˜J˜—šž œœœœ˜%Jšœœœ˜š˜Jšœœœœ˜-J˜J˜Jš œœœœœœ˜Jšœ˜—J˜š˜J˜Jšœœœœ˜-J˜J˜Jšœ˜—J˜ Jšœœ˜J˜—šžœœœœ&˜IJšœœ˜šœ˜Jš œœœœœœœ˜?Jšœ˜ J˜——Jšž œœœœ˜7J˜Jšž œœœœ˜;J˜Jšž œœœœ˜7J˜š žœœœœ'œœ˜SJšœœœ˜)J˜—šžœœœœ&˜NJšœœ˜Jšœœ˜ Jš œœœœœ˜:J˜šœ ˜Jš œœœœœ˜9Jšœœ ˜—J˜J˜ J˜J˜š˜J˜J˜Jšœ œ œœ˜!J˜Jšœ˜—J˜ J˜ Jšœœ˜J˜—šžœœœ˜J˜ š˜Jšœœœœ˜EJšœ˜—J˜J˜ Jšœœœ˜J˜—šž œœ˜Jš œœ œœœœ˜;J˜—Jšœ™J˜J˜šž œœ œœ˜?Jšœœ˜J˜Jšœœ˜ J˜J˜šœœ˜J˜-Jš œœœœœœ˜AJšœ˜—Jšœ œ ˜J˜J˜—š žœœœœœœ˜Ešœœœ˜,Jšœ#œœœ˜:—Jšœ ˜J˜—šžœœ(œ œ˜PJšœœ ˜J˜ šœ ˜˜Jšœ œœ ˜%š˜Jšœœœœ˜@Jšœ œ˜-Jšœ˜—Jšœ œ˜$—Jšœœœœ˜?šœ˜Jšœ œœ ˜&J˜J˜—šœ œ˜šœ˜ ˜ Jšœœ˜'Jšœœœ˜.—˜ š˜šœ ˜Jšœœœœ˜)Jšœœ œ˜8—J˜Jšœ˜—Jšœ œ˜$—Jšœœ˜——Jšœœ ˜—J˜ Jšœ˜J˜—š žœœœœœ˜4Jšœœœ ˜)Jšœœœ ˜)Jšœœœ˜*J˜—š žœœœœœ˜6Jšœœœ ˜)Jšœœœ ˜)Jšœœœ ˜)Jšœœœ˜*J˜—Jšœ/™/J˜J˜šžœœ˜Jšœœ˜J˜šœœ˜Jšœ8œ˜@—Jšœœ˜J˜—Jšžœœœœœœœ˜;J˜šžœœ˜2Jšœœ˜ Jšœœ˜Jšœ œ ˜J˜šž œœœœ˜&Jšœœ˜2Jšœœ5œ˜CJšœ˜J˜—šžœœ˜Jšœœœœ˜!Jšœ œœ˜J˜J˜—J˜J˜J˜šœœ˜J˜J˜!J˜J˜Jšœœ+œ˜9J˜ J˜#J˜J˜Jšœ˜—Jšœœœ˜LJ˜J˜"J˜—šžœœ˜Jšœœ˜ J˜š˜Jšœœ˜šœ˜Jšœœœ˜Jšœœ˜Jšœœ˜%Jšœ˜—Jšœ˜—J˜J˜—Jšœ™J˜J˜šœœœ˜šœœ˜Jšœ œœœ˜7——Jšœœ˜J˜Jšœœœ˜J˜šžœœ˜Jšœœ˜!Jš œœœ œœ"˜IJšœ œœ˜J˜ J˜ š˜šœ ˜šœ˜J˜ J˜$—˜Jšœ œœ˜Jšœœœœ˜2Jšœœœœ˜7J˜Jšœ˜—Jšœ#œ ˜2Jšœ%œ ˜4Jšœœ˜Jš œœ œœœœ˜@˜!Jšœ œ!œ˜9Jšœœ˜ —Jšœœ˜ —Jšœ œ˜š˜Jšœœ˜&˜ Jšœ œœ˜J˜šœ˜J˜#JšœœÏc˜6Jšœ˜—Jšœ œœ˜2J˜Jšœ˜——Jšœ˜ J˜——Jšœœ˜J˜šžœœœ ˜"šœ œ˜˜ Jšœ œœ˜J˜J˜ šœœ˜Jšœ œ œ œ˜,Jšœ˜—Jšœ˜—Jšœœ˜Jšœ˜ J˜——šžœœœ ˜!šœœ˜˜Jšœ œ)œ˜B—Jšœ˜—Jšœ˜J˜—šžœœœ ˜"J˜J˜ š˜šœœ˜˜šœ˜J˜+J˜2Jšœ+œ˜6Jšœœ˜——Jšœœ˜—Jšœ˜—Jšœ˜J˜—šžœœœ ˜J˜š˜šœœ˜˜šœ˜J˜.J˜.Jšœœ˜ Jšœœ˜Jšœœ˜——Jšœœ˜—Jšœ˜—Jšœ˜J˜—šžœœœœ˜.Jšœœ ˜J˜—šžœœ˜Jšœ œœ˜+J˜ Jšœ œ˜)J˜ š œœ œœ˜9Jšœœ˜—J˜J˜—šžœœ˜JšœŸœ˜$Jšœ œ˜Jšœœœ ˜Jšœœ˜ Jš˜šœ˜˜2Jšœ œœ˜—˜Jšœ/œœ˜<—Jšœ3œœ˜@˜ J˜ J˜šœ˜J˜!J˜'J˜%Jšœ˜—J˜Jšœœ˜ —Jšœ"œœ˜2˜ J˜ šœœœ˜/J˜J˜šœœ˜Jšœœ˜šœ˜ J˜J˜Jšœ˜—J˜$Jšœœœ˜BJšœ˜—J˜Jš œ œœœœ˜>Jšœ˜—Jšœœ˜ —Jšœ˜—Jšœ œ˜Jšœ œ˜šœ œ˜J˜ J˜J˜š˜Jšœ$œ ˜9J˜Jšœ œ˜J˜Jšœœœœ˜!Jšœ˜ ——J˜J˜!Jšœ œ˜šœ˜J˜J˜Jšœœ˜.Jšœœ˜Jšœœ˜Jšœœ˜Jšœ˜—Jšœ œ˜Jšœ œ˜Jšœ˜J˜J˜—Jšžœœœ˜"J˜šž œœ˜Jšœœ˜J˜ Jšœœœ˜J˜J˜J˜J˜—Jšœœœ˜J˜šž œœœ œ˜/J˜ J˜!J˜*J˜—Jšœ œœ˜J˜šž œœœ˜Jšœœœœ˜#Jšœœ˜ Jšœœ˜J˜Jšœœœ˜,J˜J˜—J˜J˜J˜—Jšœ(™(J˜šœ%œ˜CJšœœ˜—šœAœ ˜LJšœœ˜"—Jšœ2œ ˜=Jšœ œ˜Jšœœœ˜-J˜'Jšœ1œ˜:Jšœœ˜4J˜DJšœCœ˜MJ˜Jšœ œ˜ J˜—…—C€a#