Received: from localhost (unknown [200.46.204.183]) by postgresql.org (Postfix) with ESMTP id E865B64FC2D for ; Fri, 26 Sep 2008 11:51:29 -0300 (ADT) Received: from postgresql.org ([200.46.204.86]) by localhost (mx1.hub.org [200.46.204.183]) (amavisd-maia, port 10024) with ESMTP id 26434-06 for ; Fri, 26 Sep 2008 11:51:21 -0300 (ADT) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from outmail136026.authsmtp.com (outmail136026.authsmtp.com [62.13.136.26]) by postgresql.org (Postfix) with ESMTP id 920F964FC03 for ; Fri, 26 Sep 2008 11:51:20 -0300 (ADT) Received: from punt7.authsmtp.com (punt7.authsmtp.com [62.13.128.13]) by punt5.authsmtp.com (8.14.2/8.14.2/Kp) with ESMTP id m8QEpGSR032828 for ; Fri, 26 Sep 2008 15:51:16 +0100 (BST) Received: from mail-c187.authsmtp.com (mail-c187.authsmtp.com [62.13.128.33]) by punt7.authsmtp.com (8.14.2/8.14.2/Kp) with ESMTP id m8QEpFjP015057; Fri, 26 Sep 2008 15:51:15 +0100 (BST) Received: from [192.168.0.3] (85-211-71-126.dyn.gotadsl.co.uk [85.211.71.126]) (authenticated bits=0) by mail.authsmtp.com (8.14.2/8.14.2/Kp) with ESMTP id m8QEpDr8068102; Fri, 26 Sep 2008 15:51:13 +0100 (BST) Subject: Re: [HACKERS] get_relation_stats_hook() From: Simon Riggs To: Tom Lane , Gregory Stark Cc: Alvaro Herrera , List pgsql-patches In-Reply-To: <1218062303.4549.302.camel@ebony.2ndQuadrant> References: <1214490037.3845.136.camel@ebony.site> <16415.1214493494@sss.pgh.pa.us> <1214496170.3845.196.camel@ebony.site> <17759.1214499056@sss.pgh.pa.us> <1214858056.3845.514.camel@ebony.site> <12400.1215716369@sss.pgh.pa.us> <1218037047.4549.291.camel@ebony.2ndQuadrant> <1218062303.4549.302.camel@ebony.2ndQuadrant> Content-Type: multipart/mixed; boundary="=-tUvbn5EHTHuZ9RWtZFHf" Date: Fri, 26 Sep 2008 15:52:20 +0100 Message-Id: <1222440740.4445.966.camel@ebony.2ndQuadrant> Mime-Version: 1.0 X-Mailer: Evolution 2.12.0 X-Server-Quench: 9160985c-8bda-11dd-8155-001185d377ca X-AuthRoute: OCdxZQATClZOTQEd DAteCiNZVAwpPBRK HVkIKg5MJUcNSQVJ NksachtFagNbflxB HGQLW1xEUVh7XGJ/ ag4fZQBDYEtPQQJr TklLRE1QEQdtHhxP WxZ/J1kGNQ1GfnZx ZUQsW3NZWUM0fEd7 QkdcED4bbTU0OX0e URQMagtVdQZXfh9E a1h6AHAKZjZWKBg1 TUcABxkNFhVyExEd cSEkBnE/e30+VjEx WycYEDEmAUwCQRIo MxU6MWkcG0EScgRa X-Authentic-SMTP: 61633235383639.squirrel.dmpriest.net.uk:1378/Kp X-Report-SPAM: If SPAM / abuse - report it at: http://www.authsmtp.com/abuse X-Virus-Status: No virus detected - but ensure you scan with your own anti-virus system! X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=0 tagged_above=0 required=5 tests=none X-Spam-Level: X-Archive-Number: 200809/171 X-Sequence-Number: 7186 --=-tUvbn5EHTHuZ9RWtZFHf Content-Type: text/plain Content-Transfer-Encoding: 7bit On Wed, 2008-08-06 at 23:38 +0100, Simon Riggs wrote: > On Wed, 2008-08-06 at 16:37 +0100, Simon Riggs wrote: > > > I'll submit the fully working plugin once we've stabilised the API. It's > > designed as a contrib module, so it can go in pgfoundry or contrib. > > OK, here's fully working plugin, plus API patch. > > I expect to open a pgfoundry project for the plugin, but will wait for > the main patch review. > > I've tried the APIs three different ways and this seems cleanest and > most widely applicable approach. It's possible to add calls in more > places, but I haven't done this for reasons discussed previously. New version of Postgres patch, v5. Implements suggested changes. Ready for review and apply. New version of stats plugin, v3. Works with v5. Corrected problems: * now loads using preload_shared_libraries as well as LOAD * example test script fix -- Simon Riggs www.2ndQuadrant.com PostgreSQL Training, Services and Support --=-tUvbn5EHTHuZ9RWtZFHf Content-Disposition: attachment; filename=stat_hooks.v5.patch Content-Type: text/x-patch; name=stat_hooks.v5.patch; charset=UTF-8 Content-Transfer-Encoding: 7bit Index: src/backend/utils/adt/selfuncs.c =================================================================== RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/utils/adt/selfuncs.c,v retrieving revision 1.253 diff -c -r1.253 selfuncs.c *** src/backend/utils/adt/selfuncs.c 25 Aug 2008 22:42:34 -0000 1.253 --- src/backend/utils/adt/selfuncs.c 25 Sep 2008 15:57:58 -0000 *************** *** 118,123 **** --- 118,126 ---- #include "utils/selfuncs.h" #include "utils/syscache.h" + /* Hook for plugins to get control when we ask for stats */ + get_relation_stats_hook_type get_relation_stats_hook = NULL; + release_relation_stats_hook_type release_relation_stats_hook = NULL; static double var_eq_const(VariableStatData *vardata, Oid operator, Datum constval, bool constisnull, *************** *** 3996,4005 **** } else if (rte->rtekind == RTE_RELATION) { ! vardata->statsTuple = SearchSysCache(STATRELATT, ObjectIdGetDatum(rte->relid), Int16GetDatum(var->varattno), 0, 0); } else { --- 3999,4017 ---- } else if (rte->rtekind == RTE_RELATION) { ! if (get_relation_stats_hook) ! vardata->statsTuple = (*get_relation_stats_hook) ! (rte->relid, ! var->varattno, ! vardata->freefunc); ! if (!vardata->statsTuple) ! { ! vardata->statsTuple = SearchSysCache(STATRELATT, ObjectIdGetDatum(rte->relid), Int16GetDatum(var->varattno), 0, 0); + vardata->freefunc = ReleaseSysCache; + } } else { *************** *** 4116,4125 **** index->indpred == NIL) vardata->isunique = true; /* Has it got stats? */ ! vardata->statsTuple = SearchSysCache(STATRELATT, ObjectIdGetDatum(index->indexoid), ! Int16GetDatum(pos + 1), ! 0, 0); if (vardata->statsTuple) break; } --- 4128,4147 ---- index->indpred == NIL) vardata->isunique = true; /* Has it got stats? */ ! if (get_relation_stats_hook) ! vardata->statsTuple = (*get_relation_stats_hook) ! (index->indexoid, ! pos + 1, ! vardata->freefunc); ! if (!vardata->statsTuple) ! { ! vardata->statsTuple = SearchSysCache(STATRELATT, ObjectIdGetDatum(index->indexoid), ! Int16GetDatum(pos + 1), ! 0, 0); ! vardata->freefunc = ReleaseSysCache; ! } ! if (vardata->statsTuple) break; } *************** *** 5551,5557 **** double *indexCorrelation = (double *) PG_GETARG_POINTER(7); Oid relid; AttrNumber colnum; ! HeapTuple tuple; double numIndexTuples; List *indexBoundQuals; int indexcol; --- 5573,5580 ---- double *indexCorrelation = (double *) PG_GETARG_POINTER(7); Oid relid; AttrNumber colnum; ! HeapTuple tuple = NULL; ! void (*freefunc) (HeapTuple tuple) = NULL; double numIndexTuples; List *indexBoundQuals; int indexcol; *************** *** 5756,5765 **** colnum = 1; } ! tuple = SearchSysCache(STATRELATT, ! ObjectIdGetDatum(relid), ! Int16GetDatum(colnum), ! 0, 0); if (HeapTupleIsValid(tuple)) { --- 5779,5795 ---- colnum = 1; } ! if (get_relation_stats_hook) ! tuple = (*get_relation_stats_hook) (relid, colnum, freefunc); ! ! if (!tuple) ! { ! tuple = SearchSysCache(STATRELATT, ! ObjectIdGetDatum(relid), ! Int16GetDatum(colnum), ! 0, 0); ! freefunc = ReleaseSysCache; ! } if (HeapTupleIsValid(tuple)) { *************** *** 5800,5806 **** free_attstatsslot(InvalidOid, NULL, 0, numbers, nnumbers); } ! ReleaseSysCache(tuple); } PG_RETURN_VOID(); --- 5830,5837 ---- free_attstatsslot(InvalidOid, NULL, 0, numbers, nnumbers); } ! ! ReleaseStatsTuple(tuple, freefunc); } PG_RETURN_VOID(); Index: src/backend/utils/cache/lsyscache.c =================================================================== RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/utils/cache/lsyscache.c,v retrieving revision 1.159 diff -c -r1.159 lsyscache.c *** src/backend/utils/cache/lsyscache.c 2 Aug 2008 21:32:00 -0000 1.159 --- src/backend/utils/cache/lsyscache.c 25 Sep 2008 14:16:01 -0000 *************** *** 27,32 **** --- 27,33 ---- #include "catalog/pg_proc.h" #include "catalog/pg_statistic.h" #include "catalog/pg_type.h" + #include "optimizer/plancat.h" #include "miscadmin.h" #include "nodes/makefuncs.h" #include "utils/array.h" *************** *** 35,40 **** --- 36,43 ---- #include "utils/lsyscache.h" #include "utils/syscache.h" + /* Hook for plugins to get control in get_attavgwidth() */ + get_attavgwidth_hook_type get_attavgwidth_hook = NULL; /* ---------- AMOP CACHES ---------- */ *************** *** 2492,2507 **** * * Given the table and attribute number of a column, get the average * width of entries in the column. Return zero if no data available. */ int32 get_attavgwidth(Oid relid, AttrNumber attnum) { HeapTuple tp; tp = SearchSysCache(STATRELATT, ! ObjectIdGetDatum(relid), ! Int16GetDatum(attnum), ! 0, 0); if (HeapTupleIsValid(tp)) { int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth; --- 2495,2524 ---- * * Given the table and attribute number of a column, get the average * width of entries in the column. Return zero if no data available. + * + * Calling a hook at this point looks somewhat strange, but is required + * because the optimizer handles inheritance relations by calling for + * the avg width later in the planner than get_relation_info_hook(). + * So the APIs and call points of hooks must match the optimizer. */ int32 get_attavgwidth(Oid relid, AttrNumber attnum) { HeapTuple tp; + int32 stawidth; + + if (get_attavgwidth_hook) + { + stawidth = (*get_attavgwidth_hook) (relid, attnum); + if (stawidth > 0) + return stawidth; + } tp = SearchSysCache(STATRELATT, ! ObjectIdGetDatum(relid), ! Int16GetDatum(attnum), ! 0, 0); ! if (HeapTupleIsValid(tp)) { int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth; Index: src/include/optimizer/plancat.h =================================================================== RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/include/optimizer/plancat.h,v retrieving revision 1.51 diff -c -r1.51 plancat.h *** src/include/optimizer/plancat.h 16 Aug 2008 00:01:38 -0000 1.51 --- src/include/optimizer/plancat.h 25 Sep 2008 15:57:06 -0000 *************** *** 14,19 **** --- 14,20 ---- #ifndef PLANCAT_H #define PLANCAT_H + #include "access/htup.h" #include "nodes/relation.h" #include "utils/relcache.h" *************** *** 24,29 **** --- 25,43 ---- RelOptInfo *rel); extern PGDLLIMPORT get_relation_info_hook_type get_relation_info_hook; + /* Hooks for plugins to get control in lsyscache.c and selfuncs.c */ + typedef HeapTuple (*get_relation_stats_hook_type) (Oid relid, AttrNumber attnum, + void (*freefunc) (HeapTuple tuple)); + extern PGDLLIMPORT get_relation_stats_hook_type get_relation_stats_hook; + + /* must match ReleaseSysCache call signature */ + typedef void (*release_relation_stats_hook_type) (HeapTuple tuple); + extern PGDLLIMPORT release_relation_stats_hook_type release_relation_stats_hook; + + typedef int32 (*get_attavgwidth_hook_type) (Oid relid, AttrNumber attnum); + extern PGDLLIMPORT get_attavgwidth_hook_type get_attavgwidth_hook; + + extern void get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel); Index: src/include/utils/selfuncs.h =================================================================== RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/include/utils/selfuncs.h,v retrieving revision 1.46 diff -c -r1.46 selfuncs.h *** src/include/utils/selfuncs.h 16 Aug 2008 00:01:38 -0000 1.46 --- src/include/utils/selfuncs.h 25 Sep 2008 15:55:05 -0000 *************** *** 74,85 **** Oid atttype; /* type to pass to get_attstatsslot */ int32 atttypmod; /* typmod to pass to get_attstatsslot */ bool isunique; /* true if matched to a unique index */ } VariableStatData; #define ReleaseVariableStats(vardata) \ do { \ if (HeapTupleIsValid((vardata).statsTuple)) \ ! ReleaseSysCache((vardata).statsTuple); \ } while(0) --- 74,102 ---- Oid atttype; /* type to pass to get_attstatsslot */ int32 atttypmod; /* typmod to pass to get_attstatsslot */ bool isunique; /* true if matched to a unique index */ + void (*freefunc) (HeapTuple tuple); /* funct ptr to free statsTuple */ } VariableStatData; + #define ReleaseStatsTuple(tuple, freefunc) \ + do { \ + if (HeapTupleIsValid(tuple)) \ + { \ + if (freefunc) \ + freefunc(tuple); \ + else \ + elog(ERROR, "unable to release variable stats correctly"); \ + } \ + } while(0) + #define ReleaseVariableStats(vardata) \ do { \ if (HeapTupleIsValid((vardata).statsTuple)) \ ! { \ ! if ((vardata).freefunc) \ ! (vardata).freefunc((vardata).statsTuple); \ ! else \ ! elog(ERROR, "unable to release variable stats correctly"); \ ! } \ } while(0) --=-tUvbn5EHTHuZ9RWtZFHf Content-Disposition: attachment; filename=TOM.v3.tar Content-Type: application/x-tar; name=TOM.v3.tar Content-Transfer-Encoding: base64 Y29udHJpYi9UT00vAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDA3NTUAMDAwMTc1 MAAwMDAwMTQ0ADAwMDAwMDAwMDAwADExMDY3MTcyNjU0ADAxMjQwMwAgNQAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhciAgAHNyaWdncwAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAdXNlcnMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABj b250cmliL1RPTS9nZXRfbWFwcGluZ19mb3JfdG9tLnNxbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMDc1NQAwMDAxNzUw ADAwMDAxNDQAMDAwMDAwMDEwMDEAMTEwNDE1NTQ3NzMAMDE3MTM0ACAwAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHVzdGFyICAAc3JpZ2dzAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAB1c2VycwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0t Ci0tIEdldCBtYXBwaW5nIGZvciBUcmFuc3BvcnRhYmxlIE9wdGltaXplciBNb2RlCi0tCi0tIHNp bW9uQDJuZHF1YWRyYW50LmNvbQotLQotLSBFZGl0IHRoaXMgdG8gY3JlYXRlIGEgY3VzdG9tIG1h cHBpbmcgaWYgcmVxdWlyZWQKLS0gb3IganVzdCBhZGQgbWFwcGluZyBkYXRhIHRvIHN1aXQgeW91 ciBuZWVkcwoKLS0gTm90ZSB0aGF0IHdlIGFyZSB1c2luZyBhbiBpbm5lciBqb2luCgpJTlNFUlQg SU5UTyA6VE9NX1NDSEVNQS50b21fbWFwcGluZwoKU0VMRUNUCiBjLm9pZAoscy5zY2hlbWFuYW1l CixzLnJlbG5hbWUKCkZST00KIDpUT01fU0NIRU1BLnRvbV9wZ19jbGFzcyBzCixwZ19jbGFzcyBj CixwZ19uYW1lc3BhY2UgbgoKV0hFUkUKCglzLnJlbG5hbWUgPSBjLnJlbG5hbWUKQU5EIHMuc2No ZW1hbmFtZSA9IG4ubnNwbmFtZQpBTkQgYy5yZWxuYW1lc3BhY2UgPSBuLm9pZAo7CgotLQotLSBF bmQgb2YgZ2V0IG1hcHBpbmcgZm9yIFRyYW5zcG9ydGFibGUgT3B0aW1pemVyIE1vZGUKLS0KCgAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjb250 cmliL1RPTS9nZXRfZGF0YV9mb3JfdG9tLnNxbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMDc1NQAwMDAxNzUwADAw MDAxNDQAMDAwMDAwMDM2NDUAMTEwNDYwMDUxNjYAMDE2NDIyACAwAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHVzdGFyICAAc3JpZ2dzAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAB1c2VycwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0tCi0t IEdldCBkYXRhIGZvciBUcmFuc3BvcnRhYmxlIE9wdGltaXplciBNb2RlCi0tCi0tIHNpbW9uQDJu ZHF1YWRyYW50LmNvbQoKLS0gT3V0cHV0IG11c3QgYmUgYSBzZXQgb2YgZmlsZXMuIFdlIHdhbnQg dGhpcyB0byBydW4gYnkgYW4gdW5wcml2aWxlZ2VkIHVzZXIsCgpDUkVBVEUgT1IgUkVQTEFDRSBU RU1QT1JBUlkgVklFVyB0b21fZ2V0X3N0YXRzIEFTClNFTEVDVCAKICBuLm5zcG5hbWUgQVMgc2No ZW1hbmFtZQosIGMucmVsbmFtZSBBUyB0YWJsZW5hbWUKLCBhLmF0dG51bSBBUyBhdHRudW0KLCBz dGFudWxsZnJhYyBBUyBzMQosIHN0YXdpZHRoIEFTIHMyCiwgc3RhZGlzdGluY3QgQVMgczMKLCBz dGFraW5kMSBBUyBzNAosIHN0YWtpbmQyIEFTIHM1Ciwgc3Rha2luZDMgQVMgczYKLCBzdGFraW5k NCBBUyBzNwosIHN0YW9wMSBBUyBzOAosIHN0YW9wMiBBUyBzOQosIHN0YW9wMyBBUyBzMTAKLCBz dGFvcDQgQVMgczExCiwgc3RhbnVtYmVyczEgQVMgczEyCiwgc3RhbnVtYmVyczIgQVMgczEzCiwg c3RhbnVtYmVyczMgQVMgczE0Ciwgc3RhbnVtYmVyczQgQVMgczE1Ciwgc3RhdmFsdWVzMTo6dGV4 dCBBUyBzMTYKLCBzdGF2YWx1ZXMyOjp0ZXh0IEFTIHMxNwosIHN0YXZhbHVlczM6OnRleHQgQVMg czE4Ciwgc3RhdmFsdWVzNDo6dGV4dCBBUyBzMTkKCkZST00KIHBnX3N0YXRpc3RpYyBzCixwZ19j bGFzcyBjCixwZ19hdHRyaWJ1dGUgYQoscGdfbmFtZXNwYWNlIG4KCldIRVJFIGhhc190YWJsZV9w cml2aWxlZ2UoYy5vaWQsICdzZWxlY3QnOjp0ZXh0KQogIEFORCBuLm5zcG5hbWUgbm90IGluICgn cGdfY2F0YWxvZycsICdpbmZvcm1hdGlvbl9zY2hlbWEnLCAncGdfdG9hc3QnKQogIEFORCBhLmF0 dG5hbWUgbm90IGluICgnY3RpZCcsJ3htaW4nLCd4bWF4JywnY21pbicsJ2NtYXgnLCd0YWJsZW9p ZCcpCiAgQU5EIGMucmVsbmFtZSBub3QgbGlrZSAndG9tXyUnCgogIEFORCBjLm9pZCA9IHMuc3Rh cmVsaWQKICBBTkQgYS5hdHRudW0gPSBzLnN0YWF0dG51bQogIEFORCBjLm9pZCA9IGEuYXR0cmVs aWQKICBBTkQgbi5vaWQgPSBjLnJlbG5hbWVzcGFjZQoKT1JERVIgQlkgbi5uc3BuYW1lCjsKXGNv cHkgKHNlbGVjdCAqIGZyb20gdG9tX2dldF9zdGF0cykgVE8gJ3RvbV9wZ19zdGF0aXN0aWMuZGF0 YScKCkNSRUFURSBPUiBSRVBMQUNFIFRFTVBPUkFSWSBWSUVXIHRvbV9nZXRfcGdfY2xhc3MgQVMK U0VMRUNUIAogIG4ubnNwbmFtZSBBUyBzY2hlbWFuYW1lCiwgYy5yZWxuYW1lIEFTIHJlbG5hbWUK LCBwZ19yZWxhdGlvbl9zaXplKGMub2lkKS84MTkyIEFTIHBhZ2VzCiwgY2FzZQoJLyogc2VxdWVu Y2VzICovIAkKCXdoZW4gYy5yZWxraW5kID0gJ1MnIHRoZW4gMQoJZWxzZSBjYXNlCgkJCS8qIHpl cm8gc2l6ZSByZWxhdGlvbiAqLwoJCQl3aGVuIHBnX3JlbGF0aW9uX3NpemUoYy5vaWQpID0gMCBv ciBjLnJlbHBhZ2VzID0gMCB0aGVuIDAKCQkJCgkJCS8qIG5vcm1hbCBjYXNlICovCgkJCWVsc2Ug cGdfcmVsYXRpb25fc2l6ZShjLm9pZCkvODE5MiAqIChjLnJlbHR1cGxlcy9jLnJlbHBhZ2VzKQoJ CSAgZW5kCgllbmQKRlJPTQogcGdfY2xhc3MgYwoscGdfbmFtZXNwYWNlIG4KCldIRVJFIGhhc190 YWJsZV9wcml2aWxlZ2UoYy5vaWQsICdzZWxlY3QnOjp0ZXh0KQogIEFORCBuLm5zcG5hbWUgbm90 IGluICgncGdfY2F0YWxvZycsICdpbmZvcm1hdGlvbl9zY2hlbWEnLCAncGdfdG9hc3QnKQogIEFO RCBjLnJlbG5hbWUgbm90IGxpa2UgJ3RvbV8lJwogIEFORCBjLnJlbGtpbmQgaW4gKCdyJywgJ2kn LCAnUycsICd0JykKCiAgQU5EIG4ub2lkID0gYy5yZWxuYW1lc3BhY2UKCk9SREVSIEJZIG4ubnNw bmFtZQo7Clxjb3B5IChzZWxlY3QgKiBmcm9tIHRvbV9nZXRfcGdfY2xhc3MpIFRPICd0b21fcGdf Y2xhc3MuZGF0YScKCi0tCi0tIEVuZCBvZiBnZXQgZGF0YSBmb3IgVHJhbnNwb3J0YWJsZSBPcHRp bWl6ZXIgTW9kZQotLQoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY29udHJpYi9U T00vdG9tX3Rlc3Quc2guZXhhbXBsZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMDA3NTUAMDAwMTc1MAAwMDAwMTQ0 ADAwMDAwMDAyMjUxADExMDY3MTcyMzA0ADAxNjIyMgAgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhciAgAHNyaWdncwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAdXNlcnMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjIS9iaW4vc2gK IyAkSWQkCiMKIyBUZXN0IHNjcmlwdCBmb3IgVHJhbnNwb3J0YWJsZSBPcHRpbWl6ZXIgTW9kZSAo VE9NKQojCiMgQ2hyaXMgQnJvd25lIAkJc2VsZWN0ICdjYmJyb3duZScgfHwgJ0AnIHx8ICdsaW51 eGZpbmFuY2VzLmluZm8nOwojCiNzb3VyY2Ugfi9kYnMvcGdzcWw4My5zaCBlbnYgICAgIyBBIGNi YnJvd25lLWlzbSB0byBzZXQgdXAgYWNjZXNzIHRvIG15IGZhdm9yaXRlIERCIGNsdXN0ZXIuLi4K CiMgVGhlc2UgYWxsIHByb3ZpZGUgb3ZlcnJpZGFibGUgZGVmYXVsdHMKU09VUkNFREI9JHtTT1VS Q0VEQjotInBvc3RncmVzIn0gICAgICAgICAjIHdoaWNoIGRhdGFiYXNlIGRvZXMgdGhlIGRhdGEg Y29tZSBmcm9tClNPVVJDRVNDSEVNQT0ke1NPVVJDRVNDSEVNQTotInB1YmxpYyJ9ICAgIyB3aGlj aCBzY2hlbWEgaXMgaW4gdXNlIChlLmcuIC0gd2hhdCBzY2hlbWEgdG8gcGdfZHVtcCkKVEVTVERC PSR7VEVTVERCOi0idG9tdGVzdGRiIn0gICAgICAgICAgICAjIHRhcmdldCBkYXRhYmFzZSBmb3Ig VE9NIHRlc3QKVE9NU0NIRU1BPSR7VE9NU0NIRU1BOi0idG9tIn0gICAgICAgICAgICAjIHNjaGVt YSB0byB1c2UgZm9yIFRPTSB0YWJsZXMKCnBzcWwgLWQgJHtTT1VSQ0VEQn0gLWMgImFuYWx5emU7 Igpwc3FsIC1kICR7U09VUkNFREJ9IC1mIGdldF9kYXRhX2Zvcl90b20uc3FsCgojIHVubG9hZCB5 b3VyIHRhYmxlcyBoZXJlCgpkcm9wZGIgJHtURVNUREJ9CmNyZWF0ZWRiICR7VEVTVERCfQpwc3Fs IC1kICR7VEVTVERCfSAtYyAiY3JlYXRlIHNjaGVtYSAke1RPTVNDSEVNQX07IgoKcGdfZHVtcCAt biAke1NPVVJDRVNDSEVNQX0gLXMgJHtTT1VSQ0VEQn0gfCBwc3FsIC1kICR7VEVTVERCfQoKcHNx bCAtZCAke1RFU1REQn0gLWYgY3JlYXRlX3RvbV90YWJsZXMuc3FsIC0tc2luZ2xlLXRyYW5zYWN0 aW9uIC12IFRPTV9TQ0hFTUE9JHtUT01TQ0hFTUF9CnBzcWwgLWQgJHtURVNUREJ9IC1mIGxvYWRf ZGF0YV9mb3JfdG9tLnNxbCAtLXNpbmdsZS10cmFuc2FjdGlvbiAtdiBUT01fU0NIRU1BPSR7VE9N U0NIRU1BfQoKIyBsb2FkIHlvdXIgdGFibGVzIGhlcmUKCnBzcWwgLWQgJHtURVNUREJ9IC1mIGdl dF9tYXBwaW5nX2Zvcl90b20uc3FsIC12IFRPTV9TQ0hFTUE9JHtUT01TQ0hFTUF9CnBzcWwgLWQg JHtURVNUREJ9IC1jICJsb2FkICdcJGxpYmRpci90b21faG9va3MnOyIKCgAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABjb250cmliL1RPTS90 b21faG9va3MuYwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMDc1NQAwMDAxNzUwADAwMDAxNDQAMDAw MDAwMjI1MDYAMTEwNjcxNzE3MDIAMDE0NTUyACAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAHVzdGFyICAAc3JpZ2dzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1 c2VycwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC8qLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLQogKgogKiB0b21faG9va3MuYwogKgogKgkgIFBvc3RncmVzIHBsYW5uaW5nIGhvb2tzIGZv ciBUcmFuc3BvcnRhYmxlIE9wdGltaXplciBNb2RlCiAqCiAqCSAgJFBvc3RncmVTUUwkCiAqCiAq IAkgIHNpbW9uQDJuZHF1YWRyYW50LmNvbQogKi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICovCgojaW5jbHVk ZSAicG9zdGdyZXMuaCIKCiNpbmNsdWRlICJmdW5jYXBpLmgiCiNpbmNsdWRlICJtaXNjYWRtaW4u aCIKCiNpbmNsdWRlICJhY2Nlc3MvaHR1cC5oIgojaW5jbHVkZSAiY2F0YWxvZy9wZ19zdGF0aXN0 aWMuaCIKI2luY2x1ZGUgImV4ZWN1dG9yL3NwaS5oIgojaW5jbHVkZSAib3B0aW1pemVyL3BsYW5j YXQuaCIKI2luY2x1ZGUgInV0aWxzL2Vsb2cuaCIKI2luY2x1ZGUgInV0aWxzL2J1aWx0aW5zLmgi CiNpbmNsdWRlICJ1dGlscy9zeXNjYWNoZS5oIgoKUEdfTU9EVUxFX01BR0lDOwkvKiBUZWxsIHRo ZSBzZXJ2ZXIgYWJvdXQgb3VyIGNvbXBpbGUgZW52aXJvbm1lbnQgKi8KCiNkZWZpbmUgUExBTlNf VU5QTEFOTkVEIAkwCiNkZWZpbmUgUExBTlNfSU5fUFJPR1JFU1MgCTEKI2RlZmluZSBQTEFOU19S RUFEWSAJCTIKdHlwZWRlZiBzdHJ1Y3QgdG9tX3BsYW5faW5mbwp7CglpbnQJCQlwbGFuc3RhdGU7 Cgl2b2lkCSAgICpwbGFuX3RvbV9wZ19jbGFzczsJCS8qIHBsYW4gb2YgYWNjZXNzIHRvIHRvbV9w Z19jbGFzcyAqLwoJdm9pZAkgICAqcGxhbl90b21fcGdfc3RhdGlzdGljOwkvKiBwbGFuIG9mIGFj Y2VzcyB0byB0b21fcGdfc3RhdGlzdGljICovCglpbnQJCQl0b21fb2lkWzNdOwkJCQkvKiAKCQkJ CQkJCQkJCSAqIGtlZXAgdHJhY2sgb2Ygb2lkcyBvZiBUT00gdGFibGVzCgkJCQkJCQkJCQkgKiBz byB3ZSBhdm9pZCByZWN1cnNpdmUgY2FsbHMgdG8KCQkJCQkJCQkJCSAqIHRoZSBwbHVnaW4gd2hl biB3ZSBhY2Nlc3MgdGFibGVzIGhlcmUKCQkJCQkJCQkJCSAqLwp9IHRvbV9wbGFuX2luZm87Cgpz dGF0aWMgdG9tX3BsYW5faW5mbyAqdHBpOwoKLyogZXh0ZXJuYWwgY2FsbHMgKi8Kdm9pZCBwbHVn aW5fZ2V0X3JlbGF0aW9uX2luZm8oUGxhbm5lckluZm8gKnJvb3QsCgkJCQkJCQkJT2lkIHJlbGF0 aW9uT2JqZWN0SWQsCgkJCQkJCQkJYm9vbCBpbmhwYXJlbnQsCgkJCQkJCQkJUmVsT3B0SW5mbyAq cmVsKTsKSGVhcFR1cGxlIHBsdWdpbl9nZXRfcmVsYXRpb25fc3RhdHMoT2lkIHJlbGlkLCBBdHRy TnVtYmVyIGF0dG51bSwgCgkJCQkJCQkJCXZvaWQgKCpmcmVlZnVuYykgKEhlYXBUdXBsZSB0dXBs ZSkpOwp2b2lkIHBsdWdpbl9yZWxlYXNlX3JlbGF0aW9uX3N0YXRzKEhlYXBUdXBsZSBzdGF0c3R1 cCk7CmludDMyIHBsdWdpbl9nZXRfYXR0YXZnd2lkdGgoT2lkIHJlbGlkLCBBdHRyTnVtYmVyIGF0 dG51bSk7CgoKdm9pZCBfUEdfaW5pdCh2b2lkKTsKCi8qIGludGVybmFsIGNhbGxzICovCnN0YXRp YyB2b2lkIHRvbV9pbml0KHZvaWQpOwpzdGF0aWMgdm9pZCBnZXRfdG9tX3JlbGF0aW9uX3NpemUo T2lkIHJlbGlkLCBkb3VibGUgKnR1cGxlcywgQmxvY2tOdW1iZXIgKnBhZ2VzKTsKc3RhdGljIGJv b2wgZ2V0X3RvbV9zdGF0c190dXBsZXRhYmxlKE9pZCByZWxpZCwgQXR0ck51bWJlciBhdHRudW0p OwoKdm9pZApfUEdfaW5pdCh2b2lkKQp7CglnZXRfcmVsYXRpb25faW5mb19ob29rID0gJnBsdWdp bl9nZXRfcmVsYXRpb25faW5mbzsKCXJlbGVhc2VfcmVsYXRpb25fc3RhdHNfaG9vayA9ICZwbHVn aW5fcmVsZWFzZV9yZWxhdGlvbl9zdGF0czsKCWdldF9yZWxhdGlvbl9zdGF0c19ob29rID0gJnBs dWdpbl9nZXRfcmVsYXRpb25fc3RhdHM7CglnZXRfYXR0YXZnd2lkdGhfaG9vayA9ICZwbHVnaW5f Z2V0X2F0dGF2Z3dpZHRoOwp9Cgp2b2lkCnRvbV9pbml0KHZvaWQpCnsKCWludAkJCXJjOwoJY2hh cgkJcXVlcnlbMTAyNF07CglPaWQJCQlwbGFuX3R5cGVzWzNdOwoKCWlmICh0cGkgPT0gTlVMTCkK CXsKCQkvKgoJCSAqIE5vIHRwaSBmb3VuZCwgc28gY3JlYXRlIGl0CgkJICovCgkJdHBpID0gKHRv bV9wbGFuX2luZm8gKikgbWFsbG9jKHNpemVvZih0b21fcGxhbl9pbmZvKSk7CgkJbWVtc2V0KHRw aSwgMCwgc2l6ZW9mKHRvbV9wbGFuX2luZm8pKTsKCgkJdHBpLT5wbGFuc3RhdGUgPSBQTEFOU19V TlBMQU5ORUQ7Cgl9CgoJLyoKCSAqIFByZXBhcmUgYW5kIHNhdmUgdGhlIHBsYW5zCgkgKi8KCWlm ICh0cGktPnBsYW5zdGF0ZSA9PSBQTEFOU19VTlBMQU5ORUQpCgl7CgkJdHBpLT5wbGFuc3RhdGUg PSBQTEFOU19JTl9QUk9HUkVTUzsKCgkJaWYgKChyYyA9IFNQSV9jb25uZWN0KCkpIDwgMCkKCQkJ ZWxvZyhFUlJPUiwgInRvbTogU1BJX2Nvbm5lY3QoKSBmYWlsZWQgaW4gX1BHX2luaXQiKTsKCgkJ LyoKCQkgKiBJZGVudGlmeSB0aGUgb2lkcyBvZiB0aGUgVE9NIHRhYmxlcywgc28gd2UgY2FuIGV4 Y2x1ZGUgdGhlbQoJCSAqIGZyb20gcHJvY2Vzc2luZyBlbHNld2hlcmUgaW4gdGhlIHBsdWdpbi4g T3RoZXJ3aXNlIHdlCgkJICogZ2VuZXJhdGUgcmVjdXJzaXZlIGNhbGxzIHdoaWNoIG1ha2UgbGlm ZSBkaWZmaWN1bHQgZm9yIHVzLgoJCSAqLwoJCXNwcmludGYocXVlcnksIAoJCSJTRUxFQ1QgYy5v aWQgRlJPTSBwZ19jbGFzcyBjIEpPSU4gcGdfbmFtZXNwYWNlIG4iCgkJIiBPTiBuLm9pZCA9IGMu cmVsbmFtZXNwYWNlIgoJCSIgV0hFUkUgbi5uc3BuYW1lID0gJ3RvbSciCgkJIiBBTkQgYy5yZWxu YW1lIElOICgndG9tX21hcHBpbmcnLCAndG9tX3BnX2NsYXNzJywgJ3RvbV9wZ19zdGF0aXN0aWMn KSIKCQkiIExJTUlUIDMiKTsKCgkJcmMgPSBTUElfZXhlYyhxdWVyeSwgMCk7CgoJCXRwaS0+dG9t X29pZFswXSA9IERhdHVtR2V0SW50MzIoU1BJX2dldGJpbnZhbChTUElfdHVwdGFibGUtPnZhbHNb MF0sCgkJCQkJCQkJCVNQSV90dXB0YWJsZS0+dHVwZGVzYywgMSwgTlVMTCkpOwoJCXRwaS0+dG9t X29pZFsxXSA9IERhdHVtR2V0SW50MzIoU1BJX2dldGJpbnZhbChTUElfdHVwdGFibGUtPnZhbHNb MV0sCgkJCQkJCQkJCVNQSV90dXB0YWJsZS0+dHVwZGVzYywgMSwgTlVMTCkpOwoJCXRwaS0+dG9t X29pZFsyXSA9IERhdHVtR2V0SW50MzIoU1BJX2dldGJpbnZhbChTUElfdHVwdGFibGUtPnZhbHNb Ml0sCgkJCQkJCQkJCVNQSV90dXB0YWJsZS0+dHVwZGVzYywgMSwgTlVMTCkpOwoKCQlTUElfZnJl ZXR1cHRhYmxlKFNQSV90dXB0YWJsZSk7CgoJCS8qCgkJICogUGxhbjogR2V0IHN0YXRzIGZvciBh IHJlbGF0aW9uLiBTUUwgYXNzdW1lcyB0aGF0IHRoZSBQSyBvZgoJCSAqIHRvbV9tYXBwaW5nIGlz IGxvY2FsX3JlbGlkIGFuZCB0aGUgUEsgb2YgdG9tX3BnX2NsYXNzIGlzCgkJICogc2NoZW1hbmFt ZSBhbmQgcmVsbmFtZS4KCQkgKi8KCQlzcHJpbnRmKHF1ZXJ5LCAKCQkiU0VMRUNUIG51bWJlcl84 a2Jsb2NrcywgbnVtYmVyX3R1cGxlcyBGUk9NIHRvbS50b21fcGdfY2xhc3MgYyIKCQkiIEpPSU4g dG9tLnRvbV9tYXBwaW5nIG0gIgoJCSIgT04gbS5zY2hlbWFuYW1lID0gYy5zY2hlbWFuYW1lIEFO RCBtLnJlbG5hbWUgPSBjLnJlbG5hbWUiCgkJIiBXSEVSRSBsb2NhbF9yZWxpZCA9ICQxIgoJCSIg TElNSVQgMSIpOwoKCQlwbGFuX3R5cGVzWzBdID0gSU5UNE9JRDsKCgkJdHBpLT5wbGFuX3RvbV9w Z19jbGFzcyA9IFNQSV9zYXZlcGxhbihTUElfcHJlcGFyZShxdWVyeSwgMSwgcGxhbl90eXBlcykp OwoJCWlmICh0cGktPnBsYW5fdG9tX3BnX2NsYXNzID09IE5VTEwpCgkJCWVsb2coRVJST1IsICJ0 b206IFNQSV9wcmVwYXJlKCkgZmFpbGVkIGZvciBwbGFuX3RvbV9wZ19jbGFzcyIpOwoKCQkvKgoJ CSAqIFBsYW46IEdldCBzdGF0aXN0aWNzIGZvciBhIGNvbHVtbi4gU1FMIGFzc3VtZXMgdGhhdCB0 aGUgUEsgb2YKCQkgKiB0b21fbWFwcGluZyBpcyBsb2NhbF9yZWxpZCBhbmQgdGhlIFBLIG9mIHRv bV9wZ19zdGF0aXN0aWMgaXMKCQkgKiBzY2hlbWFuYW1lLCByZWxuYW1lIGFuZCBhdHRudW0uIE5l c3RlZCBsb29wcyBqb2luIGV4cGVjdGVkLgoJCSAqLwoJCXNwcmludGYocXVlcnksIAoJCSJTRUxF Q1QgKiBGUk9NIHRvbS50b21fcGdfc3RhdGlzdGljIHMiCgkJIiBKT0lOIHRvbS50b21fbWFwcGlu ZyBtIgoJCSIgT04gbS5zY2hlbWFuYW1lID0gcy5zY2hlbWFuYW1lIEFORCBtLnJlbG5hbWUgPSBz LnJlbG5hbWUiCgkJIiBXSEVSRSBtLmxvY2FsX3JlbGlkID0gJDEgQU5EIHMuYXR0bnVtID0gJDIi CgkJIiBMSU1JVCAxIik7CgoJCXBsYW5fdHlwZXNbMF0gPSBJTlQ0T0lEOwoJCXBsYW5fdHlwZXNb MV0gPSBJTlQ0T0lEOwoKCQl0cGktPnBsYW5fdG9tX3BnX3N0YXRpc3RpYyA9IFNQSV9zYXZlcGxh bihTUElfcHJlcGFyZShxdWVyeSwgMiwgcGxhbl90eXBlcykpOwoJCWlmICh0cGktPnBsYW5fdG9t X3BnX3N0YXRpc3RpYyA9PSBOVUxMKQoJCQllbG9nKEVSUk9SLCAidG9tOiBTUElfcHJlcGFyZSgp IGZhaWxlZCBmb3IgcGxhbl90b21fcGdfc3RhdGlzdGljIik7CgoJCXRwaS0+cGxhbnN0YXRlID0g UExBTlNfUkVBRFk7CgoJCVNQSV9maW5pc2goKTsKCX0KfQoKLyoKICogcGx1Z2luX2dldF9yZWxh dGlvbl9pbmZvKCkKICoKICogVGhpcyBwbHVnaW4gd29ya3MgYnkgb3ZlcnJpZGluZyBleGlzdGlu ZyB2YWx1ZXMgc2V0IGJ5IHBsYW5uZXIKICogTm8gb3ZlcnJpZGUsIG5vIGFjdGlvbgogKi8Kdm9p ZApwbHVnaW5fZ2V0X3JlbGF0aW9uX2luZm8oUGxhbm5lckluZm8gKnJvb3QsCgkJCQkJCQkJT2lk IHJlbGF0aW9uT2JqZWN0SWQsCgkJCQkJCQkJYm9vbCBpbmhwYXJlbnQsIAoJCQkJCQkJCVJlbE9w dEluZm8gKnJlbCkKewoJdG9tX2luaXQoKTsKCgkvKiAKCSAqIERvbid0IGxvb2sgZm9yIG92ZXJy aWRlIGluZm8gZm9yIFRPTSB0YWJsZXMgdGhlbXNlbHZlcwoJICovCglpZiAocmVsYXRpb25PYmpl Y3RJZCA9PSB0cGktPnRvbV9vaWRbMF0gfHwKCQlyZWxhdGlvbk9iamVjdElkID09IHRwaS0+dG9t X29pZFsxXSB8fAoJCXJlbGF0aW9uT2JqZWN0SWQgPT0gdHBpLT50b21fb2lkWzJdIHx8CgkJdHBp LT5wbGFuc3RhdGUgIT0gUExBTlNfUkVBRFkpCgkJcmV0dXJuOwoKCS8qIAoJICogT3ZlcnJpZGUg dGhlIGFjdHVhbCBzaXplIG9mIHJlbGF0aW9uIG9uIHRoaXMgc2VydmVyLgoJICogU2V0IHRoZSB0 dXBsZXMgYW5kIHBhZ2VzIHZhbHVlcyBkaXJlY3RseSBmcm9tIHRvbV9wZ19jbGFzcywKCSAqIHdp dGhvdXQgdHJ5aW5nIHRvIGNhbGN1bGF0ZSB0dXBsZXMgZGVuc2l0eSBldGMgYXMgd2UgZG8gaW4g dGhlCgkgKiBzdGFuZGFyZCBwbGFubmVyLgoJICovCglnZXRfdG9tX3JlbGF0aW9uX3NpemUocmVs YXRpb25PYmplY3RJZCwgJnJlbC0+dHVwbGVzLCAmcmVsLT5wYWdlcyk7CgoJLyoKCSAqIEdldCBz aXplIGZvciBhbnkgSW5kZXhPcHRJbmZvIG5vZGVzIHByZXNlbnQKCSAqLwoJaWYgKHJlbC0+aW5k ZXhsaXN0KQoJewoJCUxpc3QJICAgKmluZGV4bGlzdDsKCQlMaXN0Q2VsbCAgICpsOwoKCQlpbmRl eGxpc3QgPSByZWwtPmluZGV4bGlzdDsKCgkJZm9yZWFjaChsLCBpbmRleGxpc3QpCgkJewoJCQlJ bmRleE9wdEluZm8gKmluZm8gPSBsZmlyc3QobCk7CgoJCQkvKiAKCQkJICogT3ZlcnJpZGUgdGhl IGFjdHVhbCBzaXplIG9mIGluZGV4IG9uIHRoaXMgc2VydmVyLgoJCQkgKiBTZXQgdGhlIHR1cGxl cyBhbmQgcGFnZXMgdmFsdWVzIGRpcmVjdGx5IGZyb20gdG9tX3BnX2NsYXNzCgkJCSAqLwoJCQln ZXRfdG9tX3JlbGF0aW9uX3NpemUoaW5mby0+aW5kZXhvaWQsICZpbmZvLT50dXBsZXMsICZpbmZv LT5wYWdlcyk7CgkJfQoJfQp9CgovKgogKiBnZXRfdG9tX3JlbGF0aW9uX3NpemUoKQogKgogKiBD b252ZW5pZW5jZSByb3V0aW5lIGZvciBwbHVnaW5fZ2V0X3JlbGF0aW9uX2luZm8oKQogKiBObyBv dmVycmlkZSwgbm8gYWN0aW9uCiAqLwpzdGF0aWMgdm9pZApnZXRfdG9tX3JlbGF0aW9uX3NpemUo T2lkIHJlbGlkLCBkb3VibGUgKnR1cGxlcywgQmxvY2tOdW1iZXIgKnBhZ2VzKQp7CglpbnQJCQly YzsKCURhdHVtIAkJdG9tX3BnX2NsYXNzX3ZhbHVlc1sxXTsKCglpZiAoKHJjID0gU1BJX2Nvbm5l Y3QoKSkgPCAwKQoJewoJCWVsb2coTE9HLCAidG9tOiBTUElfY29ubmVjdCgpIGZhaWxlZCBpbiBn ZXRfdG9tX3JlbGF0aW9uX3NpemUoKSIpOwoJCXJldHVybjsKCX0KCgl0b21fcGdfY2xhc3NfdmFs dWVzWzBdID0gT2JqZWN0SWRHZXREYXR1bShyZWxpZCk7CglyYyA9IFNQSV9leGVjcCh0cGktPnBs YW5fdG9tX3BnX2NsYXNzLCB0b21fcGdfY2xhc3NfdmFsdWVzLCBOVUxMLCAxKTsKCgkvKgoJICog SWYgd2UgZ2V0IGFuIGVycm9yLCBsb2cgYSBtZXNzYWdlLCBidXQgbm8gbmVlZCB0byBmYWlsIGNv bXBsZXRlbHkuCgkgKiBUaGlzIGlzbid0IHN1cHBvc2VkIHRvIGJlIGEgY3JpdGljYWwgdXRpbGl0 eQoJICovCglpZiAocmMgIT0gU1BJX09LX1NFTEVDVCkKCXsKCQllbG9nKExPRywgInRvbTogY2Fu bm90IGdldCB0b21fcGdfY2xhc3MgdHVwbGUgZm9yIHJlbGlkPSVkIChyYz0lZCkiLCByZWxpZCwg cmMpOwoJCVNQSV9maW5pc2goKTsKCQlyZXR1cm47Cgl9CgoJLyoKCSAqIElmIHRoZXJlIGlzIGEg cm93IGluIHRvbV9wZ19jbGFzcyB0YWJsZSwgYXBwbHkgdmFsdWVzCgkgKi8JCglpZiAoU1BJX3By b2Nlc3NlZCA9PSAxKQoJewoJCSpwYWdlcyA9IERhdHVtR2V0SW50MzIoU1BJX2dldGJpbnZhbChT UElfdHVwdGFibGUtPnZhbHNbMF0sCgkJCQkJCQkJCVNQSV90dXB0YWJsZS0+dHVwZGVzYywgMSwg TlVMTCkpOwoJCSp0dXBsZXMgPSAoZG91YmxlKSBEYXR1bUdldEludDY0KFNQSV9nZXRiaW52YWwo U1BJX3R1cHRhYmxlLT52YWxzWzBdLAoJCQkJCQkJCQlTUElfdHVwdGFibGUtPnR1cGRlc2MsIDIs IE5VTEwpKTsKCX0KCglTUElfZnJlZXR1cHRhYmxlKFNQSV90dXB0YWJsZSk7CgoJU1BJX2Zpbmlz aCgpOwp9Cgp2b2lkCnBsdWdpbl9yZWxlYXNlX3JlbGF0aW9uX3N0YXRzKEhlYXBUdXBsZSBzdGF0 c3R1cCkKewoJaWYgKEhlYXBUdXBsZUlzVmFsaWQoc3RhdHN0dXApKQoJCXBmcmVlKHN0YXRzdHVw KTsKfQoKLyoKICogcGx1Z2luX2dldF9yZWxhdGlvbl9zdGF0cygpCiAqCiAqIFRoaXMgcGx1Z2lu IHdvcmtzIGJ5IHJldHVybmluZyBkaWZmZXJlbnQgc3RhdHMsIGlmIHRoZXkgYXJlIGF2YWlsYWJs ZS4KICogU2V0dGluZyB1cCB0aGUgbWFwcGluZyB0YWJsZSBjb3JyZWN0bHkgaXMgZXNzZW50aWFs IHRvIG1ha2luZyB0aGlzIHdvcmsuCiAqLwpIZWFwVHVwbGUgCnBsdWdpbl9nZXRfcmVsYXRpb25f c3RhdHMoT2lkIHJlbGlkLCBBdHRyTnVtYmVyIGF0dG51bSwgdm9pZCAoKmZyZWVmdW5jKSAoSGVh cFR1cGxlIHR1cGxlKSkKewoJSGVhcFR1cGxlCXN0YXRzdHVwID0gTlVMTDsKCglpZiAoIWdldF90 b21fc3RhdHNfdHVwbGV0YWJsZShyZWxpZCwgYXR0bnVtKSkKCQlyZXR1cm4gTlVMTDsKCgkvKgoJ ICogR2V0IHN0YXRzIGlmIHByZXNlbnQuIFdlIGFza2VkIGZvciBvbmx5IG9uZSByb3csIHNvIG5v IG5lZWQgZm9yIGxvb3BzLgoJICovCQoJaWYgKFNQSV9wcm9jZXNzZWQgPiAwKQoJCXN0YXRzdHVw ID0gU1BJX2NvcHl0dXBsZShTUElfdHVwdGFibGUtPnZhbHNbMF0pOwoKCVNQSV9mcmVldHVwdGFi bGUoU1BJX3R1cHRhYmxlKTsKCVNQSV9maW5pc2goKTsKCgkvKiBkZWZpbmUgZnVuY3Rpb24gdG8g dXNlIHdoZW4gdGltZSB0byBmcmVlIHRoZSB0dXBsZSAqLwoJZnJlZWZ1bmMgPSBoZWFwX2ZyZWV0 dXBsZTsKCglyZXR1cm4gc3RhdHN0dXA7Cn0KCi8qIAogKiBTaW1pbGFyIHRvIHBsdWdpbl9nZXRf cmVsYXRpb25fc3RhdHMsIGp1c3QgcmVzdHJpY3RlZCB0byBvbmUgY29sdW1uIG9ubHkuCiAqIFdl IHByZXBhcmVkIFNFTEVDVCAqLCBzbyBqdXN0IHVzZSB0aGF0IHBsYW4gYW5kIHJldHJpZXZlIHRo ZSBjb3JyZWN0CiAqIGNvbHVtbiBmcm9tIHRoZSByZXN1bHRzZXQuCiAqLwppbnQzMiAKcGx1Z2lu X2dldF9hdHRhdmd3aWR0aChPaWQgcmVsaWQsIEF0dHJOdW1iZXIgYXR0bnVtKQp7CglpbnQzMgkJ c3Rhd2lkdGggPSAwOwoKCWlmICghZ2V0X3RvbV9zdGF0c190dXBsZXRhYmxlKHJlbGlkLCBhdHRu dW0pKQoJCXJldHVybiAwOwoKCS8qCgkgKiBHZXQgc3RhdHMgaWYgcHJlc2VudC4gV2UgYXNrZWQg Zm9yIG9ubHkgb25lIHJvdywgc28gbm8gbmVlZCBmb3IgbG9vcHMuCgkgKi8JCglpZiAoU1BJX3By b2Nlc3NlZCA+IDApCgkJc3Rhd2lkdGggPSBEYXR1bUdldEludDMyKFNQSV9nZXRiaW52YWwoU1BJ X3R1cHRhYmxlLT52YWxzWzBdLAoJCQkJCQkJCQlTUElfdHVwdGFibGUtPnR1cGRlc2MsIAoJCQkJ CQkJCQk1LCAJLyogYXR0bnVtIG9mIHRvbV9wZ19zdGF0aXN0aWMuc3Rhd2lkdGggKi8KCQkJCQkJ CQkJTlVMTCkpOwkJLyogc3Rhd2lkdGggaXMgTk9UIE5VTEwgKi8KCglTUElfZnJlZXR1cHRhYmxl KFNQSV90dXB0YWJsZSk7CglTUElfZmluaXNoKCk7CgoJcmV0dXJuIHN0YXdpZHRoOwp9CgovKgog KiBnZXRfdG9tX3N0YXRzX3R1cGxldGFibGUoKQogKgogKiBDb21tb24gcm91dGluZSBiZXR3ZWVu IHN0YXRzX2hvb2sgYW5kIGF0dGF2Z3dpZHRoX2hvb2sKICoKICogUmV0dXJucyB0cnVlIGlmIGEg U1BJIHR1cGxldGFibGUgZXhpc3RzIHdpdGggcmVzdWx0cyBmb3IgZnVydGhlcgogKiBwcm9jZXNz aW5nLCBvciBmYWxzZSBpZiBub3RoaW5nIGVsc2UgdG8gZG8KICovCnN0YXRpYyBib29sCmdldF90 b21fc3RhdHNfdHVwbGV0YWJsZShPaWQgcmVsaWQsIEF0dHJOdW1iZXIgYXR0bnVtKQp7CglEYXR1 bSAJCXRvbV9wZ19zdGF0aXN0aWNfdmFsdWVzWzJdOwoJaW50CQkJcmM7CgoJdG9tX2luaXQoKTsK CgkvKiAKCSAqIERvbid0IGxvb2sgZm9yIG92ZXJyaWRlIGluZm8gZm9yIFRPTSB0YWJsZXMgdGhl bXNlbHZlcwoJICovCglpZiAocmVsaWQgPT0gdHBpLT50b21fb2lkWzBdIHx8CgkJcmVsaWQgPT0g dHBpLT50b21fb2lkWzFdIHx8CgkJcmVsaWQgPT0gdHBpLT50b21fb2lkWzJdIHx8CgkJdHBpLT5w bGFuc3RhdGUgIT0gUExBTlNfUkVBRFkpCgkJcmV0dXJuIGZhbHNlOwoKCWlmICgocmMgPSBTUElf Y29ubmVjdCgpKSA8IDApCgl7CgkJZWxvZyhMT0csICJ0b206IFNQSV9jb25uZWN0KCkgZmFpbGVk IGluIGdldF90b21fcmVsYXRpb25fc3RhdHMoKSIpOwoJCXJldHVybiBmYWxzZTsKCX0KCgl0b21f cGdfc3RhdGlzdGljX3ZhbHVlc1swXSA9IE9iamVjdElkR2V0RGF0dW0ocmVsaWQpOwoJdG9tX3Bn X3N0YXRpc3RpY192YWx1ZXNbMV0gPSBJbnQxNkdldERhdHVtKGF0dG51bSk7CglyYyA9IFNQSV9l eGVjcCh0cGktPnBsYW5fdG9tX3BnX3N0YXRpc3RpYywgdG9tX3BnX3N0YXRpc3RpY192YWx1ZXMs IE5VTEwsIDEpOwoKCWlmIChyYyAhPSBTUElfT0tfU0VMRUNUKQoJewoJCWVsb2coTE9HLCAidG9t OiBjYW5ub3QgZ2V0IHRvbV9wZ19zdGF0aXN0aWMgdHVwbGUgZm9yIHJlbGlkPSVkIChyYz0lZCki LCByZWxpZCwgcmMpOwoJCVNQSV9maW5pc2goKTsKCQlyZXR1cm4gZmFsc2U7Cgl9CgoJcmV0dXJu IHRydWU7Cn0KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY29udHJpYi9UT00vbG9hZF9kYXRhX2Zvcl90b20uc3Fs AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAADAwMDA3NTUAMDAwMTc1MAAwMDAwMTQ0ADAwMDAwMDAwNDU0ADExMDQxNTc2NTU0 ADAxNjU2NgAgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3Rh ciAgAHNyaWdncwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdXNlcnMAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtLQotLSBMb2FkIGRhdGEgZm9yIFRyYW5zcG9ydGFibGUg T3B0aW1pemVyIE1vZGUKLS0KLS0gc2ltb25AMm5kcXVhZHJhbnQuY29tCgpUUlVOQ0FURSBUT00u dG9tX3BnX3N0YXRpc3RpYzsKXGNvcHkgdG9tLnRvbV9wZ19zdGF0aXN0aWMgZnJvbSAndG9tX3Bn X3N0YXRpc3RpYy5kYXRhJwoKVFJVTkNBVEUgVE9NLnRvbV9wZ19jbGFzczsKXGNvcHkgdG9tLnRv bV9wZ19jbGFzcyBmcm9tICd0b21fcGdfY2xhc3MuZGF0YScKCi0tCi0tIEVuZCBvZiBnZXQgZGF0 YSBmb3IgVHJhbnNwb3J0YWJsZSBPcHRpbWl6ZXIgTW9kZQotLQoAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAGNvbnRyaWIvVE9NL2dldF9kYXRhX2Zvcl90b20uc2gAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAwMDAwNzU1ADAwMDE3NTAAMDAwMDE0NAAwMDAwMDAwMTE0NAAxMTA0NTA2MDYxMQAw MTYyMjAAIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdXN0YXIg IABzcmlnZ3MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHVzZXJzAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAIyEvYmluL3NoCiMgJElkJAojCiMgRXh0cmFjdCBzY3JpcHQg Zm9yIFRyYW5zcG9ydGFibGUgT3B0aW1pemVyIE1vZGUgKFRPTSkKIwojIENocmlzIEJyb3duZSAJ CXNlbGVjdCAnY2Jicm93bmUnIHx8ICdAJyB8fCAnbGludXhmaW5hbmNlcy5pbmZvJzsKIwojc291 cmNlIH4vZGJzL3Bnc3FsODMuc2ggZW52ICAgICMgQSBjYmJyb3duZS1pc20gdG8gc2V0IHVwIGFj Y2VzcyB0byBteSBmYXZvcml0ZSBEQiBjbHVzdGVyLi4uCgojIFRoZXNlIGFsbCBwcm92aWRlIG92 ZXJyaWRhYmxlIGRlZmF1bHRzClNPVVJDRURCPSR7U09VUkNFREI6LSJwb3N0Z3JlcyJ9ICAgICAg ICAgIyB3aGljaCBkYXRhYmFzZSBkb2VzIHRoZSBkYXRhIGNvbWUgZnJvbQpTT1VSQ0VTQ0hFTUE9 JHtTT1VSQ0VTQ0hFTUE6LSJwdWJsaWMifSAgICMgd2hpY2ggc2NoZW1hIGlzIGluIHVzZSAoZS5n LiAtIHdoYXQgc2NoZW1hIHRvIHBnX2R1bXApCgpwc3FsIC1kICR7U09VUkNFREJ9IC1jICJhbmFs eXplOyIKcHNxbCAtZCAke1NPVVJDRURCfSAtZiBnZXRfZGF0YV9mb3JfdG9tLnNxbApwZ19kdW1w IC1uICR7U09VUkNFU0NIRU1BfSAtcyAke1NPVVJDRURCfSA+ICR7U09VUkNFU0NIRU1BfV9kdW1w LnNxbAoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAGNvbnRyaWIvVE9NL1JFQURNRQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAwMDAwNzU1ADAwMDE3NTAAMDAwMDE0NAAwMDAwMDAwNTIzMAAxMTA2NzE3MjEyMQAwMTMy NTMAIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdXN0YXIgIABz cmlnZ3MAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHVzZXJzAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAALS0KLS0gVHJhbnNwb3J0YWJsZSBPcHRpbWl6ZXIgTW9kZSAoVE9N KSBmb3IgUG9zdGdyZVNRTAotLQotLSBEZXZlbG9wbWVudCAJc2ltb25AMm5kcXVhZHJhbnQuY29t Ci0tIEluc3RhbGxhdGlvbiBjYmJyb3duZUBhY20ub3JnCi0tCgpUT00gaXMgZGVzaWduZWQgdG8g YWxsb3cgeW91IHRvIHRha2Ugc3RhdGlzdGljcyBmcm9tIG9uZSBkYXRhYmFzZQpzZXJ2ZXIgdG8g YW5vdGhlciwgZnVsbHkgZW11bGF0aW5nIHRoZSBlbnZpcm9ubWVudCBmb3IgU1FMIHBsYW5uaW5n LgoKRXhhbXBsZSB1c2UgY2FzZXMgYXJlCiogY3JlYXRpbmcgYSBkZXZlbG9wbWVudCBzZXJ2ZXIg CiogcHJvdmlkaW5nIGRldGFpbHMgb2YgYSBwcm9ibGVtIFNRTCBzdGF0ZW1lbnQgdG8gYSByZW1v dGUgYW5hbHlzdAoKUHJvY2VzcyBpcyBzdHJhaWdodGZvcndhcmQgaWYgeW91IGFyZSB1c2luZyBz YW1lIHNjaGVtYSBhbmQgdGFibGVuYW1lcwpvbiBib3RoIGRhdGFiYXNlIHNlcnZlcnMgKHJlY29t bWVuZGVkKS4KCkFjdGlvbnMgb24gU291cmNlIGRhdGFiYXNlOgo9PT09PT09PT09PT09PT09PT09 PT09PT09PT0KWzAuIEluc3RhbGwgVE9NLCBpZiBub3QgYWxyZWFkeSBpbnN0YWxsZWRdCgljZCA8 cG9zdGdyZXNxbC1zb3VyY2UtdHJlZT4KCXRhciBjdmYgVE9NLnRhcgoJY2QgY29udHJpYi9UT00K CW1ha2UKCW1ha2UgaW5zdGFsbCAtIGNvcGllcyAuc28gZmlsZSB0byAkTElCIGRpcmVjdG9yeQoK CU5vIGZ1bmN0aW9ucyBuZWVkIHRvIGJlIGNyZWF0ZWQKCjEuIFZBQ1VVTSBBTkFMWVpFIGFsbCBy ZXF1aXJlZCB0YWJsZXMgCgoJVkFDVVVNIEFOQUxZWkUgW3RhYmxlbmFtZV07CgoJVGhpcyBpcyBq dXN0IHRvIG1ha2Ugc3VyZSBzdGF0cyBhcmUgdXAgdG8gZGF0ZSBiZWZvcmUgd2UgdHJhbnNwb3J0 IHRoZW0uCgoyLiBHZXQgc3RhdHMgZGF0YSBmb3IgVE9NIAoKCXBzcWwgLWYgZ2V0X2RhdGFfZm9y X3RvbS5zcWwKCglQcm9kdWNlcyAKCQl0b21fcGdfc3RhdGlzdGljLmRhdGEgCgkJdG9tX3BnX2Ns YXNzLmRhdGEKCglUaGlzIGluY2x1ZGVzIGFsbCBzdGF0cyBmb3IgdGFibGVzIHlvdSBoYXZlIGFj Y2VzcyB0bywgc28geW91IG1heSB3aXNoCgl0byBlZGl0IHRoaXMgZG93biBpZiB5b3UgaGF2ZSBz ZWN1cml0eSBjb25jZXJucy4KCjMuIEdldCB0YWJsZSBtZXRhZGF0YSAoYW5kIHBvc3NpYmx5IGRh dGEsIG9yIGEgc2FtcGxlIG9mIGl0KQoKCXBnX2R1bXAgWy1zXSAtdCB0YWJsZW5hbWUgPiB1c2Vy X3RhYmxlcy5zcWwKCglJZiB5b3UgaW5jbHVkZSBkYXRhIGFzIHdlbGwsIHRoZW4gaXQgbWF5IGJl IHBvc3NpYmxlIHRvIHJ1biBhbgoJRVhQTEFJTiBBTkFMWVpFIGFzIHdlbGwgYXMgYW4gRVhQTEFJ Ti4gT2YgY291cnNlLCBleHRyYWN0aW5nIGEKCXJlcHJlc2VudGF0aXZlIHNhbXBsZSBpcyBkaWZm aWN1bHQuCgpCZXR3ZWVuIGRhdGFiYXNlczoKPT09PT09PT09PT09PT09PT09CjQuIFRyYW5zcG9y dCBkYXRhIHRvIHRhcmdldCBzeXN0ZW0KZS5nLiBSRkMgMTE0OSwgZW1haWwgZXRjCgpBY3Rpb25z IG9uIFRhcmdldCBkYXRhYmFzZToKPT09PT09PT09PT09PT09PT09PT09PT09PT09Cgo1LiBEZXRl cm1pbmUgdGhlIG5hbWUgb2YgdGhlIGRhdGFiYXNlIGFuZCBzY2hlbWEgeW91IGludGVuZCB0byB1 c2UgZm9yIFRPTQoKCVRPTVNDSEVNQT10b20KCVRFU1REQj10ZXN0dG9tZGIKCWV4cG9ydCBUT01T Q0hFTUEgVEVTVERCCgo2LiBDcmVhdGUgdXNlciB0YWJsZXMgKGFuZCBsb2FkIGRhdGEgZnVsbC9z YW1wbGUgYXMgcmVxdWlyZWQpCgoJZS5nLgoJY3JlYXRlZGIgJHtURVNUREJ9Cglwc3FsIC1mIHVz ZXJfdGFibGVzLnNxbCAtZCAke1RFU1REQn0KCjcuIENyZWF0ZSBUT00gdGFibGVzCgoJcHNxbCAt YyAiY3JlYXRlIHNjaGVtYSAke1RPTVNDSEVNQX07IiAtZCAke1RFU1REQn0KCXBzcWwgLWYgY3Jl YXRlX3RvbV90YWJsZXMuc3FsIC0tc2luZ2xlLXRyYW5zYWN0aW9uIC12IFRPTV9TQ0hFTUE9JyR7 VE9NU0NIRU1BfScgLWQgJHtURVNUREJ9Cgo4LiBMb2FkIFRPTSBkYXRhIGludG8gdGFyZ2V0IGRh dGFiYXNlCgoJZS5nLgoJcHNxbCAtZiBsb2FkX2RhdGFfZm9yX3RvbS5zcWwgLS1zaW5nbGUtdHJh bnNhY3Rpb24gIC12IFRPTV9TQ0hFTUE9JyR7VE9NU0NIRU1BfScgLWQgJHtURVNUREJ9Cgo5LiBD cmVhdGUgbWFwcGluZyBiZXR3ZWVuIHRhcmdldCBjYXRhbG9nIGFuZCBzb3VyY2Ugc3RhdHMKCglw c3FsIC1mIGdldF9tYXBwaW5nX2Zvcl90b20uc3FsIC12IFRPTV9TQ0hFTUE9JHtUT01TQ0hFTUF9 IC1kICR7VEVTVERCfQoKCVdlIG5lZWQgdG8gYmUgYWJsZSB0byBtYXRjaCB1cCBvYmplY3RzIGJl dHdlZW4gc291cmNlIGFuZCB0YXJnZXQuIFRoaXMKCXNjcmlwdCBtYXRjaGVzIHVwIG9iamVjdHMg dGhhdCBoYXZlIG1hdGNoaW5nIHNjaGVtYSBhbmQgdGFibGVuYW1lcy4gSWYKCXlvdSBoYXZlIGEg ZGlmZmVyZW50IG9yIG1vcmUgY29tcGxleCBtYXRjaGluZyBhbGdvcml0aG0sIHJ1biBpdCBub3cu CgoxMC4gU2V0dXAgVE9NIHBsdWdpbgoKICAgIEVpdGhlciBzZXQgZm9yIGFsbCB1c2VycyB2aWEg cG9zdGdyZXNxbC5jb25mCgoJICAgc2hhcmVkX3ByZWxvYWRfbGlicmFyaWVzID0gJyRsaWJkaXIv dG9tX2hvb2tzJwoKCW9yIHNldCBmb3IgaW5kaXZpZHVhbCBzZXNzaW9ucyB1c2luZwoKCSAgTE9B RCAnJGxpYmRpci90b21faG9va3MnOwoKMTEuIEVYUExBSU4geW91ciBxdWVyaWVzCgoKAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAY29udHJpYi9UT00vY3JlYXRlX3RvbV90YWJsZXMuc3FsAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAw MDA3NTUAMDAwMTc1MAAwMDAwMTQ0ADAwMDAwMDAzNDM0ADExMDQ2NDIwNDMyADAxNjU3MgAgMAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhciAgAHNyaWdncwAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdXNlcnMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAtLQotLSBUYWJsZXMgZm9yIFRyYW5zcG9ydGFibGUgT3B0aW1pemVyIE1vZGUK LS0KLS0gc2ltb25AMm5kcXVhZHJhbnQuY29tCgpTRVQgc2VhcmNoX3BhdGg9OlRPTV9TQ0hFTUE7 ClNFVCBjbGllbnRfbWluX21lc3NhZ2VzPUVSUk9SOwoKRFJPUCBUQUJMRSBJRiBFWElTVFMgdG9t X21hcHBpbmc7CkNSRUFURSBUQUJMRSB0b21fbWFwcGluZyAoCiAgICBsb2NhbF9yZWxpZCBvaWQg bm90IG51bGwsCglzY2hlbWFuYW1lIG5hbWUgbm90IG51bGwsCglyZWxuYW1lIG5hbWUgbm90IG51 bGwKKTsKCkNPTU1FTlQgb24gVEFCTEUgdG9tX21hcHBpbmcgSVMgCidNYXBwaW5nIGJldHdlZW4g bG9jYWwgY2F0YWxvZyBlbnRyaWVzIGFuZCB0b21fcGdfc3RhdGlzdGljIHRhYmxlJzsKCkFMVEVS IFRBQkxFIHRvbV9tYXBwaW5nIEFERCBQUklNQVJZIEtFWSAobG9jYWxfcmVsaWQpOwoKLS0KLS0g VGFibGVzLCBJbmRleGVzCi0tCkRST1AgVEFCTEUgSUYgRVhJU1RTIHRvbV9wZ19jbGFzczsKQ1JF QVRFIFRBQkxFIHRvbV9wZ19jbGFzcyAoCglzY2hlbWFuYW1lIG5hbWUgbm90IG51bGwsCglyZWxu YW1lIG5hbWUgbm90IG51bGwsCgludW1iZXJfOGtibG9ja3MgaW50ZWdlciBub3QgbnVsbCwKCW51 bWJlcl90dXBsZXMgYmlnaW50IG5vdCBudWxsKTsKCkNPTU1FTlQgb24gVEFCTEUgdG9tX3BnX2Ns YXNzIElTIAonTWFwcGluZyBiZXR3ZWVuIGxvY2FsIGNhdGFsb2cgZW50cmllcyBhbmQgdG9tX3Bn X3N0YXRpc3RpYyB0YWJsZSc7CgpBTFRFUiBUQUJMRSB0b21fcGdfY2xhc3MgQUREIFBSSU1BUlkg S0VZIChzY2hlbWFuYW1lLCByZWxuYW1lKTsKCi0tCi0tIFN0YXRzIGZvciBUYWJsZXMgb25seSBh dCBwcmVzZW50Ci0tCkRST1AgVEFCTEUgSUYgRVhJU1RTIHRvbV9wZ19zdGF0aXN0aWM7CkNSRUFU RSBUQUJMRSB0b21fcGdfc3RhdGlzdGljICgKCXNjaGVtYW5hbWUgbmFtZSBub3QgbnVsbCwKCXJl bG5hbWUgbmFtZSBub3QgbnVsbCwKCWF0dG51bSBzbWFsbGludCBub3QgbnVsbCwKICAgIHN0YW51 bGxmcmFjIHJlYWwgTk9UIE5VTEwsCiAgICBzdGF3aWR0aCBpbnRlZ2VyIE5PVCBOVUxMLAkJLyog V2UgZXhwZWN0IHRoaXMgdG8gYmUgY29sdW1uIDUgKi8KICAgIHN0YWRpc3RpbmN0IHJlYWwgTk9U IE5VTEwsCiAgICBzdGFraW5kMSBzbWFsbGludCBOT1QgTlVMTCwKICAgIHN0YWtpbmQyIHNtYWxs aW50IE5PVCBOVUxMLAogICAgc3Rha2luZDMgc21hbGxpbnQgTk9UIE5VTEwsCiAgICBzdGFraW5k NCBzbWFsbGludCBOT1QgTlVMTCwKICAgIHN0YW9wMSBvaWQgTk9UIE5VTEwsCiAgICBzdGFvcDIg b2lkIE5PVCBOVUxMLAogICAgc3Rhb3AzIG9pZCBOT1QgTlVMTCwKICAgIHN0YW9wNCBvaWQgTk9U IE5VTEwsCiAgICBzdGFudW1iZXJzMSByZWFsW10sCiAgICBzdGFudW1iZXJzMiByZWFsW10sCiAg ICBzdGFudW1iZXJzMyByZWFsW10sCiAgICBzdGFudW1iZXJzNCByZWFsW10sCiAgICBzdGF2YWx1 ZXMxIHRleHQsCiAgICBzdGF2YWx1ZXMyIHRleHQsCiAgICBzdGF2YWx1ZXMzIHRleHQsCiAgICBz dGF2YWx1ZXM0IHRleHQKKTsKCkNPTU1FTlQgb24gVEFCTEUgdG9tX3BnX3N0YXRpc3RpYyBJUyAK J0V4dGVybmFsIGRhdGEgdGFrZW4gZnJvbSByZW1vdGUgcGdfc3RhdGlzdGljIHRhYmxlcyBwbHVz IG9iamVjdG5hbWVzJzsKCkFMVEVSIFRBQkxFIHRvbV9wZ19zdGF0aXN0aWMgQUREIFBSSU1BUlkg S0VZICAoc2NoZW1hbmFtZSwgcmVsbmFtZSwgYXR0bnVtKTsKClJFU0VUIGNsaWVudF9taW5fbWVz c2FnZXM7CgotLQotLSBFbmQgb2YgdGFibGVzIGZvciBUcmFuc3BvcnRhYmxlIE9wdGltaXplciBN b2RlCi0tCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAGNvbnRyaWIvVE9NL01ha2VmaWxlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwNzU1 ADAwMDE3NTAAMDAwMDE0NAAwMDAwMDAwMDQ0NgAxMTA0MTU3NTEwNwAwMTQwNDIAIDAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdXN0YXIgIABzcmlnZ3MAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAHVzZXJzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAIyAkUG9zdGdyZVNRTCQKCk1PRFVMRVMgPSB0b21faG9va3MKT0JKUwk9IHRvbV9ob29r cy5zbwoKaWZkZWYgVVNFX1BHWFMKUEdfQ09ORklHID0gcGdfY29uZmlnClBHWFMgOj0gJChzaGVs bCAkKFBHX0NPTkZJRykgLS1wZ3hzKQkKaW5jbHVkZSAkKFBHWFMpCmVsc2UKc3ViZGlyID0gY29u dHJpYi9UT00KdG9wX2J1aWxkZGlyID0gLi4vLi4KaW5jbHVkZSAkKHRvcF9idWlsZGRpcikvc3Jj L01ha2VmaWxlLmdsb2JhbAppbmNsdWRlICQodG9wX3NyY2RpcikvY29udHJpYi9jb250cmliLWds b2JhbC5tawplbmRpZgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA --=-tUvbn5EHTHuZ9RWtZFHf--