diff options
| author | Jack Jansen <jack.jansen@cwi.nl> | 2001-03-10 13:24:41 (GMT) |
|---|---|---|
| committer | Jack Jansen <jack.jansen@cwi.nl> | 2001-03-10 13:24:41 (GMT) |
| commit | dbc692e286816f1acd1c915e6318f8fb3a25fe5e (patch) | |
| tree | 37a022901f415a1b99dfb3c167d60f186c66b998 | |
| parent | 22fcae976af53e8a3a26e8d1fb799a17992dc678 (diff) | |
| download | cpython-dbc692e286816f1acd1c915e6318f8fb3a25fe5e.zip cpython-dbc692e286816f1acd1c915e6318f8fb3a25fe5e.tar.gz cpython-dbc692e286816f1acd1c915e6318f8fb3a25fe5e.tar.bz2 | |
Chris Stern's BBEdit Python language module.
| -rw-r--r-- | Mac/Contrib/BBPy.lm/BBPy.c | 456 | ||||
| -rw-r--r-- | Mac/Contrib/BBPy.lm/BBPythonLM.mcp | 1 | ||||
| -rw-r--r-- | Mac/Contrib/BBPy.lm/BBpy.r | 35 | ||||
| -rw-r--r-- | Mac/Contrib/BBPy.lm/Python | 1 | ||||
| -rw-r--r-- | Mac/Contrib/BBPy.lm/Python Keywords.rsrc | 1 | ||||
| -rw-r--r-- | Mac/Contrib/BBPy.lm/PythonBBLM.txt | 16 |
6 files changed, 510 insertions, 0 deletions
diff --git a/Mac/Contrib/BBPy.lm/BBPy.c b/Mac/Contrib/BBPy.lm/BBPy.c new file mode 100644 index 0000000..85f0dd2 --- /dev/null +++ b/Mac/Contrib/BBPy.lm/BBPy.c @@ -0,0 +1,456 @@ +#include <AEDataModel.h> + +#define DEBUG 0 + +#define kComponentSignatureString "BBPy.LM" +#include <Debugging.h> + + +#include <BBLMInterface.h> +#include <BBXTInterface.h> +//#include <BBLMTextIterator.h> + +#include <ctype.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> + +#include <Sound.h> + +#if DEBUG +void debugf_(const char* func,const char* fileName,long line, const char*fmt,...) +{ + va_list arg; + char msg[256]; + va_start(arg, fmt); + vsnprintf(msg,256 ,fmt, arg); + DebugAssert(COMPONENT_SIGNATURE, DEBUG_NO_OPTIONS, kComponentSignatureString ": " , msg, nil, fileName, line, 0 ); + + //debug_string(msg); +} +#define debugf(FMT,...) debugf_( __FUNCTION__,__FILE__, __LINE__,FMT,__VA_ARGS__); +#else +#define debugf(FMT,...) +#endif + +typedef const char *Str; + + +enum{ + kPyBBLMStringSubst = kBBLMFirstUserRunKind +}; + +#define iswordchar(x) (isalnum(x)||x=='_') + + +struct runloc{ + bool past_gap; + long pos; + long last_start; + unsigned char*p; +}; + +char start(struct runloc& r,BBLMParamBlock &pb) +{ + r.past_gap = false; + r.last_start = pb.fCalcRunParams.fStartOffset; + r.pos = pb.fCalcRunParams.fStartOffset; + r.p = ((unsigned char*)pb.fText) + pb.fCalcRunParams.fStartOffset; + // Adjust for the gap if wešre not already past it. + if ((!r.past_gap) && (r.pos >= pb.fTextGapLocation)){ + r.p += pb.fTextGapLength; + r.past_gap = true; + } + return *r.p; + +} + +char nextchar(struct runloc&r,BBLMParamBlock &pb) +{ + if ( r.pos< pb.fTextLength){ + ++r.pos; + ++r.p; + if ((!r.past_gap) && (r.pos >= pb.fTextGapLocation)){ + r.p += pb.fTextGapLength; + r.past_gap = true; + } + return *r.p; + } + else{ + return 0; + } +} + +bool addRun(BBLMRunCode kind, int start,int len , const BBLMCallbackBlock& bblm_callbacks) +{ + if (len > 0){ // Tie off the code run we were in, unless the length is zero. + debugf("Run %d %d:%d", kind, start, start+len-1 ); + return bblmAddRun( &bblm_callbacks, 'Pyth', + kind, start, len, false); + + } + else{ + return true; + } +} + +bool addRunBefore (BBLMRunCode kind,struct runloc& r, const BBLMCallbackBlock& bblm_callbacks) +{ + bool more_runs = addRun(kind, r.last_start, r.pos - r.last_start, bblm_callbacks); + r.last_start = r.pos; + return more_runs; +} + +bool addRunTo (BBLMRunCode kind, struct runloc& r, const BBLMCallbackBlock& bblm_callbacks) +{ + bool more_runs = addRun(kind, r.last_start, r.pos - r.last_start+1, bblm_callbacks); + r.last_start = r.pos+1; + return more_runs; +} + + +bool colorstr( char delim, + BBLMParamBlock &pb, + struct runloc &r, + const BBLMCallbackBlock &bblm_callbacks) +{ + bool tripple = false , pers = false, lookup = false, more_runs = true; + char c = nextchar(r,pb); + + if (c == delim){ + c = nextchar(r,pb); + if (c == delim){ + tripple = true; + c = nextchar(r,pb); + } + else{ + //double + return addRunBefore(kBBLMRunIsSingleString,r,bblm_callbacks); + } + } + while (c && more_runs){ + if (pers ){ + if (isalpha(c)){ + more_runs = addRunTo(kPyBBLMStringSubst,r,bblm_callbacks); + } + else if (c == '('){ + lookup = true; + } + } + pers = false; + if (c == delim){ + if (tripple){ + if ((c = nextchar(r,pb))== delim && (c = nextchar(r,pb)) == delim){ + break; // end of tripple-quote. + } + } + else{ + break; // end of single-quote. + } + + } + else if (c== '\\'){ + nextchar(r,pb); + } + else if (c=='\r'||c=='\n'){ + if (!tripple){ + break; + } + } + else if (c=='%'){ + more_runs = addRunBefore(kBBLMRunIsSingleString,r,bblm_callbacks); + pers = true; + } + else if (c==')' && lookup){ + more_runs = addRunTo(kPyBBLMStringSubst,r,bblm_callbacks); + lookup = false; + } + c = nextchar(r,pb); + } + return more_runs && addRunTo(lookup?kPyBBLMStringSubst:kBBLMRunIsSingleString,r,bblm_callbacks); +} + +bool colorcomment(BBLMParamBlock &pb, + struct runloc &r, + const BBLMCallbackBlock &bblm_callbacks) +{ + while (char c = nextchar(r,pb)){ + if (c=='\r'|| c=='\n'){ + break; + } + } + return addRunTo(kBBLMRunIsLineComment,r,bblm_callbacks); +} + +void CalculateRuns(BBLMParamBlock &pb, + const BBLMCallbackBlock &bblm_callbacks) + +{ + const struct rundesc *state = NULL; + bool more_runs=true; + + struct runloc r; + + char c = start(r,pb); + + while (c && more_runs){ + loop: + // Process a char + if (state==NULL){ + //If we're in the basic 'code' state, check for each interesting char (rundelims[i].start). + switch (c){ + case '\'': + case '"': + more_runs = addRunBefore(kBBLMRunIsCode,r,bblm_callbacks); + if (more_runs){ + more_runs = colorstr(c,pb,r,bblm_callbacks); + } + break; + case '#' : + more_runs = addRunBefore(kBBLMRunIsCode,r,bblm_callbacks); + if (more_runs){ + more_runs = colorcomment(pb,r,bblm_callbacks); + } + break; + default: + break; + } + + } + c = nextchar(r,pb); + } + if (more_runs){ + addRunBefore(kBBLMRunIsCode,r,bblm_callbacks); + } + + +} +static void AdjustRange(BBLMParamBlock ¶ms, + const BBLMCallbackBlock &callbacks) +{ + DescType language; + BBLMRunCode kind; + SInt32 charPos; + SInt32 length; + UInt32 index = params.fAdjustRangeParams.fStartIndex; + + while( index > 0 && + bblmGetRun(&callbacks, index, language, kind, charPos, length) && + (kind==kPyBBLMStringSubst||kind==kBBLMRunIsSingleString)){ + index--; + }; + params.fAdjustRangeParams.fStartIndex = index; +} + + +// The next couple funcs process the text of a file assumming it's in 1 piece in memory, +// so they may not be called from CalculateRuns. + +bool matchword(BBLMParamBlock &pb, const char *pat ,unsigned long *pos) +{ + const char *asciText = (const char *) (pb.fTextIsUnicode?NULL:pb.fText); + + int i; + for (i=0; pat[i]; i++){ + if (*pos+i>=pb.fTextLength){ + return false; + } + if (asciText[*pos+i] != pat[i]){ + return false; + } + } + if ((*pos+i<pb.fTextLength)&&iswordchar(asciText[*pos+i])){ + return false; + } + *pos+=i; + return true; +} + +int matchindent(BBLMParamBlock &pb, UInt32 *pos) +{ + const char *asciText = (const char *) (pb.fTextIsUnicode?NULL:pb.fText); + int indent=0; + + while(*pos<pb.fTextLength){ + switch (/*(char)(pb.fTextIsUnicode?uniText[pos]:*/asciText[*pos]/*)*/){ + case ' ': + ++*pos; + indent++; + break; + case '\t': + ++*pos; + indent+=8; + break; + case '#': + return -1; + break; + default: + return indent; + break; + } + } +} + + +void eat_line(BBLMParamBlock &pb, unsigned long* pos) +{ + const char *asciText = (const char *) (pb.fTextIsUnicode?NULL:pb.fText); + while (asciText[*pos]!='\r' && asciText[*pos]!='\n' && *pos<pb.fTextLength) {++*pos;} + while ((asciText[*pos]=='\r' || asciText[*pos]=='\n') && *pos<pb.fTextLength) {++*pos;} + +} + +void addItem(BBLMParamBlock &pb, UInt32 pos, int nest, BBLMFunctionKinds kind, + const BBLMCallbackBlock *bblm_callbacks) +{ + UInt32 funcstartpos = pos; + UInt32 funcnamelen=0; + UInt32 offset=0; + const char *asciText = (const char *) pb.fText; + UInt32 index; + OSErr err; + + while (isspace(asciText[pos]) && pos<pb.fTextLength) {++pos;} + UInt32 fnamestart = pos; + while ((isalnum(asciText[pos])||asciText[pos]=='_') && pos<pb.fTextLength) {pos++; funcnamelen++;} + + err = bblmAddTokenToBuffer( bblm_callbacks, + pb.fFcnParams.fTokenBuffer, + (void*)&asciText[fnamestart], + funcnamelen, + pb.fTextIsUnicode, + &offset); + BBLMProcInfo procInfo; + procInfo.fFunctionStart = fnamestart; // char offset in file of first character of function + procInfo.fFunctionEnd = pos; // char offset of last character of function + + procInfo.fSelStart = fnamestart; // first character to select when choosing function + procInfo.fSelEnd = pos; // last character to select when choosing function + + procInfo.fFirstChar = fnamestart; // first character to make visible when choosing function + + procInfo.fKind = kind; + + procInfo.fIndentLevel = nest; // indentation level of token + procInfo.fFlags = 0; // token flags (see BBLMFunctionFlags) + procInfo.fNameStart = offset; // char offset in token buffer of token name + procInfo.fNameLength = funcnamelen; // length of token name + + err = bblmAddFunctionToList(bblm_callbacks, + pb.fFcnParams.fFcnList, + procInfo, + &index); +} + + + +enum{ + maxnest=5 +}; + +void ScanForFunctions(BBLMParamBlock &pb, + const BBLMCallbackBlock &bblm_callbacks) +{ + + const char *asciText = (const char *) (pb.fTextIsUnicode?NULL:pb.fText); + UniCharPtr uniText = (UniCharPtr) (pb.fTextIsUnicode?pb.fText:NULL); + + int indents[maxnest]= {0}; + int nest = 0; + + UInt32 pos=0; // current character offset + + + while (pos<pb.fTextLength){ + + int indent = matchindent(pb, &pos); + + if (indent >= 0){ + for (int i=0; i <= nest; i++){ + if (indent<=indents[i]){ + nest = i; + indents[nest]=indent; + goto x; + } + } + indents[++nest]=indent; + x: + + if (matchword(pb,"def",&pos)){ + addItem( pb, pos, nest, kBBLMFunctionMark, &bblm_callbacks); + } + else if (matchword(pb, "class", &pos)){ + addItem( pb, pos, nest, kBBLMTypedef, &bblm_callbacks); + } + } + eat_line(pb,&pos); + } + +} + +OSErr main( BBLMParamBlock ¶ms, + const BBLMCallbackBlock &bblm_callbacks, + const BBXTCallbackBlock &bbxt_callbacks) +{ + OSErr result; + + if ((params.fSignature != kBBLMParamBlockSignature) || + (params.fLength < sizeof(BBLMParamBlock))) + { + return paramErr; + } + + switch (params.fMessage) + { + case kBBLMInitMessage: + case kBBLMDisposeMessage: + { + result = noErr; // nothing to do + break; + } + + case kBBLMCalculateRunsMessage: + CalculateRuns(params, bblm_callbacks); + result = noErr; + break; + + case kBBLMScanForFunctionsMessage: + ScanForFunctions(params, bblm_callbacks); + result = noErr; + break; + + case kBBLMAdjustRangeMessage: + AdjustRange(params, bblm_callbacks); + result = noErr; + break; + + case kBBLMMapRunKindToColorCodeMessage: + switch (params.fMapRunParams.fRunKind){ + case kPyBBLMStringSubst: + params.fMapRunParams.fColorCode = kBBLMSGMLAttributeNameColor; + params.fMapRunParams.fMapped = true; + break; + default: + params.fMapRunParams.fMapped = false; + } + result = noErr; + break; + + case kBBLMEscapeStringMessage: + case kBBLMAdjustEndMessage: + case kBBLMMapColorCodeToColorMessage: + case kBBLMSetCategoriesMessage: + case kBBLMMatchKeywordMessage: + { + result = userCanceledErr; + break; + } + + default: + { + result = paramErr; + break; + } + } + return result; +}
\ No newline at end of file diff --git a/Mac/Contrib/BBPy.lm/BBPythonLM.mcp b/Mac/Contrib/BBPy.lm/BBPythonLM.mcp new file mode 100644 index 0000000..b5be524 --- /dev/null +++ b/Mac/Contrib/BBPy.lm/BBPythonLM.mcp @@ -0,0 +1 @@ +(This file must be converted with BinHex 4.0)
:!!"069"b3eG*43#3",#B!!!"(SU(Bfp[E!!!!!-!!!%S!!#Sb!!!UI!!!!DS!!!
!4`%#!3#3#80[C'9ABA*bD@pb)&"bEfTPBh3!N1e#BA0TBb"8EfpXBQpi)&"33cT
$GA0dEfdJ5f9jGfpbC(-!3Q&cD@-J9'p[E'*[H#"38%-k3@0MCA0c)&"KG'Kc!%*
KFfPM)&4[EfaLEhJJ8&"$1P4KFQGPG#"6CA4dD@jRF`"#BA0TBb"8EfpXBQpi)&"
33cT'D@aP)%eKF("TEQGc!%*KFfPM)&4[EfaLEhJJ8&"$1N*eD@aN)%9iG(*KF`"
#BA0TBb"8EfpXBQpi)&"33cSf1%XJ3fpNC8GPEJ"#BA0TBb"8EfpXBQpi)&"33cS
f1%XJ4'PcBA0cC@eLE'9b!%*KFfPM)&4[EfaLEhJJ8&"$1MBi5b"-D@jVCA)!3Q&
cD@-J9'p[E'*[H#"38%-k0MK,)&"bEfTPBh3!3Q&cD@-J9'p[E'*[H#"38%-k3bp
$+bXJ3fpYF'PXCA)!3Q&cD@-J9'p[E'*[H#"38%-k3bp$+bXJ9f&bEQPZCh-!3Q&
cD@-J9'p[E'*[H#"38%-k3dC00MK,!%*KFfPM)&4[EfaLEhJJ8&"$1NP5)%p`G'P
YDATPFJ"#BA0TBb"8EfpXBQpi)&"33cT+BACK)%peG("eG!"#BA0TBb"8EfpXBQp
i)&"33cT+BACK)&"bEfTPBh3!3Q&cD@-J9'p[E'*[H#"38%-k5Q&fB5"@63"#BA0
TBb"8EfpXBQpi)&"33cT0B@028b"0CA*RC5"3B@jPE!"#BA0TBb"8EfpXBQpi)&"
33cT3BA0MB@`J3fpYF'PXCA)!3Q&cD@-J9'p[E'*[H#"38%-k8'&cBf&X)&GKFQj
TEQGc!%*KFfPM)&4[EfaLEhJJ8&"$1P"33b"$Ef4P4f9Z!%*KFfPM)&4[EfaLEhJ
J8&"$1P"33b"%DA0KFh0PE@*XCA)!3Q&cD@-J9'p[E'*[H#"38%-k8&"$)%aTEQY
PFJ"#BA0TBb"8EfpXBQpi)&"33cT38%-J8%9'!%*KFfPM)&4[EfaLEhJJ8&"$1P"
33b"3FQpUC@0d!%*KFfPM)&4[EfaLEhJJ8&"$1P"33d&cE5"3B@jPE!"#BA0TBb"
8EfpXBQpi)&"33cT5CASJ3fpYF'PXCA)!3Q&cD@-J9'p[E'*[H#"38%-k9fPZ8N-
J3fpYF'PXCA)!3Q&cD@-J9'p[E'*[H#"38%-kH$Jf)%0[C'9(C@i!3Q&cD@-J9'p
[E'*[H#"38%-kH$Jf)%aTEQYPFJ"#BA0TBb"8EfpXBQpi)&"33cTi1$BJ8(*[DQ9
MG!"3FQpUC@0d)%CTE'8J6'PcG!"6CA4PH(3k3h9cG'pY)%YPHAG[FQ4c!&0PG'9
iG$T"Bf0PFh-J8'&dD(-!8f9dCAKd1P4KFQGPG#"6CA4dD@jRF`"6CA4PH(3k4QP
XC5"0BA"`D@jRF`"6CA4PH(3k3R9TE'3J4AKdFQ&c!&0PG'9iG$Sf1%XJ3fpNC8G
PEJ"6CA4PH(3k0MK,)%4TFf&cFf9YBQaPFJ"6CA4PH(3k0MK,)%aTEQYPFJ"6CA4
PH(3k0MK,)&"bEfTPBh3!8f9dCAKd1N-[3bXV)%0[EA"TE'9b!&0PG'9iG$T$,d-
V+b"ABA*ZD@jRF`"6CA4PH(3k3dC00MK,!&0PG'9iG$T*8L"2F(4TE@PkCA)!8f9
dCAKd1NTKGQ%J6h9dF(9d!&0PG'9iG$T+BACK)&"bEfTPBh3!8f9dCAKd1NTKGQ%
J9Nd!8f9dCAKd1NeKBdp6)%ePFQGP)&"KEQ9X!&0PG'9iG$T3BA0MB@`J3fpYF'P
XCA)!8f9dCAKd1P"KFf0KE#"ABA*ZD@jRF`"6CA4PH(3k8&"$)%0[C'9(C@i!8f9
dCAKd1P"33b"%DA0KFh0PE@*XCA)!8f9dCAKd1P"33b"-D@jVCA)!8f9dCAKd1P"
33b"348B!8f9dCAKd1P"33b"3FQpUC@0d!&0PG'9iG$T38%0"FfdJ8'&ZC@`!8f9
dCAKd1P*PHL"$Efe`D@aPFJ"6CA4PH(3k9fPZ8N-J3fpYF'PXCA)!8f9dCAKd1RJ
i0L"$Ef4P4f9Z!&0PG'9iG$Ti1$BJ6'PZDf9b!&0PG'9iG$Ti1$BJ8(*[DQ9MG!"
6CA4PH(3k8fpeFQ0P)&4bC@9c!&0PG'9iG$T%C@*eCfGPFL"5G@jdD@eP!&0PG'9
iG$T%C@*eCfGPFL"8BA*RCA3!8f9dCAKd1P*PE@pdC5"%C@*eC`"6CA4PH(3k3A9
dEbedBA*RCA3!8f9dCAKd1MBi5b"(E'pLB@`J6h"dD@eTHQ9b!&0PG'9iG$T%H@a
KEL"$Efe`D@aPFJ"6CA4PH(3k4P43)&"KEQ9X!&0PG'9iG$T+BACK)%0[E@eKEQ3
J6'PZC3"6CA4PH(3k5Q&fB5"-B@jRG@&RC3"6CA4PH(3k5Q&fB5"08NT"F("#G@P
XC'9b!&0PG'9iG$T+BACK4'pM)&"bEfTPBh3!8f9dCAKd1NpeG("eG#"'E'&RF`"
6CA4PH(3k8'&MDf&RCA)J8'&ZC@`!8f9dCAKd1P"33b"(E'pLB@`J6h"dD@eTHQ9
b!&0PG'9iG$Ti1$BJ4'PcBA0cC@eLE'9b!&0PG'9iG$Ti1$BJ4AKMCA"dD@pZFb"
3B@jPE!"6CA4PH(3kH$Jf)%GXEf*KE#"2F(4TE@PkCA)!3N*3H5j`F'-k8fpeFQ0
P)&4bC@9c!%*#8(NZF("M1N&MBf9cFb"3BA4SF`"#3P"j,R"`BcT%C@*eCfGPFL"
5G@jdD@eP!%*#8(NZF("M1P4KFQGPG#"6CA4dD@jRF`"#3P"j,R"`BcT'D@aP)%e
KF("TEQGc!%*#8(NZF("M1N*eD@aN)%9iG(*KF`"#3P"j,R"`BcT%C@*eCfGPFL"
8BA*RCA3!3N*3H5j`F'-k8Q9YEh4P)%4PBR9R!%*#8(NZF("M1N&eG'mYG'&bCf9
d!%*#8(NZF("M1N0eFh4[E5",CAPhEh*NF`"#3P"j,R"`BcSf1%XJ3fpNC8GPEJ"
#3P"j,R"`BcSf1%XJ4'PcBA0cC@eLE'9b!%*#8(NZF("M1MBi5b"(E'pLB@`J6h"
dD@eTHQ9b!%*#8(NZF("M1MBi5b"-D@jVCA)!3N*3H5j`F'-k0MK,)&"bEfTPBh3
!3N*3H5j`F'-k3bp$+bXJ3fpYF'PXCA)!3N*3H5j`F'-k3bp$+bXJ9f&bEQPZCh-
!3N*3H5j`F'-k3dC00MK,!%*#8(NZF("M1NC88#"3B@jPE!"#3P"j,R"`BcT+BAC
K)%0[E@eKEQ3J6'PZC3"#3P"j,R"`BcT+BACK)%aKEQGeB@GP!%*#8(NZF("M1NT
KGQ%J69*+3A"`3R9TE'4PFJ"#3P"j,R"`BcT+BACK)%peG("eG!"#3P"j,R"`BcT
+BACK)&"bEfTPBh3!3N*3H5j`F'-k5Q&fB84[Bb"3FQpUC@0d!%*#8(NZF("M1Ne
KBdp6)%ePFQGP)&"KEQ9X!%*#8(NZF("M1NpeG("eG#"'E'&RF`"#3P"j,R"`BcT
3B@0VB@GPFL"3B@jPE!"#3P"j,R"`BcT38%-J3fpNC8GPEJ"#3P"j,R"`BcT38%-
J4'PcBA0cC@eLE'9b!%*#8(NZF("M1P"33b"(E'pLB@`J6h"dD@eTHQ9b!%*#8(N
ZF("M1P"33b"-D@jVCA)!3N*3H5j`F'-k8&"$)&"&4J"#3P"j,R"`BcT38%-J8(*
[DQ9MG!"#3P"j,R"`BcT38%0"FfdJ8'&ZC@`!3N*3H5j`F'-k8Q9k)%0[EA"TE'9
b!%*#8(NZF("M1PGTEP*$)%0[EA"TE'9b!%*#8(NZF("M1RJi0L"$Ef4P4f9Z!%*
#8(NZF("M1RJi0L"%DA0KFh0PE@*XCA)!3N*3H5j`F'-kH$Jf)%9iBf9`G'P[ER-
J8'&ZC@`!3N*3H5j`F'-kH$Jf)%GXEf*KE#"2F(4TE@PkCA)!3N*3H5j`F'-kH$J
f)%aTEQYPFJ"#3P"j,R"`BcTi1$BJ8(*[DQ9MG!#3D!%MYh!B!!!!)J!!!!)!N!G
"!!!!!h9PG@8!!!"M!!!!"!)Yl1!!!!#$!!!!"A3+4AB!!!#L!!!!"JK(CA3!!!$
!!!!!"fPXE%3!!!$M!!!!#'pZ#93!!!%!N!3*"dGPG!!!!4i!!!!+G%e[G3!!!6m
!!!!,G%4TB3!!!@!!!!!-C%4TB3!!!AN!!!!04'PKE!!!!CJ!!!!1D@&XE`!!!EB
!!!!2Gd4TB3!!!G8!!!!3D@&XE`!!!Hm!!!!4H(3053!!!K-!!!!5GQ9ZG!!!!M8
!!!!6C@aPB`!!!PF!!!!8B@a[C`!!!R8!!!!9B@a[C`!!!TJ!!!!@4'PKE!!!!V8
!!!!A5A4PE3!!!Xm!!!!BG'p`33!!!Zd!!!!CC8&XC3!!!``!!!!DEfj"E!!!!bX
!!!!EC%&XC3!!!d`!!!!FE'9bG!!!!fS!!!!GH(3+43!!!iF!!!!HC!K(C3!!!k8
!!!!ICA4%53!!!lF!!!!J9'9iG!!!!mi!!!!K!*!'!q)!!!!L!*!'!rN!!!!M!*!
'"!i!!!!N!*!'"#)!!!!P!*!'"$8!!!!Q!*!'"%d!!!!R!*!'"&m!!!!S!*!'"()
!!!!T!*!'")J!!!!U!*!'"*i!!!!V!*!'"+`!!!!X!*!'"-!!!!!Y!*!'"0-!!!!
Z!*!'"1F!!!