From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BD17DC10F29 for ; Wed, 11 Mar 2020 09:05:14 +0000 (UTC) Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7921320873 for ; Wed, 11 Mar 2020 09:05:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Pl9BVoh4" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7921320873 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Received: from localhost ([::1]:48324 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jBxIf-00042D-GM for qemu-devel@archiver.kernel.org; Wed, 11 Mar 2020 05:05:13 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:43811) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jBxHw-0003Ah-F3 for qemu-devel@nongnu.org; Wed, 11 Mar 2020 05:04:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1jBxHn-00020C-MD for qemu-devel@nongnu.org; Wed, 11 Mar 2020 05:04:28 -0400 Received: from us-smtp-delivery-1.mimecast.com ([205.139.110.120]:49275 helo=us-smtp-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1jBxHn-0001yP-DK for qemu-devel@nongnu.org; Wed, 11 Mar 2020 05:04:19 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1583917458; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sPR0YSx1QehTynk6jU1HmFDsih12cPV/9tVeV8aqNDU=; b=Pl9BVoh4OVuoq+cS2dsBdZtSDK1AZWKoFprLy9oYQkzz/Wp4BdVW6Sj99dDX74B4I9l4wx 8a8UL69ygItZjI4M/XlUsqzcNvot5lYdXfmx8aXruNCQOjADweTpByhk9SjWLhzOW71mN7 BxuEpkLA63xOMJJHF5SKEsffQQWsXmo= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-468-fAjBGl85Mr2CW_86WuhCCg-1; Wed, 11 Mar 2020 05:04:15 -0400 X-MC-Unique: fAjBGl85Mr2CW_86WuhCCg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7218B107ACC4; Wed, 11 Mar 2020 09:04:12 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-34.ams2.redhat.com [10.36.116.34]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 19C6460C87; Wed, 11 Mar 2020 09:04:06 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 92F5B11386A6; Wed, 11 Mar 2020 10:04:04 +0100 (CET) From: Markus Armbruster To: Vladimir Sementsov-Ogievskiy Subject: Re: [PATCH v8 02/10] scripts: add coccinelle script to use auto propagated errp References: <20200306051536.27803-1-vsementsov@virtuozzo.com> <20200306051536.27803-3-vsementsov@virtuozzo.com> <87lfo997hs.fsf@dusky.pond.sub.org> <87lfo8nrdo.fsf@dusky.pond.sub.org> <4ad4f78d-bdf2-1302-a9b4-0324119217c7@virtuozzo.com> Date: Wed, 11 Mar 2020 10:04:04 +0100 In-Reply-To: <4ad4f78d-bdf2-1302-a9b4-0324119217c7@virtuozzo.com> (Vladimir Sementsov-Ogievskiy's message of "Wed, 11 Mar 2020 09:55:01 +0300") Message-ID: <87a74ni7p7.fsf@dusky.pond.sub.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 205.139.110.120 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Stefano Stabellini , qemu-block@nongnu.org, Paul Durrant , Laszlo Ersek , Christian Schoenebeck , Michael Roth , qemu-devel@nongnu.org, Greg Kurz , Gerd Hoffmann , Stefan Hajnoczi , Anthony Perard , xen-devel@lists.xenproject.org, Max Reitz , Philippe =?utf-8?Q?Mathieu-Daud=C3=A9?= , Stefan Berger Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: "Qemu-devel" Vladimir Sementsov-Ogievskiy writes: > 10.03.2020 18:47, Markus Armbruster wrote: >> Vladimir Sementsov-Ogievskiy writes: >> >>> 09.03.2020 12:56, Markus Armbruster wrote: >>>> Suggest >>>> >>>> scripts: Coccinelle script to use auto-propagated errp >>>> >>>> or >>>> >>>> scripts: Coccinelle script to use ERRP_AUTO_PROPAGATE() >>>> >>>> Vladimir Sementsov-Ogievskiy writes: >>>> >>>>> Script adds ERRP_AUTO_PROPAGATE macro invocation where appropriate an= d >>>>> does corresponding changes in code (look for details in >>>>> include/qapi/error.h) >>>>> >>>>> Usage example: >>>>> spatch --sp-file scripts/coccinelle/auto-propagated-errp.cocci \ >>>>> --macro-file scripts/cocci-macro-file.h --in-place --no-show-diff = \ >>>>> blockdev-nbd.c qemu-nbd.c {block/nbd*,nbd/*,include/block/nbd*}.[h= c] >>>> >>>> Suggest FILES... instead of a specific set of files. >>>> >>>>> Signed-off-by: Vladimir Sementsov-Ogievskiy >>>>> --- >>>>> >>>>> Cc: Eric Blake >>>>> Cc: Kevin Wolf >>>>> Cc: Max Reitz >>>>> Cc: Greg Kurz >>>>> Cc: Christian Schoenebeck >>>>> Cc: Stefano Stabellini >>>>> Cc: Anthony Perard >>>>> Cc: Paul Durrant >>>>> Cc: Stefan Hajnoczi >>>>> Cc: "Philippe Mathieu-Daud=C3=A9" >>>>> Cc: Laszlo Ersek >>>>> Cc: Gerd Hoffmann >>>>> Cc: Stefan Berger >>>>> Cc: Markus Armbruster >>>>> Cc: Michael Roth >>>>> Cc: qemu-block@nongnu.org >>>>> Cc: qemu-devel@nongnu.org >>>>> Cc: xen-devel@lists.xenproject.org >>>>> >>>>> include/qapi/error.h | 3 + >>>>> scripts/coccinelle/auto-propagated-errp.cocci | 231 ++++++++++++++= ++++ >>>>> 2 files changed, 234 insertions(+) >>>>> create mode 100644 scripts/coccinelle/auto-propagated-errp.cocci >>>>> >>>>> diff --git a/include/qapi/error.h b/include/qapi/error.h >>>>> index bb9bcf02fb..fbfc6f1c0b 100644 >>>>> --- a/include/qapi/error.h >>>>> +++ b/include/qapi/error.h >>>>> @@ -211,6 +211,9 @@ >>>>> * } >>>>> * ... >>>>> * } >>>>> + * >>>>> + * For mass conversion use script >>>> >>>> mass-conversion (we're not converting mass, we're converting en masse) >>>> >>>>> + * scripts/coccinelle/auto-propagated-errp.cocci >>>>> */ >>>>> #ifndef ERROR_H >>>>> diff --git a/scripts/coccinelle/auto-propagated-errp.cocci b/scripts/= coccinelle/auto-propagated-errp.cocci >>>>> new file mode 100644 >>>>> index 0000000000..bff274bd6d >>>>> --- /dev/null >>>>> +++ b/scripts/coccinelle/auto-propagated-errp.cocci >>>> >>>> Preface to my review of this script: may aim isn't to make it >>>> bullet-proof. I want to (1) make it good enough (explained in a >>>> jiffie), and (2) automatically identify the spots where it still isn't >>>> obviously safe for manual review. >>>> >>>> The latter may involve additional scripting. That's okay. >>>> >>>> The script is good enough when the number of possibly unsafe spots is >>>> low enough for careful manual review. >>>> >>>> When I ask for improvements that, in your opinion, go beyond "good >>>> enough", please push back. I'm sure we can work it out together. >>>> >>>>> @@ -0,0 +1,231 @@ >>>>> +// Use ERRP_AUTO_PROPAGATE (see include/qapi/error.h) >>>>> +// >>>>> +// Copyright (c) 2020 Virtuozzo International GmbH. >>>>> +// >>>>> +// This program is free software; you can redistribute it and/or mod= ify >>>>> +// it under the terms of the GNU General Public License as published= by >>>>> +// the Free Software Foundation; either version 2 of the License, or >>>>> +// (at your option) any later version. >>>>> +// >>>>> +// This program is distributed in the hope that it will be useful, >>>>> +// but WITHOUT ANY WARRANTY; without even the implied warranty of >>>>> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >>>>> +// GNU General Public License for more details. >>>>> +// >>>>> +// You should have received a copy of the GNU General Public License >>>>> +// along with this program. If not, see . >>>>> +// >>>>> +// Usage example: >>>>> +// spatch --sp-file scripts/coccinelle/auto-propagated-errp.cocci \ >>>>> +// --macro-file scripts/cocci-macro-file.h --in-place --no-show-dif= f \ >>>>> +// --max-width 80 blockdev-nbd.c qemu-nbd.c \ >>>> >>>> You have --max-width 80 here, but not in the commit message. Default >>>> seems to be 78. Any particular reason to change it to 80? >>> >>> Hmm. As I remember, without this parameter, reindenting doesn't work co= rrectly. >>> So, I'm OK with "--max-width 78", but I doubt that it will work without= a parameter. >>> Still, may be I'm wrong, we can check it. >> >> If you can point to an example where --max-width helps, keep it, and >> update the commit message to match. Else, drop it. >> >>>> >>>>> +// {block/nbd*,nbd/*,include/block/nbd*}.[hc] As our discussion shows, this script is somewhat hard to understand. That's okay, it solves a somewhat thorny problem, and I don't have better ideas. But let me state the intended transformations once more, so I don't get lost in the details. Motivation: 1. Make error propagation less error-prone and improve stack backtraces The "receive error in &local_error, propagate to @errp" pattern is tedious, error-prone, and produces unhelpful stack backtraces with &error_abort. ERRP_AUTO_PROPAGATE() removes manual propagation. It additionally gives us the stack backtraces we want. 2. Improve error messages with &error_fatal Passing @errp to error_append_hint(), error_prepend() or error_vprepend() is useless when @errp is &error_fatal. ERRP_AUTO_PROPAGATE() fixes this by delaying &error_fatal handling until the automatic propagation. The intended transformation has three parts: * Replace declaration of @local_err by ERRP_AUTO_PROPAGATE() where needed for 1 or 2. It's needed when we also drop some error propagation from the function (motivation 1), or the function calls error_append_hint(), error_prepend() or error_vprepend() (motivation 2). A function could do both. I'll refer back to this below. * Drop error_propagate(errp, local_err) Special case: error_propagate_prepend(errp, local_err, ...) becomes error_prepend(errp, ...). Only correct if there is no other such error_propagate() / error_propagate_prepend() on any path from the here to return. * Replace remaining use of @local_err by *errp >>>>> + >>>>> +// Switch unusual (Error **) parameter names to errp >>>> >>>> Let's drop the parenthesis around Error ** >>>> >>>>> +// (this is necessary to use ERRP_AUTO_PROPAGATE). >>>> >>>> Perhaps ERRP_AUTO_PROPAGATE() should be ERRP_AUTO_PROPAGATE(errp) to >>>> make the fact we're messing with @errp more obvious. Too late; I >>>> shouldn't rock the boat that much now. >>>> >>>>> +// >>>>> +// Disable optional_qualifier to skip functions with "Error *const *= errp" >>>>> +// parameter. >>>>> +// >>>>> +// Skip functions with "assert(_errp && *_errp)" statement, as they = have >>>>> +// non generic semantics and may have unusual Error ** argument name= for purpose >>>> >>>> non-generic >>>> >>>> for a purpose >>>> >>>> Wrap comment lines around column 70, please. It's easier to read. >>>> >>>> Maybe >>>> >>>> // Skip functions with "assert(_errp && *_errp)" statement, becau= se that >>>> // signals unusual semantics, and the parameter name may well ser= ve a >>>> // purpose. >>> >>> Sounds good. >>> >>>> >>>>> +// (like nbd_iter_channel_error()). >>>>> +// >>>>> +// Skip util/error.c to not touch, for example, error_propagate and >>>>> +// error_propagate_prepend(). >>>> >>>> error_propagate() >>>> >>>> I much appreciate your meticulous explanation of what you skip and why= . >>>> >>>>> +@ depends on !(file in "util/error.c") disable optional_qualifier@ >>>>> +identifier fn; >>>>> +identifier _errp !=3D errp; >>>>> +@@ >>>>> + >>>>> + fn(..., >>>>> +- Error **_errp >>>>> ++ Error **errp >>>>> + ,...) >>>>> + { >>>>> +( >>>>> + ... when !=3D assert(_errp && *_errp) >>>>> +& >>>>> + <... >>>>> +- _errp >>>>> ++ errp >>>>> + ...> >>>>> +) >>>>> + } >>>> >>>> This rule is required to make the actual transformations (below) work >>>> even for parameters with names other than @errp. I believe it's not >>>> used in this series. In fact, I can't see a use for it in the entire >>>> tree right now. Okay anyway. >>>> >>>>> + >>>>> +// Add invocation of ERRP_AUTO_PROPAGATE to errp-functions where nec= essary >>>>> +// >>>>> +// Note, that without "when any" final "..." may not want to mach so= mething >>>> >>>> s/final "..." may not mach/the final "..." does not match/ >>>> >>>>> +// matched by previous pattern, i.e. the rule will not match double >>>>> +// error_prepend in control flow like in vfio_set_irq_signaling(). >>>> >>>> Can't say I fully understand Coccinelle there. I figure you came to >>>> this knowledge the hard way. >>> >>> It's follows from smpl grammar document: >>> >>> "Implicitly, =E2=80=9C...=E2=80=9D matches the shortest path between so= mething that matches the pattern before the dots (or the beginning of the f= unction, if there is nothing before the dots) and something that matches th= e pattern after the dots (or the end of the function, if there is nothing a= fter the dots)." >>> ... >>> "_when any_ removes the aforementioned constraint that =E2=80=9C...=E2= =80=9D matches the shortest path" >> >> Let me think that through. >> >> The pattern with the cases other than error_prepend() omitted: >> >> fn(..., Error **errp, ...) >> { >> + ERRP_AUTO_PROPAGATE(); >> ... when !=3D ERRP_AUTO_PROPAGATE(); >> error_prepend(errp, ...); >> ... when any >> } >> >> Tail of vfio_set_irq_signaling(): >> >> name =3D index_to_str(vbasedev, index); >> if (name) { >> error_prepend(errp, "%s-%d: ", name, subindex); >> } else { >> error_prepend(errp, "index %d-%d: ", index, subindex); >> } >> error_prepend(errp, >> "Failed to %s %s eventfd signaling for interrupt = ", >> fd < 0 ? "tear down" : "set up", action_to_str(ac= tion)); >> return ret; >> } >> >> The pattern's first ... matches a "shortest" path to an error_prepend(), >> where "shortest" means "does not cross an error_prepend(). Its when >> clause makes us ignore functions that already use ERRP_AUTO_PROPAGATE(). >> >> There are two such "shortest" paths, one to the first error_prepend() in >> vfio_set_irq_signaling(), and one to the second. Neither path to the >> third one is not "shortest": they both cross one of the other two >> error_prepend(). >> >> The pattern' s second ... matches a path from a matched error_prepend() >> to the end of the function. There are two paths. Both cross the third >> error_prepend(). You need "when any" to make the pattern match anyway. >> >> Alright, I think I got it. But now I'm paranoid about ... elsewhere. >> For instance, here's rule1 with error_propagate_prepend() omitted: >> >> // Match scenarios with propagation of local error to errp. >> @rule1 disable optional_qualifier exists@ >> identifier fn, local_err; >> symbol errp; >> @@ >> >> fn(..., Error **errp, ...) >> { >> ... >> Error *local_err =3D NULL; >> ... >> error_propagate(errp, local_err); >> ... >> } >> >> The second and third ... won't match anything containing >> error_propagate(). What if a function has multiple error_propagate() on >> all paths? > > I thought about this, but decided that double error propagation is a stra= nge pattern, and may be better not match it... I'm fine with not touching "strange" patterns. But we do at least in the example I gave below: we still add ERRP_AUTO_PROPAGATE(). We either avoid that in the Coccinelle script, or we catch it afterwards. Catching it afterwards should be feasible: * If we also drop some error propagation from this function: okay. * If this function call error_append_hint(), error_prepend() or error_vprepend(): okay. * Else: unwanted, back out. Moreover, I'd like us to double-check we really don't want to touch the things we don't touch. Feels feasible to me, too: after running Coccinelle, search for unconverted error_append_hint(), error_prepend(), error_vprepend(), error_propagate_prepend(), error_propagate(). >> Like this one: >> >> extern foo(int, Error **); >> extern bar(int, Error **); >> >> void frob(Error **errp) >> { >> Error *local_err =3D NULL; >> int arg; >> >> foo(arg, errp); >> bar(arg, &local_err); >> error_propagate(errp, local_err); >> bar(arg + 1, &local_err); >> error_propagate(errp, local_err); >> } >> >> This is actually a variation of error.h's "Receive and accumulate >> multiple errors (first one wins)" code snippet. > > ah yes, we can propagate to already filled errp, which just clean local_e= rr. > >> >> The Coccinelle script transforms it like this: >> >> void frob(Error **errp) >> { >> + ERRP_AUTO_PROPAGATE(); >> Error *local_err =3D NULL; >> int arg; >> >> The rule that adds ERRP_AUTO_PROPAGATE() matches (it has ... when any), >> but rule1 does not, and we therefore don't convert any of the >> error_propagate(). >> >> The result isn't wrong, just useless. >> >> Is this the worst case? >> >> Possible improvement to the ERRP_AUTO_PROPAGATE() rule: don't use >> "... when any" in the error_propagate() case, only in the other cases. >> Would that help? > > I think not, as it will anyway match functions with error_prepend (and an= y > number of following error_propagate calls)... I'm not sure I understand this sentence. The aim of my "possible improvement" is to avoid unwanted ERRP_AUTO_PROPAGATE() in the Coccinelle script. We can instead search for unwanted ones after the Coccinelle run, and back them out. >> I think this is the only other rule with "..." matching control flow. >> >>>> >>>>> +// >>>>> +// Note, "exists" says that we want apply rule even if it matches no= t on >>>>> +// all possible control flows (otherwise, it will not match standard= pattern >>>>> +// when error_propagate() call is in if branch). >>>> >>>> Learned something new. Example: kvm_set_kvm_shadow_mem(). >>>> >>>> Spelling it "exists disable optional_qualifier" would avoid giving >>>> readers the idea we're disabling "exists", but Coccinelle doesn't let >>>> us. Oh well. >>>> >>>>> +@ disable optional_qualifier exists@ >>>>> +identifier fn, local_err, errp; >>>> >>>> I believe this causes >>>> >>>> warning: line 98: errp, previously declared as a metavariable, i= s used as an identifier >>>> warning: line 104: errp, previously declared as a metavariable, = is used as an identifier >>>> warning: line 106: errp, previously declared as a metavariable, = is used as an identifier >>>> warning: line 131: errp, previously declared as a metavariable, = is used as an identifier >>>> warning: line 192: errp, previously declared as a metavariable, = is used as an identifier >>>> warning: line 195: errp, previously declared as a metavariable, = is used as an identifier >>>> warning: line 228: errp, previously declared as a metavariable, = is used as an identifier >>>> >>>> Making @errp symbol instead of identifier should fix this. >>> >>> Hmm, I didn't see these warnings.. But yes, it should be symbol. >>> >>>> >>>>> +@@ >>>>> + >>>>> + fn(..., Error **errp, ...) >>>>> + { >>>>> ++ ERRP_AUTO_PROPAGATE(); >>>>> + ... when !=3D ERRP_AUTO_PROPAGATE(); >>>>> +( >>>>> + error_append_hint(errp, ...); >>>>> +| >>>>> + error_prepend(errp, ...); >>>>> +| >>>>> + error_vprepend(errp, ...); >>>>> +| >>>>> + Error *local_err =3D NULL; >>>>> + ... >>>>> +( >>>>> + error_propagate_prepend(errp, local_err, ...); >>>>> +| >>>>> + error_propagate(errp, local_err); >>>>> +) >>>>> +) >>>>> + ... when any >>>>> + } >>>>> + >>>>> + >>>>> +// Match scenarios with propagation of local error to errp. >>>>> +@rule1 disable optional_qualifier exists@ >>>>> +identifier fn, local_err; >>>>> +symbol errp; >>>>> +@@ >>>>> + >>>>> + fn(..., Error **errp, ...) >>>>> + { >>>>> + ... >>>>> + Error *local_err =3D NULL; >>>>> + ... >>>>> +( >>>>> + error_propagate_prepend(errp, local_err, ...); >>>>> +| >>>>> + error_propagate(errp, local_err); >>>>> +) >>>> >>>> Indentation off by one. >>>> >>>>> + ... >>>>> + } >>>>> + >>>>> +// Convert special case with goto in separate. >>>> >>>> s/in separate/separately/ >>>> >>>>> +// We can probably merge this into the following hunk with help of (= | ) >>>>> +// operator, but it significantly reduce performance on block.c pars= ing (or it >>>> >>>> s/reduce/reduces/ >>>> >>>>> +// hangs, I don't know) >>>> >>>> Sounds like you tried to merge this into the following hunk, but then >>>> spatch took so long on block.c that you killed it. Correct? >>> >>> Yes. >> >> I'd say something like "I tried merging this into the following rule the >> obvious way, but it made Coccinelle hang on block.c." >> >>>> >>>>> +// >>>>> +// Note interesting thing: if we don't do it here, and try to fixup = "out: }" >>>>> +// things later after all transformations (the rule will be the same= , just >>>>> +// without error_propagate() call), coccinelle fails to match this "= out: }". >>>> >>>> Weird, but not worth further investigation. >>> >>> It partially match to the idea which I saw somewhere in coccinelle docu= mentation, >>> that coccinelle converts correct C code to correct C code. "out: }" is = an example >>> of incorrect, impossible code flow, and coccinelle can't work with it..= . But it's >>> just a thought. >>> >>>> >>>>> +@@ >>>>> +identifier rule1.fn, rule1.local_err, out; >>>>> +symbol errp; >>>>> +@@ >>>>> + >>>>> + fn(...) >>>>> + { >>>>> + <... >>>>> +- goto out; >>>>> ++ return; >>>>> + ...> >>>>> +- out: >>>>> +- error_propagate(errp, local_err); >>>> >>>> You neglect to match error_propagate_prepend(). Okay, because (1) tha= t >>>> pattern doesn't occur in the tree right now, and (2) if it gets added, >>>> gcc will complain. >>> >>> No, because it should not removed. error_propagate_prepend should be co= nverted >>> to prepend, not removed. So, corresponding gotos should not be removed = as well. >> >> You're right. >> >>>> >>>>> + } >>>>> + >>>>> +// Convert most of local_err related staff. >>>> >>>> s/staff/stuff/ >>>> >>>>> +// >>>>> +// Note, that we update everything related to matched by rule1 funct= ion name >>>>> +// and local_err name. We may match something not related to the pat= tern >>>>> +// matched by rule1. For example, local_err may be defined with the = same name >>>>> +// in different blocks inside one function, and in one block follow = the >>>>> +// propagation pattern and in other block doesn't. Or we may have se= veral >>>>> +// functions with the same name (for different configurations). >>>> >>>> Context: rule1 matches functions that have all three of >>>> >>>> * an Error **errp parameter >>>> >>>> * an Error *local_err =3D NULL variable declaration >>>> >>>> * an error_propagate(errp, local_err) or error_propagate_prepend(errp, >>>> local_err, ...) expression, where @errp is the parameter and >>>> @local_err is the variable. >>>> >>>> If I understand you correctly, you're pointing out two potential issue= s: >>>> >>>> 1. This rule can match functions rule1 does not match if there is >>>> another function with the same name that rule1 does match. >>>> >>>> 2. This rule matches in the entire function matched by rule1, even whe= n >>>> parts of that function use a different @errp or @local_err. >>>> >>>> I figure these apply to all rules with identifier rule1.fn, not just >>>> this one. Correct? >>> >>> Yes. >> >> Thanks! >> >>>> >>>> Regarding 1. There must be a better way to chain rules together, but = I >>>> don't know it. >>>> Can we make Coccinelle at least warn us when it converts >>>> multiple functions with the same name? What about this: >>>> >>>> @initialize:python@ >>>> @@ >>>> fnprev =3D {} >>>> >>>> def pr(fn, p): >>>> print("### %s:%s: %s()" % (p[0].file, p[0].line, fn)) >>>> >>>> @r@ >>>> identifier rule1.fn; >>>> position p; >>>> @@ >>>> fn(...)@p >>>> { >>>> ... >>>> } >>>> @script:python@ >>>> fn << rule1.fn; >>>> p << r.p; >>>> @@ >>>> if fn not in fnprev: >>>> fnprev[fn] =3D p >>>> else: >>>> if fnprev[fn]: >>> >>> hmm, the condition can't be false >>> >>>> pr(fn, fnprev[fn]) >>>> fnprev[fn] =3D None >>>> pr(fn, p) >>> >>> and we'll miss next duplication.. >> >> The idea is >> >> first instance of fn: >> fn not in fnprev >> fnprev[fn] =3D position of instance >> don't print >> second instance: >> fnprev[fn] is the position of the first instance >> print first two instances >> subsequent instances: fnprev[fn] is None >> print this instance >> >> I might have screwed up the coding, of course :) >> >>> But I like the idea. >>> >>>> >>>> For each function @fn matched by rule1, fncnt[fn] is an upper limit of >>>> the number of functions with the same name we touch. If it's more tha= n >>>> one, we print. >>>> >>>> Reports about a dozen function names for the whole tree in my testing. >>>> Inspecting the changes to them manually is feasible. None of them are >>>> in files touched by this series. >>>> >>>> The line printed for the first match is pretty useless for me: it poin= ts >>>> to a Coccinelle temporary file *shrug*. >>>> >>>> Regarding 2. Shadowing @errp or @local_err would be in bad taste, and= I >>>> sure hope we don't do that. Multiple @local_err variables... hmm. >>>> Perhaps we could again concoct some script rules to lead us to spots t= o >>>> check manually. See below for my attempt. >>>> >>>> What's the worst that could happen if we blindly converted such code? >>>> The answer to that question tells us how hard to work on finding and >>>> checking these guys. >>>> >>>>> +// >>>>> +// Note also that errp-cleaning functions >>>>> +// error_free_errp >>>>> +// error_report_errp >>>>> +// error_reportf_errp >>>>> +// warn_report_errp >>>>> +// warn_reportf_errp >>>>> +// are not yet implemented. They must call corresponding Error* - fr= eeing >>>>> +// function and then set *errp to NULL, to avoid further propagation= to >>>>> +// original errp (consider ERRP_AUTO_PROPAGATE in use). >>>>> +// For example, error_free_errp may look like this: >>>>> +// >>>>> +// void error_free_errp(Error **errp) >>>>> +// { >>>>> +// error_free(*errp); >>>>> +// *errp =3D NULL; >>>>> +// } >>>>> +@ exists@ >>>>> +identifier rule1.fn, rule1.local_err; >>>>> +expression list args; >>>>> +symbol errp; >>>>> +@@ >>>>> + >>>>> + fn(...) >>>>> + { >>>>> + <... >>>>> +( >>>> >>>> Each of the following patterns applies anywhere in the function. >>>> >>>> First pattern: delete @local_err >>>> >>>>> +- Error *local_err =3D NULL; >>>> >>>> Common case: occurs just once, not nested. Anything else is suspiciou= s. >>>> >>>> Both can be detected in the resulting patches with a bit of AWK >>>> wizardry: >>>> >>>> $ git-diff -U0 master..review-error-v8 | awk '/^@@ / { ctx =3D $= 5; for (i =3D 6; i <=3D NF; i++) ctx =3D ctx " " $i; if (ctx !=3D octx) { o= ctx =3D ctx; n =3D 0 } } /^- *Error *\* *[A-Za-z0-9_]+ *=3D *NULL;/ { if (i= ndex($0, "E") > 6) print "nested\n " ctx; if (n) print "more than one\n = " ctx; n++ }' >>>> nested >>>> static void xen_block_drive_destroy(XenBlockDrive *drive, Er= ror **errp) >>>> nested >>>> static void xen_block_device_destroy(XenBackendInstance *bac= kend, >>>> nested >>>> static void xen_block_device_destroy(XenBackendInstance *bac= kend, >>>> more than one >>>> static void xen_block_device_destroy(XenBackendInstance *bac= kend, >>>> >>>> Oh. >>>> >>>> xen_block_drive_destroy() nests its Error *local_err in a conditional. >>>> >>>> xen_block_device_destroy() has multiple Error *local_err. >>>> >>>> In both cases, manual review is required to ensure the conversion is >>>> okay. I believe it is. >>>> >>>> Note that the AWK script relies on diff showing the function name in @= @ >>>> lines, which doesn't always work due to our coding style. >>>> >>>> For the whole tree, I get some 30 spots. Feasible. >>>> >>>>> +| >>>> >>>> Second pattern: clear @errp after freeing it >>>> >>>>> + >>>>> +// Convert error clearing functions >>>> >>>> Suggest: Ensure @local_err is cleared on free >>>> >>>>> +( >>>>> +- error_free(local_err); >>>>> ++ error_free_errp(errp); >>>>> +| >>>>> +- error_report_err(local_err); >>>>> ++ error_report_errp(errp); >>>>> +| >>>>> +- error_reportf_err(local_err, args); >>>>> ++ error_reportf_errp(errp, args); >>>>> +| >>>>> +- warn_report_err(local_err); >>>>> ++ warn_report_errp(errp); >>>>> +| >>>>> +- warn_reportf_err(local_err, args); >>>>> ++ warn_reportf_errp(errp, args); >>>>> +) >>>> >>>> As you mention above, these guys don't exist, yet. Builds anyway, >>>> because this part of the rule is not used in this patch series. You >>>> don't want to omit it, because then the script becomes unsafe to use. >>>> >>>> We could also open-code: >>>> >>>> // Convert error clearing functions >>>> ( >>>> - error_free(local_err); >>>> + error_free(*errp); >>>> + *errp =3D NULL; >>>> | >>>> ... and so forth ... >>>> ) >>>> >>>> Matter of taste. Whatever is easier to explain in the comments. Sinc= e >>>> you already wrote one... >>> >>> I just feel that using helper functions is safer way.. >>> >>>> >>>> We talked about extending this series slightly so these guys are used. >>>> I may still look into that. >>>> >>>>> +?- local_err =3D NULL; >>>>> + >>>> >>>> The new helpers clear @local_err. Assignment now redundant, delete. >>>> Okay. >>>> >>>>> +| >>>> >>>> Third and fourth pattern: delete error_propagate() >>>> >>>>> +- error_propagate_prepend(errp, local_err, args); >>>>> ++ error_prepend(errp, args); >>>>> +| >>>>> +- error_propagate(errp, local_err); >>>>> +| >>>> >>>> Fifth pattern: use @errp directly >>>> >>>>> +- &local_err >>>>> ++ errp >>>>> +) >>>>> + ...> >>>>> + } >>>>> + >>>>> +// Convert remaining local_err usage. It should be different kinds o= f error >>>>> +// checking in if operators. We can't merge this into previous hunk,= as this >>>> >>>> In if conditionals, I suppose. It's the case for this patch. If I >>>> apply the script to the whole tree, the rule gets also applied in othe= r >>>> contexts. The sentence might mislead as much as it helps. Keep it or >>>> delete it? >>> >>> Maybe, just be more honest: "It should be ..., but it may be any other = pattern, be careful" >> >> "Need to be careful" means "needs careful manual review", which I >> believe is not feasible; see "Preface to my review of this script" >> above. >> >> But do we really need to be careful here? >> >> This rule should apply only where we added ERRP_AUTO_PROPAGATE(). >> >> Except when rule chaining via function name fails us, but we plan to >> detect that and review manually, so let's ignore this issue here. >> >> Thanks to ERRP_AUTO_PROPAGATE(), @errp is not null. Enabling >> replacement of @local_err by @errp is its whole point. >> >> What exactly do we need to be careful about? > > Hmm.. About some unpredicted patterns. OK, then "For example, different k= inds of .." Something like this, perhaps? // Convert remaining local_err usage, typically error checking. // We can't merge this into previous hunk, as this conflicts with ot= her // substitutions in it (at least with "- local_err =3D NULL"). >>>>> +// conflicts with other substitutions in it (at least with "- local_= err =3D NULL"). >>>>> +@@ >>>>> +identifier rule1.fn, rule1.local_err; >>>>> +symbol errp; >>>>> +@@ >>>>> + >>>>> + fn(...) >>>>> + { >>>>> + <... >>>>> +- local_err >>>>> ++ *errp >>>>> + ...> >>>>> + } >>>>> + >>>>> +// Always use the same patter for checking error >>>> >>>> s/patter/pattern/ >>>> >>>>> +@@ >>>>> +identifier rule1.fn; >>>>> +symbol errp; >>>>> +@@ >>>>> + >>>>> + fn(...) >>>>> + { >>>>> + <... >>>>> +- *errp !=3D NULL >>>>> ++ *errp >>>>> + ...> >>>>> + } >>>> >> From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.6 required=3.0 tests=DKIM_INVALID,DKIM_SIGNED, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id DAB3AC10F27 for ; Wed, 11 Mar 2020 09:04:50 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 9496220873 for ; Wed, 11 Mar 2020 09:04:50 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Pl9BVoh4" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 9496220873 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1jBxHq-0002lQ-6h; Wed, 11 Mar 2020 09:04:22 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.89) (envelope-from ) id 1jBxHp-0002lL-Dm for xen-devel@lists.xenproject.org; Wed, 11 Mar 2020 09:04:21 +0000 X-Inumbo-ID: 4a9a9db6-6377-11ea-bec1-bc764e2007e4 Received: from us-smtp-1.mimecast.com (unknown [205.139.110.61]) by us1-rack-iad1.inumbo.com (Halon) with ESMTP id 4a9a9db6-6377-11ea-bec1-bc764e2007e4; Wed, 11 Mar 2020 09:04:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1583917458; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=sPR0YSx1QehTynk6jU1HmFDsih12cPV/9tVeV8aqNDU=; b=Pl9BVoh4OVuoq+cS2dsBdZtSDK1AZWKoFprLy9oYQkzz/Wp4BdVW6Sj99dDX74B4I9l4wx 8a8UL69ygItZjI4M/XlUsqzcNvot5lYdXfmx8aXruNCQOjADweTpByhk9SjWLhzOW71mN7 BxuEpkLA63xOMJJHF5SKEsffQQWsXmo= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-468-fAjBGl85Mr2CW_86WuhCCg-1; Wed, 11 Mar 2020 05:04:15 -0400 X-MC-Unique: fAjBGl85Mr2CW_86WuhCCg-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7218B107ACC4; Wed, 11 Mar 2020 09:04:12 +0000 (UTC) Received: from blackfin.pond.sub.org (ovpn-116-34.ams2.redhat.com [10.36.116.34]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 19C6460C87; Wed, 11 Mar 2020 09:04:06 +0000 (UTC) Received: by blackfin.pond.sub.org (Postfix, from userid 1000) id 92F5B11386A6; Wed, 11 Mar 2020 10:04:04 +0100 (CET) From: Markus Armbruster To: Vladimir Sementsov-Ogievskiy References: <20200306051536.27803-1-vsementsov@virtuozzo.com> <20200306051536.27803-3-vsementsov@virtuozzo.com> <87lfo997hs.fsf@dusky.pond.sub.org> <87lfo8nrdo.fsf@dusky.pond.sub.org> <4ad4f78d-bdf2-1302-a9b4-0324119217c7@virtuozzo.com> Date: Wed, 11 Mar 2020 10:04:04 +0100 In-Reply-To: <4ad4f78d-bdf2-1302-a9b4-0324119217c7@virtuozzo.com> (Vladimir Sementsov-Ogievskiy's message of "Wed, 11 Mar 2020 09:55:01 +0300") Message-ID: <87a74ni7p7.fsf@dusky.pond.sub.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Subject: Re: [Xen-devel] [PATCH v8 02/10] scripts: add coccinelle script to use auto propagated errp X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Kevin Wolf , Stefano Stabellini , qemu-block@nongnu.org, Paul Durrant , Laszlo Ersek , Christian Schoenebeck , Michael Roth , qemu-devel@nongnu.org, Greg Kurz , Gerd Hoffmann , Stefan Hajnoczi , Anthony Perard , xen-devel@lists.xenproject.org, Max Reitz , Philippe =?utf-8?Q?Mathieu-Daud=C3=A9?= , Stefan Berger Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: base64 Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" VmxhZGltaXIgU2VtZW50c292LU9naWV2c2tpeSA8dnNlbWVudHNvdkB2aXJ0dW96em8uY29tPiB3 cml0ZXM6Cgo+IDEwLjAzLjIwMjAgMTg6NDcsIE1hcmt1cyBBcm1icnVzdGVyIHdyb3RlOgo+PiBW bGFkaW1pciBTZW1lbnRzb3YtT2dpZXZza2l5IDx2c2VtZW50c292QHZpcnR1b3p6by5jb20+IHdy aXRlczoKPj4KPj4+IDA5LjAzLjIwMjAgMTI6NTYsIE1hcmt1cyBBcm1icnVzdGVyIHdyb3RlOgo+ Pj4+IFN1Z2dlc3QKPj4+Pgo+Pj4+ICAgICAgIHNjcmlwdHM6IENvY2NpbmVsbGUgc2NyaXB0IHRv IHVzZSBhdXRvLXByb3BhZ2F0ZWQgZXJycAo+Pj4+Cj4+Pj4gb3IKPj4+Pgo+Pj4+ICAgICAgIHNj cmlwdHM6IENvY2NpbmVsbGUgc2NyaXB0IHRvIHVzZSBFUlJQX0FVVE9fUFJPUEFHQVRFKCkKPj4+ Pgo+Pj4+IFZsYWRpbWlyIFNlbWVudHNvdi1PZ2lldnNraXkgPHZzZW1lbnRzb3ZAdmlydHVvenpv LmNvbT4gd3JpdGVzOgo+Pj4+Cj4+Pj4+IFNjcmlwdCBhZGRzIEVSUlBfQVVUT19QUk9QQUdBVEUg bWFjcm8gaW52b2NhdGlvbiB3aGVyZSBhcHByb3ByaWF0ZSBhbmQKPj4+Pj4gZG9lcyBjb3JyZXNw b25kaW5nIGNoYW5nZXMgaW4gY29kZSAobG9vayBmb3IgZGV0YWlscyBpbgo+Pj4+PiBpbmNsdWRl L3FhcGkvZXJyb3IuaCkKPj4+Pj4KPj4+Pj4gVXNhZ2UgZXhhbXBsZToKPj4+Pj4gc3BhdGNoIC0t c3AtZmlsZSBzY3JpcHRzL2NvY2NpbmVsbGUvYXV0by1wcm9wYWdhdGVkLWVycnAuY29jY2kgXAo+ Pj4+PiAgICAtLW1hY3JvLWZpbGUgc2NyaXB0cy9jb2NjaS1tYWNyby1maWxlLmggLS1pbi1wbGFj ZSAtLW5vLXNob3ctZGlmZiBcCj4+Pj4+ICAgIGJsb2NrZGV2LW5iZC5jIHFlbXUtbmJkLmMge2Js b2NrL25iZCosbmJkLyosaW5jbHVkZS9ibG9jay9uYmQqfS5baGNdCj4+Pj4KPj4+PiBTdWdnZXN0 IEZJTEVTLi4uIGluc3RlYWQgb2YgYSBzcGVjaWZpYyBzZXQgb2YgZmlsZXMuCj4+Pj4KPj4+Pj4g U2lnbmVkLW9mZi1ieTogVmxhZGltaXIgU2VtZW50c292LU9naWV2c2tpeSA8dnNlbWVudHNvdkB2 aXJ0dW96em8uY29tPgo+Pj4+PiAtLS0KPj4+Pj4KPj4+Pj4gQ2M6IEVyaWMgQmxha2UgPGVibGFr ZUByZWRoYXQuY29tPgo+Pj4+PiBDYzogS2V2aW4gV29sZiA8a3dvbGZAcmVkaGF0LmNvbT4KPj4+ Pj4gQ2M6IE1heCBSZWl0eiA8bXJlaXR6QHJlZGhhdC5jb20+Cj4+Pj4+IENjOiBHcmVnIEt1cnog PGdyb3VnQGthb2Qub3JnPgo+Pj4+PiBDYzogQ2hyaXN0aWFuIFNjaG9lbmViZWNrIDxxZW11X29z c0BjcnVkZWJ5dGUuY29tPgo+Pj4+PiBDYzogU3RlZmFubyBTdGFiZWxsaW5pIDxzc3RhYmVsbGlu aUBrZXJuZWwub3JnPgo+Pj4+PiBDYzogQW50aG9ueSBQZXJhcmQgPGFudGhvbnkucGVyYXJkQGNp dHJpeC5jb20+Cj4+Pj4+IENjOiBQYXVsIER1cnJhbnQgPHBhdWxAeGVuLm9yZz4KPj4+Pj4gQ2M6 IFN0ZWZhbiBIYWpub2N6aSA8c3RlZmFuaGFAcmVkaGF0LmNvbT4KPj4+Pj4gQ2M6ICJQaGlsaXBw ZSBNYXRoaWV1LURhdWTDqSIgPHBoaWxtZEByZWRoYXQuY29tPgo+Pj4+PiBDYzogTGFzemxvIEVy c2VrIDxsZXJzZWtAcmVkaGF0LmNvbT4KPj4+Pj4gQ2M6IEdlcmQgSG9mZm1hbm4gPGtyYXhlbEBy ZWRoYXQuY29tPgo+Pj4+PiBDYzogU3RlZmFuIEJlcmdlciA8c3RlZmFuYkBsaW51eC5pYm0uY29t Pgo+Pj4+PiBDYzogTWFya3VzIEFybWJydXN0ZXIgPGFybWJydUByZWRoYXQuY29tPgo+Pj4+PiBD YzogTWljaGFlbCBSb3RoIDxtZHJvdGhAbGludXgudm5ldC5pYm0uY29tPgo+Pj4+PiBDYzogcWVt dS1ibG9ja0Bub25nbnUub3JnCj4+Pj4+IENjOiBxZW11LWRldmVsQG5vbmdudS5vcmcKPj4+Pj4g Q2M6IHhlbi1kZXZlbEBsaXN0cy54ZW5wcm9qZWN0Lm9yZwo+Pj4+Pgo+Pj4+PiAgICBpbmNsdWRl L3FhcGkvZXJyb3IuaCAgICAgICAgICAgICAgICAgICAgICAgICAgfCAgIDMgKwo+Pj4+PiAgICBz Y3JpcHRzL2NvY2NpbmVsbGUvYXV0by1wcm9wYWdhdGVkLWVycnAuY29jY2kgfCAyMzEgKysrKysr KysrKysrKysrKysrCj4+Pj4+ICAgIDIgZmlsZXMgY2hhbmdlZCwgMjM0IGluc2VydGlvbnMoKykK Pj4+Pj4gICAgY3JlYXRlIG1vZGUgMTAwNjQ0IHNjcmlwdHMvY29jY2luZWxsZS9hdXRvLXByb3Bh Z2F0ZWQtZXJycC5jb2NjaQo+Pj4+Pgo+Pj4+PiBkaWZmIC0tZ2l0IGEvaW5jbHVkZS9xYXBpL2Vy cm9yLmggYi9pbmNsdWRlL3FhcGkvZXJyb3IuaAo+Pj4+PiBpbmRleCBiYjliY2YwMmZiLi5mYmZj NmYxYzBiIDEwMDY0NAo+Pj4+PiAtLS0gYS9pbmNsdWRlL3FhcGkvZXJyb3IuaAo+Pj4+PiArKysg Yi9pbmNsdWRlL3FhcGkvZXJyb3IuaAo+Pj4+PiBAQCAtMjExLDYgKzIxMSw5IEBACj4+Pj4+ICAg ICAqICAgICAgICAgfQo+Pj4+PiAgICAgKiAgICAgICAgIC4uLgo+Pj4+PiAgICAgKiAgICAgfQo+ Pj4+PiArICoKPj4+Pj4gKyAqIEZvciBtYXNzIGNvbnZlcnNpb24gdXNlIHNjcmlwdAo+Pj4+Cj4+ Pj4gbWFzcy1jb252ZXJzaW9uICh3ZSdyZSBub3QgY29udmVydGluZyBtYXNzLCB3ZSdyZSBjb252 ZXJ0aW5nIGVuIG1hc3NlKQo+Pj4+Cj4+Pj4+ICsgKiAgIHNjcmlwdHMvY29jY2luZWxsZS9hdXRv LXByb3BhZ2F0ZWQtZXJycC5jb2NjaQo+Pj4+PiAgICAgKi8KPj4+Pj4gICAgICAjaWZuZGVmIEVS Uk9SX0gKPj4+Pj4gZGlmZiAtLWdpdCBhL3NjcmlwdHMvY29jY2luZWxsZS9hdXRvLXByb3BhZ2F0 ZWQtZXJycC5jb2NjaSBiL3NjcmlwdHMvY29jY2luZWxsZS9hdXRvLXByb3BhZ2F0ZWQtZXJycC5j b2NjaQo+Pj4+PiBuZXcgZmlsZSBtb2RlIDEwMDY0NAo+Pj4+PiBpbmRleCAwMDAwMDAwMDAwLi5i ZmYyNzRiZDZkCj4+Pj4+IC0tLSAvZGV2L251bGwKPj4+Pj4gKysrIGIvc2NyaXB0cy9jb2NjaW5l bGxlL2F1dG8tcHJvcGFnYXRlZC1lcnJwLmNvY2NpCj4+Pj4KPj4+PiBQcmVmYWNlIHRvIG15IHJl dmlldyBvZiB0aGlzIHNjcmlwdDogbWF5IGFpbSBpc24ndCB0byBtYWtlIGl0Cj4+Pj4gYnVsbGV0 LXByb29mLiAgSSB3YW50IHRvICgxKSBtYWtlIGl0IGdvb2QgZW5vdWdoIChleHBsYWluZWQgaW4g YQo+Pj4+IGppZmZpZSksIGFuZCAoMikgYXV0b21hdGljYWxseSBpZGVudGlmeSB0aGUgc3BvdHMg d2hlcmUgaXQgc3RpbGwgaXNuJ3QKPj4+PiBvYnZpb3VzbHkgc2FmZSBmb3IgbWFudWFsIHJldmll dy4KPj4+Pgo+Pj4+IFRoZSBsYXR0ZXIgbWF5IGludm9sdmUgYWRkaXRpb25hbCBzY3JpcHRpbmcu ICBUaGF0J3Mgb2theS4KPj4+Pgo+Pj4+IFRoZSBzY3JpcHQgaXMgZ29vZCBlbm91Z2ggd2hlbiB0 aGUgbnVtYmVyIG9mIHBvc3NpYmx5IHVuc2FmZSBzcG90cyBpcwo+Pj4+IGxvdyBlbm91Z2ggZm9y IGNhcmVmdWwgbWFudWFsIHJldmlldy4KPj4+Pgo+Pj4+IFdoZW4gSSBhc2sgZm9yIGltcHJvdmVt ZW50cyB0aGF0LCBpbiB5b3VyIG9waW5pb24sIGdvIGJleW9uZCAiZ29vZAo+Pj4+IGVub3VnaCIs IHBsZWFzZSBwdXNoIGJhY2suICBJJ20gc3VyZSB3ZSBjYW4gd29yayBpdCBvdXQgdG9nZXRoZXIu Cj4+Pj4KPj4+Pj4gQEAgLTAsMCArMSwyMzEgQEAKPj4+Pj4gKy8vIFVzZSBFUlJQX0FVVE9fUFJP UEFHQVRFIChzZWUgaW5jbHVkZS9xYXBpL2Vycm9yLmgpCj4+Pj4+ICsvLwo+Pj4+PiArLy8gQ29w eXJpZ2h0IChjKSAyMDIwIFZpcnR1b3p6byBJbnRlcm5hdGlvbmFsIEdtYkguCj4+Pj4+ICsvLwo+ Pj4+PiArLy8gVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmli dXRlIGl0IGFuZC9vciBtb2RpZnkKPj4+Pj4gKy8vIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUg R05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5Cj4+Pj4+ICsvLyB0aGUg RnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXIgdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNl LCBvcgo+Pj4+PiArLy8gKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi4KPj4+Pj4g Ky8vCj4+Pj4+ICsvLyBUaGlzIHByb2dyYW0gaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhh dCBpdCB3aWxsIGJlIHVzZWZ1bCwKPj4+Pj4gKy8vIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsg d2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mCj4+Pj4+ICsvLyBNRVJDSEFOVEFC SUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlCj4+Pj4+ ICsvLyBHTlUgR2VuZXJhbCBQdWJsaWMgTGljZW5zZSBmb3IgbW9yZSBkZXRhaWxzLgo+Pj4+PiAr Ly8KPj4+Pj4gKy8vIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBH ZW5lcmFsIFB1YmxpYyBMaWNlbnNlCj4+Pj4+ICsvLyBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbS4g IElmIG5vdCwgc2VlIDxodHRwOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi4KPj4+Pj4gKy8vCj4+ Pj4+ICsvLyBVc2FnZSBleGFtcGxlOgo+Pj4+PiArLy8gc3BhdGNoIC0tc3AtZmlsZSBzY3JpcHRz L2NvY2NpbmVsbGUvYXV0by1wcm9wYWdhdGVkLWVycnAuY29jY2kgXAo+Pj4+PiArLy8gIC0tbWFj cm8tZmlsZSBzY3JpcHRzL2NvY2NpLW1hY3JvLWZpbGUuaCAtLWluLXBsYWNlIC0tbm8tc2hvdy1k aWZmIFwKPj4+Pj4gKy8vICAtLW1heC13aWR0aCA4MCBibG9ja2Rldi1uYmQuYyBxZW11LW5iZC5j IFwKPj4+Pgo+Pj4+IFlvdSBoYXZlIC0tbWF4LXdpZHRoIDgwIGhlcmUsIGJ1dCBub3QgaW4gdGhl IGNvbW1pdCBtZXNzYWdlLiAgRGVmYXVsdAo+Pj4+IHNlZW1zIHRvIGJlIDc4LiAgQW55IHBhcnRp Y3VsYXIgcmVhc29uIHRvIGNoYW5nZSBpdCB0byA4MD8KPj4+Cj4+PiBIbW0uIEFzIEkgcmVtZW1i ZXIsIHdpdGhvdXQgdGhpcyBwYXJhbWV0ZXIsIHJlaW5kZW50aW5nIGRvZXNuJ3Qgd29yayBjb3Jy ZWN0bHkuCj4+PiBTbywgSSdtIE9LIHdpdGggIi0tbWF4LXdpZHRoIDc4IiwgYnV0IEkgZG91YnQg dGhhdCBpdCB3aWxsIHdvcmsgd2l0aG91dCBhIHBhcmFtZXRlci4KPj4+IFN0aWxsLCBtYXkgYmUg SSdtIHdyb25nLCB3ZSBjYW4gY2hlY2sgaXQuCj4+Cj4+IElmIHlvdSBjYW4gcG9pbnQgdG8gYW4g ZXhhbXBsZSB3aGVyZSAtLW1heC13aWR0aCBoZWxwcywga2VlcCBpdCwgYW5kCj4+IHVwZGF0ZSB0 aGUgY29tbWl0IG1lc3NhZ2UgdG8gbWF0Y2guICBFbHNlLCBkcm9wIGl0Lgo+Pgo+Pj4+Cj4+Pj4+ ICsvLyAge2Jsb2NrL25iZCosbmJkLyosaW5jbHVkZS9ibG9jay9uYmQqfS5baGNdCgpBcyBvdXIg ZGlzY3Vzc2lvbiBzaG93cywgdGhpcyBzY3JpcHQgaXMgc29tZXdoYXQgaGFyZCB0byB1bmRlcnN0 YW5kLgpUaGF0J3Mgb2theSwgaXQgc29sdmVzIGEgc29tZXdoYXQgdGhvcm55IHByb2JsZW0sIGFu ZCBJIGRvbid0IGhhdmUKYmV0dGVyIGlkZWFzLiAgQnV0IGxldCBtZSBzdGF0ZSB0aGUgaW50ZW5k ZWQgdHJhbnNmb3JtYXRpb25zIG9uY2UgbW9yZSwKc28gSSBkb24ndCBnZXQgbG9zdCBpbiB0aGUg ZGV0YWlscy4KCk1vdGl2YXRpb246CgoxLiBNYWtlIGVycm9yIHByb3BhZ2F0aW9uIGxlc3MgZXJy b3ItcHJvbmUgYW5kIGltcHJvdmUgc3RhY2sgYmFja3RyYWNlcwoKICAgVGhlICJyZWNlaXZlIGVy cm9yIGluICZsb2NhbF9lcnJvciwgcHJvcGFnYXRlIHRvIEBlcnJwIiBwYXR0ZXJuIGlzCiAgIHRl ZGlvdXMsIGVycm9yLXByb25lLCBhbmQgcHJvZHVjZXMgdW5oZWxwZnVsIHN0YWNrIGJhY2t0cmFj ZXMgd2l0aAogICAmZXJyb3JfYWJvcnQuCgogICBFUlJQX0FVVE9fUFJPUEFHQVRFKCkgcmVtb3Zl cyBtYW51YWwgcHJvcGFnYXRpb24uICBJdCBhZGRpdGlvbmFsbHkKICAgZ2l2ZXMgdXMgdGhlIHN0 YWNrIGJhY2t0cmFjZXMgd2Ugd2FudC4KCjIuIEltcHJvdmUgZXJyb3IgbWVzc2FnZXMgd2l0aCAm ZXJyb3JfZmF0YWwKCiAgIFBhc3NpbmcgQGVycnAgdG8gZXJyb3JfYXBwZW5kX2hpbnQoKSwgZXJy b3JfcHJlcGVuZCgpIG9yCiAgIGVycm9yX3ZwcmVwZW5kKCkgaXMgdXNlbGVzcyB3aGVuIEBlcnJw IGlzICZlcnJvcl9mYXRhbC4KCiAgIEVSUlBfQVVUT19QUk9QQUdBVEUoKSBmaXhlcyB0aGlzIGJ5 IGRlbGF5aW5nICZlcnJvcl9mYXRhbCBoYW5kbGluZwogICB1bnRpbCB0aGUgYXV0b21hdGljIHBy b3BhZ2F0aW9uLgoKVGhlIGludGVuZGVkIHRyYW5zZm9ybWF0aW9uIGhhcyB0aHJlZSBwYXJ0czoK CiogUmVwbGFjZSBkZWNsYXJhdGlvbiBvZiBAbG9jYWxfZXJyIGJ5IEVSUlBfQVVUT19QUk9QQUdB VEUoKSB3aGVyZQogIG5lZWRlZCBmb3IgMSBvciAyLgoKICBJdCdzIG5lZWRlZCB3aGVuIHdlIGFs c28gZHJvcCBzb21lIGVycm9yIHByb3BhZ2F0aW9uIGZyb20gdGhlIGZ1bmN0aW9uCiAgKG1vdGl2 YXRpb24gMSksIG9yIHRoZSBmdW5jdGlvbiBjYWxscyBlcnJvcl9hcHBlbmRfaGludCgpLAogIGVy cm9yX3ByZXBlbmQoKSBvciBlcnJvcl92cHJlcGVuZCgpIChtb3RpdmF0aW9uIDIpLiAgQSBmdW5j dGlvbiBjb3VsZAogIGRvIGJvdGguICBJJ2xsIHJlZmVyIGJhY2sgdG8gdGhpcyBiZWxvdy4KCiog RHJvcCBlcnJvcl9wcm9wYWdhdGUoZXJycCwgbG9jYWxfZXJyKQoKICBTcGVjaWFsIGNhc2U6IGVy cm9yX3Byb3BhZ2F0ZV9wcmVwZW5kKGVycnAsIGxvY2FsX2VyciwgLi4uKSBiZWNvbWVzCiAgZXJy b3JfcHJlcGVuZChlcnJwLCAuLi4pLgoKICBPbmx5IGNvcnJlY3QgaWYgdGhlcmUgaXMgbm8gb3Ro ZXIgc3VjaCBlcnJvcl9wcm9wYWdhdGUoKSAvCiAgZXJyb3JfcHJvcGFnYXRlX3ByZXBlbmQoKSBv biBhbnkgcGF0aCBmcm9tIHRoZSBoZXJlIHRvIHJldHVybi4KCiogUmVwbGFjZSByZW1haW5pbmcg dXNlIG9mIEBsb2NhbF9lcnIgYnkgKmVycnAKCj4+Pj4+ICsKPj4+Pj4gKy8vIFN3aXRjaCB1bnVz dWFsIChFcnJvciAqKikgcGFyYW1ldGVyIG5hbWVzIHRvIGVycnAKPj4+Pgo+Pj4+IExldCdzIGRy b3AgdGhlIHBhcmVudGhlc2lzIGFyb3VuZCBFcnJvciAqKgo+Pj4+Cj4+Pj4+ICsvLyAodGhpcyBp cyBuZWNlc3NhcnkgdG8gdXNlIEVSUlBfQVVUT19QUk9QQUdBVEUpLgo+Pj4+Cj4+Pj4gUGVyaGFw cyBFUlJQX0FVVE9fUFJPUEFHQVRFKCkgc2hvdWxkIGJlIEVSUlBfQVVUT19QUk9QQUdBVEUoZXJy cCkgdG8KPj4+PiBtYWtlIHRoZSBmYWN0IHdlJ3JlIG1lc3Npbmcgd2l0aCBAZXJycCBtb3JlIG9i dmlvdXMuICBUb28gbGF0ZTsgSQo+Pj4+IHNob3VsZG4ndCByb2NrIHRoZSBib2F0IHRoYXQgbXVj aCBub3cuCj4+Pj4KPj4+Pj4gKy8vCj4+Pj4+ICsvLyBEaXNhYmxlIG9wdGlvbmFsX3F1YWxpZmll ciB0byBza2lwIGZ1bmN0aW9ucyB3aXRoICJFcnJvciAqY29uc3QgKmVycnAiCj4+Pj4+ICsvLyBw YXJhbWV0ZXIuCj4+Pj4+ICsvLwo+Pj4+PiArLy8gU2tpcCBmdW5jdGlvbnMgd2l0aCAiYXNzZXJ0 KF9lcnJwICYmICpfZXJycCkiIHN0YXRlbWVudCwgYXMgdGhleSBoYXZlCj4+Pj4+ICsvLyBub24g Z2VuZXJpYyBzZW1hbnRpY3MgYW5kIG1heSBoYXZlIHVudXN1YWwgRXJyb3IgKiogYXJndW1lbnQg bmFtZSBmb3IgcHVycG9zZQo+Pj4+Cj4+Pj4gbm9uLWdlbmVyaWMKPj4+Pgo+Pj4+IGZvciBhIHB1 cnBvc2UKPj4+Pgo+Pj4+IFdyYXAgY29tbWVudCBsaW5lcyBhcm91bmQgY29sdW1uIDcwLCBwbGVh c2UuICBJdCdzIGVhc2llciB0byByZWFkLgo+Pj4+Cj4+Pj4gTWF5YmUKPj4+Pgo+Pj4+ICAgICAg Ly8gU2tpcCBmdW5jdGlvbnMgd2l0aCAiYXNzZXJ0KF9lcnJwICYmICpfZXJycCkiIHN0YXRlbWVu dCwgYmVjYXVzZSB0aGF0Cj4+Pj4gICAgICAvLyBzaWduYWxzIHVudXN1YWwgc2VtYW50aWNzLCBh bmQgdGhlIHBhcmFtZXRlciBuYW1lIG1heSB3ZWxsIHNlcnZlIGEKPj4+PiAgICAgIC8vIHB1cnBv c2UuCj4+Pgo+Pj4gU291bmRzIGdvb2QuCj4+Pgo+Pj4+Cj4+Pj4+ICsvLyAobGlrZSBuYmRfaXRl cl9jaGFubmVsX2Vycm9yKCkpLgo+Pj4+PiArLy8KPj4+Pj4gKy8vIFNraXAgdXRpbC9lcnJvci5j IHRvIG5vdCB0b3VjaCwgZm9yIGV4YW1wbGUsIGVycm9yX3Byb3BhZ2F0ZSBhbmQKPj4+Pj4gKy8v IGVycm9yX3Byb3BhZ2F0ZV9wcmVwZW5kKCkuCj4+Pj4KPj4+PiBlcnJvcl9wcm9wYWdhdGUoKQo+ Pj4+Cj4+Pj4gSSBtdWNoIGFwcHJlY2lhdGUgeW91ciBtZXRpY3Vsb3VzIGV4cGxhbmF0aW9uIG9m IHdoYXQgeW91IHNraXAgYW5kIHdoeS4KPj4+Pgo+Pj4+PiArQCBkZXBlbmRzIG9uICEoZmlsZSBp biAidXRpbC9lcnJvci5jIikgZGlzYWJsZSBvcHRpb25hbF9xdWFsaWZpZXJACj4+Pj4+ICtpZGVu dGlmaWVyIGZuOwo+Pj4+PiAraWRlbnRpZmllciBfZXJycCAhPSBlcnJwOwo+Pj4+PiArQEAKPj4+ Pj4gKwo+Pj4+PiArIGZuKC4uLiwKPj4+Pj4gKy0gICBFcnJvciAqKl9lcnJwCj4+Pj4+ICsrICAg RXJyb3IgKiplcnJwCj4+Pj4+ICsgICAgLC4uLikKPj4+Pj4gKyB7Cj4+Pj4+ICsoCj4+Pj4+ICsg ICAgIC4uLiB3aGVuICE9IGFzc2VydChfZXJycCAmJiAqX2VycnApCj4+Pj4+ICsmCj4+Pj4+ICsg ICAgIDwuLi4KPj4+Pj4gKy0gICAgX2VycnAKPj4+Pj4gKysgICAgZXJycAo+Pj4+PiArICAgICAu Li4+Cj4+Pj4+ICspCj4+Pj4+ICsgfQo+Pj4+Cj4+Pj4gVGhpcyBydWxlIGlzIHJlcXVpcmVkIHRv IG1ha2UgdGhlIGFjdHVhbCB0cmFuc2Zvcm1hdGlvbnMgKGJlbG93KSB3b3JrCj4+Pj4gZXZlbiBm b3IgcGFyYW1ldGVycyB3aXRoIG5hbWVzIG90aGVyIHRoYW4gQGVycnAuICBJIGJlbGlldmUgaXQn cyBub3QKPj4+PiB1c2VkIGluIHRoaXMgc2VyaWVzLiAgSW4gZmFjdCwgSSBjYW4ndCBzZWUgYSB1 c2UgZm9yIGl0IGluIHRoZSBlbnRpcmUKPj4+PiB0cmVlIHJpZ2h0IG5vdy4gIE9rYXkgYW55d2F5 Lgo+Pj4+Cj4+Pj4+ICsKPj4+Pj4gKy8vIEFkZCBpbnZvY2F0aW9uIG9mIEVSUlBfQVVUT19QUk9Q QUdBVEUgdG8gZXJycC1mdW5jdGlvbnMgd2hlcmUgbmVjZXNzYXJ5Cj4+Pj4+ICsvLwo+Pj4+PiAr Ly8gTm90ZSwgdGhhdCB3aXRob3V0ICJ3aGVuIGFueSIgZmluYWwgIi4uLiIgbWF5IG5vdCB3YW50 IHRvIG1hY2ggc29tZXRoaW5nCj4+Pj4KPj4+PiBzL2ZpbmFsICIuLi4iIG1heSBub3QgbWFjaC90 aGUgZmluYWwgIi4uLiIgZG9lcyBub3QgbWF0Y2gvCj4+Pj4KPj4+Pj4gKy8vIG1hdGNoZWQgYnkg cHJldmlvdXMgcGF0dGVybiwgaS5lLiB0aGUgcnVsZSB3aWxsIG5vdCBtYXRjaCBkb3VibGUKPj4+ Pj4gKy8vIGVycm9yX3ByZXBlbmQgaW4gY29udHJvbCBmbG93IGxpa2UgaW4gdmZpb19zZXRfaXJx X3NpZ25hbGluZygpLgo+Pj4+Cj4+Pj4gQ2FuJ3Qgc2F5IEkgZnVsbHkgdW5kZXJzdGFuZCBDb2Nj aW5lbGxlIHRoZXJlLiAgSSBmaWd1cmUgeW91IGNhbWUgdG8KPj4+PiB0aGlzIGtub3dsZWRnZSB0 aGUgaGFyZCB3YXkuCj4+Pgo+Pj4gSXQncyBmb2xsb3dzIGZyb20gc21wbCBncmFtbWFyIGRvY3Vt ZW50Ogo+Pj4KPj4+ICJJbXBsaWNpdGx5LCDigJwuLi7igJ0gbWF0Y2hlcyB0aGUgc2hvcnRlc3Qg cGF0aCBiZXR3ZWVuIHNvbWV0aGluZyB0aGF0IG1hdGNoZXMgdGhlIHBhdHRlcm4gYmVmb3JlIHRo ZSBkb3RzIChvciB0aGUgYmVnaW5uaW5nIG9mIHRoZSBmdW5jdGlvbiwgaWYgdGhlcmUgaXMgbm90 aGluZyBiZWZvcmUgdGhlIGRvdHMpIGFuZCBzb21ldGhpbmcgdGhhdCBtYXRjaGVzIHRoZSBwYXR0 ZXJuIGFmdGVyIHRoZSBkb3RzIChvciB0aGUgZW5kIG9mIHRoZSBmdW5jdGlvbiwgaWYgdGhlcmUg aXMgbm90aGluZyBhZnRlciB0aGUgZG90cykuIgo+Pj4gLi4uCj4+PiAiX3doZW4gYW55XyByZW1v dmVzIHRoZSBhZm9yZW1lbnRpb25lZCBjb25zdHJhaW50IHRoYXQg4oCcLi4u4oCdIG1hdGNoZXMg dGhlIHNob3J0ZXN0IHBhdGgiCj4+Cj4+IExldCBtZSB0aGluayB0aGF0IHRocm91Z2guCj4+Cj4+ IFRoZSBwYXR0ZXJuIHdpdGggdGhlIGNhc2VzIG90aGVyIHRoYW4gZXJyb3JfcHJlcGVuZCgpIG9t aXR0ZWQ6Cj4+Cj4+ICAgICAgIGZuKC4uLiwgRXJyb3IgKiplcnJwLCAuLi4pCj4+ICAgICAgIHsK Pj4gICAgICArICAgRVJSUF9BVVRPX1BST1BBR0FURSgpOwo+PiAgICAgICAgICAuLi4gIHdoZW4g IT0gRVJSUF9BVVRPX1BST1BBR0FURSgpOwo+PiAgICAgICAgICBlcnJvcl9wcmVwZW5kKGVycnAs IC4uLik7Cj4+ICAgICAgICAgIC4uLiB3aGVuIGFueQo+PiAgICAgICB9Cj4+Cj4+IFRhaWwgb2Yg dmZpb19zZXRfaXJxX3NpZ25hbGluZygpOgo+Pgo+PiAgICAgICAgICBuYW1lID0gaW5kZXhfdG9f c3RyKHZiYXNlZGV2LCBpbmRleCk7Cj4+ICAgICAgICAgIGlmIChuYW1lKSB7Cj4+ICAgICAgICAg ICAgICBlcnJvcl9wcmVwZW5kKGVycnAsICIlcy0lZDogIiwgbmFtZSwgc3ViaW5kZXgpOwo+PiAg ICAgICAgICB9IGVsc2Ugewo+PiAgICAgICAgICAgICAgZXJyb3JfcHJlcGVuZChlcnJwLCAiaW5k ZXggJWQtJWQ6ICIsIGluZGV4LCBzdWJpbmRleCk7Cj4+ICAgICAgICAgIH0KPj4gICAgICAgICAg ZXJyb3JfcHJlcGVuZChlcnJwLAo+PiAgICAgICAgICAgICAgICAgICAgICAgICJGYWlsZWQgdG8g JXMgJXMgZXZlbnRmZCBzaWduYWxpbmcgZm9yIGludGVycnVwdCAiLAo+PiAgICAgICAgICAgICAg ICAgICAgICAgIGZkIDwgMCA/ICJ0ZWFyIGRvd24iIDogInNldCB1cCIsIGFjdGlvbl90b19zdHIo YWN0aW9uKSk7Cj4+ICAgICAgICAgIHJldHVybiByZXQ7Cj4+ICAgICAgfQo+Pgo+PiBUaGUgcGF0 dGVybidzIGZpcnN0IC4uLiBtYXRjaGVzIGEgInNob3J0ZXN0IiBwYXRoIHRvIGFuIGVycm9yX3By ZXBlbmQoKSwKPj4gd2hlcmUgInNob3J0ZXN0IiBtZWFucyAiZG9lcyBub3QgY3Jvc3MgYW4gZXJy b3JfcHJlcGVuZCgpLiAgSXRzIHdoZW4KPj4gY2xhdXNlIG1ha2VzIHVzIGlnbm9yZSBmdW5jdGlv bnMgdGhhdCBhbHJlYWR5IHVzZSBFUlJQX0FVVE9fUFJPUEFHQVRFKCkuCj4+Cj4+IFRoZXJlIGFy ZSB0d28gc3VjaCAic2hvcnRlc3QiIHBhdGhzLCBvbmUgdG8gdGhlIGZpcnN0IGVycm9yX3ByZXBl bmQoKSBpbgo+PiB2ZmlvX3NldF9pcnFfc2lnbmFsaW5nKCksIGFuZCBvbmUgdG8gdGhlIHNlY29u ZC4gIE5laXRoZXIgcGF0aCB0byB0aGUKPj4gdGhpcmQgb25lIGlzIG5vdCAic2hvcnRlc3QiOiB0 aGV5IGJvdGggY3Jvc3Mgb25lIG9mIHRoZSBvdGhlciB0d28KPj4gZXJyb3JfcHJlcGVuZCgpLgo+ Pgo+PiBUaGUgcGF0dGVybicgcyBzZWNvbmQgLi4uIG1hdGNoZXMgYSBwYXRoIGZyb20gYSBtYXRj aGVkIGVycm9yX3ByZXBlbmQoKQo+PiB0byB0aGUgZW5kIG9mIHRoZSBmdW5jdGlvbi4gIFRoZXJl IGFyZSB0d28gcGF0aHMuICBCb3RoIGNyb3NzIHRoZSB0aGlyZAo+PiBlcnJvcl9wcmVwZW5kKCku ICBZb3UgbmVlZCAid2hlbiBhbnkiIHRvIG1ha2UgdGhlIHBhdHRlcm4gbWF0Y2ggYW55d2F5Lgo+ Pgo+PiBBbHJpZ2h0LCBJIHRoaW5rIEkgZ290IGl0LiAgQnV0IG5vdyBJJ20gcGFyYW5vaWQgYWJv dXQgLi4uIGVsc2V3aGVyZS4KPj4gRm9yIGluc3RhbmNlLCBoZXJlJ3MgcnVsZTEgd2l0aCBlcnJv cl9wcm9wYWdhdGVfcHJlcGVuZCgpIG9taXR0ZWQ6Cj4+Cj4+ICAgICAgLy8gTWF0Y2ggc2NlbmFy aW9zIHdpdGggcHJvcGFnYXRpb24gb2YgbG9jYWwgZXJyb3IgdG8gZXJycC4KPj4gICAgICBAcnVs ZTEgZGlzYWJsZSBvcHRpb25hbF9xdWFsaWZpZXIgZXhpc3RzQAo+PiAgICAgIGlkZW50aWZpZXIg Zm4sIGxvY2FsX2VycjsKPj4gICAgICBzeW1ib2wgZXJycDsKPj4gICAgICBAQAo+Pgo+PiAgICAg ICBmbiguLi4sIEVycm9yICoqZXJycCwgLi4uKQo+PiAgICAgICB7Cj4+ICAgICAgICAgICAuLi4K Pj4gICAgICAgICAgIEVycm9yICpsb2NhbF9lcnIgPSBOVUxMOwo+PiAgICAgICAgICAgLi4uCj4+ ICAgICAgICAgICBlcnJvcl9wcm9wYWdhdGUoZXJycCwgbG9jYWxfZXJyKTsKPj4gICAgICAgICAg IC4uLgo+PiAgICAgICB9Cj4+Cj4+IFRoZSBzZWNvbmQgYW5kIHRoaXJkIC4uLiB3b24ndCBtYXRj aCBhbnl0aGluZyBjb250YWluaW5nCj4+IGVycm9yX3Byb3BhZ2F0ZSgpLiAgV2hhdCBpZiBhIGZ1 bmN0aW9uIGhhcyBtdWx0aXBsZSBlcnJvcl9wcm9wYWdhdGUoKSBvbgo+PiBhbGwgcGF0aHM/Cj4K PiBJIHRob3VnaHQgYWJvdXQgdGhpcywgYnV0IGRlY2lkZWQgdGhhdCBkb3VibGUgZXJyb3IgcHJv cGFnYXRpb24gaXMgYSBzdHJhbmdlIHBhdHRlcm4sIGFuZCBtYXkgYmUgYmV0dGVyIG5vdCBtYXRj aCBpdC4uLgoKSSdtIGZpbmUgd2l0aCBub3QgdG91Y2hpbmcgInN0cmFuZ2UiIHBhdHRlcm5zLiAg QnV0IHdlIGRvIGF0IGxlYXN0IGluCnRoZSBleGFtcGxlIEkgZ2F2ZSBiZWxvdzogd2Ugc3RpbGwg YWRkIEVSUlBfQVVUT19QUk9QQUdBVEUoKS4KCldlIGVpdGhlciBhdm9pZCB0aGF0IGluIHRoZSBD b2NjaW5lbGxlIHNjcmlwdCwgb3Igd2UgY2F0Y2ggaXQKYWZ0ZXJ3YXJkcy4gIENhdGNoaW5nIGl0 IGFmdGVyd2FyZHMgc2hvdWxkIGJlIGZlYXNpYmxlOgoKKiBJZiB3ZSBhbHNvIGRyb3Agc29tZSBl cnJvciBwcm9wYWdhdGlvbiBmcm9tIHRoaXMgZnVuY3Rpb246IG9rYXkuCgoqIElmIHRoaXMgZnVu Y3Rpb24gY2FsbCBlcnJvcl9hcHBlbmRfaGludCgpLCBlcnJvcl9wcmVwZW5kKCkgb3IKICBlcnJv cl92cHJlcGVuZCgpOiBva2F5LgoKKiBFbHNlOiB1bndhbnRlZCwgYmFjayBvdXQuCgpNb3Jlb3Zl ciwgSSdkIGxpa2UgdXMgdG8gZG91YmxlLWNoZWNrIHdlIHJlYWxseSBkb24ndCB3YW50IHRvIHRv dWNoIHRoZQp0aGluZ3Mgd2UgZG9uJ3QgdG91Y2guICBGZWVscyBmZWFzaWJsZSB0byBtZSwgdG9v OiBhZnRlciBydW5uaW5nCkNvY2NpbmVsbGUsIHNlYXJjaCBmb3IgdW5jb252ZXJ0ZWQgZXJyb3Jf YXBwZW5kX2hpbnQoKSwgZXJyb3JfcHJlcGVuZCgpLAplcnJvcl92cHJlcGVuZCgpLCBlcnJvcl9w cm9wYWdhdGVfcHJlcGVuZCgpLCBlcnJvcl9wcm9wYWdhdGUoKS4KCj4+IExpa2UgdGhpcyBvbmU6 Cj4+Cj4+ICAgICAgZXh0ZXJuIGZvbyhpbnQsIEVycm9yICoqKTsKPj4gICAgICBleHRlcm4gYmFy KGludCwgRXJyb3IgKiopOwo+Pgo+PiAgICAgIHZvaWQgZnJvYihFcnJvciAqKmVycnApCj4+ICAg ICAgewo+PiAgICAgICAgICBFcnJvciAqbG9jYWxfZXJyID0gTlVMTDsKPj4gICAgICAgICAgaW50 IGFyZzsKPj4KPj4gICAgICAgICAgZm9vKGFyZywgZXJycCk7Cj4+ICAgICAgICAgIGJhcihhcmcs ICZsb2NhbF9lcnIpOwo+PiAgICAgICAgICBlcnJvcl9wcm9wYWdhdGUoZXJycCwgbG9jYWxfZXJy KTsKPj4gICAgICAgICAgYmFyKGFyZyArIDEsICZsb2NhbF9lcnIpOwo+PiAgICAgICAgICBlcnJv cl9wcm9wYWdhdGUoZXJycCwgbG9jYWxfZXJyKTsKPj4gICAgICB9Cj4+Cj4+IFRoaXMgaXMgYWN0 dWFsbHkgYSB2YXJpYXRpb24gb2YgZXJyb3IuaCdzICJSZWNlaXZlIGFuZCBhY2N1bXVsYXRlCj4+ IG11bHRpcGxlIGVycm9ycyAoZmlyc3Qgb25lIHdpbnMpIiBjb2RlIHNuaXBwZXQuCj4KPiBhaCB5 ZXMsIHdlIGNhbiBwcm9wYWdhdGUgdG8gYWxyZWFkeSBmaWxsZWQgZXJycCwgd2hpY2gganVzdCBj bGVhbiBsb2NhbF9lcnIuCj4KPj4KPj4gVGhlIENvY2NpbmVsbGUgc2NyaXB0IHRyYW5zZm9ybXMg aXQgbGlrZSB0aGlzOgo+Pgo+PiAgICAgICB2b2lkIGZyb2IoRXJyb3IgKiplcnJwKQo+PiAgICAg ICB7Cj4+ICAgICAgKyAgICBFUlJQX0FVVE9fUFJPUEFHQVRFKCk7Cj4+ICAgICAgICAgICBFcnJv ciAqbG9jYWxfZXJyID0gTlVMTDsKPj4gICAgICAgICAgIGludCBhcmc7Cj4+Cj4+IFRoZSBydWxl IHRoYXQgYWRkcyBFUlJQX0FVVE9fUFJPUEFHQVRFKCkgbWF0Y2hlcyAoaXQgaGFzIC4uLiB3aGVu IGFueSksCj4+IGJ1dCBydWxlMSBkb2VzIG5vdCwgYW5kIHdlIHRoZXJlZm9yZSBkb24ndCBjb252 ZXJ0IGFueSBvZiB0aGUKPj4gZXJyb3JfcHJvcGFnYXRlKCkuCj4+Cj4+IFRoZSByZXN1bHQgaXNu J3Qgd3JvbmcsIGp1c3QgdXNlbGVzcy4KPj4KPj4gSXMgdGhpcyB0aGUgd29yc3QgY2FzZT8KPj4K Pj4gUG9zc2libGUgaW1wcm92ZW1lbnQgdG8gdGhlIEVSUlBfQVVUT19QUk9QQUdBVEUoKSBydWxl OiBkb24ndCB1c2UKPj4gIi4uLiB3aGVuIGFueSIgaW4gdGhlIGVycm9yX3Byb3BhZ2F0ZSgpIGNh c2UsIG9ubHkgaW4gdGhlIG90aGVyIGNhc2VzLgo+PiBXb3VsZCB0aGF0IGhlbHA/Cj4KPiBJIHRo aW5rIG5vdCwgYXMgaXQgd2lsbCBhbnl3YXkgbWF0Y2ggZnVuY3Rpb25zIHdpdGggZXJyb3JfcHJl cGVuZCAoYW5kIGFueQo+IG51bWJlciBvZiBmb2xsb3dpbmcgZXJyb3JfcHJvcGFnYXRlIGNhbGxz KS4uLgoKSSdtIG5vdCBzdXJlIEkgdW5kZXJzdGFuZCB0aGlzIHNlbnRlbmNlLgoKVGhlIGFpbSBv ZiBteSAicG9zc2libGUgaW1wcm92ZW1lbnQiIGlzIHRvIGF2b2lkIHVud2FudGVkCkVSUlBfQVVU T19QUk9QQUdBVEUoKSBpbiB0aGUgQ29jY2luZWxsZSBzY3JpcHQuICBXZSBjYW4gaW5zdGVhZCBz ZWFyY2gKZm9yIHVud2FudGVkIG9uZXMgYWZ0ZXIgdGhlIENvY2NpbmVsbGUgcnVuLCBhbmQgYmFj ayB0aGVtIG91dC4KCj4+IEkgdGhpbmsgdGhpcyBpcyB0aGUgb25seSBvdGhlciBydWxlIHdpdGgg Ii4uLiIgbWF0Y2hpbmcgY29udHJvbCBmbG93Lgo+Pgo+Pj4+Cj4+Pj4+ICsvLwo+Pj4+PiArLy8g Tm90ZSwgImV4aXN0cyIgc2F5cyB0aGF0IHdlIHdhbnQgYXBwbHkgcnVsZSBldmVuIGlmIGl0IG1h dGNoZXMgbm90IG9uCj4+Pj4+ICsvLyBhbGwgcG9zc2libGUgY29udHJvbCBmbG93cyAob3RoZXJ3 aXNlLCBpdCB3aWxsIG5vdCBtYXRjaCBzdGFuZGFyZCBwYXR0ZXJuCj4+Pj4+ICsvLyB3aGVuIGVy cm9yX3Byb3BhZ2F0ZSgpIGNhbGwgaXMgaW4gaWYgYnJhbmNoKS4KPj4+Pgo+Pj4+IExlYXJuZWQg c29tZXRoaW5nIG5ldy4gIEV4YW1wbGU6IGt2bV9zZXRfa3ZtX3NoYWRvd19tZW0oKS4KPj4+Pgo+ Pj4+IFNwZWxsaW5nIGl0ICJleGlzdHMgZGlzYWJsZSBvcHRpb25hbF9xdWFsaWZpZXIiIHdvdWxk IGF2b2lkIGdpdmluZwo+Pj4+IHJlYWRlcnMgdGhlIGlkZWEgd2UncmUgZGlzYWJsaW5nICJleGlz dHMiLCBidXQgQ29jY2luZWxsZSBkb2Vzbid0IGxldAo+Pj4+IHVzLiAgT2ggd2VsbC4KPj4+Pgo+ Pj4+PiArQCBkaXNhYmxlIG9wdGlvbmFsX3F1YWxpZmllciBleGlzdHNACj4+Pj4+ICtpZGVudGlm aWVyIGZuLCBsb2NhbF9lcnIsIGVycnA7Cj4+Pj4KPj4+PiBJIGJlbGlldmUgdGhpcyBjYXVzZXMK Pj4+Pgo+Pj4+ICAgICAgIHdhcm5pbmc6IGxpbmUgOTg6IGVycnAsIHByZXZpb3VzbHkgZGVjbGFy ZWQgYXMgYSBtZXRhdmFyaWFibGUsIGlzIHVzZWQgYXMgYW4gaWRlbnRpZmllcgo+Pj4+ICAgICAg IHdhcm5pbmc6IGxpbmUgMTA0OiBlcnJwLCBwcmV2aW91c2x5IGRlY2xhcmVkIGFzIGEgbWV0YXZh cmlhYmxlLCBpcyB1c2VkIGFzIGFuIGlkZW50aWZpZXIKPj4+PiAgICAgICB3YXJuaW5nOiBsaW5l IDEwNjogZXJycCwgcHJldmlvdXNseSBkZWNsYXJlZCBhcyBhIG1ldGF2YXJpYWJsZSwgaXMgdXNl ZCBhcyBhbiBpZGVudGlmaWVyCj4+Pj4gICAgICAgd2FybmluZzogbGluZSAxMzE6IGVycnAsIHBy ZXZpb3VzbHkgZGVjbGFyZWQgYXMgYSBtZXRhdmFyaWFibGUsIGlzIHVzZWQgYXMgYW4gaWRlbnRp Zmllcgo+Pj4+ICAgICAgIHdhcm5pbmc6IGxpbmUgMTkyOiBlcnJwLCBwcmV2aW91c2x5IGRlY2xh cmVkIGFzIGEgbWV0YXZhcmlhYmxlLCBpcyB1c2VkIGFzIGFuIGlkZW50aWZpZXIKPj4+PiAgICAg ICB3YXJuaW5nOiBsaW5lIDE5NTogZXJycCwgcHJldmlvdXNseSBkZWNsYXJlZCBhcyBhIG1ldGF2 YXJpYWJsZSwgaXMgdXNlZCBhcyBhbiBpZGVudGlmaWVyCj4+Pj4gICAgICAgd2FybmluZzogbGlu ZSAyMjg6IGVycnAsIHByZXZpb3VzbHkgZGVjbGFyZWQgYXMgYSBtZXRhdmFyaWFibGUsIGlzIHVz ZWQgYXMgYW4gaWRlbnRpZmllcgo+Pj4+Cj4+Pj4gTWFraW5nIEBlcnJwIHN5bWJvbCBpbnN0ZWFk IG9mIGlkZW50aWZpZXIgc2hvdWxkIGZpeCB0aGlzLgo+Pj4KPj4+IEhtbSwgSSBkaWRuJ3Qgc2Vl IHRoZXNlIHdhcm5pbmdzLi4gQnV0IHllcywgaXQgc2hvdWxkIGJlIHN5bWJvbC4KPj4+Cj4+Pj4K Pj4+Pj4gK0BACj4+Pj4+ICsKPj4+Pj4gKyBmbiguLi4sIEVycm9yICoqZXJycCwgLi4uKQo+Pj4+ PiArIHsKPj4+Pj4gKysgICBFUlJQX0FVVE9fUFJPUEFHQVRFKCk7Cj4+Pj4+ICsgICAgLi4uICB3 aGVuICE9IEVSUlBfQVVUT19QUk9QQUdBVEUoKTsKPj4+Pj4gKygKPj4+Pj4gKyAgICBlcnJvcl9h cHBlbmRfaGludChlcnJwLCAuLi4pOwo+Pj4+PiArfAo+Pj4+PiArICAgIGVycm9yX3ByZXBlbmQo ZXJycCwgLi4uKTsKPj4+Pj4gK3wKPj4+Pj4gKyAgICBlcnJvcl92cHJlcGVuZChlcnJwLCAuLi4p Owo+Pj4+PiArfAo+Pj4+PiArICAgIEVycm9yICpsb2NhbF9lcnIgPSBOVUxMOwo+Pj4+PiArICAg IC4uLgo+Pj4+PiArKAo+Pj4+PiArICAgIGVycm9yX3Byb3BhZ2F0ZV9wcmVwZW5kKGVycnAsIGxv Y2FsX2VyciwgLi4uKTsKPj4+Pj4gK3wKPj4+Pj4gKyAgICBlcnJvcl9wcm9wYWdhdGUoZXJycCwg bG9jYWxfZXJyKTsKPj4+Pj4gKykKPj4+Pj4gKykKPj4+Pj4gKyAgICAuLi4gd2hlbiBhbnkKPj4+ Pj4gKyB9Cj4+Pj4+ICsKPj4+Pj4gKwo+Pj4+PiArLy8gTWF0Y2ggc2NlbmFyaW9zIHdpdGggcHJv cGFnYXRpb24gb2YgbG9jYWwgZXJyb3IgdG8gZXJycC4KPj4+Pj4gK0BydWxlMSBkaXNhYmxlIG9w dGlvbmFsX3F1YWxpZmllciBleGlzdHNACj4+Pj4+ICtpZGVudGlmaWVyIGZuLCBsb2NhbF9lcnI7 Cj4+Pj4+ICtzeW1ib2wgZXJycDsKPj4+Pj4gK0BACj4+Pj4+ICsKPj4+Pj4gKyBmbiguLi4sIEVy cm9yICoqZXJycCwgLi4uKQo+Pj4+PiArIHsKPj4+Pj4gKyAgICAgLi4uCj4+Pj4+ICsgICAgIEVy cm9yICpsb2NhbF9lcnIgPSBOVUxMOwo+Pj4+PiArICAgICAuLi4KPj4+Pj4gKygKPj4+Pj4gKyAg ICBlcnJvcl9wcm9wYWdhdGVfcHJlcGVuZChlcnJwLCBsb2NhbF9lcnIsIC4uLik7Cj4+Pj4+ICt8 Cj4+Pj4+ICsgICAgZXJyb3JfcHJvcGFnYXRlKGVycnAsIGxvY2FsX2Vycik7Cj4+Pj4+ICspCj4+ Pj4KPj4+PiBJbmRlbnRhdGlvbiBvZmYgYnkgb25lLgo+Pj4+Cj4+Pj4+ICsgICAgIC4uLgo+Pj4+ PiArIH0KPj4+Pj4gKwo+Pj4+PiArLy8gQ29udmVydCBzcGVjaWFsIGNhc2Ugd2l0aCBnb3RvIGlu IHNlcGFyYXRlLgo+Pj4+Cj4+Pj4gcy9pbiBzZXBhcmF0ZS9zZXBhcmF0ZWx5Lwo+Pj4+Cj4+Pj4+ ICsvLyBXZSBjYW4gcHJvYmFibHkgbWVyZ2UgdGhpcyBpbnRvIHRoZSBmb2xsb3dpbmcgaHVuayB3 aXRoIGhlbHAgb2YgKCB8ICkKPj4+Pj4gKy8vIG9wZXJhdG9yLCBidXQgaXQgc2lnbmlmaWNhbnRs eSByZWR1Y2UgcGVyZm9ybWFuY2Ugb24gYmxvY2suYyBwYXJzaW5nIChvciBpdAo+Pj4+Cj4+Pj4g cy9yZWR1Y2UvcmVkdWNlcy8KPj4+Pgo+Pj4+PiArLy8gaGFuZ3MsIEkgZG9uJ3Qga25vdykKPj4+ Pgo+Pj4+IFNvdW5kcyBsaWtlIHlvdSB0cmllZCB0byBtZXJnZSB0aGlzIGludG8gdGhlIGZvbGxv d2luZyBodW5rLCBidXQgdGhlbgo+Pj4+IHNwYXRjaCB0b29rIHNvIGxvbmcgb24gYmxvY2suYyB0 aGF0IHlvdSBraWxsZWQgaXQuICBDb3JyZWN0Pwo+Pj4KPj4+IFllcy4KPj4KPj4gSSdkIHNheSBz b21ldGhpbmcgbGlrZSAiSSB0cmllZCBtZXJnaW5nIHRoaXMgaW50byB0aGUgZm9sbG93aW5nIHJ1 bGUgdGhlCj4+IG9idmlvdXMgd2F5LCBidXQgaXQgbWFkZSBDb2NjaW5lbGxlIGhhbmcgb24gYmxv Y2suYy4iCj4+Cj4+Pj4KPj4+Pj4gKy8vCj4+Pj4+ICsvLyBOb3RlIGludGVyZXN0aW5nIHRoaW5n OiBpZiB3ZSBkb24ndCBkbyBpdCBoZXJlLCBhbmQgdHJ5IHRvIGZpeHVwICJvdXQ6IH0iCj4+Pj4+ ICsvLyB0aGluZ3MgbGF0ZXIgYWZ0ZXIgYWxsIHRyYW5zZm9ybWF0aW9ucyAodGhlIHJ1bGUgd2ls bCBiZSB0aGUgc2FtZSwganVzdAo+Pj4+PiArLy8gd2l0aG91dCBlcnJvcl9wcm9wYWdhdGUoKSBj YWxsKSwgY29jY2luZWxsZSBmYWlscyB0byBtYXRjaCB0aGlzICJvdXQ6IH0iLgo+Pj4+Cj4+Pj4g V2VpcmQsIGJ1dCBub3Qgd29ydGggZnVydGhlciBpbnZlc3RpZ2F0aW9uLgo+Pj4KPj4+IEl0IHBh cnRpYWxseSBtYXRjaCB0byB0aGUgaWRlYSB3aGljaCBJIHNhdyBzb21ld2hlcmUgaW4gY29jY2lu ZWxsZSBkb2N1bWVudGF0aW9uLAo+Pj4gdGhhdCBjb2NjaW5lbGxlIGNvbnZlcnRzIGNvcnJlY3Qg QyBjb2RlIHRvIGNvcnJlY3QgQyBjb2RlLiAib3V0OiB9IiBpcyBhbiBleGFtcGxlCj4+PiBvZiBp bmNvcnJlY3QsIGltcG9zc2libGUgY29kZSBmbG93LCBhbmQgY29jY2luZWxsZSBjYW4ndCB3b3Jr IHdpdGggaXQuLi4gQnV0IGl0J3MKPj4+IGp1c3QgYSB0aG91Z2h0Lgo+Pj4KPj4+Pgo+Pj4+PiAr QEAKPj4+Pj4gK2lkZW50aWZpZXIgcnVsZTEuZm4sIHJ1bGUxLmxvY2FsX2Vyciwgb3V0Owo+Pj4+ PiArc3ltYm9sIGVycnA7Cj4+Pj4+ICtAQAo+Pj4+PiArCj4+Pj4+ICsgZm4oLi4uKQo+Pj4+PiAr IHsKPj4+Pj4gKyAgICAgPC4uLgo+Pj4+PiArLSAgICBnb3RvIG91dDsKPj4+Pj4gKysgICAgcmV0 dXJuOwo+Pj4+PiArICAgICAuLi4+Cj4+Pj4+ICstIG91dDoKPj4+Pj4gKy0gICAgZXJyb3JfcHJv cGFnYXRlKGVycnAsIGxvY2FsX2Vycik7Cj4+Pj4KPj4+PiBZb3UgbmVnbGVjdCB0byBtYXRjaCBl cnJvcl9wcm9wYWdhdGVfcHJlcGVuZCgpLiAgT2theSwgYmVjYXVzZSAoMSkgdGhhdAo+Pj4+IHBh dHRlcm4gZG9lc24ndCBvY2N1ciBpbiB0aGUgdHJlZSByaWdodCBub3csIGFuZCAoMikgaWYgaXQg Z2V0cyBhZGRlZCwKPj4+PiBnY2Mgd2lsbCBjb21wbGFpbi4KPj4+Cj4+PiBObywgYmVjYXVzZSBp dCBzaG91bGQgbm90IHJlbW92ZWQuIGVycm9yX3Byb3BhZ2F0ZV9wcmVwZW5kIHNob3VsZCBiZSBj b252ZXJ0ZWQKPj4+IHRvIHByZXBlbmQsIG5vdCByZW1vdmVkLiBTbywgY29ycmVzcG9uZGluZyBn b3RvcyBzaG91bGQgbm90IGJlIHJlbW92ZWQgYXMgd2VsbC4KPj4KPj4gWW91J3JlIHJpZ2h0Lgo+ Pgo+Pj4+Cj4+Pj4+ICsgfQo+Pj4+PiArCj4+Pj4+ICsvLyBDb252ZXJ0IG1vc3Qgb2YgbG9jYWxf ZXJyIHJlbGF0ZWQgc3RhZmYuCj4+Pj4KPj4+PiBzL3N0YWZmL3N0dWZmLwo+Pj4+Cj4+Pj4+ICsv Lwo+Pj4+PiArLy8gTm90ZSwgdGhhdCB3ZSB1cGRhdGUgZXZlcnl0aGluZyByZWxhdGVkIHRvIG1h dGNoZWQgYnkgcnVsZTEgZnVuY3Rpb24gbmFtZQo+Pj4+PiArLy8gYW5kIGxvY2FsX2VyciBuYW1l LiBXZSBtYXkgbWF0Y2ggc29tZXRoaW5nIG5vdCByZWxhdGVkIHRvIHRoZSBwYXR0ZXJuCj4+Pj4+ ICsvLyBtYXRjaGVkIGJ5IHJ1bGUxLiBGb3IgZXhhbXBsZSwgbG9jYWxfZXJyIG1heSBiZSBkZWZp bmVkIHdpdGggdGhlIHNhbWUgbmFtZQo+Pj4+PiArLy8gaW4gZGlmZmVyZW50IGJsb2NrcyBpbnNp ZGUgb25lIGZ1bmN0aW9uLCBhbmQgaW4gb25lIGJsb2NrIGZvbGxvdyB0aGUKPj4+Pj4gKy8vIHBy b3BhZ2F0aW9uIHBhdHRlcm4gYW5kIGluIG90aGVyIGJsb2NrIGRvZXNuJ3QuIE9yIHdlIG1heSBo YXZlIHNldmVyYWwKPj4+Pj4gKy8vIGZ1bmN0aW9ucyB3aXRoIHRoZSBzYW1lIG5hbWUgKGZvciBk aWZmZXJlbnQgY29uZmlndXJhdGlvbnMpLgo+Pj4+Cj4+Pj4gQ29udGV4dDogcnVsZTEgbWF0Y2hl cyBmdW5jdGlvbnMgdGhhdCBoYXZlIGFsbCB0aHJlZSBvZgo+Pj4+Cj4+Pj4gKiBhbiBFcnJvciAq KmVycnAgcGFyYW1ldGVyCj4+Pj4KPj4+PiAqIGFuIEVycm9yICpsb2NhbF9lcnIgPSBOVUxMIHZh cmlhYmxlIGRlY2xhcmF0aW9uCj4+Pj4KPj4+PiAqIGFuIGVycm9yX3Byb3BhZ2F0ZShlcnJwLCBs b2NhbF9lcnIpIG9yIGVycm9yX3Byb3BhZ2F0ZV9wcmVwZW5kKGVycnAsCj4+Pj4gICAgIGxvY2Fs X2VyciwgLi4uKSBleHByZXNzaW9uLCB3aGVyZSBAZXJycCBpcyB0aGUgcGFyYW1ldGVyIGFuZAo+ Pj4+ICAgICBAbG9jYWxfZXJyIGlzIHRoZSB2YXJpYWJsZS4KPj4+Pgo+Pj4+IElmIEkgdW5kZXJz dGFuZCB5b3UgY29ycmVjdGx5LCB5b3UncmUgcG9pbnRpbmcgb3V0IHR3byBwb3RlbnRpYWwgaXNz dWVzOgo+Pj4+Cj4+Pj4gMS4gVGhpcyBydWxlIGNhbiBtYXRjaCBmdW5jdGlvbnMgcnVsZTEgZG9l cyBub3QgbWF0Y2ggaWYgdGhlcmUgaXMKPj4+PiBhbm90aGVyIGZ1bmN0aW9uIHdpdGggdGhlIHNh bWUgbmFtZSB0aGF0IHJ1bGUxIGRvZXMgbWF0Y2guCj4+Pj4KPj4+PiAyLiBUaGlzIHJ1bGUgbWF0 Y2hlcyBpbiB0aGUgZW50aXJlIGZ1bmN0aW9uIG1hdGNoZWQgYnkgcnVsZTEsIGV2ZW4gd2hlbgo+ Pj4+IHBhcnRzIG9mIHRoYXQgZnVuY3Rpb24gdXNlIGEgZGlmZmVyZW50IEBlcnJwIG9yIEBsb2Nh bF9lcnIuCj4+Pj4KPj4+PiBJIGZpZ3VyZSB0aGVzZSBhcHBseSB0byBhbGwgcnVsZXMgd2l0aCBp ZGVudGlmaWVyIHJ1bGUxLmZuLCBub3QganVzdAo+Pj4+IHRoaXMgb25lLiAgQ29ycmVjdD8KPj4+ Cj4+PiBZZXMuCj4+Cj4+IFRoYW5rcyEKPj4KPj4+Pgo+Pj4+IFJlZ2FyZGluZyAxLiAgVGhlcmUg bXVzdCBiZSBhIGJldHRlciB3YXkgdG8gY2hhaW4gcnVsZXMgdG9nZXRoZXIsIGJ1dCBJCj4+Pj4g ZG9uJ3Qga25vdyBpdC4KPj4+PiAgIENhbiB3ZSBtYWtlIENvY2NpbmVsbGUgYXQgbGVhc3Qgd2Fy biB1cyB3aGVuIGl0IGNvbnZlcnRzCj4+Pj4gbXVsdGlwbGUgZnVuY3Rpb25zIHdpdGggdGhlIHNh bWUgbmFtZT8gIFdoYXQgYWJvdXQgdGhpczoKPj4+Pgo+Pj4+ICAgICAgQGluaXRpYWxpemU6cHl0 aG9uQAo+Pj4+ICAgICAgQEAKPj4+PiAgICAgIGZucHJldiA9IHt9Cj4+Pj4KPj4+PiAgICAgIGRl ZiBwcihmbiwgcCk6Cj4+Pj4gICAgICAgICAgcHJpbnQoIiMjIyAlczolczogJXMoKSIgJSAocFsw XS5maWxlLCBwWzBdLmxpbmUsIGZuKSkKPj4+Pgo+Pj4+ICAgICAgQHJACj4+Pj4gICAgICBpZGVu dGlmaWVyIHJ1bGUxLmZuOwo+Pj4+ICAgICAgcG9zaXRpb24gcDsKPj4+PiAgICAgIEBACj4+Pj4g ICAgICAgZm4oLi4uKUBwCj4+Pj4gICAgICAgewo+Pj4+ICAgICAgICAgICAuLi4KPj4+PiAgICAg ICB9Cj4+Pj4gICAgICBAc2NyaXB0OnB5dGhvbkAKPj4+PiAgICAgICAgICBmbiA8PCBydWxlMS5m bjsKPj4+PiAgICAgICAgICBwIDw8IHIucDsKPj4+PiAgICAgIEBACj4+Pj4gICAgICBpZiBmbiBu b3QgaW4gZm5wcmV2Ogo+Pj4+ICAgICAgICAgIGZucHJldltmbl0gPSBwCj4+Pj4gICAgICBlbHNl Ogo+Pj4+ICAgICAgICAgIGlmIGZucHJldltmbl06Cj4+Pgo+Pj4gaG1tLCB0aGUgY29uZGl0aW9u IGNhbid0IGJlIGZhbHNlCj4+Pgo+Pj4+ICAgICAgICAgICAgICBwcihmbiwgZm5wcmV2W2ZuXSkK Pj4+PiAgICAgICAgICAgICAgZm5wcmV2W2ZuXSA9IE5vbmUKPj4+PiAgICAgICAgICBwcihmbiwg cCkKPj4+Cj4+PiBhbmQgd2UnbGwgbWlzcyBuZXh0IGR1cGxpY2F0aW9uLi4KPj4KPj4gVGhlIGlk ZWEgaXMKPj4KPj4gICAgICBmaXJzdCBpbnN0YW5jZSBvZiBmbjoKPj4gICAgICAgICAgZm4gbm90 IGluIGZucHJldgo+PiAgICAgICAgICBmbnByZXZbZm5dID0gcG9zaXRpb24gb2YgaW5zdGFuY2UK Pj4gICAgICAgICAgZG9uJ3QgcHJpbnQKPj4gICAgICBzZWNvbmQgaW5zdGFuY2U6Cj4+ICAgICAg ICAgIGZucHJldltmbl0gaXMgdGhlIHBvc2l0aW9uIG9mIHRoZSBmaXJzdCBpbnN0YW5jZQo+PiAg ICAgICAgICBwcmludCBmaXJzdCB0d28gaW5zdGFuY2VzCj4+ICAgICAgc3Vic2VxdWVudCBpbnN0 YW5jZXM6IGZucHJldltmbl0gaXMgTm9uZQo+PiAgICAgICAgICBwcmludCB0aGlzIGluc3RhbmNl Cj4+Cj4+IEkgbWlnaHQgaGF2ZSBzY3Jld2VkIHVwIHRoZSBjb2RpbmcsIG9mIGNvdXJzZSA6KQo+ Pgo+Pj4gQnV0IEkgbGlrZSB0aGUgaWRlYS4KPj4+Cj4+Pj4KPj4+PiBGb3IgZWFjaCBmdW5jdGlv biBAZm4gbWF0Y2hlZCBieSBydWxlMSwgZm5jbnRbZm5dIGlzIGFuIHVwcGVyIGxpbWl0IG9mCj4+ Pj4gdGhlIG51bWJlciBvZiBmdW5jdGlvbnMgd2l0aCB0aGUgc2FtZSBuYW1lIHdlIHRvdWNoLiAg SWYgaXQncyBtb3JlIHRoYW4KPj4+PiBvbmUsIHdlIHByaW50Lgo+Pj4+Cj4+Pj4gUmVwb3J0cyBh Ym91dCBhIGRvemVuIGZ1bmN0aW9uIG5hbWVzIGZvciB0aGUgd2hvbGUgdHJlZSBpbiBteSB0ZXN0 aW5nLgo+Pj4+IEluc3BlY3RpbmcgdGhlIGNoYW5nZXMgdG8gdGhlbSBtYW51YWxseSBpcyBmZWFz aWJsZS4gIE5vbmUgb2YgdGhlbSBhcmUKPj4+PiBpbiBmaWxlcyB0b3VjaGVkIGJ5IHRoaXMgc2Vy aWVzLgo+Pj4+Cj4+Pj4gVGhlIGxpbmUgcHJpbnRlZCBmb3IgdGhlIGZpcnN0IG1hdGNoIGlzIHBy ZXR0eSB1c2VsZXNzIGZvciBtZTogaXQgcG9pbnRzCj4+Pj4gdG8gYSBDb2NjaW5lbGxlIHRlbXBv cmFyeSBmaWxlICpzaHJ1ZyouCj4+Pj4KPj4+PiBSZWdhcmRpbmcgMi4gIFNoYWRvd2luZyBAZXJy cCBvciBAbG9jYWxfZXJyIHdvdWxkIGJlIGluIGJhZCB0YXN0ZSwgYW5kIEkKPj4+PiBzdXJlIGhv cGUgd2UgZG9uJ3QgZG8gdGhhdC4gIE11bHRpcGxlIEBsb2NhbF9lcnIgdmFyaWFibGVzLi4uIGht bS4KPj4+PiBQZXJoYXBzIHdlIGNvdWxkIGFnYWluIGNvbmNvY3Qgc29tZSBzY3JpcHQgcnVsZXMg dG8gbGVhZCB1cyB0byBzcG90cyB0bwo+Pj4+IGNoZWNrIG1hbnVhbGx5LiAgU2VlIGJlbG93IGZv ciBteSBhdHRlbXB0Lgo+Pj4+Cj4+Pj4gV2hhdCdzIHRoZSB3b3JzdCB0aGF0IGNvdWxkIGhhcHBl biBpZiB3ZSBibGluZGx5IGNvbnZlcnRlZCBzdWNoIGNvZGU/Cj4+Pj4gVGhlIGFuc3dlciB0byB0 aGF0IHF1ZXN0aW9uIHRlbGxzIHVzIGhvdyBoYXJkIHRvIHdvcmsgb24gZmluZGluZyBhbmQKPj4+ PiBjaGVja2luZyB0aGVzZSBndXlzLgo+Pj4+Cj4+Pj4+ICsvLwo+Pj4+PiArLy8gTm90ZSBhbHNv IHRoYXQgZXJycC1jbGVhbmluZyBmdW5jdGlvbnMKPj4+Pj4gKy8vICAgZXJyb3JfZnJlZV9lcnJw Cj4+Pj4+ICsvLyAgIGVycm9yX3JlcG9ydF9lcnJwCj4+Pj4+ICsvLyAgIGVycm9yX3JlcG9ydGZf ZXJycAo+Pj4+PiArLy8gICB3YXJuX3JlcG9ydF9lcnJwCj4+Pj4+ICsvLyAgIHdhcm5fcmVwb3J0 Zl9lcnJwCj4+Pj4+ICsvLyBhcmUgbm90IHlldCBpbXBsZW1lbnRlZC4gVGhleSBtdXN0IGNhbGwg Y29ycmVzcG9uZGluZyBFcnJvciogLSBmcmVlaW5nCj4+Pj4+ICsvLyBmdW5jdGlvbiBhbmQgdGhl biBzZXQgKmVycnAgdG8gTlVMTCwgdG8gYXZvaWQgZnVydGhlciBwcm9wYWdhdGlvbiB0bwo+Pj4+ PiArLy8gb3JpZ2luYWwgZXJycCAoY29uc2lkZXIgRVJSUF9BVVRPX1BST1BBR0FURSBpbiB1c2Up Lgo+Pj4+PiArLy8gRm9yIGV4YW1wbGUsIGVycm9yX2ZyZWVfZXJycCBtYXkgbG9vayBsaWtlIHRo aXM6Cj4+Pj4+ICsvLwo+Pj4+PiArLy8gICAgdm9pZCBlcnJvcl9mcmVlX2VycnAoRXJyb3IgKipl cnJwKQo+Pj4+PiArLy8gICAgewo+Pj4+PiArLy8gICAgICAgIGVycm9yX2ZyZWUoKmVycnApOwo+ Pj4+PiArLy8gICAgICAgICplcnJwID0gTlVMTDsKPj4+Pj4gKy8vICAgIH0KPj4+Pj4gK0AgZXhp c3RzQAo+Pj4+PiAraWRlbnRpZmllciBydWxlMS5mbiwgcnVsZTEubG9jYWxfZXJyOwo+Pj4+PiAr ZXhwcmVzc2lvbiBsaXN0IGFyZ3M7Cj4+Pj4+ICtzeW1ib2wgZXJycDsKPj4+Pj4gK0BACj4+Pj4+ ICsKPj4+Pj4gKyBmbiguLi4pCj4+Pj4+ICsgewo+Pj4+PiArICAgICA8Li4uCj4+Pj4+ICsoCj4+ Pj4KPj4+PiBFYWNoIG9mIHRoZSBmb2xsb3dpbmcgcGF0dGVybnMgYXBwbGllcyBhbnl3aGVyZSBp biB0aGUgZnVuY3Rpb24uCj4+Pj4KPj4+PiBGaXJzdCBwYXR0ZXJuOiBkZWxldGUgQGxvY2FsX2Vy cgo+Pj4+Cj4+Pj4+ICstICAgIEVycm9yICpsb2NhbF9lcnIgPSBOVUxMOwo+Pj4+Cj4+Pj4gQ29t bW9uIGNhc2U6IG9jY3VycyBqdXN0IG9uY2UsIG5vdCBuZXN0ZWQuICBBbnl0aGluZyBlbHNlIGlz IHN1c3BpY2lvdXMuCj4+Pj4KPj4+PiBCb3RoIGNhbiBiZSBkZXRlY3RlZCBpbiB0aGUgcmVzdWx0 aW5nIHBhdGNoZXMgd2l0aCBhIGJpdCBvZiBBV0sKPj4+PiB3aXphcmRyeToKPj4+Pgo+Pj4+ICAg ICAgICQgZ2l0LWRpZmYgLVUwIG1hc3Rlci4ucmV2aWV3LWVycm9yLXY4IHwgYXdrICcvXkBAIC8g eyBjdHggPSAkNTsgZm9yIChpID0gNjsgaSA8PSBORjsgaSsrKSBjdHggPSBjdHggIiAiICRpOyBp ZiAoY3R4ICE9IG9jdHgpIHsgb2N0eCA9IGN0eDsgbiA9IDAgfSB9IC9eLSAqRXJyb3IgKlwqICpb QS1aYS16MC05X10rICo9ICpOVUxMOy8geyBpZiAoaW5kZXgoJDAsICJFIikgPiA2KSBwcmludCAi bmVzdGVkXG4gICAgIiBjdHg7IGlmIChuKSBwcmludCAibW9yZSB0aGFuIG9uZVxuICAgICIgY3R4 OyBuKysgfScKPj4+PiAgICAgICBuZXN0ZWQKPj4+PiAgICAgICAgICAgc3RhdGljIHZvaWQgeGVu X2Jsb2NrX2RyaXZlX2Rlc3Ryb3koWGVuQmxvY2tEcml2ZSAqZHJpdmUsIEVycm9yICoqZXJycCkK Pj4+PiAgICAgICBuZXN0ZWQKPj4+PiAgICAgICAgICAgc3RhdGljIHZvaWQgeGVuX2Jsb2NrX2Rl dmljZV9kZXN0cm95KFhlbkJhY2tlbmRJbnN0YW5jZSAqYmFja2VuZCwKPj4+PiAgICAgICBuZXN0 ZWQKPj4+PiAgICAgICAgICAgc3RhdGljIHZvaWQgeGVuX2Jsb2NrX2RldmljZV9kZXN0cm95KFhl bkJhY2tlbmRJbnN0YW5jZSAqYmFja2VuZCwKPj4+PiAgICAgICBtb3JlIHRoYW4gb25lCj4+Pj4g ICAgICAgICAgIHN0YXRpYyB2b2lkIHhlbl9ibG9ja19kZXZpY2VfZGVzdHJveShYZW5CYWNrZW5k SW5zdGFuY2UgKmJhY2tlbmQsCj4+Pj4KPj4+PiBPaC4KPj4+Pgo+Pj4+IHhlbl9ibG9ja19kcml2 ZV9kZXN0cm95KCkgbmVzdHMgaXRzIEVycm9yICpsb2NhbF9lcnIgaW4gYSBjb25kaXRpb25hbC4K Pj4+Pgo+Pj4+IHhlbl9ibG9ja19kZXZpY2VfZGVzdHJveSgpIGhhcyBtdWx0aXBsZSBFcnJvciAq bG9jYWxfZXJyLgo+Pj4+Cj4+Pj4gSW4gYm90aCBjYXNlcywgbWFudWFsIHJldmlldyBpcyByZXF1 aXJlZCB0byBlbnN1cmUgdGhlIGNvbnZlcnNpb24gaXMKPj4+PiBva2F5LiAgSSBiZWxpZXZlIGl0 IGlzLgo+Pj4+Cj4+Pj4gTm90ZSB0aGF0IHRoZSBBV0sgc2NyaXB0IHJlbGllcyBvbiBkaWZmIHNo b3dpbmcgdGhlIGZ1bmN0aW9uIG5hbWUgaW4gQEAKPj4+PiBsaW5lcywgd2hpY2ggZG9lc24ndCBh bHdheXMgd29yayBkdWUgdG8gb3VyIGNvZGluZyBzdHlsZS4KPj4+Pgo+Pj4+IEZvciB0aGUgd2hv bGUgdHJlZSwgSSBnZXQgc29tZSAzMCBzcG90cy4gIEZlYXNpYmxlLgo+Pj4+Cj4+Pj4+ICt8Cj4+ Pj4KPj4+PiBTZWNvbmQgcGF0dGVybjogY2xlYXIgQGVycnAgYWZ0ZXIgZnJlZWluZyBpdAo+Pj4+ Cj4+Pj4+ICsKPj4+Pj4gKy8vIENvbnZlcnQgZXJyb3IgY2xlYXJpbmcgZnVuY3Rpb25zCj4+Pj4K Pj4+PiBTdWdnZXN0OiBFbnN1cmUgQGxvY2FsX2VyciBpcyBjbGVhcmVkIG9uIGZyZWUKPj4+Pgo+ Pj4+PiArKAo+Pj4+PiArLSAgICBlcnJvcl9mcmVlKGxvY2FsX2Vycik7Cj4+Pj4+ICsrICAgIGVy cm9yX2ZyZWVfZXJycChlcnJwKTsKPj4+Pj4gK3wKPj4+Pj4gKy0gICAgZXJyb3JfcmVwb3J0X2Vy cihsb2NhbF9lcnIpOwo+Pj4+PiArKyAgICBlcnJvcl9yZXBvcnRfZXJycChlcnJwKTsKPj4+Pj4g K3wKPj4+Pj4gKy0gICAgZXJyb3JfcmVwb3J0Zl9lcnIobG9jYWxfZXJyLCBhcmdzKTsKPj4+Pj4g KysgICAgZXJyb3JfcmVwb3J0Zl9lcnJwKGVycnAsIGFyZ3MpOwo+Pj4+PiArfAo+Pj4+PiArLSAg ICB3YXJuX3JlcG9ydF9lcnIobG9jYWxfZXJyKTsKPj4+Pj4gKysgICAgd2Fybl9yZXBvcnRfZXJy cChlcnJwKTsKPj4+Pj4gK3wKPj4+Pj4gKy0gICAgd2Fybl9yZXBvcnRmX2Vycihsb2NhbF9lcnIs IGFyZ3MpOwo+Pj4+PiArKyAgICB3YXJuX3JlcG9ydGZfZXJycChlcnJwLCBhcmdzKTsKPj4+Pj4g KykKPj4+Pgo+Pj4+IEFzIHlvdSBtZW50aW9uIGFib3ZlLCB0aGVzZSBndXlzIGRvbid0IGV4aXN0 LCB5ZXQuICBCdWlsZHMgYW55d2F5LAo+Pj4+IGJlY2F1c2UgdGhpcyBwYXJ0IG9mIHRoZSBydWxl IGlzIG5vdCB1c2VkIGluIHRoaXMgcGF0Y2ggc2VyaWVzLiAgWW91Cj4+Pj4gZG9uJ3Qgd2FudCB0 byBvbWl0IGl0LCBiZWNhdXNlIHRoZW4gdGhlIHNjcmlwdCBiZWNvbWVzIHVuc2FmZSB0byB1c2Uu Cj4+Pj4KPj4+PiBXZSBjb3VsZCBhbHNvIG9wZW4tY29kZToKPj4+Pgo+Pj4+ICAgICAgLy8gQ29u dmVydCBlcnJvciBjbGVhcmluZyBmdW5jdGlvbnMKPj4+PiAgICAgICgKPj4+PiAgICAgIC0gICAg ZXJyb3JfZnJlZShsb2NhbF9lcnIpOwo+Pj4+ICAgICAgKyAgICBlcnJvcl9mcmVlKCplcnJwKTsK Pj4+PiAgICAgICsgICAgKmVycnAgPSBOVUxMOwo+Pj4+ICAgICAgfAo+Pj4+ICAgICAgLi4uIGFu ZCBzbyBmb3J0aCAuLi4KPj4+PiAgICAgICkKPj4+Pgo+Pj4+IE1hdHRlciBvZiB0YXN0ZS4gIFdo YXRldmVyIGlzIGVhc2llciB0byBleHBsYWluIGluIHRoZSBjb21tZW50cy4gIFNpbmNlCj4+Pj4g eW91IGFscmVhZHkgd3JvdGUgb25lLi4uCj4+Pgo+Pj4gSSBqdXN0IGZlZWwgdGhhdCB1c2luZyBo ZWxwZXIgZnVuY3Rpb25zIGlzIHNhZmVyIHdheS4uCj4+Pgo+Pj4+Cj4+Pj4gV2UgdGFsa2VkIGFi b3V0IGV4dGVuZGluZyB0aGlzIHNlcmllcyBzbGlnaHRseSBzbyB0aGVzZSBndXlzIGFyZSB1c2Vk Lgo+Pj4+IEkgbWF5IHN0aWxsIGxvb2sgaW50byB0aGF0Lgo+Pj4+Cj4+Pj4+ICs/LSAgICBsb2Nh bF9lcnIgPSBOVUxMOwo+Pj4+PiArCj4+Pj4KPj4+PiBUaGUgbmV3IGhlbHBlcnMgY2xlYXIgQGxv Y2FsX2Vyci4gIEFzc2lnbm1lbnQgbm93IHJlZHVuZGFudCwgZGVsZXRlLgo+Pj4+IE9rYXkuCj4+ Pj4KPj4+Pj4gK3wKPj4+Pgo+Pj4+IFRoaXJkIGFuZCBmb3VydGggcGF0dGVybjogZGVsZXRlIGVy cm9yX3Byb3BhZ2F0ZSgpCj4+Pj4KPj4+Pj4gKy0gICAgZXJyb3JfcHJvcGFnYXRlX3ByZXBlbmQo ZXJycCwgbG9jYWxfZXJyLCBhcmdzKTsKPj4+Pj4gKysgICAgZXJyb3JfcHJlcGVuZChlcnJwLCBh cmdzKTsKPj4+Pj4gK3wKPj4+Pj4gKy0gICAgZXJyb3JfcHJvcGFnYXRlKGVycnAsIGxvY2FsX2Vy cik7Cj4+Pj4+ICt8Cj4+Pj4KPj4+PiBGaWZ0aCBwYXR0ZXJuOiB1c2UgQGVycnAgZGlyZWN0bHkK Pj4+Pgo+Pj4+PiArLSAgICAmbG9jYWxfZXJyCj4+Pj4+ICsrICAgIGVycnAKPj4+Pj4gKykKPj4+ Pj4gKyAgICAgLi4uPgo+Pj4+PiArIH0KPj4+Pj4gKwo+Pj4+PiArLy8gQ29udmVydCByZW1haW5p bmcgbG9jYWxfZXJyIHVzYWdlLiBJdCBzaG91bGQgYmUgZGlmZmVyZW50IGtpbmRzIG9mIGVycm9y Cj4+Pj4+ICsvLyBjaGVja2luZyBpbiBpZiBvcGVyYXRvcnMuIFdlIGNhbid0IG1lcmdlIHRoaXMg aW50byBwcmV2aW91cyBodW5rLCBhcyB0aGlzCj4+Pj4KPj4+PiBJbiBpZiBjb25kaXRpb25hbHMs IEkgc3VwcG9zZS4gIEl0J3MgdGhlIGNhc2UgZm9yIHRoaXMgcGF0Y2guICBJZiBJCj4+Pj4gYXBw bHkgdGhlIHNjcmlwdCB0byB0aGUgd2hvbGUgdHJlZSwgdGhlIHJ1bGUgZ2V0cyBhbHNvIGFwcGxp ZWQgaW4gb3RoZXIKPj4+PiBjb250ZXh0cy4gIFRoZSBzZW50ZW5jZSBtaWdodCBtaXNsZWFkIGFz IG11Y2ggYXMgaXQgaGVscHMuICBLZWVwIGl0IG9yCj4+Pj4gZGVsZXRlIGl0Pwo+Pj4KPj4+IE1h eWJlLCBqdXN0IGJlIG1vcmUgaG9uZXN0OiAiSXQgc2hvdWxkIGJlIC4uLiwgYnV0IGl0IG1heSBi ZSBhbnkgb3RoZXIgcGF0dGVybiwgYmUgY2FyZWZ1bCIKPj4KPj4gIk5lZWQgdG8gYmUgY2FyZWZ1 bCIgbWVhbnMgIm5lZWRzIGNhcmVmdWwgbWFudWFsIHJldmlldyIsIHdoaWNoIEkKPj4gYmVsaWV2 ZSBpcyBub3QgZmVhc2libGU7IHNlZSAiUHJlZmFjZSB0byBteSByZXZpZXcgb2YgdGhpcyBzY3Jp cHQiCj4+IGFib3ZlLgo+Pgo+PiBCdXQgZG8gd2UgcmVhbGx5IG5lZWQgdG8gYmUgY2FyZWZ1bCBo ZXJlPwo+Pgo+PiBUaGlzIHJ1bGUgc2hvdWxkIGFwcGx5IG9ubHkgd2hlcmUgd2UgYWRkZWQgRVJS UF9BVVRPX1BST1BBR0FURSgpLgo+Pgo+PiBFeGNlcHQgd2hlbiBydWxlIGNoYWluaW5nIHZpYSBm dW5jdGlvbiBuYW1lIGZhaWxzIHVzLCBidXQgd2UgcGxhbiB0bwo+PiBkZXRlY3QgdGhhdCBhbmQg cmV2aWV3IG1hbnVhbGx5LCBzbyBsZXQncyBpZ25vcmUgdGhpcyBpc3N1ZSBoZXJlLgo+Pgo+PiBU aGFua3MgdG8gRVJSUF9BVVRPX1BST1BBR0FURSgpLCBAZXJycCBpcyBub3QgbnVsbC4gIEVuYWJs aW5nCj4+IHJlcGxhY2VtZW50IG9mIEBsb2NhbF9lcnIgYnkgQGVycnAgaXMgaXRzIHdob2xlIHBv aW50Lgo+Pgo+PiBXaGF0IGV4YWN0bHkgZG8gd2UgbmVlZCB0byBiZSBjYXJlZnVsIGFib3V0Pwo+ Cj4gSG1tLi4gQWJvdXQgc29tZSB1bnByZWRpY3RlZCBwYXR0ZXJucy4gT0ssIHRoZW4gIkZvciBl eGFtcGxlLCBkaWZmZXJlbnQga2luZHMgb2YgLi4iCgpTb21ldGhpbmcgbGlrZSB0aGlzLCBwZXJo YXBzPwoKICAgICAgIC8vIENvbnZlcnQgcmVtYWluaW5nIGxvY2FsX2VyciB1c2FnZSwgdHlwaWNh bGx5IGVycm9yIGNoZWNraW5nLgogICAgICAgLy8gV2UgY2FuJ3QgbWVyZ2UgdGhpcyBpbnRvIHBy ZXZpb3VzIGh1bmssIGFzIHRoaXMgY29uZmxpY3RzIHdpdGggb3RoZXIKICAgICAgIC8vIHN1YnN0 aXR1dGlvbnMgaW4gaXQgKGF0IGxlYXN0IHdpdGggIi0gbG9jYWxfZXJyID0gTlVMTCIpLgoKPj4+ Pj4gKy8vIGNvbmZsaWN0cyB3aXRoIG90aGVyIHN1YnN0aXR1dGlvbnMgaW4gaXQgKGF0IGxlYXN0 IHdpdGggIi0gbG9jYWxfZXJyID0gTlVMTCIpLgo+Pj4+PiArQEAKPj4+Pj4gK2lkZW50aWZpZXIg cnVsZTEuZm4sIHJ1bGUxLmxvY2FsX2VycjsKPj4+Pj4gK3N5bWJvbCBlcnJwOwo+Pj4+PiArQEAK Pj4+Pj4gKwo+Pj4+PiArIGZuKC4uLikKPj4+Pj4gKyB7Cj4+Pj4+ICsgICAgIDwuLi4KPj4+Pj4g Ky0gICAgbG9jYWxfZXJyCj4+Pj4+ICsrICAgICplcnJwCj4+Pj4+ICsgICAgIC4uLj4KPj4+Pj4g KyB9Cj4+Pj4+ICsKPj4+Pj4gKy8vIEFsd2F5cyB1c2UgdGhlIHNhbWUgcGF0dGVyIGZvciBjaGVj a2luZyBlcnJvcgo+Pj4+Cj4+Pj4gcy9wYXR0ZXIvcGF0dGVybi8KPj4+Pgo+Pj4+PiArQEAKPj4+ Pj4gK2lkZW50aWZpZXIgcnVsZTEuZm47Cj4+Pj4+ICtzeW1ib2wgZXJycDsKPj4+Pj4gK0BACj4+ Pj4+ICsKPj4+Pj4gKyBmbiguLi4pCj4+Pj4+ICsgewo+Pj4+PiArICAgICA8Li4uCj4+Pj4+ICst ICAgICplcnJwICE9IE5VTEwKPj4+Pj4gKysgICAgKmVycnAKPj4+Pj4gKyAgICAgLi4uPgo+Pj4+ PiArIH0KPj4+Pgo+PgoKCl9fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19f X19fX19fClhlbi1kZXZlbCBtYWlsaW5nIGxpc3QKWGVuLWRldmVsQGxpc3RzLnhlbnByb2plY3Qu b3JnCmh0dHBzOi8vbGlzdHMueGVucHJvamVjdC5vcmcvbWFpbG1hbi9saXN0aW5mby94ZW4tZGV2 ZWw=