From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: MON KEY Newsgroups: gmane.emacs.devel Subject: Re: locate-library, the NOSUFFIX arg and a [PATCH] Date: Thu, 28 Jan 2010 21:55:28 -0500 Message-ID: References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary=000e0cd6ab82a2573c047e44c450 X-Trace: ger.gmane.org 1264733748 8275 80.91.229.12 (29 Jan 2010 02:55:48 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Fri, 29 Jan 2010 02:55:48 +0000 (UTC) Cc: emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Fri Jan 29 03:55:45 2010 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1Nah1L-00085n-MR for ged-emacs-devel@m.gmane.org; Fri, 29 Jan 2010 03:55:44 +0100 Original-Received: from localhost ([127.0.0.1]:53770 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Nah1K-0003BH-9m for ged-emacs-devel@m.gmane.org; Thu, 28 Jan 2010 21:55:42 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Nah1D-00038E-KV for emacs-devel@gnu.org; Thu, 28 Jan 2010 21:55:35 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Nah19-00031j-S4 for emacs-devel@gnu.org; Thu, 28 Jan 2010 21:55:35 -0500 Original-Received: from [199.232.76.173] (port=36924 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Nah19-00031Y-IM for emacs-devel@gnu.org; Thu, 28 Jan 2010 21:55:31 -0500 Original-Received: from mail-gx0-f228.google.com ([209.85.217.228]:59778) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Nah18-00028e-PP for emacs-devel@gnu.org; Thu, 28 Jan 2010 21:55:31 -0500 Original-Received: by gxk28 with SMTP id 28so1308837gxk.9 for ; Thu, 28 Jan 2010 18:55:28 -0800 (PST) Original-Received: by 10.150.5.5 with SMTP id 5mr886314ybe.71.1264733728691; Thu, 28 Jan 2010 18:55:28 -0800 (PST) In-Reply-To: X-Google-Sender-Auth: e51ccdd66dd6dc4b X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:120625 Archived-At: --000e0cd6ab82a2573c047e44c450 Content-Type: text/plain; charset=UTF-8 On Wed, Jan 27, 2010 at 9:46 PM, Stefan Monnier wrote: > >>> Depending on this question, we may be able to determine things like >>> whether you'd like (your-locate-library "foo.el" t) to return "/bar/foo" >>> or "/bar/foo.el". >> Exactly. > > Now that was helpful. I'm just wasting my time here. > Indeed, it appears you are wasting time. Your question contained the answer(s) I have already given. These are the determinations sought. What else would you have me reply??? I've gone out of my way to identify the perceived problem, along with my expectations, as I understand them. I've included two patches (now three) to transparently identify with unambiguous Elisp both the perceived problem and a perceived solution. I've indicated multiple times that the proposed solution needn't be breaking. I'm including some elisp source which: a) A function which does to not alter the semantics of NOSUFFIX and uses an external functional call to tdo the work. b) A revised version of the previously proposed patch that does alter the semantics of NOSUFFIX. This newest revision fixes a bug where the return value of the altered NOSUFFIX semantic was orthogonal to the existing unmodified locate-library. With this bug fixed the revised version should be transparent to the user. I've written adequate documentation for b) which clarifies the existing behavior of locate-library and illustrates the proposed semantics of the proposed patch. I won't bother wasting your time your with those details unless you should find them useful. Let me know and I'll forward them along. Following is the elisp. Knock yourself out... ;;; ============================== ;;; :UNMODIFIED `locate-library'. Evaluate me later to get back to Kansas. (defun locate-library (library &optional nosuffix path interactive-call) (interactive (list (completing-read "Locate library: " (apply-partially 'locate-file-completion-table load-path (get-load-suffixes))) nil nil t)) (let ((file (locate-file library (or path load-path) (append (unless nosuffix (get-load-suffixes)) load-file-rep-suffixes)))) (if interactive-call (if file (message "Library is file %s" (abbreviate-file-name file)) (message "No library %s in search path" library))) file)) ;;; ============================== ;;; :MODIFIED `locate-library'. ;;; NOSUFFIX with alternative semantics and new arg SHOW-COMPRESSED. ;;; Revised version of previous patch(s). ;;; (defun locate-library (library &optional nosuffix path interactive-call show-compressed) (interactive (list (completing-read "Locate library: " (apply-partially 'locate-file-completion-table load-path (get-load-suffixes))) nil nil t (if current-prefix-arg t))) (let* ((lfrs (remove "" load-file-rep-suffixes)) (gls (sort (get-load-suffixes) #'(lambda (l1 l2) (< (length l1) (length l2))))) (sfx (cond ((booleanp nosuffix) (delete-dups (append gls lfrs))) ((and nosuffix (stringp nosuffix)) `(,nosuffix ,@(mapcar #'(lambda (z) (concat nosuffix z)) lfrs))) ((consp nosuffix) (delete-dups (append nosuffix lfrs))) (t (append gls lfrs)))) (cln-lib (if (string= (file-name-sans-extension library) library) library (let ((lib-cln library)) (mapc #'(lambda (rgx) (let ((ms (string-match-p rgx lib-cln))) (when ms (setq lib-cln (substring lib-cln 0 ms))))) '("\\(\\(\\.elc\\|\\.el\\)\\.gz\\)" ; -> 1 .el[c].gz "\\(\\.elc\\|\\.el\\)" ; -> 1 .elc | .el "\\(\\.gz\\)")) ; -> 1 .gz lib-cln))) (file (locate-file cln-lib (or path load-path) sfx))) (when (and file (or nosuffix (and show-compressed (not nosuffix)))) (setq file (file-truename file)) (let ((smp-gz ;;(string-match-p ".*.gz" file))) (string-match-p ".*\\.gz" file))) (setq file (concat (file-name-directory file) (cond ((or (not show-compressed) (and show-compressed (not smp-gz))) (file-name-sans-extension (file-name-nondirectory (file-name-sans-extension file)))) ((or (and show-compressed smp-gz) t) (file-name-nondirectory file))))))) (if interactive-call (if file (message "Library is file %s" (abbreviate-file-name file)) (message "No library %s in search path" library))) file)) ;;; ============================== ;;; :MODIFIED `locate-library'. Semantics of NOSUFFIX untouched. ;;; Additional arg STRIPSUFFIX when non-nil evaluates `locate-library-rmv-sfx' ;;; (defun locate-library (library &optional nosuffix path interactive-call stripsuffix) (interactive (list (completing-read "Locate library: " (apply-partially 'locate-file-completion-table load-path (get-load-suffixes))) nil nil t)) (let ((file (if (and (not nosuffix) stripsuffix) (locate-library-rmv-sfx library path stripsuffix) (locate-file library (or path load-path) (append (unless nosuffix (get-load-suffixes)) load-file-rep-suffixes))))) (if interactive-call (if file (message "Library is file %s" (abbreviate-file-name file)) (message "No library %s in search path" library))) file)) ;;; ;;; Assume the following files are present in "/home/MON/loc-libr": ;;; "subr" "subr.bubba" "subr.bubba.gz" "subr.el" "subr.el.gz" "subr.elc.gz" "subr.el~" ;;; ;;; :TEST-ME (locate-library "subr.el" nil '("/home/MON/loc-libr") nil '((".bubba" ".el" ".el.gz") . t)) ;;; => "/home/MON/loc-libr/subr.el.gz" ;;; ;;; :TEST-ME (locate-library "subr.el" nil '("/home/MON/loc-libr") nil '((".bubba" ".el" ".el.gz") . nil)) ;;; => "/home/MON/loc-libr/subr" ;;; ;;; :TEST-ME (locate-library "subr.el" t) ;;; => "/home/MON/loc-libr/subr" ;;; ;;; ============================== ;;; :NOTE For backwards compat we strip the extension in the `cln-lib' var. ;;; Not using `file-name-extension'/`file-name-extension' b/c: ;;; (file-name-extension "subr.elc.gz") => "gz" ;;; (file-name-sans-extension "subr.elc.gz") => "subr.elc" ;;; ;;; (defun locate-library-rmv-sfx (library locpath rmvsfx-shw-gz) "LIBRARY is a string naming the library to locate. LOCPATH is a list of paths in which to locate LIBRARY RMVSFX-SHW-GZ is a dotted list with the form:\n '\(\(\".el\" \".el.gz\" \".bubba\"\) . t\)\" The first element is a list of suffix names which LIBRARY might have. When present the second element is a boolean, t or nil. If t when LIBRARY is found in PATH with a suffix matching the first element of RMVSFX-SHW-GZ and that element represents a compressed file extension show the file name with the extension." (let* ((gls (sort (get-load-suffixes) #'(lambda (l1 l2) (< (length l1) (length l2))))) (lfrs (remove "" load-file-rep-suffixes)) (cln-lib (if (string= (file-name-sans-extension library) library) library (let ((lib-cln library)) (mapc #'(lambda (rgx) (let ((ms (string-match-p rgx lib-cln))) (when ms (setq lib-cln (substring lib-cln 0 ms))))) '("\\(\\(\\.elc\\|\\.el\\)\\.gz\\)" ; -> 1 .el[c].gz "\\(\\.elc\\|\\.el\\)" ; -> 1 .elc | .el "\\(\\.gz\\)")) ; -> 1 .gz lib-cln))) ;; :NOTE arg (shw-gz (cdr rmvsfx-shw-gz)) ; => t (rmvsfx (car rmvsfx-shw-gz)) ; => (".el" ".el.gz" ".bubba") (sfx (cond ((booleanp rmvsfx) (delete-dups (append gls lfrs))) ((and rmvsfx (stringp rmvsfx)) `(,rmvsfx ,@(mapcar #'(lambda (z) (concat rmvsfx z)) lfrs))) ((consp rmvsfx) (delete-dups (append rmvsfx lfrs))) ;; (t (append gls lfrs)))) ;; <-should not happen. )) (file (locate-file cln-lib locpath sfx 'exists))) (when file (setq file (file-truename file)) (let ((smp-gz (string-match-p ".*\\.gz" file))) (setq file (concat (file-name-directory file) (cond ((or (not shw-gz) (and shw-gz (not smp-gz))) ;; Call it twice to knock the .gz off the .el.gz (file-name-sans-extension (file-name-nondirectory (file-name-sans-extension file)))) ((or (and shw-gz smp-gz) t) (file-name-nondirectory file))))))) file)) ;; ;;; ;;; :TEST-ME (locate-library-rmv-sfx "subr.el" '("/home/MON/loc-libr") '((".bubba" ".el" ".el.gz") . t)) ;;; => "/home/MON/loc-libr/subr" ;;; :TEST-ME (locate-library-rmv-sfx "subr.el" '("/home/MON/loc-libr") '((".bubba" ".el" ".el.gz"))) ;;; => "/home/MON/loc-libr/subr" ;;; :TEST-ME (locate-library-rmv-sfx "subr" '("/home/MON/loc-libr") '((".el.gz" ".bubba" ".el") . t)) ;;; =>"/home/MON/loc-libr/subr.el.gz" ;;; :TEST-ME (locate-library-rmv-sfx "subr.el" '("/home/MON/loc-libr") '((".el.gz" ".bubba" ".el") . nil)) ;;; => "/home/MON/loc-libr/subr" ;;; :TEST-ME (locate-library-rmv-sfx "subr.el.gz" '("/home/MON/loc-libr") '((".el.gz" ".bubba" ".el") . nil)) ;;; => "/home/MON/loc-libr/subr" ;;; :TEST-ME (locate-library-rmv-sfx "subr.el.gz" '("/home/MON/loc-libr") '((".el.gz" ".bubba" ".el") . t)) ;;; => "/home/MON/loc-libr/subr.el.gz" ;;; :TEST-ME (locate-library-rmv-sfx "subr.el.gz" '("/home/MON/loc-libr") '((".el.gz" ".bubba" ".el") . t)) ;;; ;;; :TEST-ME (locate-library-rmv-sfx "subr.el.gz" '("/home/MON/loc-libr" "/usr/share/emacs/23.1.90/lisp") ;;; '((".el.gz" ".bubba" ".el") . t)) ;;; => "/home/MON/loc-libr/subr.el.gz" ;;; ;;; :TEST-ME (locate-library-rmv-sfx "subr.el.gz" '("/usr/share/emacs/23.1.90/lisp" "/home/MON/loc-libr" ) ;;; '((".el.gz" ".bubba" ".el") . t)) ;;; => "/usr/share/emacs/23.1.90/lisp/subr.el.gz" ;;; ;;; :TEST-ME (locate-library-rmv-sfx "subr" '("/usr/share/emacs/23.1.90/lisp""/home/MON/loc-libr") ;;; '((".el.gz" ".bubba" ".el") . t)) ;;; => "/usr/share/emacs/23.1.90/lisp/subr.el.gz" ;;; ;;; :TEST-ME (locate-library-rmv-sfx "subr" '("/usr/share/emacs/23.1.90/lisp" "/home/MON/loc-libr") ;;; '((".el.gz" ".bubba" ".el"))) ;;; => "/usr/share/emacs/23.1.90/lisp/subr" ;;; ;;; :TEST-ME ;;; :NOTE :SEE `ffap-locate-file' for more on why this is a relevant use-case. ;;; (let ((find-vaguely ;;; (locate-library-rmv-sfx ;;; "subr" ;;; '( "/home/MON/loc-libr" "/usr/share/emacs/23.1.90/lisp") ;;; '(( ".bubba" ".el.gz" ".el") .t)))) ;;; (if (file-exists-p find-vaguely) ;;; (find-file find-vaguely) ;;; (completing-read "Which file :" ;;; (file-expand-wildcards (concat find-vaguely "*"))))) ;;; ;;; ============================== --000e0cd6ab82a2573c047e44c450 Content-Type: application/octet-stream; name=locate-library-redux Content-Disposition: attachment; filename=locate-library-redux Content-Transfer-Encoding: base64 X-Attachment-Id: f_g50dn3fh0 Ozs7ID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQo7OzsgOlVOTU9ESUZJRUQgYGxvY2F0 ZS1saWJyYXJ5Jy4gRXZhbHVhdGUgbWUgbGF0ZXIgdG8gZ2V0IGJhY2sgdG8gS2Fuc2FzLgooZGVm dW4gbG9jYXRlLWxpYnJhcnkgKGxpYnJhcnkgJm9wdGlvbmFsIG5vc3VmZml4IHBhdGggaW50ZXJh Y3RpdmUtY2FsbCkKICAoaW50ZXJhY3RpdmUgKGxpc3QgKGNvbXBsZXRpbmctcmVhZCAiTG9jYXRl IGxpYnJhcnk6ICIKCQkJCSAgICAgIChhcHBseS1wYXJ0aWFsbHkKICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgJ2xvY2F0ZS1maWxlLWNvbXBsZXRpb24tdGFibGUKICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZC1wYXRoIChnZXQtbG9hZC1zdWZm aXhlcykpKQoJCSAgICAgbmlsIG5pbAoJCSAgICAgdCkpCiAgKGxldCAoKGZpbGUgKGxvY2F0ZS1m aWxlIGxpYnJhcnkKCQkJICAgKG9yIHBhdGggbG9hZC1wYXRoKQoJCQkgICAoYXBwZW5kICh1bmxl c3Mgbm9zdWZmaXggKGdldC1sb2FkLXN1ZmZpeGVzKSkKCQkJCSAgIGxvYWQtZmlsZS1yZXAtc3Vm Zml4ZXMpKSkpCiAgICAoaWYgaW50ZXJhY3RpdmUtY2FsbAoJKGlmIGZpbGUKCSAgICAobWVzc2Fn ZSAiTGlicmFyeSBpcyBmaWxlICVzIiAoYWJicmV2aWF0ZS1maWxlLW5hbWUgZmlsZSkpCgkgICht ZXNzYWdlICJObyBsaWJyYXJ5ICVzIGluIHNlYXJjaCBwYXRoIiBsaWJyYXJ5KSkpCiAgICBmaWxl KSkKCjs7OyA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KOzs7IDpNT0RJRklFRCBgbG9j YXRlLWxpYnJhcnknLiAKOzs7IE5PU1VGRklYIHdpdGggYWx0ZXJuYXRpdmUgc2VtYW5pdGNzIGFu ZCBTSE9XLUNPTVBSRVNTRUQuCjs7OyBSZXZpc2VkIHZlcnNpb24gb2YgcHJldmlvdXMgcGF0Y2go cykuCjs7OyA8VGltZXN0YW1wOiAjezIwMTAtMDEtMjhUMjE6NDU6MjAtMDU6MDBafSN7MTAwNDR9 IC0gYnkgTU9OPgooZGVmdW4gbG9jYXRlLWxpYnJhcnkgKGxpYnJhcnkgJm9wdGlvbmFsIG5vc3Vm Zml4IHBhdGggaW50ZXJhY3RpdmUtY2FsbCBzaG93LWNvbXByZXNzZWQpIAogIChpbnRlcmFjdGl2 ZSAobGlzdCAoY29tcGxldGluZy1yZWFkICJMb2NhdGUgbGlicmFyeTogIgoJCQkJICAgICAgKGFw cGx5LXBhcnRpYWxseQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbG9j YXRlLWZpbGUtY29tcGxldGlvbi10YWJsZQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICBsb2FkLXBhdGggKGdldC1sb2FkLXN1ZmZpeGVzKSkpCgkJICAgICBuaWwgbmlsCgkJ ICAgICB0IChpZiBjdXJyZW50LXByZWZpeC1hcmcgdCkpKQogIChsZXQqICgobGZycyAocmVtb3Zl ICIiIGxvYWQtZmlsZS1yZXAtc3VmZml4ZXMpKQogICAgICAgICAoZ2xzIChzb3J0IChnZXQtbG9h ZC1zdWZmaXhlcykgIycobGFtYmRhIChsMSBsMikgKDwgKGxlbmd0aCBsMSkgKGxlbmd0aCBsMikp KSkpCiAgICAgICAgIChzZnggIChjb25kICgoYm9vbGVhbnAgbm9zdWZmaXgpCiAgICAgICAgICAg ICAgICAgICAgICAoZGVsZXRlLWR1cHMgKGFwcGVuZCBnbHMgbGZycykpKQogICAgICAgICAgICAg ICAgICAgICAoKGFuZCBub3N1ZmZpeCAoc3RyaW5ncCBub3N1ZmZpeCkpCiAgICAgICAgICAgICAg ICAgICAgICBgKCxub3N1ZmZpeCAKICAgICAgICAgICAgICAgICAgICAgICAgLEAobWFwY2FyICMn KGxhbWJkYSAoeikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY29uY2F0 IG5vc3VmZml4IHopKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGZycykpKQog ICAgICAgICAgICAgICAgICAgICAoKGNvbnNwIG5vc3VmZml4KSAoZGVsZXRlLWR1cHMgKGFwcGVu ZCBub3N1ZmZpeCBsZnJzKSkpCiAgICAgICAgICAgICAgICAgICAgICh0IChhcHBlbmQgZ2xzIGxm cnMpKSkpCiAgICAgICAgIChjbG4tbGliIChpZiAoc3RyaW5nPSAoZmlsZS1uYW1lLXNhbnMtZXh0 ZW5zaW9uIGxpYnJhcnkpIGxpYnJhcnkpCiAgICAgICAgICAgICAgICAgICAgICBsaWJyYXJ5CiAg ICAgICAgICAgICAgICAgICAgICAobGV0ICgobGliLWNsbiBsaWJyYXJ5KSkKICAgICAgICAgICAg ICAgICAgICAgICAgKG1hcGMgIycobGFtYmRhIChyZ3gpIAogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgKGxldCAoKG1zIChzdHJpbmctbWF0Y2gtcCByZ3ggbGliLWNsbikpKQogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAod2hlbiBtcyAoc2V0cSBsaWItY2xuIChz dWJzdHJpbmcgbGliLWNsbiAwIG1zKSkpKSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg JygiXFwoXFwoXFwuZWxjXFx8XFwuZWxcXClcXC5nelxcKSIgOyAtPiAxIC5lbFtjXS5negogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcXChcXC5lbGNcXHxcXC5lbFxcKSIgICAgICAg ICAgICA7IC0+IDEgLmVsYyB8IC5lbCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAi XFwoXFwuZ3pcXCkiKSkgICAgICAgICAgICAgICAgICAgOyAtPiAxIC5negogICAgICAgICAgICAg ICAgICAgICAgICBsaWItY2xuKSkpCiAgICAgICAgIChmaWxlIChsb2NhdGUtZmlsZSBjbG4tbGli IChvciBwYXRoIGxvYWQtcGF0aCkgc2Z4KSkpCiAgICAod2hlbiAoYW5kIGZpbGUgKG9yIG5vc3Vm Zml4IChhbmQgc2hvdy1jb21wcmVzc2VkIChub3Qgbm9zdWZmaXgpKSkpCiAgICAgIChzZXRxIGZp bGUgKGZpbGUtdHJ1ZW5hbWUgZmlsZSkpCiAgICAgIChsZXQgKChzbXAtZ3ogOzsoc3RyaW5nLW1h dGNoLXAgIi4qLmd6IiBmaWxlKSkpCiAgICAgICAgICAgICAoc3RyaW5nLW1hdGNoLXAgIi4qXFwu Z3oiIGZpbGUpKSkKICAgICAgICAoc2V0cSBmaWxlIChjb25jYXQgKGZpbGUtbmFtZS1kaXJlY3Rv cnkgZmlsZSkKICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNvbmQgKChvciAobm90IHNob3ct Y29tcHJlc3NlZCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoYW5kIHNo b3ctY29tcHJlc3NlZCAobm90IHNtcC1neikpKQogICAgICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgKGZpbGUtbmFtZS1zYW5zLWV4dGVuc2lvbgogICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIChmaWxlLW5hbWUtbm9uZGlyZWN0b3J5IAogICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAoZmlsZS1uYW1lLXNhbnMtZXh0ZW5zaW9uIGZpbGUpKSkpCiAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICgob3IgKGFuZCBzaG93LWNvbXByZXNzZWQgc21wLWd6 KSB0KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGZpbGUtbmFtZS1ub25kaXJl Y3RvcnkgZmlsZSkpKSkpKSkKICAgIChpZiBpbnRlcmFjdGl2ZS1jYWxsCiAgICAgICAgKGlmIGZp bGUKICAgICAgICAgICAgKG1lc3NhZ2UgIkxpYnJhcnkgaXMgZmlsZSAlcyIgKGFiYnJldmlhdGUt ZmlsZS1uYW1lIGZpbGUpKQogICAgICAgICAgICAobWVzc2FnZSAiTm8gbGlicmFyeSAlcyBpbiBz ZWFyY2ggcGF0aCIgbGlicmFyeSkpKQogICAgZmlsZSkpCgo7OzsgPT09PT09PT09PT09PT09PT09 PT09PT09PT09PT09Cjs7OyA6TU9ESUZJRUQgYGxvY2F0ZS1saWJyYXJ5Jy4gU2VtYW50aWNzIG9m IE5PU1VGRklYIHVuYWx0ZXJlZC4KOzs7IEFkZGl0aW9uYWwgYXJnIFNUUklQU1VGRklYIHdoZW4g bm9uLW5pbCBldmFsdWF0ZXMgYGxvY2F0ZS1saWJyYXJ5LXJtdi1zZngnCjs7OyA8VGltZXN0YW1w OiAjezIwMTAtMDEtMjhUMjE6NDU6MzMtMDU6MDBafSN7MTAwNDR9IC0gYnkgTU9OPgooZGVmdW4g bG9jYXRlLWxpYnJhcnkgKGxpYnJhcnkgJm9wdGlvbmFsIG5vc3VmZml4IHBhdGggaW50ZXJhY3Rp dmUtY2FsbCBzdHJpcHN1ZmZpeCkKICAoaW50ZXJhY3RpdmUgKGxpc3QgKGNvbXBsZXRpbmctcmVh ZCAiTG9jYXRlIGxpYnJhcnk6ICIKCQkJCSAgICAgIChhcHBseS1wYXJ0aWFsbHkKICAgICAgICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2xvY2F0ZS1maWxlLWNvbXBsZXRpb24tdGFi bGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9hZC1wYXRoIChnZXQt bG9hZC1zdWZmaXhlcykpKQoJCSAgICAgbmlsIG5pbAoJCSAgICAgdCkpCiAgKGxldCAoKGZpbGUg CiAgICAgICAgIChpZiAoYW5kIChub3Qgbm9zdWZmaXgpIHN0cmlwc3VmZml4KQogICAgICAgICAg ICAgKGxvY2F0ZS1saWJyYXJ5LXJtdi1zZnggbGlicmFyeSBwYXRoIHN0cmlwc3VmZml4KQogICAg ICAgICAgICAgKGxvY2F0ZS1maWxlIGxpYnJhcnkKICAgICAgICAgICAgICAgICAgICAgICAgICAo b3IgcGF0aCBsb2FkLXBhdGgpCiAgICAgICAgICAgICAgICAgICAgICAgICAgKGFwcGVuZCAodW5s ZXNzIG5vc3VmZml4IChnZXQtbG9hZC1zdWZmaXhlcykpCiAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICBsb2FkLWZpbGUtcmVwLXN1ZmZpeGVzKSkpKSkKICAgIChpZiBpbnRlcmFjdGl2 ZS1jYWxsCgkoaWYgZmlsZQoJICAgIChtZXNzYWdlICJMaWJyYXJ5IGlzIGZpbGUgJXMiIChhYmJy ZXZpYXRlLWZpbGUtbmFtZSBmaWxlKSkKICAgICAgICAgICAgKG1lc3NhZ2UgIk5vIGxpYnJhcnkg JXMgaW4gc2VhcmNoIHBhdGgiIGxpYnJhcnkpKSkKICAgIGZpbGUpKQo7OzsKOzs7IEFzc3VtZSB0 aGUgZm9sbG93aW5nIGZpbGVzIGFyZSBwcmVzZW50IGluICIvaG9tZS9NT04vbG9jLWxpYnIiOgo7 OzsgInN1YnIiICJzdWJyLmJ1YmJhIiAic3Vici5idWJiYS5neiIgInN1YnIuZWwiICJzdWJyLmVs Lmd6IiAic3Vici5lbGMuZ3oiICJzdWJyLmVsfiIKOzs7Cjs7OyA6VEVTVC1NRSAobG9jYXRlLWxp YnJhcnkgInN1YnIuZWwiIG5pbCAnKCIvaG9tZS9NT04vbG9jLWxpYnIiKSBuaWwgICcoKCIuYnVi YmEiICIuZWwiICIuZWwuZ3oiKSAuIHQpKQo7OzsgICAgICAgICAgPT4gIi9ob21lL01PTi9sb2Mt bGlici9zdWJyLmVsLmd6Igo7OzsKOzs7IDpURVNULU1FIChsb2NhdGUtbGlicmFyeSAic3Vici5l bCIgbmlsICcoIi9ob21lL01PTi9sb2MtbGliciIpIG5pbCAgJygoIi5idWJiYSIgIi5lbCIgIi5l bC5neiIpIC4gbmlsKSkKOzs7ICAgICAgICAgICA9PiAiL2hvbWUvTU9OL2xvYy1saWJyL3N1YnIi Cjs7Owo7OzsgOlRFU1QtTUUgKGxvY2F0ZS1saWJyYXJ5ICJzdWJyLmVsIiB0KQo7OzsgICAgICAg ICAgPT4gIi9ob21lL01PTi9sb2MtbGlici9zdWJyIgo7OzsKCjs7OyA9PT09PT09PT09PT09PT09 PT09PT09PT09PT09PT0KOzs7IDpOT1RFIEZvciBiYWNrd2FyZHMgY29tcGF0IHdlIHN0cmlwIHRo ZSBleHRlbnNpb24gaW4gdGhlIGBjbG4tbGliJyB2YXIuCjs7OyAgICAgICBOb3QgdXNpbmcgYGZp bGUtbmFtZS1leHRlbnNpb24nL2BmaWxlLW5hbWUtZXh0ZW5zaW9uJyBiL2M6Cjs7OyAgICAgICAo ZmlsZS1uYW1lLWV4dGVuc2lvbiAic3Vici5lbGMuZ3oiKSA9PiAiZ3oiCjs7OyAgICAgICAoZmls ZS1uYW1lLXNhbnMtZXh0ZW5zaW9uICJzdWJyLmVsYy5neiIpID0+ICJzdWJyLmVsYyIKOzs7Cjs7 OyA8VGltZXN0YW1wOiAjezIwMTAtMDEtMjhUMTk6MzE6MDMtMDU6MDBafSN7MTAwNDR9IC0gYnkg TU9OPgooZGVmdW4gbG9jYXRlLWxpYnJhcnktcm12LXNmeCAobGlicmFyeSBsb2NwYXRoIHJtdnNm eC1zaHctZ3opCiAgIkxJQlJBUlkgaXMgYSBzdHJpbmcgbmFtaW5nIHRoZSBsaWJyYXJ5IHRvIGxv Y2F0ZS4KTE9DUEFUSCBpcyBhIGxpc3Qgb2YgcGF0aHMgaW4gd2hpY2ggdG8gbG9jYXRlIExJQlJB UlkKUk1WU0ZYLVNIVy1HWiBpcyBhIGRvdHRlZCBsaXN0IHdpdGggdGhlIGZvcm06XG4KICdcKFwo XCIuZWxcIiBcIi5lbC5nelwiIFwiLmJ1YmJhXCJcKSAuIHRcKVwiClRoZSBmaXJzdCBlbGVtZW50 IGlzIGEgbGlzdCBvZiBzdWZmaXggbmFtZXMgd2hpY2ggTElCUkFSWSBtaWdodCBoYXZlLgpXaGVu IHByZXNlbnQgdGhlIHNlY29uZCBlbGVtZW50IGlzIGEgYm9vbGVhbiwgdCBvciBuaWwuIElmIHQg d2hlbiBMSUJSQVJZIGlzCmZvdW5kIGluIFBBVEggd2l0aCBhIHN1ZmZpeCBtYXRjaGluZyB0aGUg Zmlyc3QgZWxlbWVudCBvZiBSTVZTRlgtU0hXLUdaIGFuZCB0aGF0CmVsZW1lbnQgcmVwcmVzZW50 cyBhIGNvbXByZXNzZWQgZmlsZSBleHRlbnNpb24gc2hvdyB0aGUgZmlsZSBuYW1lIHdpdGggdGhl CmV4dGVuc2lvbi4iCiAgKGxldCogKChnbHMgKHNvcnQgKGdldC1sb2FkLXN1ZmZpeGVzKSAjJyhs YW1iZGEgKGwxIGwyKSAoPCAobGVuZ3RoIGwxKSAobGVuZ3RoIGwyKSkpKSkKICAgICAgICAgKGxm cnMgICAocmVtb3ZlICIiIGxvYWQtZmlsZS1yZXAtc3VmZml4ZXMpKSAgICAgICAgIAogICAgICAg ICAoY2xuLWxpYiAoaWYgKHN0cmluZz0gKGZpbGUtbmFtZS1zYW5zLWV4dGVuc2lvbiBsaWJyYXJ5 KSBsaWJyYXJ5KQogICAgICAgICAgICAgICAgICAgICAgbGlicmFyeQogICAgICAgICAgICAgICAg ICAgICAgKGxldCAoKGxpYi1jbG4gbGlicmFyeSkpCiAgICAgICAgICAgICAgICAgICAgICAgICht YXBjICMnKGxhbWJkYSAocmd4KSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChs ZXQgKChtcyAoc3RyaW5nLW1hdGNoLXAgcmd4IGxpYi1jbG4pKSkKICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgKHdoZW4gbXMgKHNldHEgbGliLWNsbiAoc3Vic3RyaW5nIGxpYi1j bG4gMCBtcykpKSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICcoIlxcKFxcKFxcLmVs Y1xcfFxcLmVsXFwpXFwuZ3pcXCkiIDsgLT4gMSAuZWxbY10uZ3oKICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAiXFwoXFwuZWxjXFx8XFwuZWxcXCkiIDsgLT4gMSAuZWxjIHwgLmVsIAog ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJcXChcXC5nelxcKSIpKSAgICAgICAgOyAt PiAxIC5negogICAgICAgICAgICAgICAgICAgICAgICBsaWItY2xuKSkpCiAgICAgICAgIDs7IDpO T1RFIGFyZyAKICAgICAgICAgKHNody1neiAgKGNkciBybXZzZngtc2h3LWd6KSkgIDsgPT4gdAog ICAgICAgICAocm12c2Z4IChjYXIgcm12c2Z4LXNody1neikpICAgOyA9PiAoIi5lbCIgIi5lbC5n eiIgIi5idWJiYSIpCiAgICAgICAgIChzZnggIChjb25kICgoYm9vbGVhbnAgcm12c2Z4KSAoZGVs ZXRlLWR1cHMgKGFwcGVuZCBnbHMgbGZycykpKQogICAgICAgICAgICAgICAgICAgICAoKGFuZCBy bXZzZnggKHN0cmluZ3Agcm12c2Z4KSkKICAgICAgICAgICAgICAgICAgICAgIGAoLHJtdnNmeCAs QChtYXBjYXIgIycobGFtYmRhICh6KSAoY29uY2F0IHJtdnNmeCB6KSkgbGZycykpKQogICAgICAg ICAgICAgICAgICAgICAoKGNvbnNwIHJtdnNmeCkgKGRlbGV0ZS1kdXBzIChhcHBlbmQgcm12c2Z4 IGxmcnMpKSkKICAgICAgICAgICAgICAgICAgICAgOzsgKHQgKGFwcGVuZCAgZ2xzIGxmcnMpKSkp IDs7IDwtc2hvdWxkIG5vdCBoYXBwZW4uCiAgICAgICAgICAgICAgICAgICAgICkpCiAgICAgICAg IChmaWxlIChsb2NhdGUtZmlsZSBjbG4tbGliIGxvY3BhdGggc2Z4ICdleGlzdHMpKSkKICAgICh3 aGVuIGZpbGUgCiAgICAgIChzZXRxIGZpbGUgKGZpbGUtdHJ1ZW5hbWUgZmlsZSkpCiAgICAgIChs ZXQgKChzbXAtZ3ogKHN0cmluZy1tYXRjaC1wICIuKlxcLmd6IiBmaWxlKSkpCiAgICAgICAgKHNl dHEgZmlsZSAoY29uY2F0IChmaWxlLW5hbWUtZGlyZWN0b3J5IGZpbGUpCiAgICAgICAgICAgICAg ICAgICAgICAgICAgIChjb25kICgob3IgKG5vdCBzaHctZ3opIChhbmQgc2h3LWd6IChub3Qgc21w LWd6KSkpCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA7OyBDYWxsIGl0IHR3aWNl IHRvIGtub2NrIHRoZSAuZ3ogb2ZmIHRoZSAuZWwuZ3oKICAgICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgIChmaWxlLW5hbWUtc2Fucy1leHRlbnNpb24KICAgICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAoZmlsZS1uYW1lLW5vbmRpcmVjdG9yeSAKICAgICAgICAgICAgICAgICAg ICAgICAgICAgICAgICAgICAgKGZpbGUtbmFtZS1zYW5zLWV4dGVuc2lvbiBmaWxlKSkpKQogICAg ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoKG9yIChhbmQgc2h3LWd6IHNtcC1neikgdCkg CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZmlsZS1uYW1lLW5vbmRpcmVjdG9y eSBmaWxlKSkpKSkpKQogICAgZmlsZSkpCjs7Cjs7Owo7OzsgOlRFU1QtTUUgKGxvY2F0ZS1saWJy YXJ5LXJtdi1zZnggInN1YnIuZWwiICcoIi9ob21lL01PTi9sb2MtbGliciIpICcoKCIuYnViYmEi ICIuZWwiICIuZWwuZ3oiKSAuIHQpKQo7OzsgICAgICAgICAgPT4gIi9ob21lL01PTi9sb2MtbGli ci9zdWJyIgo7OzsgOlRFU1QtTUUgKGxvY2F0ZS1saWJyYXJ5LXJtdi1zZnggInN1YnIuZWwiICco Ii9ob21lL01PTi9sb2MtbGliciIpICcoKCIuYnViYmEiICIuZWwiICIuZWwuZ3oiKSkpCjs7OyAg ICAgICAgICA9PiAiL2hvbWUvTU9OL2xvYy1saWJyL3N1YnIiCjs7OyA6VEVTVC1NRSAobG9jYXRl LWxpYnJhcnktcm12LXNmeCAic3ViciIgJygiL2hvbWUvTU9OL2xvYy1saWJyIikgJygoIi5lbC5n eiIgIi5idWJiYSIgICIuZWwiKSAuIHQpKQo7OzsgICAgICAgICAgPT4iL2hvbWUvTU9OL2xvYy1s aWJyL3N1YnIuZWwuZ3oiCjs7OyA6VEVTVC1NRSAobG9jYXRlLWxpYnJhcnktcm12LXNmeCAic3Vi ci5lbCIgJygiL2hvbWUvTU9OL2xvYy1saWJyIikgJygoIi5lbC5neiIgIi5idWJiYSIgICIuZWwi KSAuIG5pbCkpCjs7OyAgICAgICAgICA9PiAiL2hvbWUvTU9OL2xvYy1saWJyL3N1YnIiCjs7OyA6 VEVTVC1NRSAobG9jYXRlLWxpYnJhcnktcm12LXNmeCAic3Vici5lbC5neiIgJygiL2hvbWUvTU9O L2xvYy1saWJyIikgJygoIi5lbC5neiIgIi5idWJiYSIgICIuZWwiKSAuIG5pbCkpCjs7OyAgICAg ICAgICA9PiAiL2hvbWUvTU9OL2xvYy1saWJyL3N1YnIiCjs7OyA6VEVTVC1NRSAobG9jYXRlLWxp YnJhcnktcm12LXNmeCAic3Vici5lbC5neiIgJygiL2hvbWUvTU9OL2xvYy1saWJyIikgJygoIi5l bC5neiIgIi5idWJiYSIgICIuZWwiKSAuIHQpKQo7OzsgICAgICAgICAgID0+ICIvaG9tZS9NT04v bG9jLWxpYnIvc3Vici5lbC5neiIKOzs7IDpURVNULU1FIChsb2NhdGUtbGlicmFyeS1ybXYtc2Z4 ICJzdWJyLmVsLmd6IiAnKCIvaG9tZS9NT04vbG9jLWxpYnIiKSAnKCgiLmVsLmd6IiAiLmJ1YmJh IiAgIi5lbCIpIC4gdCkpCjs7Owo7OzsgOlRFU1QtTUUgKGxvY2F0ZS1saWJyYXJ5LXJtdi1zZngg InN1YnIuZWwuZ3oiICcoIi9ob21lL01PTi9sb2MtbGliciIgIi91c3Ivc2hhcmUvZW1hY3MvMjMu MS45MC9saXNwIikgCjs7OyAgICAgICAgICAgICAgICAgICAgICAgICcoKCIuZWwuZ3oiICIuYnVi YmEiICAiLmVsIikgLiB0KSkKOzs7ICAgICAgICAgICAgPT4gIi9ob21lL01PTi9sb2MtbGlici9z dWJyLmVsLmd6Igo7OzsKOzs7IDpURVNULU1FIChsb2NhdGUtbGlicmFyeS1ybXYtc2Z4ICJzdWJy LmVsLmd6IiAnKCIvdXNyL3NoYXJlL2VtYWNzLzIzLjEuOTAvbGlzcCIgIi9ob21lL01PTi9sb2Mt bGliciIgKQo7OzsgICAgICAgICAgICAgICAgICAgICcoKCIuZWwuZ3oiICIuYnViYmEiICAiLmVs IikgLiB0KSkKOzs7ICAgICAgICAgICA9PiAiL3Vzci9zaGFyZS9lbWFjcy8yMy4xLjkwL2xpc3Av c3Vici5lbC5neiIKOzs7Cjs7OyA6VEVTVC1NRSAobG9jYXRlLWxpYnJhcnktcm12LXNmeCAic3Vi ciIgJygiL3Vzci9zaGFyZS9lbWFjcy8yMy4xLjkwL2xpc3AiIi9ob21lL01PTi9sb2MtbGliciIp IAo7OzsgICAgICAgICAgICAgICAgICAgICcoKCIuZWwuZ3oiICIuYnViYmEiICAiLmVsIikgLiB0 KSkKOzs7ICAgICAgICAgID0+ICIvdXNyL3NoYXJlL2VtYWNzLzIzLjEuOTAvbGlzcC9zdWJyLmVs Lmd6Igo7OzsKOzs7IDpURVNULU1FIChsb2NhdGUtbGlicmFyeS1ybXYtc2Z4ICJzdWJyIiAnKCIv dXNyL3NoYXJlL2VtYWNzLzIzLjEuOTAvbGlzcCIgIi9ob21lL01PTi9sb2MtbGliciIpIAo7Ozsg ICAgICAgICAgICAgICAgICAgICcoKCIuZWwuZ3oiICIuYnViYmEiICAiLmVsIikpKQo7OzsgICAg ICAgICAgPT4gIi91c3Ivc2hhcmUvZW1hY3MvMjMuMS45MC9saXNwL3N1YnIiCjs7OyAKOzs7IDpU RVNULU1FCjs7OyA6Tk9URSA6U0VFIGBmZmFwLWxvY2F0ZS1maWxlJyBmb3IgbW9yZSBvbiAgd2h5 IHRoaXMgaXMgYSByZWxldmFudCB1c2UtY2FzZS4KOzs7IChsZXQgKChmaW5kLXZhZ3VlbHkgCjs7 OyAgICAgICAgKGxvY2F0ZS1saWJyYXJ5LXJtdi1zZnggCjs7OyAgICAgICAgICJzdWJyIiAKOzs7 ICAgICAgICAgJyggIi9ob21lL01PTi9sb2MtbGliciIgIi91c3Ivc2hhcmUvZW1hY3MvMjMuMS45 MC9saXNwIikgCjs7OyAgICAgICAgICcoKCAiLmJ1YmJhIiAiLmVsLmd6IiAiLmVsIikgLnQpKSkp Cjs7OyAgIChpZiAoZmlsZS1leGlzdHMtcCBmaW5kLXZhZ3VlbHkpCjs7OyAgICAgICAoZmluZC1m aWxlIGZpbmQtdmFndWVseSkKOzs7ICAgICAgIChjb21wbGV0aW5nLXJlYWQgIldoaWNoIGZpbGUg OiIKOzs7ICAgICAgICAgICAgICAgICAgICAgICAgKGZpbGUtZXhwYW5kLXdpbGRjYXJkcyAoY29u Y2F0IGZpbmQtdmFndWVseSAiKiIpKSkpKQo7OzsKCjs7OyA9PT09PT09PT09PT09PT09PT09PT09 PT09PT09PT0KOzs7IEVPRg== --000e0cd6ab82a2573c047e44c450--