From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pj1-x102f.google.com (mail-pj1-x102f.google.com [IPv6:2607:f8b0:4864:20::102f]) by sourceware.org (Postfix) with ESMTPS id 90CAA3857BBF for ; Thu, 14 Jul 2022 21:09:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 90CAA3857BBF Received: by mail-pj1-x102f.google.com with SMTP id o5-20020a17090a3d4500b001ef76490983so4264863pjf.2 for ; Thu, 14 Jul 2022 14:09:52 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=E4u56rh9r1luExZ7spUCCNp/ChnDTYDjWJrw2Xa38rE=; b=ab4b5PZ2QhfaW7jhrZIjkojqnLimoTEt/HVUNVyVokVlT1FqvRlOOznub/3JqZwtPP TrZfJUXFKMqqSP72iCbLmWOFRKDfSfNEvq2xlSGB/69SBmqBTHenCwkuqs5+L8g6nn8J 7Z9u6nK8N5eTscaueh4H6q6LiR7N7Eaiv+NRsBnslZurthPm5S8Xprmk4t+MCEbKheh/ ueKkIdcAo99sf8KYyNAZYFQdcGrNZ+enjMX8GoR/Arvtx48X9eD30nx/v7HfYK9BI3m3 iP+165CK2grwsj4KggyDwWx9FWpbkKWMmxCS1EfZ/SQWjsvyBcdtrCweaTirst2aszrt Kesg== X-Gm-Message-State: AJIora88kuwUGnVR5Ggn3HISlEeLuOjonI+UXd2btc2gCr4hta95RKdZ 28HifMPmujw72lPhdX7Ql8X/slqN1Zx21r7Z7kET7cqs X-Google-Smtp-Source: AGRyM1scY0y6tjfU7zdNEtDClKZazsVeJXjoynptIOdEbnFjz9hDxKPmDoGcCliTeJ2lKK1dHqP9xwxdItJfU/bnpt8= X-Received: by 2002:a17:902:b215:b0:168:da4b:c925 with SMTP id t21-20020a170902b21500b00168da4bc925mr9649852plr.155.1657832991202; Thu, 14 Jul 2022 14:09:51 -0700 (PDT) MIME-Version: 1.0 References: <20220713165014.36469-1-hjl.tools@gmail.com> In-Reply-To: From: "H.J. Lu" Date: Thu, 14 Jul 2022 14:09:15 -0700 Message-ID: Subject: Re: [PATCH v3] Simplify memchr with small constant strings To: Richard Biener Cc: GCC Patches Content-Type: multipart/mixed; boundary="00000000000089ccd705e3ca525d" X-Spam-Status: No, score=-3024.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 14 Jul 2022 21:09:56 -0000 --00000000000089ccd705e3ca525d Content-Type: text/plain; charset="UTF-8" On Wed, Jul 13, 2022 at 11:42 PM Richard Biener wrote: > > On Wed, Jul 13, 2022 at 6:50 PM H.J. Lu wrote: > > > > When memchr is applied on a constant string of no more than the bytes of > > a word, simplify memchr by checking each byte in the constant string. > > > > int f (int a) > > { > > return __builtin_memchr ("AE", a, 2) != 0; > > } > > > > is simplified to > > > > int f (int a) > > { > > return ((char) a == 'A' || (char) a == 'E') != 0; > > } > > > > gcc/ > > > > PR tree-optimization/103798 > > * tree-ssa-forwprop.cc: Include "tree-ssa-strlen.h". > > (simplify_builtin_call): Inline memchr with constant strings of > > no more than the bytes of a word. > > * tree-ssa-strlen.cc (use_in_zero_equality): Make it global. > > * tree-ssa-strlen.h (use_in_zero_equality): New. > > > > gcc/testsuite/ > > > > PR tree-optimization/103798 > > * c-c++-common/pr103798-1.c: New test. > > * c-c++-common/pr103798-2.c: Likewise. > > * c-c++-common/pr103798-3.c: Likewise. > > * c-c++-common/pr103798-4.c: Likewise. > > * c-c++-common/pr103798-5.c: Likewise. > > * c-c++-common/pr103798-6.c: Likewise. > > * c-c++-common/pr103798-7.c: Likewise. > > * c-c++-common/pr103798-8.c: Likewise. > > * c-c++-common/pr103798-9.c: Likewise. > > * c-c++-common/pr103798-10.c: Likewise. > > --- > > gcc/testsuite/c-c++-common/pr103798-1.c | 28 +++++++++ > > gcc/testsuite/c-c++-common/pr103798-10.c | 10 ++++ > > gcc/testsuite/c-c++-common/pr103798-2.c | 30 ++++++++++ > > gcc/testsuite/c-c++-common/pr103798-3.c | 28 +++++++++ > > gcc/testsuite/c-c++-common/pr103798-4.c | 28 +++++++++ > > gcc/testsuite/c-c++-common/pr103798-5.c | 26 +++++++++ > > gcc/testsuite/c-c++-common/pr103798-6.c | 27 +++++++++ > > gcc/testsuite/c-c++-common/pr103798-7.c | 27 +++++++++ > > gcc/testsuite/c-c++-common/pr103798-8.c | 27 +++++++++ > > gcc/testsuite/c-c++-common/pr103798-9.c | 10 ++++ > > gcc/tree-ssa-forwprop.cc | 73 ++++++++++++++++++++++++ > > gcc/tree-ssa-strlen.cc | 4 +- > > gcc/tree-ssa-strlen.h | 2 + > > 13 files changed, 318 insertions(+), 2 deletions(-) > > create mode 100644 gcc/testsuite/c-c++-common/pr103798-1.c > > create mode 100644 gcc/testsuite/c-c++-common/pr103798-10.c > > create mode 100644 gcc/testsuite/c-c++-common/pr103798-2.c > > create mode 100644 gcc/testsuite/c-c++-common/pr103798-3.c > > create mode 100644 gcc/testsuite/c-c++-common/pr103798-4.c > > create mode 100644 gcc/testsuite/c-c++-common/pr103798-5.c > > create mode 100644 gcc/testsuite/c-c++-common/pr103798-6.c > > create mode 100644 gcc/testsuite/c-c++-common/pr103798-7.c > > create mode 100644 gcc/testsuite/c-c++-common/pr103798-8.c > > create mode 100644 gcc/testsuite/c-c++-common/pr103798-9.c > > > > diff --git a/gcc/testsuite/c-c++-common/pr103798-1.c b/gcc/testsuite/c-c++-common/pr103798-1.c > > new file mode 100644 > > index 00000000000..cd3edf569fc > > --- /dev/null > > +++ b/gcc/testsuite/c-c++-common/pr103798-1.c > > @@ -0,0 +1,28 @@ > > +/* { dg-do run } */ > > +/* { dg-options "-O2 -fdump-tree-optimized -save-temps" } */ > > + > > +__attribute__ ((weak)) > > +int > > +f (char a) > > +{ > > + return __builtin_memchr ("a", a, 1) == 0; > > +} > > + > > +__attribute__ ((weak)) > > +int > > +g (char a) > > +{ > > + return a != 'a'; > > +} > > + > > +int > > +main () > > +{ > > + for (int i = 0; i < 255; i++) > > + if (f (i) != g (i)) > > + __builtin_abort (); > > + > > + return 0; > > +} > > + > > +/* { dg-final { scan-assembler-not "memchr" } } */ > > diff --git a/gcc/testsuite/c-c++-common/pr103798-10.c b/gcc/testsuite/c-c++-common/pr103798-10.c > > new file mode 100644 > > index 00000000000..4677e9539fa > > --- /dev/null > > +++ b/gcc/testsuite/c-c++-common/pr103798-10.c > > @@ -0,0 +1,10 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-Os -fdump-tree-optimized -save-temps" } */ > > + > > +int > > +f (char a) > > +{ > > + return __builtin_memchr ("ac", a, 1) == 0; > > +} > > + > > +/* { dg-final { scan-assembler "memchr" } } */ > > diff --git a/gcc/testsuite/c-c++-common/pr103798-2.c b/gcc/testsuite/c-c++-common/pr103798-2.c > > new file mode 100644 > > index 00000000000..e7e99c3679e > > --- /dev/null > > +++ b/gcc/testsuite/c-c++-common/pr103798-2.c > > @@ -0,0 +1,30 @@ > > +/* { dg-do run } */ > > +/* { dg-options "-O2 -fdump-tree-optimized -save-temps" } */ > > + > > +#include > > + > > +__attribute__ ((weak)) > > +int > > +f (int a) > > +{ > > + return memchr ("aE", a, 2) != NULL; > > +} > > + > > +__attribute__ ((weak)) > > +int > > +g (char a) > > +{ > > + return a == 'a' || a == 'E'; > > +} > > + > > +int > > +main () > > +{ > > + for (int i = 0; i < 255; i++) > > + if (f (i + 256) != g (i + 256)) > > + __builtin_abort (); > > + > > + return 0; > > +} > > + > > +/* { dg-final { scan-assembler-not "memchr" } } */ > > diff --git a/gcc/testsuite/c-c++-common/pr103798-3.c b/gcc/testsuite/c-c++-common/pr103798-3.c > > new file mode 100644 > > index 00000000000..ddcedc7e238 > > --- /dev/null > > +++ b/gcc/testsuite/c-c++-common/pr103798-3.c > > @@ -0,0 +1,28 @@ > > +/* { dg-do run } */ > > +/* { dg-options "-O2 -fdump-tree-optimized -save-temps" } */ > > + > > +__attribute__ ((weak)) > > +int > > +f (char a) > > +{ > > + return __builtin_memchr ("aEgZ", a, 3) == 0; > > +} > > + > > +__attribute__ ((weak)) > > +int > > +g (char a) > > +{ > > + return a != 'a' && a != 'E' && a != 'g'; > > +} > > + > > +int > > +main () > > +{ > > + for (int i = 0; i < 255; i++) > > + if (f (i) != g (i)) > > + __builtin_abort (); > > + > > + return 0; > > +} > > + > > +/* { dg-final { scan-assembler-not "memchr" } } */ > > diff --git a/gcc/testsuite/c-c++-common/pr103798-4.c b/gcc/testsuite/c-c++-common/pr103798-4.c > > new file mode 100644 > > index 00000000000..00e8302a833 > > --- /dev/null > > +++ b/gcc/testsuite/c-c++-common/pr103798-4.c > > @@ -0,0 +1,28 @@ > > +/* { dg-do run } */ > > +/* { dg-options "-O2 -fdump-tree-optimized -save-temps" } */ > > + > > +__attribute__ ((weak)) > > +int > > +f (char a) > > +{ > > + return __builtin_memchr ("aEgi", a, 4) != 0; > > +} > > + > > +__attribute__ ((weak)) > > +int > > +g (char a) > > +{ > > + return a == 'a' || a == 'E' || a == 'g' || a == 'i'; > > +} > > + > > +int > > +main () > > +{ > > + for (int i = 0; i < 255; i++) > > + if (f (i) != g (i)) > > + __builtin_abort (); > > + > > + return 0; > > +} > > + > > +/* { dg-final { scan-assembler-not "memchr" } } */ > > diff --git a/gcc/testsuite/c-c++-common/pr103798-5.c b/gcc/testsuite/c-c++-common/pr103798-5.c > > new file mode 100644 > > index 00000000000..0d6487a13df > > --- /dev/null > > +++ b/gcc/testsuite/c-c++-common/pr103798-5.c > > @@ -0,0 +1,26 @@ > > +/* { dg-do run { target int128 } } */ > > +/* { dg-options "-O2 -fdump-tree-optimized -save-temps" } */ > > + > > +__attribute__ ((weak)) > > +int f(char a) > > +{ > > + return __builtin_memchr ("aEgiH", a, 5) == 0; > > +} > > + > > +__attribute__ ((weak)) > > +int g(char a) > > +{ > > + return a != 'a' && a != 'E' && a != 'g' && a != 'i' && a != 'H'; > > +} > > + > > +int > > +main () > > +{ > > + for (int i = 0; i < 255; i++) > > + if (f (i) != g (i)) > > + __builtin_abort (); > > + > > + return 0; > > +} > > + > > +/* { dg-final { scan-assembler-not "memchr" } } */ > > diff --git a/gcc/testsuite/c-c++-common/pr103798-6.c b/gcc/testsuite/c-c++-common/pr103798-6.c > > new file mode 100644 > > index 00000000000..5ccb5ee66e0 > > --- /dev/null > > +++ b/gcc/testsuite/c-c++-common/pr103798-6.c > > @@ -0,0 +1,27 @@ > > +/* { dg-do run { target int128 } } */ > > +/* { dg-options "-O2 -fdump-tree-optimized -save-temps" } */ > > + > > +__attribute__ ((weak)) > > +int f(char a) > > +{ > > + return __builtin_memchr ("aEgiHx", a, 6) != 0; > > +} > > + > > +__attribute__ ((weak)) > > +int g(char a) > > +{ > > + return (a == 'a' || a == 'E' || a == 'g' || a == 'i' || a == 'H' > > + || a == 'x'); > > +} > > + > > +int > > +main () > > +{ > > + for (int i = 0; i < 255; i++) > > + if (f (i) != g (i)) > > + __builtin_abort (); > > + > > + return 0; > > +} > > + > > +/* { dg-final { scan-assembler-not "memchr" } } */ > > diff --git a/gcc/testsuite/c-c++-common/pr103798-7.c b/gcc/testsuite/c-c++-common/pr103798-7.c > > new file mode 100644 > > index 00000000000..40fd38257d1 > > --- /dev/null > > +++ b/gcc/testsuite/c-c++-common/pr103798-7.c > > @@ -0,0 +1,27 @@ > > +/* { dg-do run { target int128 } } */ > > +/* { dg-options "-O2 -fdump-tree-optimized -save-temps" } */ > > + > > +__attribute__ ((weak)) > > +int f(char a) > > +{ > > + return __builtin_memchr ("aEgiHjZ", a, 7) == 0; > > +} > > + > > +__attribute__ ((weak)) > > +int g(char a) > > +{ > > + return (a != 'a' && a != 'E' && a != 'g' && a != 'i' && a != 'H' > > + && a != 'j' && a != 'Z'); > > +} > > + > > +int > > +main () > > +{ > > + for (int i = 0; i < 255; i++) > > + if (f (i) != g (i)) > > + __builtin_abort (); > > + > > + return 0; > > +} > > + > > +/* { dg-final { scan-assembler-not "memchr" } } */ > > diff --git a/gcc/testsuite/c-c++-common/pr103798-8.c b/gcc/testsuite/c-c++-common/pr103798-8.c > > new file mode 100644 > > index 00000000000..0841b18cea4 > > --- /dev/null > > +++ b/gcc/testsuite/c-c++-common/pr103798-8.c > > @@ -0,0 +1,27 @@ > > +/* { dg-do run { target int128 } } */ > > +/* { dg-options "-O2 -fdump-tree-optimized -save-temps" } */ > > + > > +__attribute__ ((weak)) > > +int f(int a) > > +{ > > + return __builtin_memchr ("aEgiHx19ABC", a, 8) != 0; > > +} > > + > > +__attribute__ ((weak)) > > +int g(char a) > > +{ > > + return (a == 'a' || a == 'E' || a == 'g' || a == 'i' || a == 'H' > > + || a == 'x' || a == '1' || a == '9'); > > +} > > + > > +int > > +main () > > +{ > > + for (int i = 0; i < 255; i++) > > + if (f (i + 256) != g (i + 256)) > > + __builtin_abort (); > > + > > + return 0; > > +} > > + > > +/* { dg-final { scan-assembler-not "memchr" } } */ > > diff --git a/gcc/testsuite/c-c++-common/pr103798-9.c b/gcc/testsuite/c-c++-common/pr103798-9.c > > new file mode 100644 > > index 00000000000..c5f0f94a4b5 > > --- /dev/null > > +++ b/gcc/testsuite/c-c++-common/pr103798-9.c > > @@ -0,0 +1,10 @@ > > +/* { dg-do compile } */ > > +/* { dg-options "-Os -fdump-tree-optimized -save-temps" } */ > > + > > +int > > +f (char a) > > +{ > > + return __builtin_memchr ("a", a, 1) == 0; > > +} > > + > > +/* { dg-final { scan-assembler-not "memchr" } } */ > > diff --git a/gcc/tree-ssa-forwprop.cc b/gcc/tree-ssa-forwprop.cc > > index 69567ab3275..28549c85f76 100644 > > --- a/gcc/tree-ssa-forwprop.cc > > +++ b/gcc/tree-ssa-forwprop.cc > > @@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see > > #include "tree-dfa.h" > > #include "tree-ssa-propagate.h" > > #include "tree-ssa-dom.h" > > +#include "tree-ssa-strlen.h" > > #include "builtins.h" > > #include "tree-cfgcleanup.h" > > #include "cfganal.h" > > @@ -1177,6 +1178,15 @@ constant_pointer_difference (tree p1, tree p2) > > memcpy (p, "abcd ", 7); > > call if the latter can be stored by pieces during expansion. > > > > + Optimize > > + memchr ("abcd", a, 4) == 0; > > + or > > + memchr ("abcd", a, 4) != 0; > > + to > > + (a == 'a' || a == 'b' || a == 'c' || a == 'd') == 0 > > + or > > + (a == 'a' || a == 'b' || a == 'c' || a == 'd') != 0 > > + > > Also canonicalize __atomic_fetch_op (p, x, y) op x > > to __atomic_op_fetch (p, x, y) or > > __atomic_op_fetch (p, x, y) iop x > > @@ -1193,8 +1203,71 @@ simplify_builtin_call (gimple_stmt_iterator *gsi_p, tree callee2) > > return false; > > stmt1 = SSA_NAME_DEF_STMT (vuse); > > > > + tree res; > > + > > switch (DECL_FUNCTION_CODE (callee2)) > > { > > + case BUILT_IN_MEMCHR: > > + if (gimple_call_num_args (stmt2) == 3 > > + && (res = gimple_call_lhs (stmt2)) != nullptr > > + && use_in_zero_equality (res) != nullptr > > + && CHAR_BIT == 8 > > + && BITS_PER_UNIT == 8) > > + { > > + tree ptr = gimple_call_arg (stmt2, 0); > > + if (TREE_CODE (ptr) != ADDR_EXPR > > + || TREE_CODE (TREE_OPERAND (ptr, 0)) != STRING_CST) > > + break; > > + unsigned HOST_WIDE_INT slen > > + = TREE_STRING_LENGTH (TREE_OPERAND (ptr, 0)); > > + /* It must be a non-empty string constant. */ > > + if (slen < 2) > > + break; > > + /* For -Os, only simplify strings with a single character. */ > > + if (!optimize_bb_for_speed_p (gimple_bb (stmt2)) > > + && slen > 2) > > + break; > > + tree size = gimple_call_arg (stmt2, 2); > > + /* Size must be a constant which is <= UNITS_PER_WORD and > > + <= the string length. */ > > + if (TREE_CODE (size) != INTEGER_CST || integer_zerop (size)) > > + break; > > + > > + if (!tree_fits_uhwi_p (size)) > > + break; > > + > > + unsigned HOST_WIDE_INT sz = tree_to_uhwi (size); > > + if (sz > UNITS_PER_WORD || sz >= slen) > > + break; > > + > > + tree ch = gimple_call_arg (stmt2, 1); > > + location_t loc = gimple_location (stmt2); > > + if (!useless_type_conversion_p (char_type_node, > > + TREE_TYPE (ch))) > > + ch = fold_convert_loc (loc, char_type_node, ch); > > + const char *p = TREE_STRING_POINTER (TREE_OPERAND (ptr, 0)); > > + unsigned int isize = sz; > > + tree *op = new tree[isize]; > > minor nit - sorry for not spotting earlier. Please use > > tree *op = XALLOCAVEC (tree, isize); > > Ok with that change. > Richard. Fixed. This is the patch I am checking in. Thanks. > > + for (unsigned int i = 0; i < isize; i++) > > + { > > + op[i] = build_int_cst (char_type_node, p[i]); > > + op[i] = fold_build2_loc (loc, EQ_EXPR, boolean_type_node, > > + op[i], ch); > > + } > > + for (unsigned int i = isize - 1; i >= 1; i--) > > + op[i - 1] = fold_convert_loc (loc, boolean_type_node, > > + fold_build2_loc (loc, > > + BIT_IOR_EXPR, > > + boolean_type_node, > > + op[i - 1], > > + op[i])); > > + res = fold_convert_loc (loc, TREE_TYPE (res), op[0]); > > + gimplify_and_update_call_from_tree (gsi_p, res); > > + delete[] op; > > + return true; > > + } > > + break; > > + > > case BUILT_IN_MEMSET: > > if (gimple_call_num_args (stmt2) != 3 > > || gimple_call_lhs (stmt2) > > diff --git a/gcc/tree-ssa-strlen.cc b/gcc/tree-ssa-strlen.cc > > index 7b3e3899ea2..5afbae1b72e 100644 > > --- a/gcc/tree-ssa-strlen.cc > > +++ b/gcc/tree-ssa-strlen.cc > > @@ -3913,8 +3913,8 @@ strlen_pass::handle_builtin_memset (bool *zero_write) > > nonnull if and only RES is used in such expressions exclusively and > > in none other. */ > > > > -static gimple * > > -use_in_zero_equality (tree res, bool exclusive = true) > > +gimple * > > +use_in_zero_equality (tree res, bool exclusive) > > { > > gimple *first_use = NULL; > > > > diff --git a/gcc/tree-ssa-strlen.h b/gcc/tree-ssa-strlen.h > > index 8d155450db8..fdb4d9d7783 100644 > > --- a/gcc/tree-ssa-strlen.h > > +++ b/gcc/tree-ssa-strlen.h > > @@ -35,6 +35,8 @@ struct c_strlen_data; > > extern void get_range_strlen_dynamic (tree, gimple *, c_strlen_data *, > > pointer_query &); > > > > +extern gimple *use_in_zero_equality (tree, bool = true); > > + > > /* APIs internal to strlen pass. Defined in gimple-ssa-sprintf.cc. */ > > extern bool handle_printf_call (gimple_stmt_iterator *, pointer_query &); > > > > -- > > 2.36.1 > > -- H.J. --00000000000089ccd705e3ca525d Content-Type: text/x-patch; charset="US-ASCII"; name="0001-Simplify-memchr-with-small-constant-strings.patch" Content-Disposition: attachment; filename="0001-Simplify-memchr-with-small-constant-strings.patch" Content-Transfer-Encoding: base64 Content-ID: X-Attachment-Id: f_l5liwudm0 RnJvbSAwMWNjMzQwMWJhM2I2YjViYTFhNGMyNmI4YjViZjlhMzhmZWI5MmZhIE1vbiBTZXAgMTcg MDA6MDA6MDAgMjAwMQpGcm9tOiAiSC5KLiBMdSIgPGhqbC50b29sc0BnbWFpbC5jb20+CkRhdGU6 IEZyaSwgMTcgSnVuIDIwMjIgMDc6MzM6MDYgLTA3MDAKU3ViamVjdDogW1BBVENIXSBTaW1wbGlm eSBtZW1jaHIgd2l0aCBzbWFsbCBjb25zdGFudCBzdHJpbmdzCgpXaGVuIG1lbWNociBpcyBhcHBs aWVkIG9uIGEgY29uc3RhbnQgc3RyaW5nIG9mIG5vIG1vcmUgdGhhbiB0aGUgYnl0ZXMgb2YKYSB3 b3JkLCBzaW1wbGlmeSBtZW1jaHIgYnkgY2hlY2tpbmcgZWFjaCBieXRlIGluIHRoZSBjb25zdGFu dCBzdHJpbmcuCgppbnQgZiAoaW50IGEpCnsKICAgcmV0dXJuICBfX2J1aWx0aW5fbWVtY2hyICgi QUUiLCBhLCAyKSAhPSAwOwp9CgppcyBzaW1wbGlmaWVkIHRvCgppbnQgZiAoaW50IGEpCnsKICBy ZXR1cm4gKChjaGFyKSBhID09ICdBJyB8fCAoY2hhcikgYSA9PSAnRScpICE9IDA7Cn0KCmdjYy8K CglQUiB0cmVlLW9wdGltaXphdGlvbi8xMDM3OTgKCSogdHJlZS1zc2EtZm9yd3Byb3AuY2M6IElu Y2x1ZGUgInRyZWUtc3NhLXN0cmxlbi5oIi4KCShzaW1wbGlmeV9idWlsdGluX2NhbGwpOiBJbmxp bmUgbWVtY2hyIHdpdGggY29uc3RhbnQgc3RyaW5ncyBvZgoJbm8gbW9yZSB0aGFuIHRoZSBieXRl cyBvZiBhIHdvcmQuCgkqIHRyZWUtc3NhLXN0cmxlbi5jYyAodXNlX2luX3plcm9fZXF1YWxpdHkp OiBNYWtlIGl0IGdsb2JhbC4KCSogdHJlZS1zc2Etc3RybGVuLmggKHVzZV9pbl96ZXJvX2VxdWFs aXR5KTogTmV3LgoKZ2NjL3Rlc3RzdWl0ZS8KCglQUiB0cmVlLW9wdGltaXphdGlvbi8xMDM3OTgK CSogYy1jKystY29tbW9uL3ByMTAzNzk4LTEuYzogTmV3IHRlc3QuCgkqIGMtYysrLWNvbW1vbi9w cjEwMzc5OC0yLmM6IExpa2V3aXNlLgoJKiBjLWMrKy1jb21tb24vcHIxMDM3OTgtMy5jOiBMaWtl d2lzZS4KCSogYy1jKystY29tbW9uL3ByMTAzNzk4LTQuYzogTGlrZXdpc2UuCgkqIGMtYysrLWNv bW1vbi9wcjEwMzc5OC01LmM6IExpa2V3aXNlLgoJKiBjLWMrKy1jb21tb24vcHIxMDM3OTgtNi5j OiBMaWtld2lzZS4KCSogYy1jKystY29tbW9uL3ByMTAzNzk4LTcuYzogTGlrZXdpc2UuCgkqIGMt YysrLWNvbW1vbi9wcjEwMzc5OC04LmM6IExpa2V3aXNlLgoJKiBjLWMrKy1jb21tb24vcHIxMDM3 OTgtOS5jOiBMaWtld2lzZS4KCSogYy1jKystY29tbW9uL3ByMTAzNzk4LTEwLmM6IExpa2V3aXNl LgotLS0KIGdjYy90ZXN0c3VpdGUvYy1jKystY29tbW9uL3ByMTAzNzk4LTEuYyAgfCAyOCArKysr KysrKysKIGdjYy90ZXN0c3VpdGUvYy1jKystY29tbW9uL3ByMTAzNzk4LTEwLmMgfCAxMCArKysr CiBnY2MvdGVzdHN1aXRlL2MtYysrLWNvbW1vbi9wcjEwMzc5OC0yLmMgIHwgMzAgKysrKysrKysr KwogZ2NjL3Rlc3RzdWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgtMy5jICB8IDI4ICsrKysrKysr KwogZ2NjL3Rlc3RzdWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgtNC5jICB8IDI4ICsrKysrKysr KwogZ2NjL3Rlc3RzdWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgtNS5jICB8IDI2ICsrKysrKysr KwogZ2NjL3Rlc3RzdWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgtNi5jICB8IDI3ICsrKysrKysr KwogZ2NjL3Rlc3RzdWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgtNy5jICB8IDI3ICsrKysrKysr KwogZ2NjL3Rlc3RzdWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgtOC5jICB8IDI3ICsrKysrKysr KwogZ2NjL3Rlc3RzdWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgtOS5jICB8IDEwICsrKysKIGdj Yy90cmVlLXNzYS1mb3J3cHJvcC5jYyAgICAgICAgICAgICAgICAgfCA3MiArKysrKysrKysrKysr KysrKysrKysrKysKIGdjYy90cmVlLXNzYS1zdHJsZW4uY2MgICAgICAgICAgICAgICAgICAgfCAg NCArLQogZ2NjL3RyZWUtc3NhLXN0cmxlbi5oICAgICAgICAgICAgICAgICAgICB8ICAyICsKIDEz IGZpbGVzIGNoYW5nZWQsIDMxNyBpbnNlcnRpb25zKCspLCAyIGRlbGV0aW9ucygtKQogY3JlYXRl IG1vZGUgMTAwNjQ0IGdjYy90ZXN0c3VpdGUvYy1jKystY29tbW9uL3ByMTAzNzk4LTEuYwogY3Jl YXRlIG1vZGUgMTAwNjQ0IGdjYy90ZXN0c3VpdGUvYy1jKystY29tbW9uL3ByMTAzNzk4LTEwLmMK IGNyZWF0ZSBtb2RlIDEwMDY0NCBnY2MvdGVzdHN1aXRlL2MtYysrLWNvbW1vbi9wcjEwMzc5OC0y LmMKIGNyZWF0ZSBtb2RlIDEwMDY0NCBnY2MvdGVzdHN1aXRlL2MtYysrLWNvbW1vbi9wcjEwMzc5 OC0zLmMKIGNyZWF0ZSBtb2RlIDEwMDY0NCBnY2MvdGVzdHN1aXRlL2MtYysrLWNvbW1vbi9wcjEw Mzc5OC00LmMKIGNyZWF0ZSBtb2RlIDEwMDY0NCBnY2MvdGVzdHN1aXRlL2MtYysrLWNvbW1vbi9w cjEwMzc5OC01LmMKIGNyZWF0ZSBtb2RlIDEwMDY0NCBnY2MvdGVzdHN1aXRlL2MtYysrLWNvbW1v bi9wcjEwMzc5OC02LmMKIGNyZWF0ZSBtb2RlIDEwMDY0NCBnY2MvdGVzdHN1aXRlL2MtYysrLWNv bW1vbi9wcjEwMzc5OC03LmMKIGNyZWF0ZSBtb2RlIDEwMDY0NCBnY2MvdGVzdHN1aXRlL2MtYysr LWNvbW1vbi9wcjEwMzc5OC04LmMKIGNyZWF0ZSBtb2RlIDEwMDY0NCBnY2MvdGVzdHN1aXRlL2Mt YysrLWNvbW1vbi9wcjEwMzc5OC05LmMKCmRpZmYgLS1naXQgYS9nY2MvdGVzdHN1aXRlL2MtYysr LWNvbW1vbi9wcjEwMzc5OC0xLmMgYi9nY2MvdGVzdHN1aXRlL2MtYysrLWNvbW1vbi9wcjEwMzc5 OC0xLmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAuLmNkM2VkZjU2OWZj Ci0tLSAvZGV2L251bGwKKysrIGIvZ2NjL3Rlc3RzdWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgt MS5jCkBAIC0wLDAgKzEsMjggQEAKKy8qIHsgZGctZG8gcnVuIH0gKi8KKy8qIHsgZGctb3B0aW9u cyAiLU8yIC1mZHVtcC10cmVlLW9wdGltaXplZCAtc2F2ZS10ZW1wcyIgfSAqLworCitfX2F0dHJp YnV0ZV9fICgod2VhaykpCitpbnQKK2YgKGNoYXIgYSkKK3sKKyAgIHJldHVybiAgX19idWlsdGlu X21lbWNociAoImEiLCBhLCAxKSA9PSAwOworfQorCitfX2F0dHJpYnV0ZV9fICgod2VhaykpCitp bnQKK2cgKGNoYXIgYSkKK3sKKyAgcmV0dXJuIGEgIT0gJ2EnOworfQorCitpbnQKK21haW4gKCkK K3sKKyBmb3IgKGludCBpID0gMDsgaSA8IDI1NTsgaSsrKQorICAgaWYgKGYgKGkpICE9IGcgKGkp KQorICAgICBfX2J1aWx0aW5fYWJvcnQgKCk7CisKKyByZXR1cm4gMDsKK30KKworLyogeyBkZy1m aW5hbCB7IHNjYW4tYXNzZW1ibGVyLW5vdCAibWVtY2hyIiB9IH0gKi8KZGlmZiAtLWdpdCBhL2dj Yy90ZXN0c3VpdGUvYy1jKystY29tbW9uL3ByMTAzNzk4LTEwLmMgYi9nY2MvdGVzdHN1aXRlL2Mt YysrLWNvbW1vbi9wcjEwMzc5OC0xMC5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4IDAwMDAw MDAwMDAwLi40Njc3ZTk1MzlmYQotLS0gL2Rldi9udWxsCisrKyBiL2djYy90ZXN0c3VpdGUvYy1j KystY29tbW9uL3ByMTAzNzk4LTEwLmMKQEAgLTAsMCArMSwxMCBAQAorLyogeyBkZy1kbyBjb21w aWxlIH0gKi8KKy8qIHsgZGctb3B0aW9ucyAiLU9zIC1mZHVtcC10cmVlLW9wdGltaXplZCAtc2F2 ZS10ZW1wcyIgfSAqLworCitpbnQKK2YgKGNoYXIgYSkKK3sKKyAgcmV0dXJuICBfX2J1aWx0aW5f bWVtY2hyICgiYWMiLCBhLCAxKSA9PSAwOworfQorCisvKiB7IGRnLWZpbmFsIHsgc2Nhbi1hc3Nl bWJsZXIgIm1lbWNociIgfSB9ICovCmRpZmYgLS1naXQgYS9nY2MvdGVzdHN1aXRlL2MtYysrLWNv bW1vbi9wcjEwMzc5OC0yLmMgYi9nY2MvdGVzdHN1aXRlL2MtYysrLWNvbW1vbi9wcjEwMzc5OC0y LmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAuLmU3ZTk5YzM2NzllCi0t LSAvZGV2L251bGwKKysrIGIvZ2NjL3Rlc3RzdWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgtMi5j CkBAIC0wLDAgKzEsMzAgQEAKKy8qIHsgZGctZG8gcnVuIH0gKi8KKy8qIHsgZGctb3B0aW9ucyAi LU8yIC1mZHVtcC10cmVlLW9wdGltaXplZCAtc2F2ZS10ZW1wcyIgfSAqLworCisjaW5jbHVkZSA8 c3RyaW5nLmg+CisKK19fYXR0cmlidXRlX18gKCh3ZWFrKSkKK2ludAorZiAoaW50IGEpCit7Cisg ICByZXR1cm4gbWVtY2hyICgiYUUiLCBhLCAyKSAhPSBOVUxMOworfQorCitfX2F0dHJpYnV0ZV9f ICgod2VhaykpCitpbnQKK2cgKGNoYXIgYSkKK3sKKyAgcmV0dXJuIGEgPT0gJ2EnIHx8IGEgPT0g J0UnOworfQorCitpbnQKK21haW4gKCkKK3sKKyBmb3IgKGludCBpID0gMDsgaSA8IDI1NTsgaSsr KQorICAgaWYgKGYgKGkgKyAyNTYpICE9IGcgKGkgKyAyNTYpKQorICAgICBfX2J1aWx0aW5fYWJv cnQgKCk7CisKKyByZXR1cm4gMDsKK30KKworLyogeyBkZy1maW5hbCB7IHNjYW4tYXNzZW1ibGVy LW5vdCAibWVtY2hyIiB9IH0gKi8KZGlmZiAtLWdpdCBhL2djYy90ZXN0c3VpdGUvYy1jKystY29t bW9uL3ByMTAzNzk4LTMuYyBiL2djYy90ZXN0c3VpdGUvYy1jKystY29tbW9uL3ByMTAzNzk4LTMu YwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMC4uZGRjZWRjN2UyMzgKLS0t IC9kZXYvbnVsbAorKysgYi9nY2MvdGVzdHN1aXRlL2MtYysrLWNvbW1vbi9wcjEwMzc5OC0zLmMK QEAgLTAsMCArMSwyOCBAQAorLyogeyBkZy1kbyBydW4gfSAqLworLyogeyBkZy1vcHRpb25zICIt TzIgLWZkdW1wLXRyZWUtb3B0aW1pemVkIC1zYXZlLXRlbXBzIiB9ICovCisKK19fYXR0cmlidXRl X18gKCh3ZWFrKSkKK2ludAorZiAoY2hhciBhKQoreworICAgcmV0dXJuICBfX2J1aWx0aW5fbWVt Y2hyICgiYUVnWiIsIGEsIDMpID09IDA7Cit9CisKK19fYXR0cmlidXRlX18gKCh3ZWFrKSkKK2lu dAorZyAoY2hhciBhKQoreworICByZXR1cm4gYSAhPSAnYScgJiYgYSAhPSAnRScgJiYgYSAhPSAn Zyc7Cit9CisKK2ludAorbWFpbiAoKQoreworIGZvciAoaW50IGkgPSAwOyBpIDwgMjU1OyBpKysp CisgICBpZiAoZiAoaSkgIT0gZyAoaSkpCisgICAgIF9fYnVpbHRpbl9hYm9ydCAoKTsKKworIHJl dHVybiAwOworfQorCisvKiB7IGRnLWZpbmFsIHsgc2Nhbi1hc3NlbWJsZXItbm90ICJtZW1jaHIi IH0gfSAqLwpkaWZmIC0tZ2l0IGEvZ2NjL3Rlc3RzdWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgt NC5jIGIvZ2NjL3Rlc3RzdWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgtNC5jCm5ldyBmaWxlIG1v ZGUgMTAwNjQ0CmluZGV4IDAwMDAwMDAwMDAwLi4wMGU4MzAyYTgzMwotLS0gL2Rldi9udWxsCisr KyBiL2djYy90ZXN0c3VpdGUvYy1jKystY29tbW9uL3ByMTAzNzk4LTQuYwpAQCAtMCwwICsxLDI4 IEBACisvKiB7IGRnLWRvIHJ1biB9ICovCisvKiB7IGRnLW9wdGlvbnMgIi1PMiAtZmR1bXAtdHJl ZS1vcHRpbWl6ZWQgLXNhdmUtdGVtcHMiIH0gKi8KKworX19hdHRyaWJ1dGVfXyAoKHdlYWspKQor aW50CitmIChjaGFyIGEpCit7CisgICByZXR1cm4gIF9fYnVpbHRpbl9tZW1jaHIgKCJhRWdpIiwg YSwgNCkgIT0gMDsKK30KKworX19hdHRyaWJ1dGVfXyAoKHdlYWspKQoraW50CitnIChjaGFyIGEp Cit7CisgIHJldHVybiBhID09ICdhJyB8fCBhID09ICdFJyB8fCBhID09ICdnJyB8fCBhID09ICdp JzsKK30KKworaW50CittYWluICgpCit7CisgZm9yIChpbnQgaSA9IDA7IGkgPCAyNTU7IGkrKykK KyAgIGlmIChmIChpKSAhPSBnIChpKSkKKyAgICAgX19idWlsdGluX2Fib3J0ICgpOworCisgcmV0 dXJuIDA7Cit9CisKKy8qIHsgZGctZmluYWwgeyBzY2FuLWFzc2VtYmxlci1ub3QgIm1lbWNociIg fSB9ICovCmRpZmYgLS1naXQgYS9nY2MvdGVzdHN1aXRlL2MtYysrLWNvbW1vbi9wcjEwMzc5OC01 LmMgYi9nY2MvdGVzdHN1aXRlL2MtYysrLWNvbW1vbi9wcjEwMzc5OC01LmMKbmV3IGZpbGUgbW9k ZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAuLjBkNjQ4N2ExM2RmCi0tLSAvZGV2L251bGwKKysr IGIvZ2NjL3Rlc3RzdWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgtNS5jCkBAIC0wLDAgKzEsMjYg QEAKKy8qIHsgZGctZG8gcnVuIHsgdGFyZ2V0IGludDEyOCB9IH0gKi8KKy8qIHsgZGctb3B0aW9u cyAiLU8yIC1mZHVtcC10cmVlLW9wdGltaXplZCAtc2F2ZS10ZW1wcyIgfSAqLworCitfX2F0dHJp YnV0ZV9fICgod2VhaykpCitpbnQgZihjaGFyIGEpCit7CisgICByZXR1cm4gIF9fYnVpbHRpbl9t ZW1jaHIgKCJhRWdpSCIsIGEsIDUpID09IDA7Cit9CisKK19fYXR0cmlidXRlX18gKCh3ZWFrKSkK K2ludCBnKGNoYXIgYSkKK3sKKyAgcmV0dXJuIGEgIT0gJ2EnICYmIGEgIT0gJ0UnICYmIGEgIT0g J2cnICYmIGEgIT0gJ2knICYmIGEgIT0gJ0gnOworfQorCitpbnQKK21haW4gKCkKK3sKKyBmb3Ig KGludCBpID0gMDsgaSA8IDI1NTsgaSsrKQorICAgaWYgKGYgKGkpICE9IGcgKGkpKQorICAgICBf X2J1aWx0aW5fYWJvcnQgKCk7CisKKyByZXR1cm4gMDsKK30KKworLyogeyBkZy1maW5hbCB7IHNj YW4tYXNzZW1ibGVyLW5vdCAibWVtY2hyIiB9IH0gKi8KZGlmZiAtLWdpdCBhL2djYy90ZXN0c3Vp dGUvYy1jKystY29tbW9uL3ByMTAzNzk4LTYuYyBiL2djYy90ZXN0c3VpdGUvYy1jKystY29tbW9u L3ByMTAzNzk4LTYuYwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMC4uNWNj YjVlZTY2ZTAKLS0tIC9kZXYvbnVsbAorKysgYi9nY2MvdGVzdHN1aXRlL2MtYysrLWNvbW1vbi9w cjEwMzc5OC02LmMKQEAgLTAsMCArMSwyNyBAQAorLyogeyBkZy1kbyBydW4geyB0YXJnZXQgaW50 MTI4IH0gfSAqLworLyogeyBkZy1vcHRpb25zICItTzIgLWZkdW1wLXRyZWUtb3B0aW1pemVkIC1z YXZlLXRlbXBzIiB9ICovCisKK19fYXR0cmlidXRlX18gKCh3ZWFrKSkKK2ludCBmKGNoYXIgYSkK K3sKKyAgIHJldHVybiAgX19idWlsdGluX21lbWNociAoImFFZ2lIeCIsIGEsIDYpICE9IDA7Cit9 CisKK19fYXR0cmlidXRlX18gKCh3ZWFrKSkKK2ludCBnKGNoYXIgYSkKK3sKKyAgcmV0dXJuIChh ID09ICdhJyB8fCBhID09ICdFJyB8fCBhID09ICdnJyB8fCBhID09ICdpJyB8fCBhID09ICdIJwor CSAgfHwgYSA9PSAneCcpOworfQorCitpbnQKK21haW4gKCkKK3sKKyBmb3IgKGludCBpID0gMDsg aSA8IDI1NTsgaSsrKQorICAgaWYgKGYgKGkpICE9IGcgKGkpKQorICAgICBfX2J1aWx0aW5fYWJv cnQgKCk7CisKKyByZXR1cm4gMDsKK30KKworLyogeyBkZy1maW5hbCB7IHNjYW4tYXNzZW1ibGVy LW5vdCAibWVtY2hyIiB9IH0gKi8KZGlmZiAtLWdpdCBhL2djYy90ZXN0c3VpdGUvYy1jKystY29t bW9uL3ByMTAzNzk4LTcuYyBiL2djYy90ZXN0c3VpdGUvYy1jKystY29tbW9uL3ByMTAzNzk4LTcu YwpuZXcgZmlsZSBtb2RlIDEwMDY0NAppbmRleCAwMDAwMDAwMDAwMC4uNDBmZDM4MjU3ZDEKLS0t IC9kZXYvbnVsbAorKysgYi9nY2MvdGVzdHN1aXRlL2MtYysrLWNvbW1vbi9wcjEwMzc5OC03LmMK QEAgLTAsMCArMSwyNyBAQAorLyogeyBkZy1kbyBydW4geyB0YXJnZXQgaW50MTI4IH0gfSAqLwor LyogeyBkZy1vcHRpb25zICItTzIgLWZkdW1wLXRyZWUtb3B0aW1pemVkIC1zYXZlLXRlbXBzIiB9 ICovCisKK19fYXR0cmlidXRlX18gKCh3ZWFrKSkKK2ludCBmKGNoYXIgYSkKK3sKKyAgIHJldHVy biAgX19idWlsdGluX21lbWNociAoImFFZ2lIaloiLCBhLCA3KSA9PSAwOworfQorCitfX2F0dHJp YnV0ZV9fICgod2VhaykpCitpbnQgZyhjaGFyIGEpCit7CisgIHJldHVybiAoYSAhPSAnYScgJiYg YSAhPSAnRScgJiYgYSAhPSAnZycgJiYgYSAhPSAnaScgJiYgYSAhPSAnSCcKKwkgICYmIGEgIT0g J2onICYmIGEgIT0gJ1onKTsKK30KKworaW50CittYWluICgpCit7CisgZm9yIChpbnQgaSA9IDA7 IGkgPCAyNTU7IGkrKykKKyAgIGlmIChmIChpKSAhPSBnIChpKSkKKyAgICAgX19idWlsdGluX2Fi b3J0ICgpOworCisgcmV0dXJuIDA7Cit9CisKKy8qIHsgZGctZmluYWwgeyBzY2FuLWFzc2VtYmxl ci1ub3QgIm1lbWNociIgfSB9ICovCmRpZmYgLS1naXQgYS9nY2MvdGVzdHN1aXRlL2MtYysrLWNv bW1vbi9wcjEwMzc5OC04LmMgYi9nY2MvdGVzdHN1aXRlL2MtYysrLWNvbW1vbi9wcjEwMzc5OC04 LmMKbmV3IGZpbGUgbW9kZSAxMDA2NDQKaW5kZXggMDAwMDAwMDAwMDAuLjA4NDFiMThjZWE0Ci0t LSAvZGV2L251bGwKKysrIGIvZ2NjL3Rlc3RzdWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgtOC5j CkBAIC0wLDAgKzEsMjcgQEAKKy8qIHsgZGctZG8gcnVuIHsgdGFyZ2V0IGludDEyOCB9IH0gKi8K Ky8qIHsgZGctb3B0aW9ucyAiLU8yIC1mZHVtcC10cmVlLW9wdGltaXplZCAtc2F2ZS10ZW1wcyIg fSAqLworCitfX2F0dHJpYnV0ZV9fICgod2VhaykpCitpbnQgZihpbnQgYSkKK3sKKyAgIHJldHVy biAgX19idWlsdGluX21lbWNociAoImFFZ2lIeDE5QUJDIiwgYSwgOCkgIT0gMDsKK30KKworX19h dHRyaWJ1dGVfXyAoKHdlYWspKQoraW50IGcoY2hhciBhKQoreworICByZXR1cm4gKGEgPT0gJ2En IHx8IGEgPT0gJ0UnIHx8IGEgPT0gJ2cnIHx8IGEgPT0gJ2knIHx8IGEgPT0gJ0gnCisJICB8fCBh ID09ICd4JyB8fCBhID09ICcxJyB8fCBhID09ICc5Jyk7Cit9CisKK2ludAorbWFpbiAoKQorewor IGZvciAoaW50IGkgPSAwOyBpIDwgMjU1OyBpKyspCisgICBpZiAoZiAoaSArIDI1NikgIT0gZyAo aSArIDI1NikpCisgICAgIF9fYnVpbHRpbl9hYm9ydCAoKTsKKworIHJldHVybiAwOworfQorCisv KiB7IGRnLWZpbmFsIHsgc2Nhbi1hc3NlbWJsZXItbm90ICJtZW1jaHIiIH0gfSAqLwpkaWZmIC0t Z2l0IGEvZ2NjL3Rlc3RzdWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgtOS5jIGIvZ2NjL3Rlc3Rz dWl0ZS9jLWMrKy1jb21tb24vcHIxMDM3OTgtOS5jCm5ldyBmaWxlIG1vZGUgMTAwNjQ0CmluZGV4 IDAwMDAwMDAwMDAwLi5jNWYwZjk0YTRiNQotLS0gL2Rldi9udWxsCisrKyBiL2djYy90ZXN0c3Vp dGUvYy1jKystY29tbW9uL3ByMTAzNzk4LTkuYwpAQCAtMCwwICsxLDEwIEBACisvKiB7IGRnLWRv IGNvbXBpbGUgfSAqLworLyogeyBkZy1vcHRpb25zICItT3MgLWZkdW1wLXRyZWUtb3B0aW1pemVk IC1zYXZlLXRlbXBzIiB9ICovCisKK2ludAorZiAoY2hhciBhKQoreworICByZXR1cm4gIF9fYnVp bHRpbl9tZW1jaHIgKCJhIiwgYSwgMSkgPT0gMDsKK30KKworLyogeyBkZy1maW5hbCB7IHNjYW4t YXNzZW1ibGVyLW5vdCAibWVtY2hyIiB9IH0gKi8KZGlmZiAtLWdpdCBhL2djYy90cmVlLXNzYS1m b3J3cHJvcC5jYyBiL2djYy90cmVlLXNzYS1mb3J3cHJvcC5jYwppbmRleCA2OTU2N2FiMzI3NS4u ZmRjNGJjODkwOWQgMTAwNjQ0Ci0tLSBhL2djYy90cmVlLXNzYS1mb3J3cHJvcC5jYworKysgYi9n Y2MvdHJlZS1zc2EtZm9yd3Byb3AuY2MKQEAgLTQyLDYgKzQyLDcgQEAgYWxvbmcgd2l0aCBHQ0M7 IHNlZSB0aGUgZmlsZSBDT1BZSU5HMy4gIElmIG5vdCBzZWUKICNpbmNsdWRlICJ0cmVlLWRmYS5o IgogI2luY2x1ZGUgInRyZWUtc3NhLXByb3BhZ2F0ZS5oIgogI2luY2x1ZGUgInRyZWUtc3NhLWRv bS5oIgorI2luY2x1ZGUgInRyZWUtc3NhLXN0cmxlbi5oIgogI2luY2x1ZGUgImJ1aWx0aW5zLmgi CiAjaW5jbHVkZSAidHJlZS1jZmdjbGVhbnVwLmgiCiAjaW5jbHVkZSAiY2ZnYW5hbC5oIgpAQCAt MTE3Nyw2ICsxMTc4LDE1IEBAIGNvbnN0YW50X3BvaW50ZXJfZGlmZmVyZW5jZSAodHJlZSBwMSwg dHJlZSBwMikKICAgIG1lbWNweSAocCwgImFiY2QgICAiLCA3KTsKICAgIGNhbGwgaWYgdGhlIGxh dHRlciBjYW4gYmUgc3RvcmVkIGJ5IHBpZWNlcyBkdXJpbmcgZXhwYW5zaW9uLgogCisgICBPcHRp bWl6ZQorICAgbWVtY2hyICgiYWJjZCIsIGEsIDQpID09IDA7CisgICBvcgorICAgbWVtY2hyICgi YWJjZCIsIGEsIDQpICE9IDA7CisgICB0bworICAgKGEgPT0gJ2EnIHx8IGEgPT0gJ2InIHx8IGEg PT0gJ2MnIHx8IGEgPT0gJ2QnKSA9PSAwCisgICBvcgorICAgKGEgPT0gJ2EnIHx8IGEgPT0gJ2In IHx8IGEgPT0gJ2MnIHx8IGEgPT0gJ2QnKSAhPSAwCisKICAgIEFsc28gY2Fub25pY2FsaXplIF9f YXRvbWljX2ZldGNoX29wIChwLCB4LCB5KSBvcCB4CiAgICB0byBfX2F0b21pY19vcF9mZXRjaCAo cCwgeCwgeSkgb3IKICAgIF9fYXRvbWljX29wX2ZldGNoIChwLCB4LCB5KSBpb3AgeApAQCAtMTE5 Myw4ICsxMjAzLDcwIEBAIHNpbXBsaWZ5X2J1aWx0aW5fY2FsbCAoZ2ltcGxlX3N0bXRfaXRlcmF0 b3IgKmdzaV9wLCB0cmVlIGNhbGxlZTIpCiAgICAgcmV0dXJuIGZhbHNlOwogICBzdG10MSA9IFNT QV9OQU1FX0RFRl9TVE1UICh2dXNlKTsKIAorICB0cmVlIHJlczsKKwogICBzd2l0Y2ggKERFQ0xf RlVOQ1RJT05fQ09ERSAoY2FsbGVlMikpCiAgICAgeworICAgIGNhc2UgQlVJTFRfSU5fTUVNQ0hS OgorICAgICAgaWYgKGdpbXBsZV9jYWxsX251bV9hcmdzIChzdG10MikgPT0gMworCSAgJiYgKHJl cyA9IGdpbXBsZV9jYWxsX2xocyAoc3RtdDIpKSAhPSBudWxscHRyCisJICAmJiB1c2VfaW5femVy b19lcXVhbGl0eSAocmVzKSAhPSBudWxscHRyCisJICAmJiBDSEFSX0JJVCA9PSA4CisJICAmJiBC SVRTX1BFUl9VTklUID09IDgpCisJeworCSAgdHJlZSBwdHIgPSBnaW1wbGVfY2FsbF9hcmcgKHN0 bXQyLCAwKTsKKwkgIGlmIChUUkVFX0NPREUgKHB0cikgIT0gQUREUl9FWFBSCisJICAgICAgfHwg VFJFRV9DT0RFIChUUkVFX09QRVJBTkQgKHB0ciwgMCkpICE9IFNUUklOR19DU1QpCisJICAgIGJy ZWFrOworCSAgdW5zaWduZWQgSE9TVF9XSURFX0lOVCBzbGVuCisJICAgID0gVFJFRV9TVFJJTkdf TEVOR1RIIChUUkVFX09QRVJBTkQgKHB0ciwgMCkpOworCSAgLyogSXQgbXVzdCBiZSBhIG5vbi1l bXB0eSBzdHJpbmcgY29uc3RhbnQuICAqLworCSAgaWYgKHNsZW4gPCAyKQorCSAgICBicmVhazsK KwkgIC8qIEZvciAtT3MsIG9ubHkgc2ltcGxpZnkgc3RyaW5ncyB3aXRoIGEgc2luZ2xlIGNoYXJh Y3Rlci4gICovCisJICBpZiAoIW9wdGltaXplX2JiX2Zvcl9zcGVlZF9wIChnaW1wbGVfYmIgKHN0 bXQyKSkKKwkgICAgICAmJiBzbGVuID4gMikKKwkgICAgYnJlYWs7CisJICB0cmVlIHNpemUgPSBn aW1wbGVfY2FsbF9hcmcgKHN0bXQyLCAyKTsKKwkgIC8qIFNpemUgbXVzdCBiZSBhIGNvbnN0YW50 IHdoaWNoIGlzIDw9IFVOSVRTX1BFUl9XT1JEIGFuZAorCSAgICAgPD0gdGhlIHN0cmluZyBsZW5n dGguICAqLworCSAgaWYgKFRSRUVfQ09ERSAoc2l6ZSkgIT0gSU5URUdFUl9DU1QgfHwgaW50ZWdl cl96ZXJvcCAoc2l6ZSkpCisJICAgIGJyZWFrOworCisJICBpZiAoIXRyZWVfZml0c191aHdpX3Ag KHNpemUpKQorCSAgICBicmVhazsKKworCSAgdW5zaWduZWQgSE9TVF9XSURFX0lOVCBzeiA9IHRy ZWVfdG9fdWh3aSAoc2l6ZSk7CisJICBpZiAoc3ogPiBVTklUU19QRVJfV09SRCB8fCBzeiA+PSBz bGVuKQorCSAgICBicmVhazsKKworCSAgdHJlZSBjaCA9IGdpbXBsZV9jYWxsX2FyZyAoc3RtdDIs IDEpOworCSAgbG9jYXRpb25fdCBsb2MgPSBnaW1wbGVfbG9jYXRpb24gKHN0bXQyKTsKKwkgIGlm ICghdXNlbGVzc190eXBlX2NvbnZlcnNpb25fcCAoY2hhcl90eXBlX25vZGUsCisJCQkJCSAgVFJF RV9UWVBFIChjaCkpKQorCSAgICBjaCA9IGZvbGRfY29udmVydF9sb2MgKGxvYywgY2hhcl90eXBl X25vZGUsIGNoKTsKKwkgIGNvbnN0IGNoYXIgKnAgPSBUUkVFX1NUUklOR19QT0lOVEVSIChUUkVF X09QRVJBTkQgKHB0ciwgMCkpOworCSAgdW5zaWduZWQgaW50IGlzaXplID0gc3o7CisJICB0cmVl ICpvcCA9IFhBTExPQ0FWRUMgKHRyZWUsIGlzaXplKTsKKwkgIGZvciAodW5zaWduZWQgaW50IGkg PSAwOyBpIDwgaXNpemU7IGkrKykKKwkgICAgeworCSAgICAgIG9wW2ldID0gYnVpbGRfaW50X2Nz dCAoY2hhcl90eXBlX25vZGUsIHBbaV0pOworCSAgICAgIG9wW2ldID0gZm9sZF9idWlsZDJfbG9j IChsb2MsIEVRX0VYUFIsIGJvb2xlYW5fdHlwZV9ub2RlLAorCQkJCSAgICAgICBvcFtpXSwgY2gp OworCSAgICB9CisJICBmb3IgKHVuc2lnbmVkIGludCBpID0gaXNpemUgLSAxOyBpID49IDE7IGkt LSkKKwkgICAgb3BbaSAtIDFdID0gZm9sZF9jb252ZXJ0X2xvYyAobG9jLCBib29sZWFuX3R5cGVf bm9kZSwKKwkJCQkJICBmb2xkX2J1aWxkMl9sb2MgKGxvYywKKwkJCQkJCQkgICBCSVRfSU9SX0VY UFIsCisJCQkJCQkJICAgYm9vbGVhbl90eXBlX25vZGUsCisJCQkJCQkJICAgb3BbaSAtIDFdLAor CQkJCQkJCSAgIG9wW2ldKSk7CisJICByZXMgPSBmb2xkX2NvbnZlcnRfbG9jIChsb2MsIFRSRUVf VFlQRSAocmVzKSwgb3BbMF0pOworCSAgZ2ltcGxpZnlfYW5kX3VwZGF0ZV9jYWxsX2Zyb21fdHJl ZSAoZ3NpX3AsIHJlcyk7CisJICByZXR1cm4gdHJ1ZTsKKwl9CisgICAgICBicmVhazsKKwogICAg IGNhc2UgQlVJTFRfSU5fTUVNU0VUOgogICAgICAgaWYgKGdpbXBsZV9jYWxsX251bV9hcmdzIChz dG10MikgIT0gMwogCSAgfHwgZ2ltcGxlX2NhbGxfbGhzIChzdG10MikKZGlmZiAtLWdpdCBhL2dj Yy90cmVlLXNzYS1zdHJsZW4uY2MgYi9nY2MvdHJlZS1zc2Etc3RybGVuLmNjCmluZGV4IDdiM2Uz ODk5ZWEyLi41YWZiYWUxYjcyZSAxMDA2NDQKLS0tIGEvZ2NjL3RyZWUtc3NhLXN0cmxlbi5jYwor KysgYi9nY2MvdHJlZS1zc2Etc3RybGVuLmNjCkBAIC0zOTEzLDggKzM5MTMsOCBAQCBzdHJsZW5f cGFzczo6aGFuZGxlX2J1aWx0aW5fbWVtc2V0IChib29sICp6ZXJvX3dyaXRlKQogICAgbm9ubnVs bCBpZiBhbmQgb25seSBSRVMgaXMgdXNlZCBpbiBzdWNoIGV4cHJlc3Npb25zIGV4Y2x1c2l2ZWx5 IGFuZAogICAgaW4gbm9uZSBvdGhlci4gICovCiAKLXN0YXRpYyBnaW1wbGUgKgotdXNlX2luX3pl cm9fZXF1YWxpdHkgKHRyZWUgcmVzLCBib29sIGV4Y2x1c2l2ZSA9IHRydWUpCitnaW1wbGUgKgor dXNlX2luX3plcm9fZXF1YWxpdHkgKHRyZWUgcmVzLCBib29sIGV4Y2x1c2l2ZSkKIHsKICAgZ2lt cGxlICpmaXJzdF91c2UgPSBOVUxMOwogCmRpZmYgLS1naXQgYS9nY2MvdHJlZS1zc2Etc3RybGVu LmggYi9nY2MvdHJlZS1zc2Etc3RybGVuLmgKaW5kZXggOGQxNTU0NTBkYjguLmZkYjRkOWQ3Nzgz IDEwMDY0NAotLS0gYS9nY2MvdHJlZS1zc2Etc3RybGVuLmgKKysrIGIvZ2NjL3RyZWUtc3NhLXN0 cmxlbi5oCkBAIC0zNSw2ICszNSw4IEBAIHN0cnVjdCBjX3N0cmxlbl9kYXRhOwogZXh0ZXJuIHZv aWQgZ2V0X3JhbmdlX3N0cmxlbl9keW5hbWljICh0cmVlLCBnaW1wbGUgKiwgY19zdHJsZW5fZGF0 YSAqLAogCQkJCSAgICAgIHBvaW50ZXJfcXVlcnkgJik7CiAKK2V4dGVybiBnaW1wbGUgKnVzZV9p bl96ZXJvX2VxdWFsaXR5ICh0cmVlLCBib29sID0gdHJ1ZSk7CisKIC8qIEFQSXMgaW50ZXJuYWwg dG8gc3RybGVuIHBhc3MuICBEZWZpbmVkIGluIGdpbXBsZS1zc2Etc3ByaW50Zi5jYy4gICovCiBl eHRlcm4gYm9vbCBoYW5kbGVfcHJpbnRmX2NhbGwgKGdpbXBsZV9zdG10X2l0ZXJhdG9yICosIHBv aW50ZXJfcXVlcnkgJik7CiAKLS0gCjIuMzYuMQoK --00000000000089ccd705e3ca525d--