From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: =?UTF-8?Q?Augustin_Ch=C3=A9neau_=28BTuin=29?= Newsgroups: gmane.emacs.devel Subject: Re: New tree-sitter mode: bison-ts-mode Date: Fri, 22 Sep 2023 16:53:08 +0200 Message-ID: <97f90014-6507-44ac-a61c-4e74d058063f@mailo.com> References: <871qeqwtbk.fsf@posteo.net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------hBY0UnMiJYIdKg2TfC9Agd20" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="3339"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Mozilla Thunderbird Cc: emacs-devel To: Philip Kaludercic Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Fri Sep 22 16:54:56 2023 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qjhYV-0000Zz-Hq for ged-emacs-devel@m.gmane-mx.org; Fri, 22 Sep 2023 16:54:55 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qjhXH-00058Q-P2; Fri, 22 Sep 2023 10:53:39 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qjhX2-0004uo-TO for emacs-devel@gnu.org; Fri, 22 Sep 2023 10:53:28 -0400 Original-Received: from msg-1.mailo.com ([213.182.54.11]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qjhWx-00011P-9n for emacs-devel@gnu.org; Fri, 22 Sep 2023 10:53:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=mailo.com; s=mailo; t=1695394389; bh=Rbtp1Ej5SMIcH9cYyB/HwDZ8xiFgBGyYsrIzoh1OHV0=; h=X-EA-Auth:Content-Type:Message-ID:Date:MIME-Version:Subject:To:Cc: References:From:In-Reply-To; b=hbkn87F5pgg60QqWwgVudkFJxCAVPP4MQc0o4RcUpMwk5e4s+TR7Q6S2G7Fi0EeEA zkhi3AYXcCzLogTFgtauJ3WVlbQ3QplzF67acrfRNsRtTPwe2gZrYOfG0gmCCtbD6x Bm6HHndKvyA0K14WZo1Gun4IrEJC7Q48zYFgDMk8= Original-Received: by b221-5.in.mailobj.net [192.168.90.25] with ESMTP via ip-20.mailobj.net [213.182.54.20] Fri, 22 Sep 2023 16:53:09 +0200 (CEST) X-EA-Auth: t0xBG7b5TdgWI01rxYXbnVQ5ntvbHsU/waGYDEbXdWkpgkk+uQewY93A9vBlC2GgAFOi92/pCtrycyQBYJ2inKMmlJ2o4OJy Content-Language: fr, en-US In-Reply-To: <871qeqwtbk.fsf@posteo.net> Received-SPF: pass client-ip=213.182.54.11; envelope-from=btuin@mailo.com; helo=msg-1.mailo.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:310971 Archived-At: This is a multi-part message in MIME format. --------------hBY0UnMiJYIdKg2TfC9Agd20 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit Le 22/09/2023 à 09:38, Philip Kaludercic a écrit : > "Augustin Chéneau (BTuin)" writes: > > A few comments on the proposed file: > >> ;;; bison-ts-mode --- Tree-sitter mode for Bison -*- lexical-binding: t; -*- >> > Could you add the usual header information here? > > ;; Copyright (C) 2022-2023 Free Software Foundation, Inc. > > --8<---------------cut here---------------start------------->8--- > ;; Author: Augustin Chéneau > > ;; This file is part of GNU Emacs. > > ;; GNU Emacs is free software: you can redistribute it and/or modify > ;; it under the terms of the GNU General Public License as published by > ;; the Free Software Foundation, either version 3 of the License, or > ;; (at your option) any later version. > > ;; GNU Emacs 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 GNU Emacs. If not, see . > --8<---------------cut here---------------end--------------->8--- > >> ;;; Commentary: >> >> ;; This is a mode based on tree-sitter for Bison and Yacc files, tools to generate parsers. > > Shouldn't you mention what tree sitter grammar is being being used here? > >> ;;; Code: >> >> (require 'treesit) >> (require 'c-ts-common) >> >> (declare-function treesit-parser-create "treesit.c") >> (declare-function treesit-induce-sparse-tree "treesit.c") >> (declare-function treesit-node-child-by-field-name "treesit.c") >> (declare-function treesit-search-subtree "treesit.c") >> (declare-function treesit-node-parent "treesit.c") >> (declare-function treesit-node-next-sibling "treesit.c") >> (declare-function treesit-node-type "treesit.c") >> (declare-function treesit-node-child "treesit.c") >> (declare-function treesit-node-end "treesit.c") >> (declare-function treesit-node-start "treesit.c") >> (declare-function treesit-node-string "treesit.c") >> (declare-function treesit-query-compile "treesit.c") >> (declare-function treesit-query-capture "treesit.c") >> (declare-function treesit-parser-add-notifier "treesit.c") >> (declare-function treesit-parser-buffer "treesit.c") >> (declare-function treesit-parser-list "treesit.c") >> >> >> (defgroup bison nil > > bison or bison-ts? > As far as I know, no group is explicitly reserved for tree-sitter. rust-ts-mode uses the group "rust", java-ts-mode uses "java", ruby-ts-mode uses "ruby"... >> "Support for Bison and Yacc." > > Shouldn't tree-sitter be mentioned here? > Same as above. >> :group 'languages) >> >> (defcustom bison-ts-mode-indent-offset 2 >> "Number of spaces for each indentation step in `bison-ts-mode'. >> It has no effect in the epilogue part of the file." >> :version "30.1" >> :type 'integer >> :safe 'integerp >> :group 'bison) >> >> (defcustom bison-ts-mode-autodetect-language t >> "Search for a %language directive in the file at initialization. >> Changing the value of this directive in the file requires to reload the mode to >> be effective. If `bison-ts-mode-buffer-language' is set by a file-local >> variable, the auto-detection is not run." >> :version "30.1" >> :type 'boolean >> :safe 'boolean >> :group 'bison) >> >> (defvar-local bison-ts-mode-embedded-language nil >> "Embedded language in Bison buffer.") >> >> (defun bison-ts-mode--merge-feature-lists (l1 l2) >> "Merge the lists of lists L1 and L2. >> The first sublist of L1 is merged with the first sublist of L2 and so on. >> L1 and L2 don't need to have the same size." >> (let ((res ())) >> (while (or l1 l2) >> (setq res (push (append (car l1) (car l2)) res)) >> (setq l1 (cdr l1) l2 (cdr l2))) >> (nreverse res))) > > Is this a generic function that should be extracted into some common file? > It probably should, it could be useful for other *-ts-mode that want to mix multiple languages, unless there already is such a function in Elisp. >> (defun bison-ts-mode--find-language-in-buffer (&optional buffer) >> "Find and return the language set by the Bison directive %language. >> If BUFFER is set, search in this buffer, otherwise search in the current >> buffer." >> (save-excursion >> (when buffer >> (switch-to-buffer buffer)) > > Or rather? > > (with-current-buffer (or buffer (current-buffer)) > (save-excursion > ...)) > >> (goto-char (point-min)) >> (let ((pos-end >> (re-search-forward >> (rx >> bol (0+ blank) "%language" (0+ blank) "\"" (1+ (in alpha "+")) "\"") >> nil >> t)) >> (pos-beg nil)) >> (when pos-end > > Using when-let might be nice here. > >> (goto-char (1- pos-end)) >> (setq pos-beg (1+ (search-backward "\"" nil t))) >> (buffer-substring-no-properties pos-beg (1- pos-end)))))) > > I'd use a single regular expression here with a group, then extract the > right information using `match-string'. > Nice, I didn't know it was possible. >> >> >> (defun bison-ts-mode--detect-language (&optional buffer) >> "Dectect the embedded language in a Bison buffer. >> Known languages are C, C++, D, and Java, but D is not supported as there is >> no support for tree-sitter D in Emacs yet. >> If BUFFER is set, search in this buffer, otherwise search in the current >> buffer." >> (if-let ((str (bison-ts-mode--find-language-in-buffer buffer))) >> (pcase (downcase str) >> ("c" 'c) >> ("c++" 'cpp) >> ("d" (progn (message "D language not yet supported") nil)) > > Each pcase case has an implicit progn. > >> ("java" 'java)) >> (progn > > Use when-let to avoid this progn. > >> (message >> "bison-ts-mode: %%language specification not found or invalid, defaulting to C.") > > Is it necessary to prefix the message with the major mode name? > If feared it would be a bit cryptic without. Anyway I modified this function to only display a message if "%language" is present but the language is invalid, so it probably isn't necessary anymore. >> 'c))) >> >> >> (defun bison-ts-mode--language-at-point-function (position) >> "Return the language at POSITION." >> (let* ((node (treesit-node-at position 'bison))) > ^ > let is enough > >> (if (equal (treesit-node-type node) >> "embedded_code") > > There is no need to break the line here. > >> bison-ts-mode-embedded-language >> 'bison))) >> >> (defun bison-ts-mode--font-lock-settings (language) >> "Return the font-lock settings for Bison. >> LANGUAGE should be set to \\='bison." >> (treesit-font-lock-rules >> :language language >> :feature 'bison-comment >> '((comment) @font-lock-comment-face) >> >> :language language >> :feature 'bison-declaration >> '((declaration_name) @font-lock-keyword-face) >> >> :language language >> :feature 'bison-type >> '((type) @font-lock-type-face) >> >> :language language >> :feature 'bison-grammar-rule-usage >> '((grammar_rule_identifier) @font-lock-variable-use-face) >> >> :language language >> :feature 'bison-grammar-rule-declaration >> '((grammar_rule (grammar_rule_declaration) >> @font-lock-variable-use-face)) >> >> :language language >> :feature 'bison-string >> :override t >> '((string) @font-lock-string-face) >> >> :language language >> :feature 'bison-literal >> :override t >> '((char_literal) @font-lock-keyword-face >> (number_literal) @font-lock-number-face) >> >> :language language >> :feature 'bison-directive-grammar-rule >> :override t >> '((grammar_rule (directive) @font-lock-keyword-face)) >> >> :language language >> :feature 'bison-operator >> :override t >> '(["|"] @font-lock-operator-face) >> >> :language language >> :feature 'bison-delimiter >> :override t >> '([";"] @font-lock-delimiter-face))) >> >> >> (defvar bison-ts-mode--font-lock-feature-list >> '(( bison-comment bison-declaration bison-type >> bison-grammar-rule-usage bison-grammar-rule-declaration >> bison-string bison-literal bison-directive-grammar-rule >> bison-operator bison-delimiter))) >> >> >> (defun bison-ts-mode--bison-matcher-action (root-name) >> "Treesit matcher to check if NODE at BOL is not located in the epilogue. >> ROOT-NAME is the highest-level node of the embedded language." >> (lambda (node _parent bol &rest _) >> (if (equal (treesit-node-type (treesit-node-parent node)) root-name) >> (let* ((bison-node (treesit-node-at bol 'bison))) > ^ > here again, let is enough > > (if (equal >> (treesit-node-type >> (treesit-node-parent(treesit-node-parent bison-node))) "action") > > Though you could bind the (treesit-node-type ...) expression under the > above let. > >> t >> nil))))) > > Why (if foo t nil) when foo would do the same job (equal only returns > nil and t, so normalising the value isn't even necessary). > Because I was stupid. >> >> (defun bison-ts-mode--bison-matcher-not-epilogue (root-name) >> "Treesit matcher to check if NODE at BOL is not located in the epilogue. >> ROOT-NAME is the highest-level node of the embedded language." >> (lambda (node _parent bol &rest _) >> (if (equal (treesit-node-type (treesit-node-parent node)) root-name) >> (let* ((bison-node (treesit-node-at bol 'bison))) >> (if (equal (treesit-node-type (treesit-node-parent bison-node)) "epilogue") >> nil >> t))))) > > Am I missing something, or couldn't these two functions be merged if you > give them a third argument NODE-TYPE and pass it "action" or "epilogue". > No, bison-ts-mode--bison-matcher-action checks if the _grandparent_ is an "action" node, while bison-ts-mode--bison-matcher-not-epilogue checks if the _parent_ is an "epilogue" node. >> >> >> (defun bison-ts-mode--bison-parent (_node _parent bol &rest _) >> "Get the parent of the bison node at BOL." >> (treesit-node-start (treesit-node-parent (treesit-node-at bol 'bison)))) >> >> >> (defun bison-ts-mode--indent-rules () >> "Indent rules supported by `bison-ts-mode'." >> (let* >> ((common >> `(((node-is "^declaration$") >> column-0 0) >> ((and (parent-is "^declaration$") >> (not (node-is "^code_block$"))) >> column-0 2) >> ((and (parent-is "comment") c-ts-common-looking-at-star) >> c-ts-common-comment-start-after-first-star -1) >> (c-ts-common-comment-2nd-line-matcher >> c-ts-common-comment-2nd-line-anchor >> 1) >> ((parent-is "comment") prev-adaptive-prefix 0) >> >> ;; Opening and closing brackets "{}" of declarations >> ((and (parent-is "^declaration$") >> (node-is "^code_block$")) >> column-0 0) >> ((and (n-p-gp "}" "" "^declaration$")) >> column-0 0) >> ((parent-is "^declaration$") parent 2) >> ((node-is "^grammar_rule$") column-0 0) >> ((and >> (parent-is "^grammar_rule$") >> (node-is ";")) >> column-0 bison-ts-mode-indent-offset) >> ((and (parent-is "^grammar_rule$") >> (node-is "|")) >> column-0 bison-ts-mode-indent-offset) >> ((and (parent-is "^grammar_rule$") >> (not (node-is "^grammar_rule_declaration$")) >> (not (node-is "^action$"))) >> column-0 ,(+ bison-ts-mode-indent-offset 2)) >> ((or >> (node-is "^action$") >> (node-is "^}$")) >> column-0 12) >> ;; Set '%%' at the beginning of the line >> ((or >> (and (parent-is "^grammar_rules_section$") >> (node-is "%%")) >> (node-is "^grammar_rules_section$")) >> column-0 0) >> (no-node parent-bol 0)))) >> `((bison . ,common) >> ;; Import and override embedded languages rules to add an offset >> ,(pcase bison-ts-mode-embedded-language >> ('c `(c >> ((bison-ts-mode--bison-matcher-action "translation_unit") >> bison-ts-mode--bison-parent ,bison-ts-mode-indent-offset) >> ((bison-ts-mode--bison-matcher-not-epilogue "translation_unit") >> column-0 ,bison-ts-mode-indent-offset) >> ,@(alist-get 'c (c-ts-mode--get-indent-style 'c)))) >> ('cpp `(cpp >> ((bison-ts-mode--bison-matcher-action "translation_unit") >> bison-ts-mode--bison-parent ,bison-ts-mode-indent-offset) >> ((bison-ts-mode--bison-matcher-not-epilogue "translation_unit") >> parent-0 ,bison-ts-mode-indent-offset) >> ,@(alist-get 'cpp (c-ts-mode--get-indent-style 'cpp)))) >> ('java `(java >> ((bison-ts-mode--bison-matcher-action "program") >> bison-ts-mode--bison-parent ,bison-ts-mode-indent-offset) >> ((bison-ts-mode--bison-matcher-not-epilogue "program") >> column-0 ,bison-ts-mode-indent-offset) >> ,@java-ts-mode--indent-rules)))))) >> >> >> (define-derived-mode bison-ts-mode prog-mode "Bison" >> "A mode for Bison." > ^ > major-mode > > Also, mentioning tree-sitter seems like something worth doing. > >> (when (treesit-ready-p 'bison) >> (when (not bison-ts-mode-embedded-language) >> (setq bison-ts-mode-embedded-language (bison-ts-mode--detect-language))) >> >> ;; Require only if needed, to avoid warnings if a grammar is not >> ;; installed but not used. >> (pcase bison-ts-mode-embedded-language > > Would a `pcase-exhaustive' be appropriate here? > No, the language D is recognized but not supported yet in Emacs, so if this language is detected it will not configure anything. >> ('c (require 'c-ts-mode)) >> ('cpp (require 'c-ts-mode)) >> ('java (require 'java-ts-mode))) >> >> (setq-local treesit-font-lock-settings >> (append (bison-ts-mode--font-lock-settings 'bison) >> (pcase bison-ts-mode-embedded-language >> ('c (c-ts-mode--font-lock-settings 'c)) >> ('cpp (c-ts-mode--font-lock-settings 'cpp)) >> ('java java-ts-mode--font-lock-settings)))) >> >> (setq-local treesit-font-lock-feature-list >> (if bison-ts-mode-embedded-language >> (bison-ts-mode--merge-feature-lists >> bison-ts-mode--font-lock-feature-list >> (pcase bison-ts-mode-embedded-language >> ('c c-ts-mode--feature-list) >> ('cpp c-ts-mode--feature-list) >> ('java java-ts-mode--feature-list))) >> bison-ts-mode--font-lock-feature-list)) >> >> (setq-local treesit-simple-imenu-settings >> `(("Grammar" >> "\\`grammar_rule_declaration\\'" >> nil >> (lambda (node) (substring-no-properties (treesit-node-text node)))))) >> >> (c-ts-common-comment-setup) >> >> (setq-local treesit-simple-indent-rules >> (bison-ts-mode--indent-rules)) >> >> (setq-local treesit-language-at-point-function 'bison-ts-mode--language-at-point-function) >> >> (when bison-ts-mode-embedded-language >> (setq-local treesit-range-settings >> (treesit-range-rules >> :embed bison-ts-mode-embedded-language >> :host 'bison >> :local t >> '((embedded_code) @capture)))) >> >> (treesit-major-mode-setup))) >> >> (provide 'bison-ts-mode) >> ;;; bison-ts-mode.el ends here > > Sorry for the number of comments, but there has been a discussion on the > code-quality of tree-sitter major modes that has been less than optimal, > so I hope that your contribution could help raise the bar. No problem, thank you for your review! You can find the updated mode attached. I've added `bison-ts-mode-embedded-language' to `safe-local-variable' with: (defvar-local bison-ts-mode-embedded-language nil "Embedded language in Bison buffer. Supported values are `c', `cpp', and `java'.") ;;;###autoload (put 'bison-ts-mode-embedded-language 'safe-local-variable 'symbolp) By the way I have sent the mail for the copyright assignment. --------------hBY0UnMiJYIdKg2TfC9Agd20 Content-Type: text/x-emacs-lisp; charset=UTF-8; name="bison-ts-mode.el" Content-Disposition: attachment; filename="bison-ts-mode.el" Content-Transfer-Encoding: base64 Ozs7IGJpc29uLXRzLW1vZGUgLS0tIHRyZWUtc2l0dGVyIHN1cHBvcnQgZm9yIEJpc29uIC0q LSBsZXhpY2FsLWJpbmRpbmc6IHQ7IC0qLQoKOzsgQ29weXJpZ2h0IChDKSAyMDIzIEZyZWUg U29mdHdhcmUgRm91bmRhdGlvbiwgSW5jLgoKOzsgQXV0aG9yICAgOiBBdWd1c3RpbiBDaMOp bmVhdSA8YnR1aW5AbWFpbG8uY29tPgo7OyBLZXl3b3JkcyA6IGJpc29uIHlhY2MgbGFuZ3Vh Z2VzIHRyZWUtc2l0dGVyCgo7OyBUaGlzIGZpbGUgaXMgcGFydCBvZiBHTlUgRW1hY3MuCgo7 OyBHTlUgRW1hY3MgaXMgZnJlZSBzb2Z0d2FyZTogeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQg YW5kL29yIG1vZGlmeQo7OyBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFs IFB1YmxpYyBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieQo7OyB0aGUgRnJlZSBTb2Z0d2FyZSBG b3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvcgo7OyAoYXQg eW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLgoKOzsgR05VIEVtYWNzIGlzIGRpc3Ry aWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsCjs7IGJ1dCBXSVRI T1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9m Cjs7IE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9T RS4gIFNlZSB0aGUKOzsgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0 YWlscy4KCjs7IFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBH ZW5lcmFsIFB1YmxpYyBMaWNlbnNlCjs7IGFsb25nIHdpdGggR05VIEVtYWNzLiAgSWYgbm90 LCBzZWUgPGh0dHBzOi8vd3d3LmdudS5vcmcvbGljZW5zZXMvPi4KCjs7OyBDb21tZW50YXJ5 OgoKOzsgVGhpcyBpcyBhIG1vZGUgYmFzZWQgb24gdHJlZS1zaXR0ZXIgZm9yIEJpc29uIGFu ZCBZYWNjIGZpbGVzLCB0b29scyB0bwo7OyBnZW5lcmF0ZSBwYXJzZXJzLiAgVGhlIGdyYW1t YXIgdXNlZCBpcyBhdmFpbGFibGUgaGVyZToKOzsgaHR0cHM6Ly9naXRsYWIuY29tL2J0dWlu Mi90cmVlLXNpdHRlci1iaXNvbgoKOzs7IENvZGU6CgoocmVxdWlyZSAndHJlZXNpdCkKKHJl cXVpcmUgJ2MtdHMtY29tbW9uKQoKKGRlY2xhcmUtZnVuY3Rpb24gdHJlZXNpdC1wYXJzZXIt Y3JlYXRlICJ0cmVlc2l0LmMiKQooZGVjbGFyZS1mdW5jdGlvbiB0cmVlc2l0LWluZHVjZS1z cGFyc2UtdHJlZSAidHJlZXNpdC5jIikKKGRlY2xhcmUtZnVuY3Rpb24gdHJlZXNpdC1ub2Rl LWNoaWxkLWJ5LWZpZWxkLW5hbWUgInRyZWVzaXQuYyIpCihkZWNsYXJlLWZ1bmN0aW9uIHRy ZWVzaXQtc2VhcmNoLXN1YnRyZWUgInRyZWVzaXQuYyIpCihkZWNsYXJlLWZ1bmN0aW9uIHRy ZWVzaXQtbm9kZS1wYXJlbnQgInRyZWVzaXQuYyIpCihkZWNsYXJlLWZ1bmN0aW9uIHRyZWVz aXQtbm9kZS1uZXh0LXNpYmxpbmcgInRyZWVzaXQuYyIpCihkZWNsYXJlLWZ1bmN0aW9uIHRy ZWVzaXQtbm9kZS10eXBlICJ0cmVlc2l0LmMiKQooZGVjbGFyZS1mdW5jdGlvbiB0cmVlc2l0 LW5vZGUtY2hpbGQgInRyZWVzaXQuYyIpCihkZWNsYXJlLWZ1bmN0aW9uIHRyZWVzaXQtbm9k ZS1lbmQgInRyZWVzaXQuYyIpCihkZWNsYXJlLWZ1bmN0aW9uIHRyZWVzaXQtbm9kZS1zdGFy dCAidHJlZXNpdC5jIikKKGRlY2xhcmUtZnVuY3Rpb24gdHJlZXNpdC1ub2RlLXN0cmluZyAi dHJlZXNpdC5jIikKKGRlY2xhcmUtZnVuY3Rpb24gdHJlZXNpdC1xdWVyeS1jb21waWxlICJ0 cmVlc2l0LmMiKQooZGVjbGFyZS1mdW5jdGlvbiB0cmVlc2l0LXF1ZXJ5LWNhcHR1cmUgInRy ZWVzaXQuYyIpCihkZWNsYXJlLWZ1bmN0aW9uIHRyZWVzaXQtcGFyc2VyLWFkZC1ub3RpZmll ciAidHJlZXNpdC5jIikKKGRlY2xhcmUtZnVuY3Rpb24gdHJlZXNpdC1wYXJzZXItYnVmZmVy ICJ0cmVlc2l0LmMiKQooZGVjbGFyZS1mdW5jdGlvbiB0cmVlc2l0LXBhcnNlci1saXN0ICJ0 cmVlc2l0LmMiKQoKCihkZWZncm91cCBiaXNvbi10cyBuaWwKICAiU3VwcG9ydCBmb3IgQmlz b24gYW5kIFlhY2MuIgogIDpncm91cCAnbGFuZ3VhZ2VzKQoKKGRlZmN1c3RvbSBiaXNvbi10 cy1tb2RlLWluZGVudC1vZmZzZXQgMgogICJOdW1iZXIgb2Ygc3BhY2VzIGZvciBlYWNoIGlu ZGVudGF0aW9uIHN0ZXAgaW4gYGJpc29uLXRzLW1vZGUnLgpJdCBoYXMgbm8gZWZmZWN0IGlu IHRoZSBlcGlsb2d1ZSBwYXJ0IG9mIHRoZSBmaWxlLiIKICA6dmVyc2lvbiAiMzAuMSIKICA6 dHlwZSAnaW50ZWdlcgogIDpzYWZlICdpbnRlZ2VycAogIDpncm91cCAnYmlzb24pCgooZGVm Y3VzdG9tIGJpc29uLXRzLW1vZGUtYXV0b2RldGVjdC1sYW5ndWFnZSB0CiAgIlNlYXJjaCBm b3IgYSAlbGFuZ3VhZ2UgZGlyZWN0aXZlIGluIHRoZSBmaWxlIGF0IGluaXRpYWxpemF0aW9u LgpDaGFuZ2luZyB0aGUgdmFsdWUgb2YgdGhpcyBkaXJlY3RpdmUgaW4gdGhlIGZpbGUgcmVx dWlyZXMgdG8gcmVsb2FkIHRoZSBtb2RlIHRvCmJlIGVmZmVjdGl2ZS4gIElmIGBiaXNvbi10 cy1tb2RlLWJ1ZmZlci1sYW5ndWFnZScgaXMgc2V0IGJ5IGEgZmlsZS1sb2NhbAogdmFyaWFi bGUsIHRoZSBhdXRvLWRldGVjdGlvbiBpcyBub3QgcnVuLiIKICA6dmVyc2lvbiAiMzAuMSIK ICA6dHlwZSAnYm9vbGVhbgogIDpzYWZlICdib29sZWFuCiAgOmdyb3VwICdiaXNvbikKCihk ZWZ2YXItbG9jYWwgYmlzb24tdHMtbW9kZS1lbWJlZGRlZC1sYW5ndWFnZSBuaWwKICAiRW1i ZWRkZWQgbGFuZ3VhZ2UgaW4gQmlzb24gYnVmZmVyLgpTdXBwb3J0ZWQgdmFsdWVzIGFyZSBg YycsIGBjcHAnLCBhbmQgYGphdmEnLiIpCjs7OyMjI2F1dG9sb2FkCihwdXQgJ2Jpc29uLXRz LW1vZGUtZW1iZWRkZWQtbGFuZ3VhZ2UgJ3NhZmUtbG9jYWwtdmFyaWFibGUgJ3N5bWJvbHAp CgoKKGRlZnVuIGJpc29uLXRzLW1vZGUtLW1lcmdlLWZlYXR1cmUtbGlzdHMgKGwxIGwyKQog ICJNZXJnZSB0aGUgbGlzdHMgb2YgbGlzdHMgTDEgYW5kIEwyLgpUaGUgZmlyc3Qgc3VibGlz dCBvZiBMMSBpcyBtZXJnZWQgd2l0aCB0aGUgZmlyc3Qgc3VibGlzdCBvZiBMMiBhbmQgc28g b24uCkwxIGFuZCBMMiBkb24ndCBuZWVkIHRvIGhhdmUgdGhlIHNhbWUgc2l6ZS4iCiAgKGxl dCAoKHJlcyAoKSkpCiAgICAod2hpbGUgKG9yIGwxIGwyKQogICAgICAoc2V0cSByZXMgKHB1 c2ggKHNlcS11bmlxIChhcHBlbmQgKGNhciBsMSkgKGNhciBsMikpICdlcSkgcmVzKSkKICAg ICAgKHNldHEgbDEgKGNkciBsMSkgbDIgKGNkciBsMikpKQogICAgKG5yZXZlcnNlIHJlcykp KQoKKGRlZnVuIGJpc29uLXRzLW1vZGUtLWZpbmQtbGFuZ3VhZ2UtaW4tYnVmZmVyICgmb3B0 aW9uYWwgYnVmZmVyKQogICJGaW5kIGFuZCByZXR1cm4gdGhlIGxhbmd1YWdlIHNldCBieSB0 aGUgQmlzb24gZGlyZWN0aXZlICVsYW5ndWFnZS4KSWYgQlVGRkVSIGlzIHNldCwgc2VhcmNo IGluIHRoaXMgYnVmZmVyLCBvdGhlcndpc2Ugc2VhcmNoIGluIHRoZSBjdXJyZW50CmJ1ZmZl ci4iCiAgKHNhdmUtZXhjdXJzaW9uCiAgICAod2l0aC1jdXJyZW50LWJ1ZmZlciAob3IgYnVm ZmVyIChjdXJyZW50LWJ1ZmZlcikpCiAgICAgIChnb3RvLWNoYXIgKHBvaW50LW1pbikpCiAg ICAgICh3aGVuCgkgIChyZS1zZWFyY2gtZm9yd2FyZAoJICAgKHJ4CgkgICAgYm9sICgwKyBi bGFuaykgIiVsYW5ndWFnZSIgKDArIGJsYW5rKSAiXCIiIChncm91cCAoMSsgKGluIGFscGhh ICIrIikpKSAiXCIiKQoJICAgbmlsCgkgICB0KSkpCiAgICAoc3Vic3RyaW5nLW5vLXByb3Bl cnRpZXMgKG1hdGNoLXN0cmluZyAxKSkpKQoKCihkZWZ1biBiaXNvbi10cy1tb2RlLS1kZXRl Y3QtbGFuZ3VhZ2UgKCZvcHRpb25hbCBidWZmZXIpCiAgIkRlY3RlY3QgdGhlIGVtYmVkZGVk IGxhbmd1YWdlIGluIGEgQmlzb24gYnVmZmVyLgpLbm93biBsYW5ndWFnZXMgYXJlIEMsIEMr KywgRCwgYW5kIEphdmEsIGJ1dCBEIGlzIG5vdCBzdXBwb3J0ZWQgYXMgdGhlcmUgaXMKbm8g c3VwcG9ydCBmb3IgdHJlZS1zaXR0ZXIgRCBpbiBFbWFjcyB5ZXQuCklmIEJVRkZFUiBpcyBz ZXQsIHNlYXJjaCBpbiB0aGlzIGJ1ZmZlciwgb3RoZXJ3aXNlIHNlYXJjaCBpbiB0aGUgY3Vy cmVudApidWZmZXIuIgogIChpZi1sZXQgKChzdHIgKGJpc29uLXRzLW1vZGUtLWZpbmQtbGFu Z3VhZ2UtaW4tYnVmZmVyIGJ1ZmZlcikpKQogICAgICAocGNhc2UtZXhoYXVzdGl2ZSAoZG93 bmNhc2Ugc3RyKQogICAgICAgICgiYyIgJ2MpCiAgICAgICAgKCJjKysiICdjcHApCiAgICAg ICAgKCJkIiAobWVzc2FnZSAiRCBsYW5ndWFnZSBub3QgeWV0IHN1cHBvcnRlZCIpIG5pbCkK ICAgICAgICAoImphdmEiICdqYXZhKQoJKF8gKG1lc3NhZ2UgIiUlbGFuZ3VhZ2Ugc3BlY2lm aWNhdGlvbiBcIiVzXCIgaXMgaW52YWxpZCwgZGVmYXVsdGluZyB0byBDIiBzdHIpICdjKSkp KQoKCihkZWZ1biBiaXNvbi10cy1tb2RlLS1sYW5ndWFnZS1hdC1wb2ludC1mdW5jdGlvbiAo cG9zaXRpb24pCiAgIlJldHVybiB0aGUgbGFuZ3VhZ2UgYXQgUE9TSVRJT04uIgogIChsZXQg KChub2RlICh0cmVlc2l0LW5vZGUtYXQgcG9zaXRpb24gJ2Jpc29uKSkpCiAgICAoaWYgKGVx dWFsICh0cmVlc2l0LW5vZGUtdHlwZSBub2RlKSAiZW1iZWRkZWRfY29kZSIpCiAgICAgICAg Ymlzb24tdHMtbW9kZS1lbWJlZGRlZC1sYW5ndWFnZQogICAgICAnYmlzb24pKSkKCihkZWZ1 biBiaXNvbi10cy1tb2RlLS1mb250LWxvY2stc2V0dGluZ3MgKGxhbmd1YWdlKQogICJSZXR1 cm4gdGhlIGZvbnQtbG9jayBzZXR0aW5ncyBmb3IgQmlzb24uCkxBTkdVQUdFIHNob3VsZCBi ZSBzZXQgdG8gXFw9J2Jpc29uLiIKICAodHJlZXNpdC1mb250LWxvY2stcnVsZXMKICAgOmxh bmd1YWdlIGxhbmd1YWdlCiAgIDpmZWF0dXJlICdjb21tZW50CiAgICcoKGNvbW1lbnQpIEBm b250LWxvY2stY29tbWVudC1mYWNlKQoKICAgOmxhbmd1YWdlIGxhbmd1YWdlCiAgIDpmZWF0 dXJlICdkZWNsYXJhdGlvbgogICAnKChkZWNsYXJhdGlvbl9uYW1lKSBAZm9udC1sb2NrLWtl eXdvcmQtZmFjZSkKCiAgIDpsYW5ndWFnZSBsYW5ndWFnZQogICA6ZmVhdHVyZSAndHlwZQog ICAnKCh0eXBlKSBAZm9udC1sb2NrLXR5cGUtZmFjZSkKCiAgIDpsYW5ndWFnZSBsYW5ndWFn ZQogICA6ZmVhdHVyZSAndmFyaWFibGUKICAgJygoZ3JhbW1hcl9ydWxlX2lkZW50aWZpZXIp IEBmb250LWxvY2stdmFyaWFibGUtdXNlLWZhY2UpCgogICA6bGFuZ3VhZ2UgbGFuZ3VhZ2UK ICAgOmZlYXR1cmUgJ2dyYW1tYXItZGVjbGFyYXRpb24KICAgJygoZ3JhbW1hcl9ydWxlIChn cmFtbWFyX3J1bGVfZGVjbGFyYXRpb24pCiAgICAgICAgICAgICAgICAgICBAZm9udC1sb2Nr LXZhcmlhYmxlLXVzZS1mYWNlKSkKCiAgIDpsYW5ndWFnZSBsYW5ndWFnZQogICA6ZmVhdHVy ZSAnc3RyaW5nCiAgIDpvdmVycmlkZSB0CiAgICcoKHN0cmluZykgQGZvbnQtbG9jay1zdHJp bmctZmFjZSkKCiAgIDpsYW5ndWFnZSBsYW5ndWFnZQogICA6ZmVhdHVyZSAnbGl0ZXJhbAog ICA6b3ZlcnJpZGUgdAogICAnKChjaGFyX2xpdGVyYWwpIEBmb250LWxvY2sta2V5d29yZC1m YWNlCiAgICAgKG51bWJlcl9saXRlcmFsKSBAZm9udC1sb2NrLW51bWJlci1mYWNlKQoKICAg Omxhbmd1YWdlIGxhbmd1YWdlCiAgIDpmZWF0dXJlICdkaXJlY3RpdmUtZ3JhbW1hci1ydWxl CiAgIDpvdmVycmlkZSB0CiAgICcoKGdyYW1tYXJfcnVsZSAoZGlyZWN0aXZlKSBAZm9udC1s b2NrLWtleXdvcmQtZmFjZSkpCgogICA6bGFuZ3VhZ2UgbGFuZ3VhZ2UKICAgOmZlYXR1cmUg J29wZXJhdG9yCiAgIDpvdmVycmlkZSB0CiAgICcoWyJ8Il0gQGZvbnQtbG9jay1vcGVyYXRv ci1mYWNlKQoKICAgOmxhbmd1YWdlIGxhbmd1YWdlCiAgIDpmZWF0dXJlICdkZWxpbWl0ZXIK ICAgOm92ZXJyaWRlIHQKICAgJyhbIjsiXSBAZm9udC1sb2NrLWRlbGltaXRlci1mYWNlKSkp CgoKKGRlZnZhciBiaXNvbi10cy1tb2RlLS1mb250LWxvY2stZmVhdHVyZS1saXN0CiAgJygo IGNvbW1lbnQgZGVjbGFyYXRpb24gZ3JhbW1hci1kZWNsYXJhdGlvbikKICAgICggdHlwZSBz dHJpbmcgZGlyZWN0aXZlLWdyYW1tYXItcnVsZSkKICAgICggbGl0ZXJhbCkKICAgICggdmFy aWFibGUgb3BlcmF0b3IgZGVsaW1pdGVyKSkpCgoKKGRlZnVuIGJpc29uLXRzLW1vZGUtLWJp c29uLW1hdGNoZXItYWN0aW9uIChyb290LW5hbWUpCiAgIlRyZWVzaXQgbWF0Y2hlciB0byBj aGVjayBpZiBOT0RFIGF0IEJPTCBpcyBsb2NhdGVkIGluIGFuIGFjdGlvbiBub2RlLgpST09U LU5BTUUgaXMgdGhlIGhpZ2hlc3QtbGV2ZWwgbm9kZSBvZiB0aGUgZW1iZWRkZWQgbGFuZ3Vh Z2UuIgogIChsYW1iZGEgKG5vZGUgX3BhcmVudCBib2wgJnJlc3QgXykKICAgIChpZiAoZXF1 YWwgKHRyZWVzaXQtbm9kZS10eXBlICh0cmVlc2l0LW5vZGUtcGFyZW50IG5vZGUpKSByb290 LW5hbWUpCiAgICAgICAgKGxldCAoKGJpc29uLW5vZGUgKHRyZWVzaXQtbm9kZS1hdCBib2wg J2Jpc29uKSkpCiAgICAgICAgICAoZXF1YWwKICAgICAgICAgICAodHJlZXNpdC1ub2RlLXR5 cGUKICAgICAgICAgICAgKHRyZWVzaXQtbm9kZS1wYXJlbnQgKHRyZWVzaXQtbm9kZS1wYXJl bnQgYmlzb24tbm9kZSkpKQoJICAgImFjdGlvbiIpKSkpKQoKKGRlZnVuIGJpc29uLXRzLW1v ZGUtLWJpc29uLW1hdGNoZXItbm90LWVwaWxvZ3VlIChyb290LW5hbWUpCiAgIlRyZWVzaXQg bWF0Y2hlciB0byBjaGVjayBpZiBOT0RFIGF0IEJPTCBpcyBub3QgbG9jYXRlZCBpbiB0aGUg ZXBpbG9ndWUuClJPT1QtTkFNRSBpcyB0aGUgaGlnaGVzdC1sZXZlbCBub2RlIG9mIHRoZSBl bWJlZGRlZCBsYW5ndWFnZS4iCiAgKGxhbWJkYSAobm9kZSBfcGFyZW50IGJvbCAmcmVzdCBf KQogICAgKGlmIChlcXVhbCAodHJlZXNpdC1ub2RlLXR5cGUgKHRyZWVzaXQtbm9kZS1wYXJl bnQgbm9kZSkpIHJvb3QtbmFtZSkKICAgICAgICAobGV0ICgoYmlzb24tbm9kZSAodHJlZXNp dC1ub2RlLWF0IGJvbCAnYmlzb24pKSkKICAgICAgICAgIChub3QgKGVxdWFsICh0cmVlc2l0 LW5vZGUtdHlwZSAodHJlZXNpdC1ub2RlLXBhcmVudCBiaXNvbi1ub2RlKSkgImVwaWxvZ3Vl IikpKSkpKQoKCihkZWZ1biBiaXNvbi10cy1tb2RlLS1iaXNvbi1wYXJlbnQgKF9ub2RlIF9w YXJlbnQgYm9sICZyZXN0IF8pCiAgIkdldCB0aGUgcGFyZW50IG9mIHRoZSBiaXNvbiBub2Rl IGF0IEJPTC4iCiAgKHRyZWVzaXQtbm9kZS1zdGFydCAodHJlZXNpdC1ub2RlLXBhcmVudCAo dHJlZXNpdC1ub2RlLWF0IGJvbCAnYmlzb24pKSkpCgoKKGRlZnVuIGJpc29uLXRzLW1vZGUt LWluZGVudC1ydWxlcyAoKQogICJJbmRlbnQgcnVsZXMgc3VwcG9ydGVkIGJ5IGBiaXNvbi10 cy1tb2RlJy4iCiAgKGxldCoKICAgICAgKChjb21tb24KICAgICAgICBgKCgobm9kZS1pcyAi XmRlY2xhcmF0aW9uJCIpCiAgICAgICAgICAgY29sdW1uLTAgMCkKICAgICAgICAgICgoYW5k IChwYXJlbnQtaXMgIl5kZWNsYXJhdGlvbiQiKQogICAgICAgICAgICAgICAgKG5vdCAobm9k ZS1pcyAiXmNvZGVfYmxvY2skIikpKQogICAgICAgICAgIGNvbHVtbi0wIDIpCiAgICAgICAg ICAoKGFuZCAocGFyZW50LWlzICJjb21tZW50IikgYy10cy1jb21tb24tbG9va2luZy1hdC1z dGFyKQogICAgICAgICAgIGMtdHMtY29tbW9uLWNvbW1lbnQtc3RhcnQtYWZ0ZXItZmlyc3Qt c3RhciAtMSkKICAgICAgICAgIChjLXRzLWNvbW1vbi1jb21tZW50LTJuZC1saW5lLW1hdGNo ZXIKICAgICAgICAgICBjLXRzLWNvbW1vbi1jb21tZW50LTJuZC1saW5lLWFuY2hvcgogICAg ICAgICAgIDEpCiAgICAgICAgICAoKHBhcmVudC1pcyAiY29tbWVudCIpIHByZXYtYWRhcHRp dmUtcHJlZml4IDApCgogICAgICAgICAgOzsgT3BlbmluZyBhbmQgY2xvc2luZyBicmFja2V0 cyAie30iIG9mIGRlY2xhcmF0aW9ucwogICAgICAgICAgKChhbmQgKHBhcmVudC1pcyAiXmRl Y2xhcmF0aW9uJCIpCiAgICAgICAgICAgICAgICAobm9kZS1pcyAiXmNvZGVfYmxvY2skIikp CiAgICAgICAgICAgY29sdW1uLTAgMCkKICAgICAgICAgICgoYW5kIChuLXAtZ3AgIn0iICIi ICJeZGVjbGFyYXRpb24kIikpCiAgICAgICAgICAgY29sdW1uLTAgMCkKICAgICAgICAgICgo cGFyZW50LWlzICJeZGVjbGFyYXRpb24kIikgcGFyZW50IDIpCiAgICAgICAgICAoKG5vZGUt aXMgIl5ncmFtbWFyX3J1bGUkIikgY29sdW1uLTAgMCkKICAgICAgICAgICgoYW5kCiAgICAg ICAgICAgIChwYXJlbnQtaXMgIl5ncmFtbWFyX3J1bGUkIikKICAgICAgICAgICAgKG5vZGUt aXMgIjsiKSkKICAgICAgICAgICBjb2x1bW4tMCBiaXNvbi10cy1tb2RlLWluZGVudC1vZmZz ZXQpCiAgICAgICAgICAoKGFuZCAocGFyZW50LWlzICJeZ3JhbW1hcl9ydWxlJCIpCiAgICAg ICAgICAgICAgICAobm9kZS1pcyAifCIpKQogICAgICAgICAgIGNvbHVtbi0wIGJpc29uLXRz LW1vZGUtaW5kZW50LW9mZnNldCkKICAgICAgICAgICgoYW5kIChwYXJlbnQtaXMgIl5ncmFt bWFyX3J1bGUkIikKICAgICAgICAgICAgICAgIChub3QgKG5vZGUtaXMgIl5ncmFtbWFyX3J1 bGVfZGVjbGFyYXRpb24kIikpCiAgICAgICAgICAgICAgICAobm90IChub2RlLWlzICJeYWN0 aW9uJCIpKSkKICAgICAgICAgICBjb2x1bW4tMCAsKCsgYmlzb24tdHMtbW9kZS1pbmRlbnQt b2Zmc2V0IDIpKQogICAgICAgICAgKChvcgogICAgICAgICAgICAobm9kZS1pcyAiXmFjdGlv biQiKQogICAgICAgICAgICAobm9kZS1pcyAiXn0kIikpCiAgICAgICAgICAgY29sdW1uLTAg MTIpCiAgICAgICAgICA7OyBTZXQgJyUlJyBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaW5l CiAgICAgICAgICAoKG9yCiAgICAgICAgICAgIChhbmQgKHBhcmVudC1pcyAiXmdyYW1tYXJf cnVsZXNfc2VjdGlvbiQiKQogICAgICAgICAgICAgICAgIChub2RlLWlzICIlJSIpKQogICAg ICAgICAgICAobm9kZS1pcyAiXmdyYW1tYXJfcnVsZXNfc2VjdGlvbiQiKSkKICAgICAgICAg ICBjb2x1bW4tMCAwKQogICAgICAgICAgKG5vLW5vZGUgcGFyZW50LWJvbCAwKSkpKQogICAg YCgoYmlzb24gLiAsY29tbW9uKQogICAgICA7OyBJbXBvcnQgYW5kIG92ZXJyaWRlIGVtYmVk ZGVkIGxhbmd1YWdlcyBydWxlcyB0byBhZGQgYW4gb2Zmc2V0CiAgICAgICwocGNhc2UgYmlz b24tdHMtbW9kZS1lbWJlZGRlZC1sYW5ndWFnZQogICAgICAgICAoJ2MgYChjCiAgICAgICAg ICAgICAgICgoYmlzb24tdHMtbW9kZS0tYmlzb24tbWF0Y2hlci1hY3Rpb24gInRyYW5zbGF0 aW9uX3VuaXQiKQogICAgICAgICAgICAgICAgYmlzb24tdHMtbW9kZS0tYmlzb24tcGFyZW50 ICxiaXNvbi10cy1tb2RlLWluZGVudC1vZmZzZXQpCiAgICAgICAgICAgICAgICgoYmlzb24t dHMtbW9kZS0tYmlzb24tbWF0Y2hlci1ub3QtZXBpbG9ndWUgInRyYW5zbGF0aW9uX3VuaXQi KQogICAgICAgICAgICAgICAgY29sdW1uLTAgLGJpc29uLXRzLW1vZGUtaW5kZW50LW9mZnNl dCkKICAgICAgICAgICAgICAgLEAoYWxpc3QtZ2V0ICdjIChjLXRzLW1vZGUtLWdldC1pbmRl bnQtc3R5bGUgJ2MpKSkpCiAgICAgICAgICgnY3BwIGAoY3BwCiAgICAgICAgICAgICAgICAg KChiaXNvbi10cy1tb2RlLS1iaXNvbi1tYXRjaGVyLWFjdGlvbiAidHJhbnNsYXRpb25fdW5p dCIpCiAgICAgICAgICAgICAgICAgIGJpc29uLXRzLW1vZGUtLWJpc29uLXBhcmVudCAsYmlz b24tdHMtbW9kZS1pbmRlbnQtb2Zmc2V0KQogICAgICAgICAgICAgICAgICgoYmlzb24tdHMt bW9kZS0tYmlzb24tbWF0Y2hlci1ub3QtZXBpbG9ndWUgInRyYW5zbGF0aW9uX3VuaXQiKQog ICAgICAgICAgICAgICAgICBwYXJlbnQtMCAsYmlzb24tdHMtbW9kZS1pbmRlbnQtb2Zmc2V0 KQogICAgICAgICAgICAgICAgICxAKGFsaXN0LWdldCAnY3BwIChjLXRzLW1vZGUtLWdldC1p bmRlbnQtc3R5bGUgJ2NwcCkpKSkKICAgICAgICAgKCdqYXZhIGAoamF2YQogICAgICAgICAg ICAgICAgICAoKGJpc29uLXRzLW1vZGUtLWJpc29uLW1hdGNoZXItYWN0aW9uICJwcm9ncmFt IikKICAgICAgICAgICAgICAgICAgIGJpc29uLXRzLW1vZGUtLWJpc29uLXBhcmVudCAsYmlz b24tdHMtbW9kZS1pbmRlbnQtb2Zmc2V0KQogICAgICAgICAgICAgICAgICAoKGJpc29uLXRz LW1vZGUtLWJpc29uLW1hdGNoZXItbm90LWVwaWxvZ3VlICJwcm9ncmFtIikKICAgICAgICAg ICAgICAgICAgIGNvbHVtbi0wICxiaXNvbi10cy1tb2RlLWluZGVudC1vZmZzZXQpCiAgICAg ICAgICAgICAgICAgICxAamF2YS10cy1tb2RlLS1pbmRlbnQtcnVsZXMpKSkpKSkKCgooZGVm aW5lLWRlcml2ZWQtbW9kZSBiaXNvbi10cy1tb2RlIHByb2ctbW9kZSAiQmlzb24iCiAgIkEg bWFqb3ItbW9kZSBmb3IgQmlzb24gYmFzZWQgb24gdHJlZS1zaXR0ZXIuIgogICh3aGVuICh0 cmVlc2l0LXJlYWR5LXAgJ2Jpc29uKQogICAgKHdoZW4gKG5vdCBiaXNvbi10cy1tb2RlLWVt YmVkZGVkLWxhbmd1YWdlKQogICAgICAoc2V0cSBiaXNvbi10cy1tb2RlLWVtYmVkZGVkLWxh bmd1YWdlIChiaXNvbi10cy1tb2RlLS1kZXRlY3QtbGFuZ3VhZ2UpKSkKCiAgICA7OyBSZXF1 aXJlIG9ubHkgaWYgbmVlZGVkLCB0byBhdm9pZCB3YXJuaW5ncyBpZiBhIGdyYW1tYXIgaXMg bm90CiAgICA7OyBpbnN0YWxsZWQgYnV0IG5vdCB1c2VkLgogICAgKHBjYXNlIGJpc29uLXRz LW1vZGUtZW1iZWRkZWQtbGFuZ3VhZ2UKICAgICAgKCdjIChyZXF1aXJlICdjLXRzLW1vZGUp KQogICAgICAoJ2NwcCAocmVxdWlyZSAnYy10cy1tb2RlKSkKICAgICAgKCdqYXZhIChyZXF1 aXJlICdqYXZhLXRzLW1vZGUpKSkKCiAgICAoc2V0cS1sb2NhbCB0cmVlc2l0LWZvbnQtbG9j ay1zZXR0aW5ncwogICAgICAgICAgICAgICAgKGFwcGVuZCAoYmlzb24tdHMtbW9kZS0tZm9u dC1sb2NrLXNldHRpbmdzICdiaXNvbikKICAgICAgICAgICAgICAgICAgICAgICAgKHBjYXNl IGJpc29uLXRzLW1vZGUtZW1iZWRkZWQtbGFuZ3VhZ2UKICAgICAgICAgICAgICAgICAgICAg ICAgICAoJ2MgKGMtdHMtbW9kZS0tZm9udC1sb2NrLXNldHRpbmdzICdjKSkKICAgICAgICAg ICAgICAgICAgICAgICAgICAoJ2NwcCAoYy10cy1tb2RlLS1mb250LWxvY2stc2V0dGluZ3Mg J2NwcCkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgKCdqYXZhIGphdmEtdHMtbW9kZS0t Zm9udC1sb2NrLXNldHRpbmdzKSkpKQoKICAgIChzZXRxLWxvY2FsIHRyZWVzaXQtZm9udC1s b2NrLWZlYXR1cmUtbGlzdAogICAgICAgICAgICAgICAgKGlmIGJpc29uLXRzLW1vZGUtZW1i ZWRkZWQtbGFuZ3VhZ2UKICAgICAgICAgICAgICAgICAgICAoYmlzb24tdHMtbW9kZS0tbWVy Z2UtZmVhdHVyZS1saXN0cwogICAgICAgICAgICAgICAgICAgICBiaXNvbi10cy1tb2RlLS1m b250LWxvY2stZmVhdHVyZS1saXN0CiAgICAgICAgICAgICAgICAgICAgIChwY2FzZSBiaXNv bi10cy1tb2RlLWVtYmVkZGVkLWxhbmd1YWdlCiAgICAgICAgICAgICAgICAgICAgICAgKCdj IGMtdHMtbW9kZS0tZmVhdHVyZS1saXN0KQogICAgICAgICAgICAgICAgICAgICAgICgnY3Bw IGMtdHMtbW9kZS0tZmVhdHVyZS1saXN0KQogICAgICAgICAgICAgICAgICAgICAgICgnamF2 YSBqYXZhLXRzLW1vZGUtLWZlYXR1cmUtbGlzdCkpKQogICAgICAgICAgICAgICAgICBiaXNv bi10cy1tb2RlLS1mb250LWxvY2stZmVhdHVyZS1saXN0KSkKCiAgICAoc2V0cS1sb2NhbCB0 cmVlc2l0LXNpbXBsZS1pbWVudS1zZXR0aW5ncwogICAgICAgICAgICAgICAgYCgoIkdyYW1t YXIiCiAgICAgICAgICAgICAgICAgICAiXFxgZ3JhbW1hcl9ydWxlX2RlY2xhcmF0aW9uXFwn IgogICAgICAgICAgICAgICAgICAgbmlsCiAgICAgICAgICAgICAgICAgICAobGFtYmRhIChu b2RlKSAoc3Vic3RyaW5nLW5vLXByb3BlcnRpZXMgKHRyZWVzaXQtbm9kZS10ZXh0IG5vZGUp KSkpKSkKCiAgICAoYy10cy1jb21tb24tY29tbWVudC1zZXR1cCkKCiAgICAoc2V0cS1sb2Nh bCB0cmVlc2l0LXNpbXBsZS1pbmRlbnQtcnVsZXMKICAgICAgICAgICAgICAgIChiaXNvbi10 cy1tb2RlLS1pbmRlbnQtcnVsZXMpKQoKICAgIChzZXRxLWxvY2FsIHRyZWVzaXQtbGFuZ3Vh Z2UtYXQtcG9pbnQtZnVuY3Rpb24gJ2Jpc29uLXRzLW1vZGUtLWxhbmd1YWdlLWF0LXBvaW50 LWZ1bmN0aW9uKQoKICAgICh3aGVuIGJpc29uLXRzLW1vZGUtZW1iZWRkZWQtbGFuZ3VhZ2UK ICAgICAgKHNldHEtbG9jYWwgdHJlZXNpdC1yYW5nZS1zZXR0aW5ncwogICAgICAgICAgICAg ICAgICAodHJlZXNpdC1yYW5nZS1ydWxlcwogICAgICAgICAgICAgICAgICAgOmVtYmVkIGJp c29uLXRzLW1vZGUtZW1iZWRkZWQtbGFuZ3VhZ2UKICAgICAgICAgICAgICAgICAgIDpob3N0 ICdiaXNvbgogICAgICAgICAgICAgICAgICAgOmxvY2FsIHQKICAgICAgICAgICAgICAgICAg ICcoKGVtYmVkZGVkX2NvZGUpIEBjYXB0dXJlKSkpKQoKICAgICh0cmVlc2l0LW1ham9yLW1v ZGUtc2V0dXApKSkKCihwcm92aWRlICdiaXNvbi10cy1tb2RlKQo7OzsgYmlzb24tdHMtbW9k ZS5lbCBlbmRzIGhlcmUK --------------hBY0UnMiJYIdKg2TfC9Agd20--